C または C++ で非常に大きな単一のメモリ チャンク ( > 4GB ) を割り当てることはできますか?

StackOverflow https://stackoverflow.com/questions/181050

  •  05-07-2019
  •  | 
  •  

質問

最近では非常に大量の RAM が使用されているので、4GB を超える単一のメモリ チャンクを割り当てることは可能でしょうか?それとも、多数の小さなチャンクを割り当て、それらの間の切り替えを処理する必要があるでしょうか?

なぜ???openstreetmap XML データの処理に取り組んでいますが、これらのファイルは巨大です。すべてを 1 つのチャンクにロードできないため、現在ストリーミングしていますが、malloc または new の上限が気になりました。

役に立ちましたか?

解決

簡単な答え:ありそうもない

これが機能するためには、64ビットプロセッサを使用する必要があります 。 第二に、4G以上のRAMを単一プロセスに割り当てるためのオペレーティングシステムのサポートに依存します。

理論上は可能ですが、メモリアロケータのドキュメントを読む必要があります。また、メモリの断片化の問題の影響を受けやすくなります。

Windowsメモリ管理に関する情報があります。

>

他のヒント

物理メモリと仮想メモリのレイアウトに関する入門書

64 ビットの CPU と O/S ビルドが必要で、ワーキング セットのスラッシングを避けるためにほぼ確実に十分なメモリが必要です。ちょっとした背景:

32 ビット マシン (概して) には、2^32 (4,294,967,296) 個の一意の値の 1 つを格納できるレジスタがあります。これは、32 ビット ポインターが 2^32 個の一意のメモリ位置のいずれかをアドレス指定できることを意味し、これが魔法の 4GB 制限の由来です。

SPARCV8 や Xeon などの一部の 32 ビット システムには、より多くの物理メモリを許可するトリックを実行する MMU が搭載されています。これにより、複数のプロセスが合計で 4 GB を超えるメモリを占有することができますが、各プロセスは独自の 32 ビット仮想アドレス空間に制限されます。仮想アドレス空間を参照する単一プロセスの場合、32 ビット ポインターでマップできるのは 2^32 の異なる物理位置のみです。

詳細には触れませんが、 このプレゼンテーション (警告:パワーポイント) でこれがどのように機能するかを説明します。一部のオペレーティング システムには、次のような機能があります。 ここ - 上記の FP のおかげで)、MMU を操作し、ユーザー レベルの制御の下で、さまざまな物理的な場所を仮想アドレス空間に交換します。

オペレーティング システムとメモリ マップされた I/O は仮想アドレス空間の一部を占有するため、その 4GB のすべてがプロセスで必ずしも利用できるわけではありません。たとえば、Windows はデフォルトで 2GB を使用しますが、起動時に /3G スイッチが呼び出された場合は 1GB のみを使用するように設定できます。これは、この種の 32 ビット アーキテクチャ上の単一プロセスがメモリ内に構築できるのは、4GB 未満の連続データ構造のみであることを意味します。

これは、明示的に使用する必要があることを意味します。 PAE Windows 上の機能または Linux 上の同等の機能 オーバーレイを手動で入れ替えます。これは必ずしも難しいことではありませんが、機能するまでに時間がかかります。

あるいは、大量のメモリを搭載した 64 ビット ボックスを入手すると、これらの問題は多かれ少なかれ解決します。64 ビット ポインターを備えた 64 ビット アーキテクチャでは、少なくとも理論上は 2^64 (18,446,744,073,709,551,616) もの一意のアドレスを持つ連続したデータ構造を構築できます。これにより、より大きな連続したデータ構造を構築および管理できるようになります。

メモリマッピングファイルの利点は、4Gb(NTFSではほぼ無限!)よりもはるかに大きいファイルを開くことができ、複数の< 4Gbメモリウィンドウを持つことができることです。
ファイルを開いてメモリに読み込むよりもはるかに効率的です。ほとんどのオペレーティングシステムでは、組み込みのページングサポートを使用しています。

これは、64ビットOS(およびそれだけのメモリを搭載したマシン)では問題になりません。

mallocが対処できない場合、OSは確かに、メモリを直接割り当てることができるAPIを提供します。 Windowsでは、 VirtualAlloc APIを使用できます。

使用しているCコンパイラ、およびプラットフォーム(もちろん)によって異なりますが、連続して利用可能なメモリの最大チャンクを割り当てることができないという根本的な理由はありません。もちろん、64ビットシステムを使用して多くのRAMをアドレス指定する必要があるかもしれません...

履歴と詳細については、 Malloc をご覧ください

利用可能な最大のブロックサイズを取得するには、alloc.hで HeapMax を呼び出します

メモリマップファイルの使用を検討しましたか?非常に大きなファイルを読み込んでいるので、これが最善の方法かもしれません。

OSが4GBを超えるメモリのアドレス指定を許可する仮想アドレス空間を提供するかどうか、およびコンパイラがnew / mallocを使用したメモリの割り当てをサポートするかどうかによって異なります。

32ビットWindowsでは、ポインターサイズが32ビットであるため、4GBを超える単一のチャンクを取得することはできません。したがって、仮想アドレス空間は4GBに制限されます。 (物理アドレス拡張機能を使用して詳細を取得できます。 4GB以上のメモリ;ただし、そのメモリを4GBの仮想アドレス空間に自分でマッピングする必要があると思います)

