2013-12-19 122 views
11

當我使用mclapply時,(隨機)它會給出不正確的結果。這個問題在互聯網上的其他文章中有相當詳細的描述, (http://r.789695.n4.nabble.com/Bug-in-mclapply-td4652743.html)。但是,沒有提供解決方案。有誰知道如何解決這個問題?謝謝!mclapply隨機返回NULL

+2

當其中一個分叉進程需要很長時間返回時,mclapply返回null;我預計會有某種內置的超時導致進程在一段時間後死亡,但在源代碼中的任何位置都找不到它。 –

+0

用戶報告此問題的另一個鏈接:http://r.789695.n4.nabble.com/Problem-with-mclapply-losing-output-data-td3395746.html –

+0

Kudzu,Steve Weston建議記憶力不足的kiluler可能會終止mclapply進程,結果是我的情況下空值的原因。你能否證實oom_killer也導致你的空值? –

回答

5

您引用的Winston Chang報告的問題似乎已在R 2.15.3中得到修復。有在mccollect分配工人結果到結果列表時發生了錯誤:

if (is.raw(r)) res[[which(pid == pids)]] <- unserialize(r) 

如果unserialize(r)返回NULL,因爲以這種方式分配NULL到列表此失敗刪除列表中的相應元素。這已在R 2.15.3中更改爲:

if (is.raw(r)) # unserialize(r) might be null 
    res[which(pid == pids)] <- list(unserialize(r)) 

這是將未知值分配給列表的安全方式。

所以如果你使用R < = 2.15.2,解決方案是升級到R> = 2.15.3。如果使用R> = 2.15.3時出現問題,則可能與Winston Chang報道的問題不同。


我還閱讀了由伊麗莎白Purdom開始的R幫助線程中討論的問題。如果沒有一個具體的測試情況下,我的猜測是,這個問題是由於mclapply,因爲我可以重現相同的症狀有以下功能中的錯誤:

work <- function(i, poison) { 
    if (i == poison) quit(save='no') 
    i 
} 

如果mclapply開始工人死亡,而執行以任何理由任務(接收信號,賽格斷裂,退出),mclapply將返回NULL所有的已分配給該工人的任務:

> library(parallel) 
> mclapply(1:4, work, 3, mc.cores=2) 
[[1]] 
NULL 

[[2]] 
[1] 2 

[[3]] 
NULL 

[[4]] 
[1] 4 

在這種情況下,被返回NULL對任務1和3由於預先安排,即使只有任務3實際上失敗。

如果工人使用的功能,如parLapply或clusterApply去世時,報告錯誤:

> cl <- makePSOCKcluster(3) 
> parLapply(cl, 1:4, work, 3) 
Error in unserialize(node$con) : error reading from connection 

我見過很多這樣的報道,我想他們往往在使用大型程序的情況發生很多軟件包很難轉化爲可重複的測試用例。

當然,在這個例子中,使用lapply時也會出錯,儘管錯誤不會像mclapply一樣隱藏。如果在使用lapply時似乎沒有發生問題,可能是因爲問題很少發生,所以它只發生在使用mclapply並行執行的非常大的運行中。但也可能發生錯誤,不是因爲任務是並行執行的,而是因爲它們是由分叉進程執行的。例如,當在分叉進程中執行時,各種圖形操作將失敗。

+0

我在R 3.0.1上看到了這個問題,所以我認爲這是另一回事。另外它不是函數返回null和刪除列表元素的問題。相反,該函數在使用lapply運行時返回非空值,但在並行運行時,結果列表包含空值。我正在研究一個例子,以便其他人可以重現此問題。 –

+0

我在校羣上使用R,確實使用Ver 2.15.2。我會試着看看它是否會用更新的版本來解決。謝謝! – Kudzu

+0

這很有幫助。我所調用的函數在並行運行時不應該先驗失敗,但我想知道在16個內核上並行執行是否會將資源限制到功能有時無法工作的程度。我明天會有一些時間,並嘗試發佈一個例子(這將不幸是一個大量的數據運行)。 –

1

我添加了這個答案,所以其他人打這個問題將不必通過長長的評論線程(我是賞金巨頭,但不是OP)。

mclapply最初使用NULLS填充它創建的列表。當工作人員處理返回值時,這些值會覆蓋NULLS。如果某個進程沒有返回值而死亡,則mclapply將返回NULL。

當內存不足時,Linux的內存殺手(OOM殺手)

https://lwn.net/Articles/317814/

將開始默默地殺死進程。它不會將任何內容打印到控制檯,以讓您知道它在做什麼,儘管oom殺手活動顯示在系統日誌中。在這種情況下,mclapply的輸出似乎已被NULLS隨機污染。