Haskellプログラムにマルチスレッド機能を追加しようとした後、パフォーマンスがまったく向上していないことに気づきました。それを追いかけて、私はスレッドスコープから次のデータを取得しました:
緑は実行中を示し、オレンジはガベージコレクションを示します。
ここで、垂直の緑色のバーはスパークの作成を示し、青色のバーは並列GC要求を示し、水色のバーはスレッドの作成を示します。
ラベルは、スパークの作成、並列GCの要求、スレッドnの作成、およびキャップ2からのスパークの盗用です。
平均して、4コアで約25%のアクティビティしか得られていません。これは、シングルスレッドプログラムではまったく改善されていません。
もちろん、実際のプログラムの説明がなければ、質問は無効になります。基本的に、トラバース可能なデータ構造(ツリーなど)を作成し、その上に関数をfmapしてから、画像書き込みルーチンにフィードします(15秒を過ぎたプログラム実行の最後に明確にシングルスレッドのセグメントを説明します) 。関数の構築とfmappingはどちらも実行にかなりの時間がかかりますが、2番目の方が少し時間がかかります。
上記のグラフは、画像の書き込みによって消費される前に、そのデータ構造にparTraversable戦略を追加することによって作成されました。また、データ構造でtoListを使用してから、さまざまな並列リスト戦略(parList、parListChunk、parBuffer)を使用してみましたが、結果は、さまざまなパラメーター(大きなチャンクを使用した場合でも)で毎回同様でした。
また、関数をfmapする前に、トラバース可能なデータ構造を完全に評価しようとしましたが、まったく同じ問題が発生しました。
以下にいくつかの追加の統計を示します(同じプログラムの別の実行に対する):
5,702,829,756 bytes allocated in the heap
385,998,024 bytes copied during GC
55,819,120 bytes maximum residency (8 sample(s))
1,392,044 bytes maximum slop
133 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 10379 colls, 10378 par 5.20s 1.40s 0.0001s 0.0327s
Gen 1 8 colls, 8 par 1.01s 0.25s 0.0319s 0.0509s
Parallel GC work balance: 1.24 (96361163 / 77659897, ideal 4)
MUT time (elapsed) GC time (elapsed)
Task 0 (worker) : 0.00s ( 15.92s) 0.02s ( 0.02s)
Task 1 (worker) : 0.27s ( 14.00s) 1.86s ( 1.94s)
Task 2 (bound) : 14.24s ( 14.30s) 1.61s ( 1.64s)
Task 3 (worker) : 0.00s ( 15.94s) 0.00s ( 0.00s)
Task 4 (worker) : 0.25s ( 14.00s) 1.66s ( 1.93s)
Task 5 (worker) : 0.27s ( 14.09s) 1.69s ( 1.84s)
SPARKS: 595854 (595854 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)
INIT time 0.00s ( 0.00s elapsed)
MUT time 15.67s ( 14.28s elapsed)
GC time 6.22s ( 1.66s elapsed)
EXIT time 0.00s ( 0.00s elapsed)
Total time 21.89s ( 15.94s elapsed)
Alloc rate 363,769,460 bytes per MUT second
Productivity 71.6% of total user, 98.4% of total elapsed
回答を支援するために他にどのような有用な情報を提供できるかわかりません。プロファイリングは興味深いものを何も明らかにしません。上記から予想されるように、追加されたIDLEが75%の時間を占めることを除いて、シングルコア統計と同じです。
有用な並列化を妨げているのは何が起こっているのでしょうか?