【问题标题】:output of doParallel workersdoParallel 工作者的输出
【发布时间】:2015-09-01 14:55:45
【问题描述】:

假设我有一个在 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 上工作。

【问题讨论】:

    标签: r parallel-processing


    【解决方案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被调用(或者更准确地说:在输出重定向到某个文件的环境中执行函数):

    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

    编辑:在 cmets 中,澄清了问题不在于写入单独的文件,而在于获得不混乱的输出。在这种情况下,return(capture.output(doNotTouch(idx))) 可以在循环中用于收集属于一起的输出并立即返回它们。此外,@Nutle 发现 Sys.getpid() 返回一个工作人员的 PID,该 PID 可用于工作人员编写单独的日志文件(与迭代相反)。

    【讨论】:

    • 谢谢,capture.output 似乎可以解决问题。但是,我面临的一个小问题是拥有大量索引(因此有大量日志文件),这可以通过将它们连接到一个文件的附加脚本轻松解决。再说一次,也许可以放一个工人 ID 而不是idx?我还没有找到,但也许有一个类似getWorkersId() 的函数,它获取一个字符串,对于当前正在进行迭代的工作人员来说是唯一的?这样,使用 append = TRUE 我将(在我的情况下)只有 4 个日志文件 :)
    • 对不起,我不知道如何获得“工人 ID”。但这看起来有点像XY problem。如果您想要单独的文件而只想要一个整洁的输出,那么循环体中的return(capture.output(doNotTouch(idx))) 怎么样?
    • 确实有点像XY问题,抱歉。就我而言,4 个日志文件与 1 个日志文件一样可以接受(只要不是 30 个),所以我没有关注这一点。 return 可能会更好,尽管我还发现 Sys.getpid() 获取了工人的 ID。再次感谢:)
    • 乐于助人;毕竟我自己也学到了一些东西。 :) 我稍后会更新我的答案,以包括 return(capture.output(...Sys.getpid() 解决方案。
    猜你喜欢
    • 2016-04-02
    • 2016-06-14
    • 2018-10-17
    • 1970-01-01
    • 2016-11-23
    • 1970-01-01
    • 2015-05-07
    • 2016-03-02
    • 2014-10-10
    相关资源
    最近更新 更多