15

当我使用 mclapply 时,有时(实际上是随机的)它会给出不正确的结果。这个问题在 Internet 上的其他帖子中得到了相当详尽的描述,例如 ( http://r.789695.n4.nabble.com/Bug-in-mclapply-td4652743.html )。但是,没有提供解决方案。有谁知道如何解决这个问题?谢谢!

4

2 回答 2

9

您引用的 Winston Chang 报告的问题似乎已在 R 2.15.3 中修复。mccollect将工作人员结果分配给结果列表时发生了一个错误:

if (is.raw(r)) res[[which(pid == pids)]] <- unserialize(r)

如果unserialize(r)返回 NULL,这将失败,因为以这种方式将 NULL 分配给列表会删除列表的相应元素。这在 R 2.15.3 中更改为:

if (is.raw(r)) # unserialize(r) might be null
    res[which(pid == pids)] <- list(unserialize(r))

这是将未知值分配给列表的安全方法。

因此,如果您使用 R <= 2.15.2,解决方案是升级到 R >= 2.15.3。如果您在使用 R >= 2.15.3 时遇到问题,那么可能与 Winston Chang 报告的问题不同。


我还阅读了 Elizabeth Purdom 发起的 R-help 线程中讨论的问题。如果没有特定的测试用例,我的猜测是问题不是由于 mclapply 中的错误,因为我可以使用以下函数重现相同的症状:

work <- function(i, poison) {
  if (i == poison) quit(save='no')
  i
}

如果由 mclapply 启动的工作人员在执行任务时因任何原因(接收信号、段错误、退出)死亡,则 mclapply 将为分配给该工作人员的所有任务返回 NULL:

> library(parallel)
> mclapply(1:4, work, 3, mc.cores=2)
[[1]]
NULL

[[2]]
[1] 2

[[3]]
NULL

[[4]]
[1] 4

在这种情况下,由于预调度,任务 1 和 3 返回了 NULL,尽管实际上只有任务 3 失败了。

如果一个worker在使用parLapply或clusterApply等函数时死掉了,会报错:

> cl <- makePSOCKcluster(3)
> parLapply(cl, 1:4, work, 3)
Error in unserialize(node$con) : error reading from connection

我见过很多这样的报告,我认为它们往往发生在使用大量包的大型程序中,这些包很难变成可重现的测试用例。

当然,在这个例子中,使用 lapply 时也会出现错误,尽管错误不会像使用 mclapply 那样被隐藏。如果在使用 lapply 时问题似乎没有发生,可能是因为问题很少发生,所以它只发生在使用 mclapply 并行执行的非常大的运行中。但是也有可能发生错误,不是因为任务是并行执行的,而是因为它们是由分叉的进程执行的。例如,各种图形操作在分叉进程中执行时会失败。

于 2014-01-06T16:31:53.373 回答
5

我正在添加这个答案,这样其他人遇到这个问题就不必费力地阅读长长的评论(我是赏金授予者,但不是 OP)。

mclapply最初用 NULLS 填充它创建的列表。当工作人员处理返回值时,这些值会覆盖 NULLS。如果一个进程在没有返回值的情况下死亡,mclapply将返回 NULL。

当内存变低时,Linux 内存不足杀手(oom killer)

https://lwn.net/Articles/317814/

将开始静默杀死进程。它不会向控制台打印任何内容以让您知道它在做什么,尽管 oom 杀手活动显示在系统日志中。在这种情况下, 的输出mclapply似乎已被 NULLS 随机污染。

于 2014-05-02T01:20:25.553 回答