2011-07-14 37 views
18

稱爲調用,其包括功能的foreach%dopar%從的Optim構造導致錯誤:的R - 與內部功能的foreach%dopar%問題通過的Optim

> workers <- startWorkers(6) # 6 cores 
> 
> registerDoSMP(workers) 
> 
> t0 <- Sys.time() 
> 
> optim(w,maxProb2,control=list(fnscale=-1)) 
> 
> Error in { : task 1 failed - "unused argument(s) (isPrebuilt = TRUE)" 
> 
> Sys.time()-t0 
> 
> Time difference of 2.032 secs 
> 
> stopWorkers(workers) 

被調用的函數看起來像這樣:

> maxProb2 <- function(wp) { 
> 
> r <- foreach (i=s0:s1, .combine=c) %dopar% { pf(i,x[i,5],wp,isPrebuilt=TRUE) } 
> 
> cat("w=",wp,"max=",sum(r),"\n") 
> 
> sum(r) 
> 
> } 

pf是一些其他函數,x是一個預先計算的元素的靜態表。

而且調用該函數進行優化,只有一次引起了同樣的錯誤:

> workers <- startWorkers(6) # 6 cores 
> 
> Warning message: 
> In startWorkers(6) : there is an existing doSMP session using doSMP1 
> 
> registerDoSMP(workers) 
> 
> maxProb2(w) 
> Error in { : task 1 failed - "unused argument(s) (isPrebuilt = TRUE)" 
> 
> stopWorkers(workers) 

有什麼奇怪的,在相同的代碼工作正常時直接調用一個時間(的Optim卡列斯同樣的功能很多次):

> workers <- startWorkers(6) # 6 - ilosc rdzeni 
> 
> Warning message: 
> In startWorkers(6) : there is an existing doSMP session using doSMP1 
> 
> registerDoSMP(workers) 
> 
> r <- foreach (i=s0:s1, .combine=c) %dopar% { pf(i,x[i,5],w,isPrebuilt=TRUE) } 
> 
> sum(r) 
> [1] 187.1781 
> 
> stopWorkers(workers) 

當使用%do%代替%dopar%時,被調用函數(maxProb2)可以正常工作。

如何正確調用包含foreach%dopar%構造的函數?

更新2011-07-17:

我已經改名爲PF功能分爲probf但問題仍然存在。

probf函數在腳本中定義,而不是在某些外部包中定義。

有兩點需要注意:操作系統:Windows 7,IDE:革命分析企業4.3

> workers <- startWorkers(workerCount = 3) 
> 
> registerDoSMP(workers) 
> 
> maxProb2(w) 
> 
Error in { : task 1 failed - "could not find function "probf"" 
+0

請始終在您的問題中包含確切的錯誤信息。 –

回答

2

[編輯]

pf功能,你的 「靜態表」 x必須分發到所有工作節點。您必須閱讀並行庫的文檔,瞭解它的工作原理。

它似乎是在通過優化運行時發現的pf函數是另一個函數(可能是stats::pf,它沒有參數isPrebuilt)。

你可以嘗試重命名你的pf函數(例如mypf)嗎?

mypf <- pf # renaming the function 

maxProb2 <- function(wp) { 
    r <- foreach (i=s0:s1, .combine=c) %dopar% { mypf(i,x[i,5],wp,isPrebuilt=TRUE) } 
    cat("w=",wp,"max=",sum(r),"\n") 
    sum(r) 
} 

或者,如果您pf函數是一個包的一部分與命名空間(比如,mypackage),你可以像這樣引用它:mypackage::pf

maxProb2 <- function(wp) { 
    r <- foreach (i=s0:s1, .combine=c) %dopar% { mypackage::pf(i,x[i,5],wp,isPrebuilt=TRUE) } 
    cat("w=",wp,"max=",sum(r),"\n") 
    sum(r) 
} 
+0

如何確保被調用的函數和表分配給工作節點? – mjaniec

+1

'pf'存在於內置的'stats'包中,並且是F分配的分配函數。 – James

+0

我更新了答案,因爲它似乎是我所懷疑的 - 調用錯誤的「pf」函數。 – Tommy

18

我遇到了同樣的問題所涉及的問題在於環境未包含在子線程中。你的錯誤

Error in { : task 1 failed - "could not find function "simple_fn""

可以通過這個非常簡單的例子被複制:

simple_fn <- function(x) 
    x+1 

test_par <- function(){ 
    library("parallel") 
    no_cores <- detectCores() 
    library("foreach") 
    cl<-makeCluster(no_cores) 
    library("doSNOW") 
    registerDoSNOW(cl) 
    out <- foreach(i=1:10) %dopar% { 
     simple_fn(i) 
    } 

    stopCluster(cl) 
    return(out) 
} 

test_par() 

現在,所有你需要的就是給foreach(i=1:10)變成foreach(i=1:10, .export=c("simple_fn"))。如果你想導出你的完整的全球環境,那麼只需編寫.export=ls(envir=globalenv()),你會得到更好或更糟的。

+1

我一直很想知道爲什麼'.export = ls()'不是默認值。在大多數情況下,這似乎是一個好主意,從這個主題的帖子數量來看......任何想法? – Ruben

+1

@Ruben - 實際上它是有意義的,因爲在處理大型數據集時並行化是最相關的 –

+1

但是,然後您會在每個節點中單獨加載大塊數據,對吧?那麼我不會在全局會話中加載整個df。一些東西會自動加載(例如,您正在迭代的矢量)。而且,使用ls並不像我剛纔所預期的那樣工作。我可靠地得到我預測會發生的唯一解決方案是在循環內部定義。效率低下,但有時很難看。 – Ruben

0

爲用foreach%dopar%的問題快速修復是重新安裝這些程序包:

install.packages("doSNOW") 

install.packages("doParallel") 

install.packages("doMPI") 

正如在StackOverflow的各個線程所提到的,這些都是負責R.錯誤並行這在舊版本中存在的這些包現在被刪除。它在我的情況下工作。我應該提到,即使你沒有在你的項目/軟件包中使用這些軟件包,這很可能會有所幫助。