我正在使用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
始终按顺序返回其结果,而不管它是否给出了可选参数?
答案 0 :(得分:15)
简短回答:它确实以正确的顺序返回结果。
但是,当然,您应该自己阅读代码(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 - cat
不显示在那里)