R并行计算和僵尸进程

lor*_*age 14 parallel-processing r zombie-process

这基本上是对这个更专业化问题的跟进.在进行并行计算时,有一些关于创建僵尸进程的帖子R:

  1. 如何阻止R离开僵尸进程
  2. 如何杀死doMC工作人员?
  3. 使用并行包删除僵尸进程

有几种方法可以进行并行计算,我将重点介绍目前在本地计算机上使用的三种方法.我在带有内核的本地计算机上使用doMCdoParallel使用foreach4:

(a)注册一个fork集群:

library(doParallel)
cl <- makeForkCluster(4)
# equivalently here: cl <- makeForkCluster(nnodes=getOption("mc.cores", 4L))
registerDoParallel(cl)
    out <- foreach(i=1:1000, .combine = "c") %dopar% {
        print(i)
    }
stopCluster(cl)
Run Code Online (Sandbox Code Playgroud)

(b)注册PSOCK集群:

library(doParallel)
cl <- makePSOCKcluster(4)
registerDoParallel(cl)
    out <- foreach(i=1:1000, .combine = "c") %dopar% {
        print(i)
    }
stopCluster(cl)
Run Code Online (Sandbox Code Playgroud)

(c)使用 doMC

library(doMC)
library(doParallel)
registerDoMC(4)
    out <- foreach(i=1:1000, .combine = "c") %dopar% {
        print(i)
    }
Run Code Online (Sandbox Code Playgroud)

有几个用户观察到在使用该doMC方法时 - 这只是mclapply函数的包装器,所以它不是doMC错误的(参见这里:如何在完成后杀死doMC工作者?) - 留下僵尸进程.在回答上一个问题(如何阻止R离开僵尸进程)时,有人建议使用fork集群可能不会让僵尸进程落后.在另一个问题中建议(使用并行程序包删除僵尸进程)使用PSOCK群集可能不会留下僵尸进程.然而,似乎这三种方法都让僵尸进程落后了.虽然僵尸进程本身通常不是问题,因为它们(通常)不绑定资源,但它们使进程树混乱.我仍然可以通过关闭和重新开放来摆脱它们,R但这不是我在会话中间的最佳选择.有没有解释为什么会发生这种情况(甚至:是否有必要发生这种情况的原因)?有没有什么可以做的,这样就不会留下任何僵尸进程?

我的系统信息(R在一个简单的使用repl与会话xtermtmux):

library(devtools)
> session_info()
Session info-------------------------------------------------------------------
 setting  value                                             
 version  R Under development (unstable) (2014-08-16 r66404)
 system   x86_64, linux-gnu                                 
 ui       X11                                               
 language (EN)                                              
 collate  en_IE.UTF-8                                       
 tz       <NA>                                              

Packages-----------------------------------------------------------------------
 package    * version  source          
 codetools    0.2.8    CRAN (R 3.2.0)  
 devtools   * 1.5.0.99 Github (c429ae2)
 digest       0.6.4    CRAN (R 3.2.0)  
 doMC       * 1.3.3    CRAN (R 3.2.0)  
 evaluate     0.5.5    CRAN (R 3.2.0)  
 foreach    * 1.4.2    CRAN (R 3.2.0)  
 httr         0.4      CRAN (R 3.2.0)  
 iterators  * 1.0.7    CRAN (R 3.2.0)  
 memoise      0.2.1    CRAN (R 3.2.0)  
 RCurl        1.95.4.3 CRAN (R 3.2.0)  
 rstudioapi   0.1      CRAN (R 3.2.0)  
 stringr      0.6.2    CRAN (R 3.2.0)  
 whisker      0.3.2    CRAN (R 3.2.0)  
Run Code Online (Sandbox Code Playgroud)

小编辑:至少因为makeForkCluster()它似乎有时产生的叉子被父母正确地杀死和收获,有时它们不会被收割并成为僵尸.似乎只有当循环中止或完成后集群没有足够快地关闭时才会发生这种情况; 至少那是在最后几次发生的时候.

Ste*_*ton 16

你可以使用"内联"包去除僵尸进程.只需实现一个调用"waitpid"的函数:

library(inline)
includes <- '#include <sys/wait.h>'
code <- 'int wstat; while (waitpid(-1, &wstat, WNOHANG) > 0) {};'
wait <- cfunction(body=code, includes=includes, convention='.C')
Run Code Online (Sandbox Code Playgroud)

我通过首先使用mclapply函数创建一些僵尸来测试这个:

> library(parallel)
> pids <- unlist(mclapply(1:4, function(i) Sys.getpid(), mc.cores=4))
> system(paste0('ps --pid=', paste(pids, collapse=',')))
  PID TTY          TIME CMD
17447 pts/4    00:00:00 R <defunct>
17448 pts/4    00:00:00 R <defunct>
17449 pts/4    00:00:00 R <defunct>
17450 pts/4    00:00:00 R <defunct>
Run Code Online (Sandbox Code Playgroud)

(请注意,我使用的是"ps"的GNU版本,它支持"--pid"选项.)

然后我调用了我的"等待"功能并再次调用"ps"以验证僵尸已经消失:

> wait()
list()
> system(paste0('ps --pid=', paste(pids, collapse=',')))
  PID TTY          TIME CMD
Run Code Online (Sandbox Code Playgroud)

看来mclapply创建的工作进程现在已经消失了.只要流程由当前R流程创建,这应该有效.