在 R 中使用 foreach 读取全局变量

标签 r foreach parallel-processing

我正在尝试使用 RStudio 在具有 16 核 CPU 和 64 GB RAM 的 Windows 服务器上运行 foreach 循环。 (使用 doParallel 包)

“worker”进程从 for 循环外部复制所有变量(通过在运行 foreach 循环时在 Windows 任务管理器中观察这些进程的实例化来观察),从而使每个进程使用的内存膨胀。我试图将一些特别大的变量声明为全局变量,同时确保这些变量也在 foreach 循环内部读取而不是写入以避免冲突。但是,进程仍然很快用完所有可用内存。

是否有一种机制可以确保“工作”进程不会创建某些“只读”变量的副本?比如有什么具体的方式来声明这样的变量?

最佳答案

doParallel包将自动将变量导出到 foreach 中引用的工作人员环形。如果您不希望它这样做,您可以使用 foreach “.noexport”选项以防止它自动导出特定变量。但是如果我理解正确的话,你的问题是 R 随后复制了其中的一些变量,这比平常更成问题,因为它发生在一台机器上的多个进程中。

没有一种方法可以声明一个变量,以便 R 永远不会复制它。您要么需要用来自 bigmemory 之类的包中的对象替换问题变量。以便永远不会复制,或者您可以尝试以不触发重复的方式修改代码。您可以使用 tracemem功能来帮助您,因为只要该对象被复制,它就会打印一条消息。

但是,您可以通过减少工作人员所需的数据来避免该问题。这减少了需要复制到每个工作人员的数据量,并减少了他们的内存占用。

这是一个典型的例子,它为工作人员提供了比他们需要的更多的数据:

x <- matrix(1:100, 10)
foreach(i=1:10, .combine='c') %dopar% {
    mean(x[,i])
}

由于矩阵xforeach 中引用循环,它将自动导出到每个工作人员,即使每个工作人员只需要列的一个子集。最简单的解决方案是迭代矩阵的实际列而不是列索引:
foreach(xc=x, .combine='c') %dopar% {
    mean(xc)
}

不仅传输给 worker 的数据更少,而且每个 worker 实际上一次只需要在内存中拥有一列,这大大减少了大型矩阵的内存占用。 xc vector 最终可能仍然会被复制,但它几乎没有受到太大的伤害,因为它比 x 小得多。 .

请注意,此技术仅在 doParallel 时有用使用“雪衍生”函数,例如 parLapplyclusterApplyLB , 不是在使用 mclapply 时.当 mclapply 时,使用这种技术可以使循环变慢一点。使用,因为所有 worker 都得到矩阵 x免费,那么当 worker 已经拥有整个矩阵时,为什么要在列周围转移呢?但是,在 Windows 上,doParallel无法使用 mclapply ,所以这个技巧非常重要。

重要的是要考虑 worker 真正需要哪些数据才能完成他们的工作,并在可能的情况下尽量减少它。有时你可以通过使用特殊的迭代器来做到这一点,或者来自 iteratorsitertools包,但您也可以通过更改算法来做到这一点。

关于在 R 中使用 foreach 读取全局变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18028452/

相关文章:

r - R 中的 Spearman 相关环

R 润滑剂 : How to put a lubridate timestamp in a dataframe?

c# 使用子字符串和正则表达式编辑大字符串

C# WPF 窗口在 foreach 循环中不更新

javascript - Array.prototype.forEach 在 IE8 中不起作用

c++ - OpenMP 第一个内核比第二个内核慢得多

java - 程序的并行化增加了执行时间

r - 如何将键值和图例放在热图的底部

c - 在 OpenCL 的内核中设置参数会导致错误

r - R包中的数据集限制 "nparcomp"