调用系统后,makePSOCKcluster在win x64上挂起

时间:2013-06-26 05:25:03

标签: windows r cran

我在Windows上的R x64上的makePSOCKcluster包中遇到parallel难以调试的问题。它不会发生在Windows上的R i386上,也不会发生在任何OSX或Linux上。不幸的是,它不会一直发生,只是偶尔而且非常随机。

会发生makePSOCKcluster函数超时并冻结R会话,但仅在会话早期执行某些(任意)system()调用时才会发生。下面的视频和脚本更清楚地说明了问题。

我尝试了一些没有成功的东西:

  • 禁用防病毒/防火墙。
  • 在致电systemmakePSOCKcluser之间等待几秒钟。
  • 使用不同的系统调用。

我如何进一步缩小范围?此处the video和视频中使用的脚本为:

cmd_exists <- function(command){
  iswin <- identical(.Platform$OS.type, "windows"); 
  if(iswin){
    test <- suppressWarnings(try(system(command, intern=TRUE, ignore.stdout=TRUE, ignore.stderr=TRUE, show.output.on.console=FALSE), silent=TRUE));
  } else {
    test <- suppressWarnings(try(system(command, intern=TRUE, ignore.stdout=TRUE, ignore.stderr=TRUE), silent=TRUE));    
  }
  !is(test, "try-error")
}

options(hasgit = cmd_exists("git --version")); 
options(haspandoc = cmd_exists("pandoc --version"));  
options(hastex = cmd_exists("texi2dvi --version"));
cluster <- parallel::makePSOCKcluster(1);

1 个答案:

答案 0 :(得分:2)

makePSOCKCluster,或更一般地makeCluster,在创建所谓的worker进程时会因任何原因而挂起,这涉及使用Rscript命令启动新的R会话执行.slaveRSOCK函数,该函数将创建一个回到主服务器的套接字连接,然后执行slaveLoop函数,它最终将执行主服务器发送给它的任务。当启动任何工作进程时出现问题,主服务器将在执行socketConnection时挂起,等待工作者连接到它,即使该工作程序可能已经死亡或甚至从未成功创建过。

使用outfile参数非常好,因为它经常会显示导致工作进程死亡的错误,从而导致主服务器挂起。但如果没有显示任何内容,请转到手动模式。在手动模式下,主服务器打印命令以启动每个工作程序,而不是执行命令本身。这是更多的工作,但它可以让您完全控制,如果需要,您甚至可以调试工人。

以下是一个例子:

> library(parallel)

> cl <- makePSOCKcluster(1, manual=TRUE, outfile='log.txt')
Manually start worker on localhost with
   '/usr/lib/R/bin/Rscript' -e 'parallel:::.slaveRSOCK()' MASTER=localhost
PORT=10187 OUT=log.txt TIMEOUT=2592000 METHODS=TRUE XDR=TRUE 

接下来打开一个新的终端窗口(命令提示符或其他),然后粘贴该Rscript命令。一旦你执行了它,makePSOCKcluster应该返回,因为我们只请求了一个worker。当然,如果出现问题,它将无法返回,但如果您很幸运,您将在终端窗口中收到错误消息,您将获得一条重要线索,希望能够解决您的问题。如果你没那么幸运,那么Rscript命令也会挂起,你将不得不深入潜水。

要调试worker,您不需要执行显示的Rscript命令,因为您需要一个交互式会话。相反,您使用以下命令启动R会话:

  

$ R --vanilla --args MASTER = localhost PORT = 10187 OUT = log.txt TIMEOUT = 2592000 METHODS = TRUE XDR = TRUE

在该R会话中,您可以在.slaveRSOCK函数上放置一个断点,然后执行它:

> debug(parallel:::.slaveRSOCK)
> parallel:::.slaveRSOCK()

现在您可以开始逐步执​​行代码,可能在slaveLoop和makeSOCKmaster函数上设置断点。

相关问题