を使用して確率分布から繰り返しサンプリングするコードがありますsequence
。道徳的には、次のようなことを行います。
sampleMean :: MonadRandom m => Int -> m Float -> m Float
sampleMean n dist = do
xs <- sequence (replicate n dist)
return (sum xs)
もう少し複雑であることを除いて。私が興味を持っている実際のコードは、この Github repo のlikelihoodWeighting
関数です。
実行時間は と非線形にスケーリングすることに気付きましたn
。特に、n
一定の値を超えるとメモリ制限に達し、実行時間が爆発的に増加します。確かではありませんが、これsequence
は の呼び出しまで評価されないサンクの長いリストを作成しているためだと思いますsum
。
約 100,000 個のサンプルを超えると、プログラムの速度が遅くなり、クロールします。これを最適化したい (私の感覚では、1000 万のサンプルは問題にならないはずです) ので、プロファイリングすることにしましたが、プロファイラーの出力を理解するのに少し問題があります。
プロファイリング
main.hs
100,000 サンプルで関数を実行する短い実行可能ファイルをファイルに作成しました。これが実行からの出力です
$ ghc -O2 -rtsopts main.hs
$ ./main +RTS -s
最初に気づいたことは、約 1.5 GB のヒープを割り当て、その時間の 60% をガベージ コレクションに費やしていることです。これは一般的に怠惰が多すぎることを示していますか?
1,377,538,232 bytes allocated in the heap
1,195,050,032 bytes copied during GC
169,411,368 bytes maximum residency (12 sample(s))
7,360,232 bytes maximum slop
423 MB total memory in use (0 MB lost due to fragmentation)
Generation 0: 2574 collections, 0 parallel, 2.40s, 2.43s elapsed
Generation 1: 12 collections, 0 parallel, 1.07s, 1.28s elapsed
INIT time 0.00s ( 0.00s elapsed)
MUT time 1.92s ( 1.94s elapsed)
GC time 3.47s ( 3.70s elapsed)
RP time 0.00s ( 0.00s elapsed)
PROF time 0.23s ( 0.23s elapsed)
EXIT time 0.00s ( 0.00s elapsed)
Total time 5.63s ( 5.87s elapsed)
%GC time 61.8% (63.1% elapsed)
Alloc rate 716,368,278 bytes per MUT second
Productivity 34.2% of total user, 32.7% of total elapsed
からの結果は次のとおりです。
$ ./main +RTS -p
これを初めて実行したとき、1 つの関数が繰り返し呼び出されていることが判明し、メモ化できることがわかりました。これにより、処理速度が 2 倍になりました。ただし、スペース リークは解決しませんでした。
COST CENTRE MODULE no. entries %time %alloc %time %alloc
MAIN MAIN 1 0 0.0 0.0 100.0 100.0
main Main 434 4 0.0 0.0 100.0 100.0
likelihoodWeighting AI.Probability.Bayes 445 1 0.0 0.3 100.0 100.0
distributionLW AI.Probability.Bayes 448 1 0.0 2.6 0.0 2.6
getSampleLW AI.Probability.Bayes 446 100000 20.0 50.4 100.0 97.1
bnProb AI.Probability.Bayes 458 400000 0.0 0.0 0.0 0.0
bnCond AI.Probability.Bayes 457 400000 6.7 0.8 6.7 0.8
bnVals AI.Probability.Bayes 455 400000 20.0 6.3 26.7 7.1
bnParents AI.Probability.Bayes 456 400000 6.7 0.8 6.7 0.8
bnSubRef AI.Probability.Bayes 454 800000 13.3 13.5 13.3 13.5
weightedSample AI.Probability.Bayes 447 100000 26.7 23.9 33.3 25.3
bnProb AI.Probability.Bayes 453 100000 0.0 0.0 0.0 0.0
bnCond AI.Probability.Bayes 452 100000 0.0 0.2 0.0 0.2
bnVals AI.Probability.Bayes 450 100000 0.0 0.3 6.7 0.5
bnParents AI.Probability.Bayes 451 100000 6.7 0.2 6.7 0.2
bnSubRef AI.Probability.Bayes 449 200000 0.0 0.7 0.0 0.7
これがヒーププロファイルです。ランタイムが 1.8 秒であると主張する理由がわかりません。この実行には約 6 秒かかりました。
プロファイラーの出力を解釈するのを手伝ってくれる人はいますか?つまり、ボトルネックがどこにあるかを特定し、スピードアップする方法を提案してくれますか?