R并行计算和僵尸进程

时间:2014-08-19 16:08:36

标签: r parallel-processing zombie-process

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

  1. How to stop R from leaving zombie processes behind
  2. How to kill a doMC worker when it's done?
  3. Remove zombie processes using parallel package
  4. 有几种方法可以进行并行计算,我将重点介绍目前在本地计算机上使用的三种方法。我在doMC内核的本地计算机上使用doParallelforeach 4包:

    (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)
    

    (b)注册PSOCK群集:

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

    (c)使用doMC

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

    有几个用户观察到使用doMC方法时 - 它只是mclapply函数的包装器,因此它不是doMC的错误(请参阅此处:{{3} }) - 留下僵尸进程。在对上一个问题(How to kill a doMC worker when it's done?)的回答中,有人建议使用fork集群可能不会留下僵尸进程。在另一个问题中,有人建议(How to stop R from leaving zombie processes behind)使用PSOCK群集可能不会让僵尸进程落后。然而,似乎这三种方法都让僵尸进程落后了。虽然僵尸进程本身通常不是问题,因为它们(通常)不会绑定资源,但它们会使进程树混乱。我仍然可以通过关闭并重新打开R来摆脱它们,但这不是我在会话中间的最佳选择。有没有解释为什么会发生这种情况(甚至:是否有必要发生这种情况的原因)?有没有什么可以做的,这样就不会留下任何僵尸进程?

    我的系统信息R用于与replxterm的简单tmux会话中:

    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)  
    

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

1 个答案:

答案 0 :(得分:16)

你可以使用&#34; inline&#34;摆脱僵尸进程。包。只需实现一个调用&#34; waitpid&#34;:

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

我通过首先用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>

(请注意,我使用GNU版本的&#34; ps&#34;它支持&#34; - pid&#34;选项。)

然后我打电话给我&#34;等待&#34;功能和称为&#34; ps&#34;再次验证僵尸已经消失:

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

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