我使用foreach
编写了一些代码来处理和组合大量的CSV文件。我在32核计算机上运行它,使用%dopar%
并使用doMC
注册32个核心。我设置了.inorder=FALSE
,.multicombine=TRUE
,verbose=TRUE
,并拥有自定义合并功能。
我注意到如果我在一个足够大的文件集上运行它,看起来R会在第一次调用.combine之前尝试处理每个文件。我的证据是,在使用htop监视我的服务器时,我最初看到所有核心都被最大化,然后对于作业的剩余部分,只使用了一个或两个核心,而它们以~100(.maxcombine
的批量进行组合。默认情况下),如详细的控制台输出中所示。真正有用的是我给foreach的工作越多,看到“First call to combine”所需的时间就越长!
这对我来说似乎是违反直觉的;我天真地期望foreach处理.maxcombine
个文件,合并它们,然后转到下一个批处理,将它们与最后一次调用.combine
的输出结合起来。我认为对于.combine
的大多数用途而言,这并不重要,因为输出的大小与输入大小的总和大致相同;但是我的组合功能减小了一些尺寸。我的工作足够大,以至于我无法同时在RAM中保存所有4200多个单独的foreach作业输出,所以我依靠节省空间的.combine
并分开批处理来看我。
我是对的。在我的所有foreach
个工作单独完成之前,才会调用.combine吗?如果是这样,为什么会这样,我如何优化(除了使每个作业的输出更小)或改变这种行为?
答案 0 :(得分:5)
简短的回答是使用doMPI
或doRedis
作为并行后端。他们的工作时间更多。
doMC
,doSNOW
和doParallel
后端是mclapply
和clusterApplyLB
等函数的相对简单的包装器,并且不调用combine函数直到所有结果都被计算出来,正如您所观察到的那样。 doMPI
,doRedis
和(现已解散)doSMP
后端更复杂,并根据需要从迭代器获取输入,并且即时调用组合函数假设他们愿意。在我看来,这些后端有许多优点,如果你有适当的迭代器和组合函数,你可以处理任意数量的任务。让我感到惊讶的是,很多人与更简单的后端相处得很好,但是如果你有很多任务,那些花哨的任务是必不可少的,允许你用parallel
之类的包做一些相当困难的事情。
我一直在考虑编写一个基于parallel
包的更复杂的后端,它会像我的doMPI
包一样处理结果,但是没有任何要求它我的知识。事实上,你所看到的是你的唯一问题。
更新
doSNOW
后端现在支持即时结果处理。遗憾的是,使用doParallel
无法做到这一点,因为parallel
包不会导出必要的功能。