1. 程式人生 > >【高效能】Matlab的平行計算之parfor

【高效能】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 doubles
parafor: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啟動並行環境也比較慢。