合計メモリ使用量が22Mbだけであるにもかかわらず、Haskellスレッドのヒープオーバーフロー?
レイトレーサーを並列化しようとしています。これは、小さな計算の非常に長いリストがあることを意味します。バニラプログラムは67.98秒で特定のシーンで実行され、合計メモリ使用量は13 MBで、生産性は99.2%です。 最初の試みparBufferでは、バッファサイズ50 の並列方式を使用しました。parBufferスパークが消費されるのと同じ速さでリストをウォークスルーしparList、大量のメモリを使用するようなリストのスパインを強制しないため、私はそれを選択しましたリストが非常に長いため。では-N2、100.46秒で実行され、合計メモリ使用量は14 MBで、生産性は97.8%でした。スパーク情報は次のとおりです。SPARKS: 480000 (476469 converted, 0 overflowed, 0 dud, 161 GC'd, 3370 fizzled) 霧状の火花の割合が高いことは、火花の粒度が小さすぎることを示しているため、次にparListChunk、リストをチャンクに分割し、チャンクごとに火花を作成する方法を試しました。チャンクサイズで最高の結果が得られました0.25 * imageWidth。プログラムは93.43秒で実行され、総メモリ使用量は236 MB、生産性は97.3%でした。スパーク情報は次のとおりSPARKS: 2400 (2400 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)です。メモリ使用量がはるかに多いのparListChunkは、リストのスパインを強制するためです。 次に、リストをチャンクに遅延して分割し、チャンクを渡しparBufferて結果を連結する独自の戦略を記述しようとしました。 concat $ withStrategy (parBuffer 40 rdeepseq) (chunksOf 100 (map colorPixel pixels)) これは、95.99秒で実行され、合計メモリ使用量は22MBで、生産性は98.8%でした。これは、すべてのスパークが変換され、メモリ使用量ははるかに少ないという意味で成功しましたが、速度は向上しません。これは、イベントログプロファイルの一部の画像です。 ご覧のとおり、ヒープオーバーフローが原因でスレッドが停止しています。+RTS -M1Gデフォルトのヒープサイズを最大1Gbまで増やす追加を試みました。結果は変わりませんでした。Haskellのメインスレッドはスタックがオーバーフローするとヒープのメモリを使用することを読んだので、デフォルトのスタックサイズも増やしてみました+RTS -M1G -K1Gが、これも影響はありませんでした。 他に試すことができるものはありますか?必要に応じて、メモリ使用量やイベントログの詳細なプロファイリング情報を投稿できます。多くの情報であり、すべてを含める必要があるとは思わなかったため、すべてを含めませんでした。 編集:私はHaskell …