64ビットWindowsの場合、VC ++コンパイラは、仮想アドレス空間の理論上の制限が8TBの64ビットポインターをサポートします。

Linux / gccにも同じことが当てはまります。32ビットでは許可されませんが、64ビットでは許可されます。

Robが指摘したように、VirtualAlloc for Windowsはこれに適したオプションであり、anonymouseファイルマッピングも同様です。ただし、特に質問に関しては、「if CまたはC ++」に対する回答は、割り当てることができます、答えはこれはWIN7 RC 64でもサポートされていません

exeファイルのPE / COFF仕様では、HEAP予約とHEAPコミットを指定するフィールドは32ビット量です。これは、Windows CRTの現在のヒープ実装の物理的なサイズ制限と一致しており、4GBに不足しています。そのため、C / C ++から4GB以上を割り当てる方法はありません(CreateFileMappingおよびVirtualAlloc / VirtualAllocNumaなどのOSサポート機能はCまたはC ++ではありません)。

また、ページテーブルとして知られるx86またはamd64 ABIの基礎となる基盤があることを認識してください。この WILL は、実際には心配していることを行い、大きなリクエストに小さなチャンクを割り当てます。これはカーネルメモリで発生していますが、システム全体に影響がありますが、これらのテーブルは有限です。

このような壮大な目的でメモリを割り当てる場合は、割り当ての粒度(VirtualAllocが適用)に基づいて割り当てること、およびより大きなページを有効にするオプションのフラグまたはメソッドを識別することをお勧めします。

4kbページは、386の最初のページサイズでしたが、ペンティアムは4MBを追加しました。今日、 AMD64 (AMD用ソフトウェア最適化ガイドファミリ10hプロセッサ)の最大ページテーブルエントリサイズは1GBです。これはここでのケースです。4GBを実行したとしましょう。プロセスのメモリを見つけて割り当て、許可するには、カーネルのディレクトリに4つの一意のエントリしか必要ありません。

Microsoftは、このマニュアル。アプリケーションメモリのより細かい点のいくつかを明確にし、Vista / 2008以降のプラットフォームで使用します。

目次

前書き。 4

Memory Manager 4

について 仮想アドレス空間。 5

カーネル仮想の動的割り当て アドレス空間。 5

x86アーキテクチャの詳細。 6

64ビットアーキテクチャの詳細。 7

x86でのカーネルモードスタックジャンプ アーキテクチャ。 7

過剰なプールメモリの使用。 8

セキュリティ:アドレス空間レイアウト ランダム化。 9

ASLRの画像負荷への影響 住所。 9

ASLRの利点..11

動的ベースを作成する方法 画像。 11

I / O帯域幅。 11

Microsoft SuperFetch。 12

ページファイルの書き込み。 12

メモリーマネージャーと キャッシュマネージャー13

プリフェッチスタイルのクラスタリング。 14

大規模ファイル管理15

休止状態およびスタンバイ。 16

高度なビデオモデル16

NUMAサポート17

資源配分。 17

デフォルトのノードとアフィニティ。 18

割り込みアフィニティ。 19

NUMA対応のシステム機能 アプリケーション。 19

NUMA対応のシステム機能 ドライバー。 19

ページング。 20

スケーラビリティ。 20

効率と並列性.. 20

ページフレーム番号とPFNデータベース。 20

ラージページ。 21

キャッシュに合わせたプールの割り当て。 21

仮想マシン。 22

負荷分散。 22

追加の最適化。 23

システムの完全性。 23

ハードウェアエラーの診断。 23

コードの整合性とドライバーの署名。 24

バグチェック中のデータ保存。 24

あなたがすべきこと。 24

ハードウェアメーカー向け。 24

ドライバー開発者向け。 24

アプリケーション開発者向け。 25

システム管理者向け。 25

リソース。 25

システムでsize_tが32ビットを超える場合、最初のハードルはクリアされています。ただし、CおよびC ++標準は、newまたはmallocへの特定の呼び出しが成功したかどうかを判断する責任を負いません(サイズが0のmallocを除く)。これは、OSとヒープの現在の状態に完全に依存します。

他の皆が言ったように、64ビットマシンを手に入れることが道です。ただし、32ビットマシンのインテルマシンでも、OSとCPUが PAE 。残念ながら、32ビットWinXPはこれを行いません(32ビットVistaを行いますか?)。 Linuxではデフォルトでこれを行うことができますが、ポインターが32ビットのままであるため、mmap()を使用しても4GBの領域に制限されます。

しかし、あなたがすべきことは、オペレーティングシステムにメモリ管理を任せることです。その量のRAMを処理できる環境に入り、XMLファイルをデータ構造に読み込んで、スペースを割り当てます。次に、XMLファイル自体ではなく、メモリ内のデータ構造を操作します。

ただし、64ビットシステムであっても、少なくともほとんどの場合、プログラムのどの部分が実際にRAM、キャッシュ、またはディスクにページングされるかを制御することはあまりありません。 MMUはこれを自分で処理します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top