プロセスが多くのリソグラフィ計算を行うため、mmap を使用してメモリ プールにメモリを割り当てました。プロセスに大量のメモリが必要な場合は、mmap を使用してチャンクを割り当て、使用後にメモリ プールに入れます。プロセスで同じチャンク メモリが再び必要な場合は、メモリを使用するのではなく、プールから直接取得します。再度マップします (必要なすべてのメモリを割り当てず、プロセスの開始時にプールに入れます)。mmaps 関数の間には、malloc() や new() など、mmap を使用しないメモリ malloc があります。
問題は次のとおりです。memset() を使用してすべてのチャンク データをメモリ プールに入れる前に 0 に設定すると、プロセスは次のように仮想メモリを使いすぎます。フォーマットは「mmap(size)=virtual address」です。
mmap(4198400)=0x2aaab4007000 mmap(4198400)=0x2aaab940c000 mmap(8392704)=0x2aaabd80f000 mmap(8392704)=0x2aaad6883000 mmap(67112960)=0x2aaad7084000 mmap(8392704)=0x2aaadb085000 mmap(2101248)=0x2aaadb886000 mmap(8392704)=0x2aaadba89000 mmap(67112960)=0x2aaadc28a000 mmap(2101248)=0x2aaae028b000 mmap(2101248)=0x2aaae0c8d000 mmap(2101248)=0x2aaae0e8e000 mmap(8392704)=0x2aaae108f000 mmap(8392704)=0x2aaae1890000 mmap(4198400)=0x2aaae2091000 mmap(4198400)=0x2aaae6494000 mmap(8392704)=0x2aaaea897000 mmap(8392704)=0x2aaaeb098000 mmap(2101248)=0x2aaaeb899000 mmap(8392704)=0x2aaaeba9a000 mmap(2101248)=0x2aaaeca9c000 mmap(8392704)=0x2aaaec29b000 mmap(8392704)=0x2aaaecc9d000 mmap(2101248)=0x2aaaed49e000 mmap(8392704)=0x2aaafd6a7000 mmap(2101248)=0x2aacc5f8c000
mmap の最後 - 最初 = 0x2aacc5f8c000 - 0x2aaab4007000 = 8.28G
しかし、メモリ プールに入れる前に memset を呼び出さないと、次のようになります。
mmap(4198400)=0x2aaab4007000 mmap(8392704)=0x2aaab940c000 mmap(8392704)=0x2aaad2480000 mmap(67112960)=0x2aaad2c81000 mmap(2101248)=0x2aaad6c82000 mmap(4198400)=0x2aaad6e83000 mmap(8392704)=0x2aaadb288000 mmap(8392704)=0x2aaadba89000 mmap(67112960)=0x2aaadc28a000 mmap(2101248)=0x2aaae0a8c000 mmap(2101248)=0x2aaae0c8d000 mmap(2101248)=0x2aaae0e8e000 mmap(8392704)=0x2aaae1890000 mmap(8392704)=0x2aaae108f000 mmap(4198400)=0x2aaae2091000 mmap(4198400)=0x2aaae6494000 mmap(8392704)=0x2aaaea897000 mmap(8392704)=0x2aaaeb098000 mmap(2101248)=0x2aaaeb899000 mmap(8392704)=0x2aaaeba9a000 mmap(2101248)=0x2aaaec29b000 mmap(8392704)=0x2aaaec49c000 mmap(8392704)=0x2aaaecc9d000 mmap(2101248)=0x2aaaed49e000
mmap 最後 - 最初 = 0x2aaaed49e000 - 0x2aaab4007000= 916M
したがって、最初のプロセスは「メモリ不足」になり、強制終了されます。
プロセスでは、mmap メモリ チャンクは完全には使用されないか、割り当てられていても使用されません。つまり、たとえば、キャリブレーションの前に、プロセス mmap 67112960(64M) は使用されません (このデータの書き込みまたは読み取りメモリ領域) または最初の 2M バイトだけを使用してから、メモリ プールに入れます。
mmapは仮想アドレスを返すだけで、物理メモリは遅延割り当てを使用することを知っています。これらのアドレスで読み取りまたは書き込みを行うと割り当てられます。
しかし、私を混乱させたのは、なぜ仮想アドレスがこれほど増加したのかということです。centos 5.3 を使用しました。カーネル バージョンは 2.6.18 です。libhoard と GLIBC(ptmalloc) の両方でこのプロセスを試しましたが、どちらも同じ動作でした。
以前に同じ問題に遭遇した人はいますか?考えられる根本的な原因は何ですか?
ありがとう。