我一直在做的F#的一些计算密集型工作。 像功能Array.Parallel.map
其使用.NET任务并行库加快了我的代码成倍的真的很最小的努力。
然而,由于存储器的担忧,我重拍的我的代码段,使得它可以在表达序列内被懒惰地评估(这意味着我必须存储并传递较少的信息)。 当它来到的时间来评估我所用:
// processor and memory intensive task, results are not stored
let calculations : seq<Calculation> = seq { ...yield one thing at a time... }
// extract results from calculations for summary data
PSeq.iter someFuncToExtractResults results
代替:
// processor and memory intensive task, storing these results is an unnecessary task
let calculations : Calculation[] = ...do all the things...
// extract results from calculations for summary data
Array.Parallel.map someFuncToExtractResults calculations
当使用任何Array.Parallel功能,我可以清楚地看到所有我的电脑上一脚芯成齿轮(〜100%的CPU使用率)。 但是需要额外的内存意味着这个程序没有完成。
随着当我运行该程序的PSeq.iter版本的话,只有约8%的CPU使用率(和最小的RAM使用)。
所以:是有一些原因PSEQ版本运行,因此很慢? 是不是因为懒惰的评价? 有一些神奇的“平行”的东西,我很想念?
谢谢,
其它资源,包括源代码的实现(他们似乎使用.NET不同并行库):
https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/array.fs
https://github.com/fsharp/powerpack/blob/master/src/FSharp.PowerPack.Parallel.Seq/pseq.fs
编辑:添加更多的细节,代码示例和细节
码:
SEQ
// processor and memory intensive task, results are not stored let calculations : seq<Calculation> = seq { for index in 0..data.length-1 do yield calculationFunc data.[index] } // extract results from calculations for summary data (different module) PSeq.iter someFuncToExtractResults results
排列
// processor and memory intensive task, storing these results is an unnecessary task let calculations : Calculation[] = Array.Parallel.map calculationFunc data // extract results from calculations for summary data (different module) Array.Parallel.map someFuncToExtractResults calculations
细节:
- 所述存储所述中间阵列版本的运行快(只要它碰撞之前获得)在10分钟内,但使用〜70GB RAM它崩溃之前(64GB物理,其余分页)
- 该序列版本接管34mins并使用RAM(只有约30GB)的一小部分
- 有一个〜十亿值,我计算。 因此,一个十亿双打(在每个64位)= 7.4505806GB。 还有更复杂的数据形式......和一些不必要的副本我清理,因此目前大规模的RAM使用。
- 是的架构不是很大,懒惰的评价是我的第一部分尝试将程序和/或批量备份数据优化成小块
- 用较小的数据集,代码输出的两个块中的相同的结果。
- @pad,我想你的建议,在PSeq.iter似乎喂计算[]时正常工作(所有核活动),但仍有RAM的物质(它最终崩溃)
- 两个代码的摘要部分和计算部分是CPU密集型(主要是因为大的数据集)
- 随着SEQ版本我的目标是一旦并行