下面的最小示例…
require(Rmpi)
set.seed(1)
foo <- parallel::mclapply(seq_len(10), function(l)
lapply(1:10, function(x) mean(rnorm(10000, mean=x))),
mc.cores=4)
…生成类型为
的警告消息1: In selectChildren(ac, 1) : error 'Interrupted system call' in select
2: In selectChildren(ac, 1) : error 'Interrupted system call' in select
3: In selectChildren(ac, 1) : error 'Interrupted system call' in select
如何避免?
我在一个包中使用Rmpi
和parallel
的mclapply
,这就是我问的原因。请注意,这已经张贴在这里,但我还没有收到一个答案(尚未)。如果这很重要,我使用Ubuntu 12.10, Emacs 24和R 2.15.2
我在使用Open MPI 1.4.3构建的Rmpi安装中发现了这个问题。我猜你也在使用Open MPI,因为你使用的是Ubuntu。加载Rmpi调用MPI_Init
,导致SIGCHLD
信号被捕获而不是被忽略。我相信结果是SIGCHLD
现在将在mclapply
派生的子进程退出时发送,这意外地中断了mclapply
中的select
系统调用。如果这不会导致任何实际错误,您可以通过在suppressWarnings
中调用mclapply
来防止警告消息。
在Open MPI用户的邮件列表中有一个关于这个问题的讨论,表明这个问题在Open MPI 1.6系列的某个时候已经修复了,所以这个问题的最佳解决方案可能是升级你的MPI安装,如果你还没有升级的话。
我使用Open MPI 1.6.5和1.7.3尝试了您的示例,但问题仍然存在。我决定使用
inline
包来实现一个函数,该函数将SIGCHLD
信号重置为默认处理。使用它,我可以运行您的示例而不生成任何警告:
library(Rmpi)
library(inline)
includes <- "#include <signal.h>"
code <- "signal(SIGCHLD, SIG_DFL);"
ignchld <- cfunction(body=code, includes=includes, convention=".C")
ignchld()
foo <- parallel::mclapply(seq_len(10), function(l)
lapply(1:10, function(x) mean(rnorm(10000, mean=x))),
mc.cores=4)
当然,禁用信号可能会给Rmpi带来一些问题。在这种情况下,您可以修改代码以保存和恢复SIGCHLD
处理程序,但我不知道这是否必要。