【问题标题】:R foreach issue (some processes returning NULL)R foreach 问题(某些进程返回 NULL)
【发布时间】:2014-01-29 16:38:07
【问题描述】:

我在 R 中使用的程序的 foreach 部分遇到问题。该程序用于运行不同参数的模拟,然后将结果返回到单个列表,然后用于生成报告。 当并非所有分配的模拟运行在报告中实际可见时,就会出现问题。在所有方面,似乎只有分配的运行的一个子集实际上是 已分配。

这更有可能发生在更大的数据集(例如,模拟的时间段更长)中。 重新运行程序时发生这种情况的可能性较小,如果某些东西已经占用了 RAM,则发生这种情况的可能性更大。 系统监视器的内存使用图有时会在 100% RAM 和 100% 交换时达到峰值,然后急剧下降,之后四个子 R 会话之一消失了。 在foreach() 中使用.verbose 时,日志文件显示未在报告中显示的模拟运行将返回为NULL,而在报告中显示的模拟运行将正常返回(列表数据帧和字符变量)。 同一组参数可以产生这种效果,也可以产生完整的图形;也就是说,这组参数不是诊断性的。

foreach() 用于大约十几个参数。 .combinecbind.inorder 为false,其他所有内部参数如.errorhandling 均为默认值。

这当然很烦人,因为模拟可能需要超过 20 分钟才能运行,但由于缺少数据而变得毫无用处。 有没有办法确保这些“丢弃”的会话不会被丢弃,或者如果它们被丢弃,那么这会以某种方式被捕获?

(如果重要的话,正在使用的计算机有八个处理器,因此运行四个子进程,并且注册的并行运算符来自DoMC包)

代码结构大致如下:

test.results <- foreach(parameter.one = parameter.one.space, .combine=cbind) %:%
foreach(parameter.two = parameter.two.space, .combine=cbind) %:%
...
foreach(parameter.last = parameter.last.space, .combine=cbind, .inorder=FALSE) %dopar%
{

run.result <- simulationRun(parameter.one,
            parameter.two,
            ...
            parameter.last)

 list(list(parameters=list(parameter.one,
            parameter.two,
            ...
            parameter.last),
  runResult <- run.result))
}

return(test.results)

【问题讨论】:

  • 我想我遇到了同样的麻烦:我的一些foreach(i = 1:ncor) %dopar% 迭代在模拟开始后不久就被任意放弃了,我正试图找出确切的时间。也许是因为内存的使用,但我不这么认为,因为模拟似乎只使用了计算机内存的一半。是否存在与计算机内存容量不同的内存阈值(在 R 中设置)?

标签: r memory foreach


【解决方案1】:

我猜你是在 Linux 上运行的,因为根据你的描述,听起来子 R 会话正在被 Linux“内存不足杀手”杀死。巧合的是,我最近在 same basic problem 工作,这里直接使用了 mclapply。

doMC 包使用 mclapply 函数并行执行 foreach 循环,不幸的是,当工作进程意外终止时,mclapply 不会发出错误信号。相反,mclapply 为分配给该工作人员的所有任务返回 NULL。我认为在 mclapply 中没有任何选项可以更改此行为。

我能想到的唯一解决方法是:

  1. 使用 foreach 后端,例如 doParallel 或 doSNOW 而不是 doMC。
  2. 将结果列表中的 NULL 视为错误并使用更少的工作人员重新运行。

如果您使用 doParallel,请确保您创建并注册了一个集群对象,否则 mclapply 将在 Linux 系统上使用。使用doParallel和doSNOW,如果worker异常死亡,master从死亡worker获取任务结果会报错:

Error in unserialize(node$con) : error reading from connection

在这种情况下,并行后端将捕获错误并使用指定的错误处理。

请记住,使用 doParallel 或 doSNOW 可能会使用比 doMC 更多的内存,因此您可能必须为它们指定更少的工作人员以避免内存不足。

【讨论】:

  • 当我从doMC 转到doSNOW 时,我一直面临有线行为,尤其是我自己的包的Rcpp 功能处理不当。有什么想法吗?
  • @clemlaflemme 许多在 doMC 中有效但在 doSNOW 中无效的东西,因为 fork 为您做了所有有用的事情。一个问题是 Rcpp 定义的函数不能被序列化,这对 doMC 来说不是问题,但对于 doSNOW 来说是一个问题。您经常需要防止 Rcpp 定义的函数被序列化并发送给工作人员。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-14
  • 2018-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多