mclapply是否保证按顺序返回结果?

时间:2013-02-04 23:53:28

标签: r parallel-processing multicore

我正在使用mclapply包中的multicore(在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始终按顺序返回其结果,而不管它是否给出了可选参数?

1 个答案:

答案 0 :(得分:15)

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

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

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

  

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

但是,如果你没有陷入低级别,

  

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

(我的重点)

现在为mclapply。 快速了解源代码会产生:

  • 如果!mc.preschedule并且没有使用核心作业(length (X) <= coresparallelcollect,请参见上文。
  • 如果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 - cat不显示在那里)