15

我正在使用mclapplymulticore(在 Ubuntu 上),我正在编写一个函数,该函数要求mclapply(x, f)按顺序返回 的结果(即f(x[1]), f(x[2]), ...., f(x[n]))。

# multicore doesn't work on Windows

require(multicore)
unlist(mclapply(
    1:10,
    function(x){
        Sys.sleep(sample(1:5, size = 1))
        identity(x)}, mc.cores = 2))

[1] 1 2 3 4 5 6 7 8 9 10

上面的代码似乎暗示mclapply返回结果的顺序与lapply.

但是,如果这个假设是错误的,我将不得不花很长时间重构我的代码,所以我希望从更熟悉这个包/并行计算的人那里得到这个假设是正确的保证。

假设mclapply无论给出什么可选参数,它总是按顺序返回结果是否安全?

4

1 回答 1

19

简短的回答:它确实以正确的顺序返回结果。

但当然,您应该自己阅读代码(mclapply是一个 R 函数......)

手册页collect提供了更多提示:

注意:如果 expr 使用诸如 sendMaster 之类的低级多核函数,则单个作业可以多次传递结果,用户有责任正确解释它们。

但是,如果你不搞低级,

collect 返回列表中可用的任何结果。结果将具有与指定作业相同的顺序。如果有多个作业并且一个作业有名称,它将用于命名结果,否则将使用其进程 ID。

(我的重点)

现在为mclapply. 快速浏览一下源代码会产生:

  • 如果!mc.preschedule并且没有比核心 ( length (X) <= cores)更多的作业parallel并且collect被使用,请参见上文。
  • 如果mc.preschedule或比核心更多的工作,mclapply它本身会处理订单 - 请参阅代码。

但是,这是您的实验稍作修改的版本:

> unlist (mclapply(1:10, function(x){
    Sys.sleep(sample(1:5, size = 1)); 
    cat (x, " ");    
    identity(x)}, 
  mc.cores = 2, mc.preschedule = FALSE))
1  2  4  3  6  5  7  8  9  10   [1]  1  2  3  4  5  6  7  8  9 10
> unlist (mclapply(1:10, function(x){
    Sys.sleep(sample(1:5, size = 1)); 
    cat (x, " ");    
    identity(x)}, 
  mc.cores = 2, mc.preschedule = TRUE))
1  3  2  5  4  6  7  8  10  9   [1]  1  2  3  4  5  6  7  8  9 10

这表明子作业以不同的顺序返回结果(更准确地说:子作业即将以不同的顺序完成),但结果是按原始顺序组装的。

(在控制台上工作,但不在 RStudio 中 - cats 不显示在那里)

于 2013-02-06T22:59:40.010 回答