2012-05-21 28 views
6

私はマルチスレッドセクションを持っています。ここでスレッドは、バッファとして使用するために、それぞれ〜100MBのような大きなデータセグメントを割り当てる必要があります。さらに、実行時にバッファを数回リサイズする必要があるかもしれません。メモリアロケータの提案

自然な解決策は、reallocを使用することですが、不要なメモリを移動させる可能性があります。 free/mallocバッファをサイズ変更するためのペア私は恐れて、手作業が他の問題を作成する前に、断片化とメモリの確保につながる可能性があります。

代わりに、メモリを割り当てる/再割り当てするために使用できるのは何ですか?

+0

"手前にメモリを予約して他の問題が発生する"プール用アロケータは適切ではありませんか?そして、あなたは標準のままにしたいと思っていますか、カスタム割り当て方式のアプローチを探していますか? – Corbin

+0

@Corbinプールは私の場合は良いとは思わない - LinuxはNUMA domanisでファーストタッチポリシーを持っている。私は、あなたがサイズ変更の必要を避けることができるように、バッファ内のデータを管理するための方法* portable * solution – Anycorn

+0

に泊まりたいですか?またはバッファサイズに上限を置くことさえできますか?どのくらいのメモリをハードウェアに搭載する予定ですか? –

答えて

5

freeおよびmallocを使用してください。これにより断片化の問題は発生しません。

現代のアロケータは、メモリの断片化にかなり抵抗しています。最近では、断片化の問題を引き起こすためにかなり病理学的なプログラムが必要です。断片化は、私たちのプログラムが物理RAMを直接アドレス指定した場合にはより深刻な問題でしたが、仮想メモリを使用すると、プログラムのヒープ内の大きな穴がリソースを消費する必要はありません。

さらに、バッファのサイズのために、ほとんどのアロケータは、各バッファの専用領域をカーネルから要求します。 Linux/OS X/BSDでは、これは各バッファのの舞台裏で匿名のmmapを意味します。これはアドレス空間の断片化を引き起こす可能性がありますが、仮想アドレス空間は基本的に64ビットシステムでは使用できません。また、数百メガは32ビットでも問題ありません。

freemallocを使用してください。

代替:各バッファを必要以上に大きくする方が早いかもしれません。 mallocの方法は、現代のUnix上で動作します。書き込まないページはメモリを消費しません。

malloc 500 MBのバッファーで、最初の100 MBしか使用しない場合は、malloc 100 MBのバッファーを使用した場合と比べてプログラムで実際に使用されるメモリが実際より多くなりません。このようにアドレススペースの断片化が増えますが、これは64ビットシステムでは問題にはならず、割り当てサイズを常に調整して32ビットシステムでも動作させることができます。 mmapを使用するための提案については

、ちょうど(1 MIBは共通のしきい値である)、それは大規模な配分のためにあるものである、mmap/munmapにシンプルなインターフェイスとしてmalloc/freeを考えます。

+0

フラグメンテーションが発生する条件を記述したリファレンスはありますか? – Anycorn

+0

16バイトのチャンクを割り当て、奇数のチャンクを解放し、24バイトのチャンクを割り当て、奇数のチャンクを解放して、次のようなことを続けるなど、いくつかの奇妙なことがあります。それ。これは基本的に 'malloc'の最悪のシナリオですが、無駄になったメモリの割合には限界があります。 –

+1

@Anycorn:実際、このような大きなバッファについては、アドレス空間*断片化であり、メモリの断片化ではありません。 64ビット版の場合、アドレス空間の断片化は気にするものではありません。 –

1

あなたのソリューションをmalloc/realloc/freeで実装し、プロファイルします。メモリの割り当てに問題がある場合は、facebookのjemallocやgoogleのtcmallocなど、mallocの実装を改善することができます。

C++ memory allocation mechanism performance comparison (tcmalloc vs. jemalloc)を参照してください。

これらはどちらも内部/外部フラグメンテーションの処理に優れています。

+1

100 MBバッファの場合、jemallocまたはtcmallocの違いは、どちらも、特定のしきい値(1 MiBが一般的)を超える割り振りのためにカーネルから直接ページを要求するためです。あなたのシステムのデフォルトの 'malloc'も同じことをします。 –

+0

@DietrichEppデフォルトのmallocに関する問題は、マルチスレッドアプリケーションの場合のロック競合です。しかし、私は確かにそれらを使用する前に自分のプログラムをプロファイルします。 –

+1

あなたが100 MBのバッファについて話しているならば、あなたがシステムコールをしなければならないので、競争の激しいロックのコストも最小限に抑えられます。 –

4

reallocを単に使用してください。最新のシステムでは、バッファが新しいアドレスに移動したとしても、ページテーブルを操作することで移動が行われます(Linuxではmremap;他のシステムにも同様のメカニズムがあると確信しています)。 (ここでは大きなバッファを想定していることに注意してください;通常は数百kb未満の小さなバッファでは実際のコピーが行われます。)

ターゲットが64ビットマシンの場合、メモリの断片化を心配する必要は全くありません。仮想アドレス空間が足りなくなるほどメモリを断片化することはありません。 32ビットマシンも処理する必要がある場合は、あまりにも多くのスレッドを持たない限り、おそらく安全です。合計メモリ消費量が1GB未満であれば、フラグメンテーションのために仮想アドレス空間を使い果たすのは非常に難しく、という使用パターンを仮定すると、となります。あなたがそれについて心配しているなら、あなたが必要とするかもしれない最大のサイズを事前に割り当てるだけです。