何時使用 parallel 與 pmap

Julia 文件建議這樣做

pmap() 是針對每個函式呼叫執行大量工作的情況而設計的。相比之下,@ parallel for 可以處理每次迭代很小的情況,也許只是將兩個數相加。

有幾個原因。首先,pmap 會帶來更大的啟動成本,從而為員工創造就業機會。因此,如果作業非常小,這些啟動成本可能變得低效。然而,相反,pmap 在工人中分配工作的聰明工作。特別是,它構建了一個作業佇列,並在該工作人員可用時向每個工作人員傳送新作業。相比之下,@parallel 將所有工作分配給工人。因此,如果一些工人的工作時間比其他工人長,那麼你最終可能會遇到這樣的情況,即大多數工人已經完成並且閒置,而少數工人在過長的時間內仍然活躍,完成工作。然而,這種情況不太可能發生在非常小而簡單的工作中。

以下說明了這一點:假設我們有兩個工人,其中一個工作緩慢,另一個工作速度快兩倍。理想情況下,我們希望快速工作者的工作量是慢工作者的兩倍。 (或者,我們可以有快速和慢速的工作,但校長完全相同)。pmap 會完成這個,但是 @parallel 不會。

對於每個測試,我們初始化以下內容:

addprocs(2)

@everywhere begin
    function parallel_func(idx)
        workernum = myid() - 1 
        sleep(workernum)
        println("job $idx")
    end
end

現在,對於 @parallel 測試,我們執行以下內容:

@parallel for idx = 1:12
    parallel_func(idx)
end

並獲得列印輸出:

julia>     From worker 2:    job 1
    From worker 3:    job 7
    From worker 2:    job 2
    From worker 2:    job 3
    From worker 3:    job 8
    From worker 2:    job 4
    From worker 2:    job 5
    From worker 3:    job 9
    From worker 2:    job 6
    From worker 3:    job 10
    From worker 3:    job 11
    From worker 3:    job 12

它幾乎是甜蜜的。工人們平均分享了工作。請注意,每個工作人員已完成 6 個工作,即使工人 2 的工作速度是工人 3 的兩倍。它可能會觸及,但效率低下。

對於 pmap 測試,我執行以下操作:

pmap(parallel_func, 1:12)

並得到輸出:

From worker 2:    job 1
From worker 3:    job 2
From worker 2:    job 3
From worker 2:    job 5
From worker 3:    job 4
From worker 2:    job 6
From worker 2:    job 8
From worker 3:    job 7
From worker 2:    job 9
From worker 2:    job 11
From worker 3:    job 10
From worker 2:    job 12

現在,請注意,工人 2 執行了 8 個工作,工人 3 執行了 4 個工作。這與他們的速度和我們想要的最佳效率成正比。pmap 是一個艱鉅的任務大師 - 從每個人的能力。