【高效能】Matlab的平行計算之parfor
當matlab計算量很大,重複獨立的迴圈計算很多的時候,我們可以使用matlab的平行計算,這裡我先試驗了parfor平行計算。以下程式碼僅適合新版的matlab,改編自《實戰matlab之並行程式設計》。
啟動程式碼:
function [pool] = startmatlabpool(size) pool=[]; isstart = 0; if isempty(gcp('nocreate'))==1 isstart = 1; end if isstart==1 if nargin==0 pool=parpool('local'); else try pool=parpool('local',size);%matlabpool('open','local',size); catch ce pool=parpool('local');%matlabpool('open','local'); size = pool.NumWorkers; display(ce.message); display(strcat('restart. wrong size=',num2str(size))); end end else display('matlabpool has started'); if nargin==1 closematlabpool; startmatlabpool(size); else startmatlabpool(); end end
關閉程式碼:
function [] = closematlabpool
if isempty(gcp('nocreate'))==0
delete(gcp('nocreate'));
end
測試程式碼:
pool = startmatlabpool(4); N=1000; M=100; data = cell(1,N); for kk = 1:N data{kk} = rand(M); end display(strcat('datasize:',num2str(N*M*M/1024/1024),'M doubles')); tic; parfor ii = 1:N c1(:,ii) = eig(data{ii}); end t1 = toc; display(strcat('parafor:',num2str(t1),'seconds')); tic; for ii = 1:N c2(:,ii) = eig(data{ii}); end t2 = toc; display(strcat('for:',num2str(t2),'seconds')); closematlabpool;
結果:
datasize:9.5367M doublesparafor:1.6411seconds
for:3.908seconds
Parallel pool using the 'local' profile is shutting down.
可以看出parfor計算速度快了一半。
問答1:能否彙總各個執行緒的資料?
在openMP中也有這個問答:
for i = 1 : 1000
sum = sum + i;
end
如果是並行的話,每個A線上程中都有自己的一份拷貝,那麼最後得到的A是不可預計的。
openMP的解決方法是增加了reduction子句:
#pragma omp parallel for reduction(+: sum)
for ( i = 1; i < 1001; i++ )
{
sum += i;
}
這樣sum就是1-1000的和。
在matlab中,matlab自己會預設把sum的加法設定為reduction加法,稱為簡約/規約操作,反正不進行這個操作的話也沒有其他意義。ORZ
程式碼:startmatlabpool(4)
sum = 0;
parfor i = 1:1000
sum = sum + i;
end
sum
closematlabpool;
結果:sum=500500
事實上可以進行連續操作的操作符都支援簡約操作,比如*,.*,+,-,&,|,[,expr]等等。
不過簡約操作有很多陷阱,所以簡化並行操作和增加一致性是非常必要的。
問答2:parfor的變數有什麼講究?
其實沒什麼講究,比起openMP來parfor要簡單的多,好用說不上,但是方便簡單的並行操作。所有的變數直接用就行了,書上的各種變數種類都是唬人的,不過請注意非簡約操作情況下答案是否正確,以及不要隨便修改輸入變數(修改後的結果無法預計)。
問答3:parfor語句作用域能用break嗎?
答案是不能。這個不能在特定情況下直接退出,就是說一旦執行就要執行下去。另外parfor是最低端的並行語句,在作用域內部也不能使用spmd,parfor巢狀,不過可以使用含有parfor的函式。
問答4:什麼時候使用parfor
其實用了一下感覺他的作用並不大,各種並行控制手段都沒有……如果資料量特別大,各個迴圈域之間相對獨立,就可以用parfor。另外matlab啟動並行環境也比較慢。