use*_*413 15 parallel-processing foreach r
我试图在使用RStudio的16核CPU和64 GB RAM的Windows服务器上运行foreach循环.(使用doParallel包)
"worker"进程复制来自for循环外部的所有变量(通过在运行foreach循环时观察windows任务管理器中这些进程的实例化来观察),从而使每个进程使用的内存膨胀.我试图将一些特别大的变量声明为全局变量,同时确保这些变量也在foreach循环中读取,而不是写入,以避免冲突.但是,这些进程仍然会快速耗尽所有可用内存.
是否有一种机制可以确保"工作"进程不会创建某些"只读"变量的副本?比如声明这样的变量的具体方法?
Ste*_*ton 17
该doParallel
包将自动导出变量到foreach
循环中引用的worker .如果您不希望它这样做,您可以使用foreach
".noexport"选项来阻止它自动导出特定变量.但是,如果我理解正确,你的问题是R随后会复制其中的一些变量,这比平常更多问题,因为它发生在一台机器上的多个进程中.
没有办法声明变量,以便R永远不会复制它.您需要使用包中的对象替换问题变量,bigmemory
以便永远不会创建副本,或者您可以尝试以不触发重复的方式修改代码.您可以使用该tracemem
功能来帮助您,因为只要该对象被复制,它就会打印一条消息.
但是,您可以通过减少工作人员所需的数据来避免此问题.这减少了需要复制到每个工作人员的数据量,并减少了他们的内存占用.
这是给工人提供超出他们需要的更多数据的典型例子:
x <- matrix(1:100, 10)
foreach(i=1:10, .combine='c') %dopar% {
mean(x[,i])
}
Run Code Online (Sandbox Code Playgroud)
由于矩阵x
在foreach
循环中被引用,因此它将自动导出到每个worker,即使每个worker只需要列的子集.最简单的解决方案是迭代矩阵的实际列而不是列索引:
foreach(xc=x, .combine='c') %dopar% {
mean(xc)
}
Run Code Online (Sandbox Code Playgroud)
不仅将较少的数据传输给工作者,而且每个工作者实际上一次只需要在内存中有一列,这大大减少了大型矩阵的内存占用.该xc
向量仍可能最终会被复制,但它不会伤害几乎一样多,因为它比要小得多x
.
请注意,此技术仅在doParallel
使用"雪派生"功能时有用,例如parLapply
和clusterApplyLB
,而不是在使用时mclapply
.使用这种技术可以使循环在mclapply
使用时稍慢,因为所有工作人员都可以x
免费获得矩阵,那么当工人已经拥有整个矩阵时,为什么要在列周围进行转移呢?但是,在Windows上,doParallel
无法使用mclapply
,所以这种技术非常重要.
重要的是要考虑工人真正需要哪些数据来执行他们的工作,并尽可能地减少工作量.有时你可以通过使用特殊的迭代器来实现这一点,或者来自iterators
或itertools
包,但你也可以通过改变你的算法来做到这一点.