轉載至:http://blog.csdn.net/caozhk/article/details/38234293?utm_source=tuicool&utm_medium=referral
通常消耗最多計算資源的程式往往是循環。把循環并行化,或者優化循環體中的代碼是最常用的加快程式運作速度的思路。
Matlab提供了parfor關鍵字,可以很友善的在多核機器或叢集上實作并行計算。
parfor關鍵字的使用
由for關鍵字引導的循環通常為串行運作,如果改為parfor則可以由多個worker以并行方式執行。
parfor可以将n次循環分解為獨立不相關的m部分,然後将各部分分别交給一個worker執行。
循環執行的結果應該與n次循環執行的順序無關。
parfor中的變量類型
簡約變量
一般parfor中各次循環對應的運算應該互相獨立,但簡約操作可以在多次循環内同時對一個變量操作。這種變量稱為簡約變量。例如下方代碼中a就是簡約變量。
a = 0;
for i = 1:1000
a = a+i;
end
簡約操作包括+ - * .* & | [,] [;] {,} {;} min max union intersect。
同一個parfor循環對簡約變量的操作必須一緻,即必須是同一種簡約操作符。而且與操作符的相對位置也必須一緻。
簡約變量指派表達式應該滿足結合律和交換律。* [] {}底層有特殊處理保證結果的正确性。
切片變量(sliced)
parfor中可能需要讀取或寫入parfor之外的矩陣,讀取寫入位置與循環變量相關。這樣就需要向worker傳輸大量的資料。
矩陣如果被Matlab識别為切片變量,則資料可以分段傳輸到各worker,提高傳輸效率。
切片變量矩陣的大小是不可在parfor中改變的,且為了保證Matlab識别正确,每次循環中隻能讀取由同一個索引值索引的切片,如a[i] a[i+1]同時出現則a不被識别為切片變量。
循環變量(loop)
如上例中的i,表示目前循環的id。
廣播變量(broadcast)
在parfor之前指派,在parfor内隻進行讀取操作,不能再parfor之内對其指派。若在parfor以内對廣播變量指派,則會顯示“the variable xxxx in a parfor cannot be classified.”
臨時變量(temporary)
作用域局限于parfor内,parfor結束後不存在。不影響parfor之前聲明的同名變量。
各種變量區分的例子
下例中,parfor中的tmp是臨時變量,parfor結束後tmp的值依然是5,不受臨時變量的影響。
broadcast是廣播變量,每次循環中的值不變。
redued是簡約變量,Matlab對其的值将分段由各worker計算後送回主程序處理。
sliced為切片變量,資料傳輸有優化提升。
i為循環變量。
tmp = 5;
broadcast = 1;
reduced = 0;
sliced = ones(1, 10);
parfor i = 1:10
tmp = i;
reduced = reduced + i + broadcast;
sliced(i) = sliced(i) * i;
end
worker配置
在運作程式之前,需要配置worker。否則如前文所說,parfor循環将以普通for循環的形式運作,無法并行。
單機配置
使用matlabpool指令可以開啟關閉本機的并行計算池。
matlabpool n指令可以打開n個worker。
matlabpool open configname按照指定配置打開,預設配置為local。
程式運作結束後,應該使用matlabpool close關閉worker。
配置項的修改可以通過Parallel -> Manage Cluster Profile完成。
n的選擇:
如果有c個cpu核心,通常可以設定為c。如果是遠端伺服器,為防止伺服器響應卡頓,可以設定為c-1。對于計算密集型程式,超線程帶來的性能提升幾乎為0,可以設定為核心數,而不是線程數。
注意事項
循環次數n最好能整除以worker個數m,否則部分worker會配置設定較多的循環,造成一部分worker閑置一段時間,降低了并行性。
并行運作時各個worker之間會進行通信,要注意大量資料傳輸帶來的性能下降。尤其對于廣播變量,如果較大可嘗試變為切片變量。