尽管只有22Mb的总内存使用量,Haskell线程还是会发生堆溢出?
我正在尝试并行化光线追踪器。这意味着我有很长的小型计算清单。Vanilla程序在特定场景上运行需要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 …