Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F#PSeq.iter似乎并没有使用所有的核_F#_Parallel Processing_Task Parallel Library_Lazy Evaluation_Seq - Fatal编程技术网

F#PSeq.iter似乎并没有使用所有的核

F#PSeq.iter似乎并没有使用所有的核,f#,parallel-processing,task-parallel-library,lazy-evaluation,seq,F#,Parallel Processing,Task Parallel Library,Lazy Evaluation,Seq,我一直在F#做一些计算密集型的工作。像Array.Parallel.map这样使用.Net任务并行库的函数以指数级的速度加速了我的代码,只需付出非常小的努力 但是,由于内存问题,我重新编写了代码的一部分,以便可以在序列表达式中对其进行惰性计算(这意味着我必须存储和传递更少的信息)。在评估时,我使用了: // processor and memory intensive task, results are not stored let calculations : seq<Calculati

我一直在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
当使用任何Array.Parallel函数时,我可以清楚地看到我的计算机上的所有内核都在运转(CPU使用率约为100%)。然而,所需的额外内存意味着程序永远不会完成

当我运行程序时,使用PSeq.iter版本时,CPU使用率只有8%左右(以及最小的RAM使用率)

那么:PSeq版本运行如此之慢有什么原因吗?这是因为懒惰的评估吗?有没有一些神奇的“平行”的东西我错过了

谢谢

其他资源,两者的源代码实现(它们似乎在.NET中使用不同的并行库):

编辑:向代码示例和详细信息添加更多详细信息

代码:

  • 序号

    // 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
    
详情:

  • 存储中间阵列版本在10分钟内运行速度很快(在崩溃之前),但在崩溃之前使用约70GB的RAM(64GB物理内存,其余分页)
  • seq版本占用了34分钟的内存,只占用了RAM的一小部分(大约30GB)
  • 我正在计算大约10亿个值。因此,十亿倍(每个64位)=7.4505806GB。还有更复杂的数据形式。。。我正在清理一些不必要的拷贝,因此目前大量使用RAM
  • 是的,架构不是很好,惰性评估是我尝试优化程序和/或将数据批处理成更小的块的第一部分
  • 对于较小的数据集,两个代码块输出相同的结果
  • @pad,我尝试了你的建议,PSeq.iter在进行计算[]时似乎工作正常(所有核都处于活动状态),但仍然存在RAM问题(它最终崩溃)
  • 代码的摘要部分和计算部分都是CPU密集型的(主要是因为数据集太大)
  • 对于Seq版本,我只想并行一次

根据您的最新信息,我将我的答案缩短为相关部分。您只需要这个,而不是您当前拥有的:

let result = data |> PSeq.map (calculationFunc >> someFuncToExtractResults)
无论您使用
PSeq.map
还是
Array.Parallel.map
,这都是一样的

然而,你真正的问题不会得到解决。这个问题可以表述为:当达到所需的并行工作程度以获得100%的CPU使用率时,没有足够的内存来支持进程

你知道这怎么解决不了吗?您可以按顺序处理事情(CPU效率较低,但内存效率较高),也可以并行处理事情(CPU效率较高,但内存不足)

然后,选项是:

  • 将这些函数使用的并行度更改为不会耗尽内存的程度:

    let result = data 
                 |> PSeq.withDegreeOfParallelism 2 
                 |> PSeq.map (calculationFunc >> someFuncToExtractResults)
    
  • 更改
    calculationFunc>>someFuncToExtractResults
    的底层逻辑,使其成为一个更高效的函数,并将数据流传输到结果。在不了解更多细节的情况下,很难看到如何做到这一点。但在内部,当然可能会有一些延迟加载


  • Array.Parallel.map
    在引擎盖下使用
    Parallel.For
    ,而
    PSeq
    PLINQ
    的薄包装。但是,它们在这里表现不同的原因是,当
    seq
    是连续的且产生新结果的速度太慢时,
    PSeq.iter
    没有足够的工作负载

    我不想使用中间seq或数组。假设
    data
    是输入数组,将所有计算移到一个位置是可行的:

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


    您可以避免消耗太多内存,并在一个位置进行密集计算,从而提高并行执行的效率

    我遇到了一个与您类似的问题,通过在解决方案的App.config文件中添加以下内容解决了此问题:

    <runtime> 
        <gcServer enabled="true" />
        <gcConcurrent enabled="true"/>
    </runtime>
    
    
    
    计算结果显示,Lasso进程的CPU利用率约为22%,计算时间为5'49'',计算结果为1'36'',CPU利用率约为80%


    另一个可能影响并行代码速度的因素是BIOS中是否启用了超线程(Intel)或SMT(AMD)。我见过一些案例,禁用会导致更快的执行

    延迟计算不能很好地处理并行执行。公平地说,将相同的
    计算[]
    传递给
    PSeq.iter
    Array.Parallel.map
    。如果没有关于
    计算
    某些函数提取结果
    的详细信息,就不可能说出原因。感谢您的建议,我尝试了这个方法,当在惰性序列上指定数组时,PSeq表现良好。。。然而,这并不能解决RAM问题。由于内存密集,我不确定你的第二点是什么意思,你能详细说明一下吗?@AnthonyTruskinger:根据你提供的额外信息,我做了一些重要的更新。请注意,如果您不想更改算法,您必须在某个地方进行权衡(如果不更改算法,您将无法获得100%的CPU和高效内存)。如果你能改变算法,那么,看看我的答案。
    // Should use PSeq.map to match with Array.Parallel.map
    PSeq.map (calculationFunc >> someFuncToExtractResults) data
    
    Array.Parallel.map (calculationFunc >> someFuncToExtractResults) data
    
    <runtime> 
        <gcServer enabled="true" />
        <gcConcurrent enabled="true"/>
    </runtime>