2013-05-31 20 views
3

節點的對象這是我覺得很難理解的東西:如何提供給在雪地裏包的R並行計算

cl = makeCluster(rep("localhost", 8), "SOCK") 

# This will not work, error: dat not found in the nodes 
pmult = function(cl, a, x) 
{ 
    mult = function(s) s*x 
    parLapply(cl, a, mult) 
} 
scalars = 1:4 
dat = rnorm(4) 
pmult(cl, scalars, dat) 

# This will work 
pmult = function(cl, a, x) 
{ 
    x 
    mult = function(s) s*x 
    parLapply(cl, a, mult) 
} 
scalars = 1:4 
dat = rnorm(4) 
pmult(cl, scalars, dat) 

# This will work 
pmult = function(cl, a, x) 
{ 
    mult = function(s, x) s*x 
    parLapply(cl, a, mult, x) 
} 
scalars = 1:4 
dat = rnorm(4) 
pmult(cl, scalars, dat) 

第一個功能不因參數懶評價工作。但什麼是懶惰評價?當mult()被執行時,它不需要x被評估嗎?第二個是有效的,因爲它迫使x被評估。現在最奇怪的事情發生在第三個函數中,沒有做任何事情,但使mult()接收x作爲額外的參數,並突然一切正常!

另一件事是,如果我不想在調用parLapply()的函數內部定義所有的變量和函數,該怎麼辦?以下是絕對不會工作:

pmult = function(cl) 
{ 
    source("a_x_mult.r") 
    parLapply(cl, a, mult, x) 
} 
scalars = 1:4 
dat = rnorm(4) 
pmult(cl, scalars, dat) 

我可以通過這些變量和函數作爲參數:

f1 = function(i) 
{ 
    return(rnorm(i)) 
} 

f2 = function(y) 
{ 
    return(f1(y)^2) 
} 

f3 = function(v) 
{ 
    return(v- floor(v) + 100) 
} 

test = function(cl, f1, f2, f3) 
{ 
    x = f2(15) 
    parLapply(cl, x, f3) 
} 

test(cl, f1, f2, f3) 

或者,我可以用clusterExport(),但是當有很多,它會很麻煩要導出的對象。有沒有更好的辦法?


+0

見'force'? –

回答

5

要理解這一點,你必須認識到,沒有什麼環境是取決於函數是如何創建與每一個功能相關聯的環境和。在腳本中簡單創建的函數與全局環境相關聯,但由另一個函數創建的函數與創建函數的本地環境相關聯。在您的示例中,pmult創建了mult,因此與mult關聯的環境包含正式參數cl,ax

與第一種情況的問題是,parLapply不知道什麼x:它只是被序列爲multparLapply環境的一部分未計算正式的說法。由於當mult被序列化併發送給羣集工作人員時,x未被評估,所以當工作人員執行mult時,會導致錯誤,因爲dat在該上下文中不可用。換句話說,在mult評估x時,已經太晚了。

第二種情況工作,因爲之前mult是系列化x進行評估,所以x的實際值與的mult環境一起序列化。如果你知道關閉而不是懶惰的爭論評估,它會做你所期望的。

第三種情況是有效的,因爲您有parLapply處理x給你。根本沒有欺騙行爲。

我應該警告你,在所有這些情況下,a正在評估(由parLapply)並連同mult的環境序列化。 parLapply也將a拆分爲塊並將這些塊發送給每個工人,因此在mult環境中的a的副本是完全不必要的。它不會導致錯誤,但可能會損害性能,因爲mult會發送給每個任務對象中的工作人員。幸運的是,這對於parLapply來說不是一個問題,因爲每個工人只有一個任務。這將是一個更糟糕的問題clusterApplyclusterApplyLB其中任務的數量等於a的長度。

我在書中「雪」一章中討論了一些與功能和環境有關的問題。涉及到一些微妙的問題,很容易被燒燬,有時甚至沒有意識到發生過。

至於第二個問題,有向工作人員輸出功能的各種策略,但有些人確實使用source來定義工作人員的功能,而不是使用clusterExport。請記住,source有一個local參數,用於控制解析表達式的評估位置,您可能需要指定腳本的絕對路徑。最後,如果您使用的是遠程集羣工作人員,則如果您沒有分佈式文件系統,則可能需要將腳本scp到工作人員。

這裏是出口的所有功能,在全局環境的集羣工人的簡單方法:對於一些解釋

ex <- Filter(function(x) is.function(get(x, .GlobalEnv)), ls(.GlobalEnv)) 
clusterExport(cl, ex) 
+0

很榮幸有你的答案在這裏,先生!我正在閱讀_Parallel R_。 – qed

+0

@CravingSpirit我希望你找到這個答案,這本書很有用。 –

+0

謝謝。在本書的第23頁腳註中,您寫道:「實際上,如果您通過名稱指定工作者函數,而不是通過提供函數的定義,大多數並行執行函數將使用該名稱來查找功能在...從而避免序列化「。我仍然不完全明白「按名稱指定」和「提供定義」之間的區別,請您解釋一下。 – qed

相關問題