Matlab 簡單的並行化運算

本文只是對於多核CPU運行單一程序的優化,以及簡單的GPU運算(非CUDA)
部分內容引自:http://blog.sina.com.cn/s/blog_6b597bfb01018wa5.html
並行化計算通過client-workers體系,client負責分發任務,workers(數量等於CPU核數)負責完成任務

1、使用parfor循環

parfor循環把變量分爲五類:循環變量*、廣播變量臨時變量分段變量以及簡約變量
舉例如下:

a = 100;
s = 0;
parfor k = 1 : 100 % k爲循環變量

if a > 10 % 廣播變量
b = 10; % 臨時變量
end

c(k) = k; % 分段變量,輸入屬性
d = 1e3; % 臨時變量
s = s + k; % 簡約變量
end

循環變量:即代碼中的k。
廣播變量:該變量不是由worker產生,而是當client把任務分配給worker時傳給worker的,每個worker都會接收到此類變量。
臨時變量:在worker中產生,worker執行完任務之後clear掉,也不會傳遞給client的變量。
分段變量:這是parfor中最爲重要的變量,可以具有輸入和輸出兩類屬性。
簡約變量:循環執行的先後次序無關的操作在MATLAB中叫簡約循環,也能在MATLAB中並行化。。

  • 並行開啓(執行parfor語句自動開啓)
  delete(gcp('nocreate'));     % 確保沒有並行池運行 
  parpool ;                   %打開並行池
  parpool(2);                  %打開特定大小的池
  p = gcp;  delete(p);         %刪除當前並行池
  • 首先使用for循環寫好對於程序,在進行如下判斷

若要並行,必須滿足以下2個條件之一:每次循環之間是相互獨立的;循環執行完之後的結果和循環執行的先後次序無關。

  • 加速要點
  • 並行運算變量不需要預先分配內存空間;因爲一旦在parfor之前預分配內存了,該分段變量就具備了輸入屬性,已在client中生成了,client再將其分段傳遞給不同的worker,這會消耗額外的時間。所以,我們的原則是:分段變量能不增加輸入屬性就不增加。(只針對並行運算)

一般編程注意
1、多使用列向量。
2、a(a>0.5) = 0; % 邏輯索引、a(find(a>0.5)) = 0; % 數值索引、毫無疑問,前者的代碼執行速度更快。
3、對於通信算法SNR仿真,可以使用break語句,在性能符合要求的SNR跳出。

  • 直接將for改爲parfor,根據提示修改程序
    一般被賦值變量的索引應該從1開始且順序存儲,被調用廣播變量等也儘量從1開始。(經驗)

    2、簡單的GPU加速

    • 將需要GPU運算的變量使用gpuArray()轉換寫入GPU,在GPU計算完成後使用gather()將需要收集的變量讀入Matlab工 作區內存空間進行下一步操作。(考慮到內存讀寫,此方法只對某些方法加速效果良好)
    • 使用arrayfun()函數
      1、例:d = arrayfun(@myfunction,a,b,c);,myfunction爲當前調用函數,在GPU進行處理,a、b、c爲輸入gpuArray類型參數(可以按照函數要求添加多個參數,每個參數維度一致;如果c不是gpuArray類型,函數運行開始將自動轉爲gpuArray)。
      2、使用gather可以收集d。不支持數組輸出(標量輸入輸出)。

非gpuArray情況
1、支持數組輸出(如輸入參數a、b、c分別爲1、2、3;輸出爲[1,2],'UniformOutput’設置爲‘false’),輸出爲cell類型;對於cell類型,通過()訪問cell數組時訪問到的是cell單元,通過{}訪問cell數組時訪問到的是cell單元儲存的內容。
2、同理數組輸入也需要使用cell類型,或者struct結構體;
3、可以使用num2cell(matrix,dismension),將輸入矩陣轉爲cell類型,將dismension維度合併,如A爲3x2矩陣,2維度,轉換後B爲3x1cell類型,B{1} = A(1,:) 。
4、對於結構體類型,例a(1).x = [1 2];a(2).x = [ 2 3];以a輸入,a.x讀取即可。

%% 定義函數
function a = add(b,c)
a = b + c;
end
%% arrayfun 三種函數使用方法
l = @(b,c) b+c;
d = arrayfun(@add,[1 2 3],[2 3 4]) ;       
d = arrayfun(@(b,c) b+c,[1 2 3],[2 3 4]) ;
d = arrayfun(l,[1 2 3],[2 3 4]) ;
%%gpuArray
d = arrayfun(l,gpuArray([1 2 3]),gpuArray([2 3 4])) ;(輸入輸出均爲標量)

3、batch批處理

  • 主要用於集羣等,簡單語句說明一下,未深入瞭解
job = batch('mywave');      %批處理,不阻塞當前程序繼續運行,使用默認集羣
%可以設置'Pool'參數,定義使用並行池數量,需要先關閉之前開啓的並行池
wait(job)                   %強行阻塞等待
diary(job);                 %打印子程序的打印信息Command Window Output
load(job,'A');              %加載job中變量到當前工作區,原始數據類型
delete(job);                %刪除數據
clear job;                  %刪除工作空間

job_function = batch(fcn,N,{x,y,z,...});          %批處理函數,fcn爲函數句柄,N爲輸出參數數量,x,y,z,...爲輸入參數
%可以設置'Pool'參數,定義使用並行池數量,需要先關閉之前開啓的並行池
wait(job_function);
if(job_function.State == 'finished')
   job_function_out = fetchOutputs(job_function); % 加載返回數據到工作區,cell類型
   class(job_function_out{1})                     %返回數據類型
end

微信公衆號:通信隨筆XIDIAN

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章