调用系统后makePSOCKcluster挂在win x64上
在Windows上,R x64上的parallel
包中makePSOCKcluster
难以debugging的问题。 它不会在Windows上的R i386上,也不在任何OSX或Linux上发生。 不幸的是,这种情况并不总是一致地发生,只是偶尔和非常随机的。
会发生什么是makePSOCKcluster
函数超时并冻结R会话,但是只有在会话的前面执行一些(任意) system()
调用时才会发生。 下面的video和脚本更清楚地说明了这个问题。
有些东西我尝试没有成功:
- 禁用防病毒/防火墙。
- 等待调用
system
和makePSOCKcluser
之间的几秒钟。 - 使用不同的系统调用。
我将如何进一步缩小这个范围? 这里video和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);
在创build所谓的worker
进程时, makePSOCKCluster
或更一般的makeCluster
可以挂起,原因有很多,其中包括使用Rscript命令启动新的R会话,该命令将执行.slaveRSOCK函数,该函数将创build一个套接字连接回到掌握,然后执行slaveLoop函数,最终将执行master发送给它的任务。 Wehen在启动任何工作进程时出现错误,在执行socketConnection时,主服务器将挂起,等待工作人员连接到该工作进程,即使该工作人员可能已经死亡或者甚至从未成功创build过。
使用outfile参数非常好,因为它经常会显示导致工作进程死亡的错误,从而导致主机挂起。 但是,如果没有揭示什么,那么去手动模式。 在手动模式下,主机打印命令以启动每个工人,而不是执行命令本身。 这是更多的工作,但它可以让你完全控制,甚至可以根据需要debugging工人。
这是一个例子:
> 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
接下来打开一个新的terminal窗口(命令提示符,或其他),并粘贴在该Rscript命令。 一旦你执行了它,makePSOCKcluster应该返回,因为我们只请求一个worker。 当然,如果出现问题,就不会返回,但如果运气好的话,terminal窗口会显示一条错误消息,您将得到一条重要线索,希望能够解决您的问题。 如果你不那么幸运,Rscript命令也会挂起,你将不得不深入下潜。
要debugging工作人员,您不需要执行显示的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函数上设置断点。