我遇到一个难以调试的问题,makePSOCKcluster从parallel包装上的Windows [R 64.它不会发生在Windows上的R i386上,也不会发生在任何OSX或Linux上.不幸的是,它不会一直发生,只是偶尔而且非常随机.
发生的是该makePSOCKcluster函数超时并冻结R会话,但只有在会话的早期执行了一些(任意)system()调用.下面的视频和脚本更清楚地说明了问题.
我试过的一些东西没有成功:
system和等待之间等待几秒钟makePSOCKcluser.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);
Run Code Online (Sandbox Code Playgroud)
makePSOCKCluster或者更一般地说makeCluster,在创建所谓的进程时,可能会因多种原因而挂起worker,其中涉及使用 Rscript 命令启动新的 R 会话,该命令将执行 .slaveRSOCK 函数,该函数将创建一个返回到主服务器的套接字连接,然后执行slaveLoop函数,它最终将执行master发送给它的任务。如果启动任何工作进程时出现问题,主进程将在执行 socketConnection 时挂起,等待工作进程连接到它,即使该工作进程可能已经死亡或什至从未成功创建。
使用 outfile 参数非常有用,因为它通常会揭示导致工作进程终止并从而导致主进程挂起的错误。但如果没有显示任何内容,则进入手动模式。在手动模式下,master打印启动每个worker的命令,而不是执行命令本身。这需要更多工作,但它可以让您完全控制,如果需要,您甚至可以调试工作人员。
这是一个例子:
> 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
Run Code Online (Sandbox Code Playgroud)
接下来打开一个新的终端窗口(命令提示符或其他),然后粘贴该 Rscript 命令。一旦执行完毕,makePSOCKcluster 就会返回,因为我们只请求了一个工作线程。当然,如果出现问题,它不会返回,但如果幸运的话,您将在终端窗口中收到一条错误消息,并且您将获得一条重要线索,有望解决您的问题。如果你没那么幸运,Rscript 命令也会挂起,你将不得不更深入地研究。
要调试工作程序,您无需执行显示的 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()
Run Code Online (Sandbox Code Playgroud)
现在您可以开始单步执行代码,可能会在slaveLoop 和makeSOCKmaster 函数上设置断点。
| 归档时间: |
|
| 查看次数: |
1043 次 |
| 最近记录: |