假设我有一个代码在 foreach 循环中执行各种计算,为简单起见,请将其作为:
foreach( idx = 1:10 ) %dopar% {
set.seed(idx)
smp <- rnorm(10)
print( sprintf('Index: %d', idx) )
print( cat(sprintf('Value: %f \n', smp[1:10])) )
}
代码的主要思想是它的输出以这样的方式写入,索引被呈现一次,之后是主代码的各种结果。使用%do%
时,可以很容易地读取日志文件并使用此类结构进行调试,但是对于%dopar%
,日志文件会变得混乱。
问题:如果不更改代码,每个工作人员是否有办法创建自己的输出文件?我是使用doParallel
的新手,所以我到目前为止找到的并行输出的唯一方法是使用以下内容:
library(doParallel)
cl <- makeCluster(4, outfile = 'log.txt')
registerDoParallel(cl)
但是,outfile
只接受一个字符串作为参数,但没有找到一种向其传递名称向量的方法。那么,也许有办法为每个工人指定一个输出文件?
注意:在Windows 7上工作。
答案 0 :(得分:1)
许多解决方案 - 比如在工作程序中不使用print
或在那里指定输出文件 - 会浮现在脑海中,但问题明确要求不更改代码。因此,我假设当前在%dopar%
正文中的代码包含在一个无法更改的函数中:
doNotTouch <- function(idx) {
set.seed(idx)
smp <- rnorm(10)
print(sprintf('Index: %d', idx))
cat(sprintf('Value: %f \n', smp[1:10]))
}
一种解决方案是在调用 这不会更改问题中提供的代码,而是将其放在一个处理正确输出文件 编辑:在评论中,有人澄清说,问题不在于写入单独的文件,而在于获取不混乱的输出。在这种情况下,可以在循环中使用doNotTouch
之前直接指定输出文件(或者更准确地说:在将输出重定向到某个文件的环境中执行该函数): / p>
library(doParallel)
cl <- makeCluster(4)
registerDoParallel(cl)
foreach(idx = 1:10) %dopar% {
capture.output(
doNotTouch(idx),
file = paste0("log", idx, ".txt"))
}
stopCluster(cl)
log_[idx].txt
的包装器中。 return(capture.output(doNotTouch(idx)))
来收集属于一起的输出并立即返回它们。此外,@ Nutle发现Sys.getpid()
返回一个工人的PID,可以用来编写单独的日志文件 by worker (通过迭代选择)。