2016-07-06 25 views
10

我正在測試parLapplyLB()函數以瞭解它如何平衡負載。但我沒有看到任何平衡發生。例如,爲什麼parLapplyLB沒有實際平衡負載?

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) 

如果它被真正平衡該休眠3秒鐘的負荷,所述第一作業(作業1)將在第一節點和其他三個作業(作業2:4)上會睡在另一個節點上總共1.5秒。總共系統時間應該只有3秒。

相反,我認爲作業1和2給予節點1,作業3和4給予節點2.這導致總時間爲3 + 0.5 = 3.5秒。如果我們使用parLapply()而不是parLapplyLB()運行上述相同的代碼,我們得到的系統時間約爲3.5秒。

我不理解或做錯什麼?

+0

我認爲R不會做自動負載平衡。我認爲它將*任務*劃分爲儘可能多的核心,而不管每個任務需要多少時間,或者每個任務何時完成。這並不是說有一個任務隊列,當一個工作人員完成時,抓住下一個任務。每個核心都分配了兩個任務。因此,第一名工人的3 + 0.5,總共3.5。 *會很高興出錯* – gregmacfarlane

+3

是的,這就是3.5來自哪裏。這不是平衡負載。但parLapplyLB聲稱要平衡。 – josiekre

回答

10

對於(爲此我曾經需要平行和,對於這個問題,對於任何任務)parLapplyLB像你這樣的任務是不是真的對這份工作的合適工具。要知道爲什麼沒有,看看的方式,它的實現:

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 

的問題是,它首先拆分它的任務列表,成大小相等的子列表,它則節點之間分發,每個在其給定的子列表上運行lapply()。因此,在這裏,您的第一個節點在第一個和第二個輸入上運行作業,而第二個節點使用第三個和第四個輸入運行作業。

相反,使用更靈活clusterApplyLB(),這就像你倒是希望:

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 
+0

謝謝!那是我正在尋找的。我不能想到parLapplyLB會產生與parLapply不同的東西,所以我不確定它的目的是什麼。 – josiekre

+0

'clusterApplyLB(cl,X,fun)'和parLapplyLB具有相同的預期行爲嗎?我一直在我的系統上嘗試了這一點,而且似乎給時'X'是一個列表相同的輸出,但我有點緊張只是換出'parLapplyLB'用'clusterApplyLB' .. – guy

+2

有用的信息在這裏,以及用戶自定義parlapplyLB http://detritus.fundacioace.com/pub/books/Oreilly.Parallel.R.Oct.2011.pdf – Olivia

1

parLapplyLB不均衡負載,因爲它有一個語義錯誤。我們發現了該錯誤並提供了修復,請參閱here。現在,它由R開發人員來包含修復程序。