F#PSeq.iter似乎并没有被使用的所有核心(F# PSeq.iter does not see

2019-07-29 01:00发布

我一直在做的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版本我的目标是一旦并行

Answer 1:

根据您的更新信息,我缩短了我的答案,只是相关的部分。 你只需要什么,而不是你现在有这样的:

let result = data |> PSeq.map (calculationFunc >> someFuncToExtractResults)

而这将工作一样,你是否使用PSeq.mapArray.Parallel.map

但是,你真正的问题是不会得到解决。 这个问题可以表述为:当为了得到100%的CPU使用率达到的并行工作的期望程度,没有足够的内存来支持流程。

你可以看到这不会得到解决? 您可以按顺序或者处理事情(CPU效率较低,但内存使用效率),也可以并行处理的事情(多CPU效率,但内存用完)。

选项则是:

  1. 更改并行通过这些功能的东西,会不会打击你的内存使用的程度:

     let result = data |> PSeq.withDegreeOfParallelism 2 |> PSeq.map (calculationFunc >> someFuncToExtractResults) 
  2. 改变底层逻辑calculationFunc >> someFuncToExtractResults使得它是一个单一的功能即是更有效的,并通过对结果流数据。 不知道更多的细节,这不是简单的看怎么可以这样做。 但在内部,肯定有的懒加载是可能的。



Answer 2:

Array.Parallel.map使用Parallel.For罩下而PSeq是围绕一个瘦包装PLINQ 。 但他们不同的表现这里的原因是没有足够的工作负载PSeq.iterseq<Calculation>是连续的,在高产新成果太慢。

我不明白使用中间序列或数组的想法。 假设data是输入数组,在一个地方移动所有的计算是要走的路:

// Should use PSeq.map to match with Array.Parallel.map
PSeq.map (calculationFunc >> someFuncToExtractResults) data

Array.Parallel.map (calculationFunc >> someFuncToExtractResults) data

你避免占用过多的内存,并有在同一个地方,这导致在并行执行效率更高密集的计算。



Answer 3:

我有类似你这样的问题,并通过将下面的解决方案的App.config文件解决了这个问题:

<runtime> 
    <gcServer enabled="true" />
    <gcConcurrent enabled="true"/>
</runtime>

这是服用5'49“A计算”和示出大致22%的CPU利用率上过程拉索了1'36“”示出大约80%的CPU利用率。

可能影响的并行化代码速度的另一个因素是在BIOS超线程(英特尔)或SMT(AMD)是否已启用。 我所看到的情况下,禁用导致更快的执行速度。



文章来源: F# PSeq.iter does not seem to be using all cores