漸近的なケースで優れていることが証明されているが、それに関連する大きな定数を持つd次元範囲検索アルゴリズムの実用性を調査しようとしています。これは、d 次元空間のポイント数を非常に大きな値まで変化させる必要があることを意味します。1<<20
(2 の 20 乗) ポイントを使用すると、 malloc
s が null ポインターを返すようになります。私はfree
できるだけ頻繁にメモリを増やしており、可能な限り少ない場所で可能な限りの節約を行っていますが、値を に近づけたいと思っています1<<28
。この種のサイズのメモリ ブロックを処理する従来の方法はありますか?
4 に答える
32 ビット プロセッサおよび/またはオペレーティング システムで実行している場合、または 64 ビットではなく 32 ビット用にコンパイルしている場合はできません。物理メモリ - malloc は連続したブロックを試行するため、スワップ ファイルは役に立ちません。SIZE_MAX は、割り当てを試行できる最大数を示しますが、失敗は物理的な制約によって異なります。
2^28 = 256MB。
十分な物理メモリがあれば、32 ビットまたは 64 ビット システムで確実に実行できるはずです。実行しているかどうかを確認するには、出力を取得して行cat /proc/meminfo
を探します。MemFree
私がお勧めする API はmmap()
、代わりに (匿名マッピング) です。malloc()
http://man7.org/linux/man-pages/man2/mmap.2.html
mmap
OSに直接メモリを要求するシステムコールです。malloc()
下に使うものです。
が失敗し始めている場合malloc()
は、(わずかに恣意的な) rlimit 制限に達している可能性があります。それらをいくらか緩和できるはずです ( を参照ulimit
) bash
。ただし、これらの制限は、一般的な用途でシステムを安定させ、予測可能に保つために設定されていることに注意してください。また、オーバーコミットに注意してください。これは、OS が提供できるよりも多くのメモリを要求する可能性があり、それを使用しようとすると強制終了する可能性がある場合です。
本当にアドレス空間が不足していて、32 ビット アプリケーションを構築している場合は、64 ビットに切り替えてください。
64 ビット アプリケーションでアドレス空間が不足している場合は、割り当てを十分に活用していないことをお勧めします。これは大量のデータを入力する必要があり、アドレス空間がなくなる前に時間切れになると思います。この場合、おそらくスペースの使用方法を再考する必要があります。
システムで使用できるよりも大きなアドレス空間が必要な場合は、必要に応じてファイル (または多数のファイル) とmmap()
それらのファイルの断片を作成できます。これにより、OS はその能力を最大限に発揮してファイルをキャッシュすることができ、物理メモリとスワップの両方が不足した場合 (このようなプロジェクトでは常にリスクになります)、データをページアウトできる場所があります。パニックに陥ったり、アプリケーションを強制終了したりすることなく。
残念ながら、mmap()
この方法を使用するには、そのファイル内で独自の割り当てを管理する必要があります。
このような大きなブロックを割り当てると、null ポインターが返されるようになると言われています。私にとって、これはしばらくの間は機能すること、時間の経過とともにこれらのかなりの数を割り当てて解放していること、そして何度か実行した後、null を取得し始めることを意味します。
その場合は、メモリの断片化の典型的なケースが見られます。(私の仮定が間違っている場合は、次の小説をご容赦ください。) 過去に、私はメモリ内のオブジェクトを再配置して新しいブロックを割り当てるためのスペースを確保できるようにする独自のメモリ マネージャーを作成することで、このような問題を処理しました。コードが割り当てられたブロックへのポインターを保持できる必要がある場合、メモリ マネージャーは、移動を透過的にするポインターの実装を含める必要があります。サードパーティのソフトウェアに依存している場合、これは困難または不可能になります。
使用する各ブロック サイズのプールを事前に割り当てることを検討することもできます。これにより、大きなブロックのプール全体を使用した場合にのみ大きなブロックが使用できなくなるような方法でメモリを断片化することはありません。これは、空きメモリが十分にあるのではなく、小さな断片だけである場合とは対照的です。Slab Allocationと呼ばれる方法を確認してください。
私の再配置可能メモリの実装は次のように機能しました。プログラムの実行の開始時に、使用可能なメモリの最大の単一ブロックを割り当てました。(mmap はあなたの友達です。) 割り当て要求を満たす空きフラグメントが見つからない場合は、その前後に空き領域のチャンクがあるブロックを見つけて、前の空き領域の場所に移動します。結果として得られる空きブロックが、新しく要求された割り当てに対して十分な大きさになるように、この移動を計画します。
これは良い一般的な解決策ではありません。非常に遅くなる可能性があり、リアルタイムのパフォーマンスが必要なシステムでは使用しません。(1 つの割り当てのために数十ブロックをシャッフルしなければならない場合はどうなるか考えてみてください。最悪の場合、1 つの要求を満たすために、割り当てられたすべてのバイトをコピーする必要があります。)このメモリを参照するすべてのポインタ。ただし、絶対に必要な場合は、スラブ アロケーターよりも効率的にメモリを使用できます。