6

Data.Vector.Unboxed.Mutable を介してメモリを割り当てる ST 内の計算があります。ベクトルは決して読み書きされず、runST の外部で参照も保持されません (私の知る限り)。私が抱えている問題は、ST 計算を複数回実行すると、ベクトルのメモリが保持されているように見えることがあります。

割り当て統計:

5,435,386,768 bytes allocated in the heap
    5,313,968 bytes copied during GC
  134,364,780 bytes maximum residency (14 sample(s))
    3,160,340 bytes maximum slop
          518 MB total memory in use (0 MB lost due to fragmentation)

ここでは、計算用に異なる値と 128MB のベクトルを使用して runST 20x を呼び出します (これも未使用で、ST の外部で返されたり参照されたりしていません)。基本的に私のベクターと数MBの他のものだけです。しかし、総メモリ使用量は、ベクトルの 4 つのコピーが同時にアクティブになっていることを示しています。これはベクトルのサイズに完全に対応し、256MB の場合、予想どおり 1030MB になります。

1GB のベクターを使用すると、メモリが不足します (4x1GB + オーバーヘッド > 32 ビット)。少なくとも割り当てが失敗する時点で、RTS が一見未使用で参照されていないメモリを単に GC するのではなく保持する理由がわかりません。

+RTS -S で実行すると、次のことがわかります。

    Alloc    Copied     Live    GC    GC     TOT     TOT  Page Flts
    bytes     bytes     bytes  user  elap    user    elap
134940616     13056 134353540  0.00  0.00    0.09    0.19    0    0  (Gen:  1)
   583416      6756 134347504  0.00  0.00    0.09    0.19    0    0  (Gen:  0)
   518020     17396 134349640  0.00  0.00    0.09    0.19    0    0  (Gen:  1)
   521104     13032 134359988  0.00  0.00    0.09    0.19    0    0  (Gen:  0)
   520972      1344 134360752  0.00  0.00    0.09    0.19    0    0  (Gen:  0)
   521100       828 134360684  0.00  0.00    0.10    0.19    0    0  (Gen:  0)
   520812       592 134360528  0.00  0.00    0.10    0.19    0    0  (Gen:  0)
   520936      1344 134361324  0.00  0.00    0.10    0.19    0    0  (Gen:  0)
   520788      1480 134361476  0.00  0.00    0.10    0.20    0    0  (Gen:  0)
134438548      5964 268673908  0.00  0.00    0.19    0.38    0    0  (Gen:  0)
   586300      3084 268667168  0.00  0.00    0.19    0.38    0    0  (Gen:  0)
   517840       952 268666340  0.00  0.00    0.19    0.38    0    0  (Gen:  0)
   520920       544 268666164  0.00  0.00    0.19    0.38    0    0  (Gen:  0)
   520780       428 268666048  0.00  0.00    0.19    0.38    0    0  (Gen:  0)
   520820      2908 268668524  0.00  0.00    0.19    0.38    0    0  (Gen:  0)
   520732      1788 268668636  0.00  0.00    0.19    0.39    0    0  (Gen:  0)
   521076       564 268668492  0.00  0.00    0.19    0.39    0    0  (Gen:  0)
   520532       712 268668640  0.00  0.00    0.19    0.39    0    0  (Gen:  0)
   520764       956 268668884  0.00  0.00    0.19    0.39    0    0  (Gen:  0)
   520816       420 268668348  0.00  0.00    0.20    0.39    0    0  (Gen:  0)
   520948      1332 268669260  0.00  0.00    0.20    0.39    0    0  (Gen:  0)
   520784       616 268668544  0.00  0.00    0.20    0.39    0    0  (Gen:  0)
   521416       836 268668764  0.00  0.00    0.20    0.39    0    0  (Gen:  0)
   520488      1240 268669168  0.00  0.00    0.20    0.40    0    0  (Gen:  0)
   520824      1608 268669536  0.00  0.00    0.20    0.40    0    0  (Gen:  0)
   520688      1276 268669204  0.00  0.00    0.20    0.40    0    0  (Gen:  0)
   520252      1332 268669260  0.00  0.00    0.20    0.40    0    0  (Gen:  0)
   520672      1000 268668928  0.00  0.00    0.20    0.40    0    0  (Gen:  0)
134553500      5640 402973292  0.00  0.00    0.29    0.58    0    0  (Gen:  0)
   586776      2644 402966160  0.00  0.00    0.29    0.58    0    0  (Gen:  0)
   518064     26784 134342772  0.00  0.00    0.29    0.58    0    0  (Gen:  1)
   520828      3120 134343528  0.00  0.00    0.29    0.59    0    0  (Gen:  0)
   521108       756 134342668  0.00  0.00    0.30    0.59    0    0  (Gen:  0)

ここでは、128MB を超える「ライブ バイト」があるようです。

プロファイルには、+RTS -hy基本的に 128MB を割り当てると書かれています。

http://imageshack.us/a/img69/7765/45q8.png

この動作をより単純なプログラムで再現しようとしましたが、ST、ベクトルを含むリーダー、同じモナド/プログラム構造などで正確なセットアップを複製しても、単純なテストプログラムはこれを示しません。私の大きなプログラムを簡素化すると、明らかに完全に無関係なコードを削除すると、最終的に動作も停止します。

質問:

  • 私は本当にこのベクトルを 20 回中 4 回程度維持していますか?
  • はいの場合、実際にどのようにそれ以降を伝え、そうではない+RTS -Hymaximum residency主張するにはどうすればよいですか? また、この行動を止めるにはどうすればよいですか?
  • いいえの場合、Haskell が GC を実行せず、アドレス空間/メモリが不足しているのはなぜですか? また、この動作を止めるにはどうすればよいですか?

ありがとう!

4

1 に答える 1

2

これは GHC や RTS のバグだと思います。

まず、実際のスペースリークなどはないと確信しています。

理由:

  • ベクトルはどこでも使用されません。読まない、書かない、参照しない。runST が完了したら、収集する必要があります。ST 計算が単一の Int を返し、それを評価するためにすぐに出力する場合でも、メモリの問題は依然として存在します。そのデータへの参照はありません。
  • RTS が提供するすべてのプロファイリング モードは、私が実際に 1 つのベクトル以上のメモリを割り当てたり参照したりすることは決してないという激しい合意に達しています。すべての統計ときれいなグラフはそれを示しています。

さて、ここに興味深い点があります。System.Mem.performGC関数を実行するたびに呼び出して手動で GC を強制すると、問題は完全に解消されます。

そのため、ランタイムに GB 相当のメモリがあり、GC によって (明らかに!) 再利用でき、それ自体の統計によると、もはや誰も保持していない場合があります。メモリ プールが不足すると、ランタイムはメモリを収集せず、OS に追加のメモリを要求します。そして、それが最終的に失敗した場合でも、ランタイムはまだ収集しません (明らかに、GB のメモリを再利用します)。代わりに、メモリ不足エラーでプログラムを終了することを選択します。

私は Haskell、GHC、または GC の専門家ではありません。しかし、これは私にはひどく壊れているように見えます。これをバグとして報告します。

于 2013-08-17T15:18:25.093 に答える