【问题标题】:reading global variables using foreach in R在 R 中使用 foreach 读取全局变量
【发布时间】:2013-08-03 01:47:18
【问题描述】:

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

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

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

【问题讨论】:

  • 我前段时间基本上问过同样的问题 (stackoverflow.com/questions/6251662/…),但同时情况可能发生了变化?
  • 感谢 Roman,我也被困在 Windows 上;希望有人知道出路。我不需要轮询/更改大变量(网络),因为我只读取它来计算中心性分数..
  • 根据您要共享的数据是否可以用矩阵表示,bigmemory 包可能会启用您所追求的。该软件包允许共享访问以进行并行处理,即使在 Windows 上也是如此。但是,如果要共享的对象不能用矩阵表示,那么您在这条路上就走不了多远。

标签: r foreach parallel-processing


【解决方案1】:

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

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

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

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

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

由于矩阵xforeach 循环中被引用,它将自动导出到每个worker,即使每个worker 只需要列的一个子集。最简单的解决方案是遍历矩阵的实际列而不是列索引:

foreach(xc=x, .combine='c') %dopar% {
    mean(xc)
}

不仅减少了传输给工作人员的数据,而且每个工作人员实际上一次只需要在内存中拥有一列,这大大减少了大型矩阵的内存占用。 xc 向量最终可能仍会被复制,但它并没有那么严重,因为它比 x 小得多。

请注意,此技术仅在doParallel 使用“雪派生”函数(例如parLapplyclusterApplyLB)时有用,而在使用mclapply 时无效。当使用mclapply 时,使用这种技术可以使循环变慢一些,因为所有工作人员都免费获得了矩阵x,那么当工作人员已经拥有整个矩阵时,为什么要围绕列进行转移呢?但是在Windows上,doParallel不能使用mclapply,所以这个技巧很重要。

重要的是要考虑工作人员真正需要哪些数据来执行他们的工作,并尽可能减少这些数据。有时您可以通过使用特殊的迭代器(来自 iteratorsitertools 包)来做到这一点,但您也可以通过更改算法来做到这一点。

【讨论】:

    猜你喜欢
    • 2021-04-24
    • 1970-01-01
    • 2019-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    • 2010-11-17
    相关资源
    最近更新 更多