为什么parLapplyLB实际上不平衡负载?

为什么parLapplyLB实际上不平衡负载?,r,rparallel,R,Rparallel,我正在测试parlapplyb()函数,以了解它如何平衡负载。但我没有看到任何平衡发生。比如说, cl <- parallel::makeCluster(2) system.time( parallel::parLapplyLB(cl, 1:4, function(y) { if (y == 1) { Sys.sleep(3) } else { Sys.sleep(0.5) }})) ## user system elapsed

我正在测试
parlapplyb()
函数,以了解它如何平衡负载。但我没有看到任何平衡发生。比如说,

cl <- parallel::makeCluster(2)

system.time(
  parallel::parLapplyLB(cl, 1:4, function(y) {
    if (y == 1) {
      Sys.sleep(3)
    } else {
      Sys.sleep(0.5)
    }}))
##   user  system elapsed 
##  0.004   0.009   3.511 

parallel::stopCluster(cl)

cl注意:自R-3.5.0以来,OP注意到并在下面解释的行为/错误已经修复。正如当时R的
新闻
文件所述:

* parLapplyLB and parSapplyLB have been fixed to do load balancing
  (dynamic scheduling).  This also means that results of
  computations depending on random number generators will now
  really be non-reproducible, as documented.

原始答案(现在仅适用于R版本<3.5.0)

对于像你这样的任务(对于我曾经需要的任何任务,parallel
parlapplyb
并不是真正适合这份工作的工具。要了解原因,请查看它的实现方式:

parLapplyLB
# function (cl = NULL, X, fun, ...) 
# {
#     cl <- defaultCluster(cl)
#     do.call(c, clusterApplyLB(cl, x = splitList(X, length(cl)), 
#         fun = lapply, fun, ...), quote = TRUE)
# }
# <bytecode: 0x000000000f20a7e8>
# <environment: namespace:parallel>

## Have a look at what `splitList()` does:
parallel:::splitList(1:4, 2)
# [[1]]
# [1] 1 2
# 
# [[2]]
# [1] 3 4

parLapplyLB
没有平衡负载,因为它有一个语义错误。我们发现了错误并提供了修复,请参阅。现在,由R开发人员来添加修复程序。

我认为R不会进行自动负载平衡。我认为它将任务划分为尽可能多的核心,而不管执行每个任务需要多少时间,或者每个任务何时完成。这不像是一个任务队列,当一个工人完成任务时,他会抓住下一个。每个核心被分配两项任务。因此,第一个工人的工资为3+0.5,总计为3.5。我很乐意犯错是的,这就是3.5的来源。它不能平衡负载。但是Parlappylb声称平衡。谢谢!这就是我要找的。我想不出parlappylb会产生与parLapply不同的东西,因此我不确定它的目的是什么。clusterApplyLB(cl,X,fun)
是否具有与
parlappylb
相同的预期行为?我一直在我的系统上尝试这一点,当
X
是一个列表时,它似乎给出了相同的输出,但我有点紧张,只是用
clusterApplyLB
替换
parlappylb
。这里的有用信息以及用户定义的parlappylb@Olivia非常有趣,特别是第13-22页(尤其是第20-22页)。谢谢有一件事没有提到,如果你正在处理大文件的任务,就要避免使用McLappy。sendMaster不喜欢返回任何2gig或更大的内容。而关闭预排似乎只需要1个核心就可以完成Lappy。parlappy(sock或fork)可以工作并且具有相似的性能时间。
system.time(
  parallel::clusterApplyLB(cl, 1:4, function(y) {
    if (y == 1) {
      Sys.sleep(3)
    } else {
      Sys.sleep(0.5)
    }}))
# user  system elapsed 
# 0.00    0.00    3.09