2017-06-01 162 views
1

我在R中環一parallelparLapply平行的,但我得到了一個錯誤:使用parLapply在一個迴路R

library(doSNOW) 
library(foreach) 
cl<-makeCluster(4) #change the 2 to your number of CPU cores 
registerDoSNOW(cl) 
foreach(1:2) %dopar% { 
    clusterExport(cl, "parLapply") 
    parLapply(cl, 1:2,function(exponent)2^exponent) 
} 

推出此代碼時,我得到了以下錯誤:

> Error in { : task 1 failed - "object 'c1' not found" 

任何人都可以幫我解釋爲什麼嗎?在循環中是否可以在parallel中使用parLapply

非常感謝!

回答

0

替換軟件包列表並使用以下更新的命令。它爲我工作。另外,您還需要在工作節點內定義單獨的羣集cl。或者你可以在cl上嘗試使用clusterCall函數來創建一個再次創建一個集羣的子進程。

library(doParallel) 
cl<-makeCluster(2,outfile = "") 
registerDoParallel(cl) 
foreach(1:2, .export = c('cl','parLapply') , .packages = 'doParallel') %dopar% { 
    cl2<-makeCluster(2,outfile = "") 
    registerDoParallel(cl2) 
    parLapply(cl2, 1:2,function(exponent)2^exponent) 
    stopCluster(cl2) 
} 
stopCluster(cl) 

在我看來,嵌套並行內部只會增加過程的開銷。避免這種嵌套可能會更好。

+0

謝謝!當我運行你的代碼時,沒有更多的錯誤,但獲得的結果是「NULL」。你知道爲什麼嗎? – Luyuan

+0

刪除「stopCluster(cl2)」時有效。但是,如果沒有stopCluster,是否有問題? – Luyuan

+0

stopCluster是確保羣集初始化已停止的好方法。否則,集羣狀態將一直持續到程序退出。這會產生間接費用,不建議。 – niths4u

3

集羣對象無法導出,因爲它們包含socketConnection對象,因此無法安全地序列化併發送給工作人員。相反,您應該在每個工作人員身上創建它們,作爲工作人員初始化的一部分。羣集創建可能需要很長時間,因此,無論foreach循環中的迭代次數如何,爲每個工作人員創建一個羣集對象都很重要。

下面是一個使用clusterEvalQ函數初始化和清理工人,所以你可以在foreach循環中執行parLapply一個例子:

library(doSNOW) 

# Start cluster on master and register it for use with doSNOW 
cl <- makeCluster(4) 
registerDoSNOW(cl) 

# Start cluster on workers 
clusterEvalQ(cl, { 
    library(parallel) 
    cl <- makeCluster(2) 
}) 

# Execute nested parallel loop 
r <- 
    foreach(1:2, .noexport='cl', .packages='parallel') %dopar% { 
     parLapply(cl, 1:2, function(exponent)2^exponent) 
    } 

# Stop clusters on workers 
clusterEvalQ(cl, { 
    stopCluster(cl) 
}) 

# Stop cluster on master 
stopCluster(cl)