matlab充分利用性能,Matlab高性能编程——代码优化和并行计算
Jeremy Lin ?@HQU
Update: 2014/4/29
Matlab代碼優化
Matlab是一種高級計算機語言,同時也是一個用于算法開發,數據可視化,數據分析和數值計算的交互式工作環境。盡管Matlab軟件提供了大量專業化的工具箱,使用戶避免了很多編程工作,但是在實際工作中仍不免需要自行編寫Matlab代碼以應對各種紛繁復雜的應用。我們需要明白Matlab是一種專門為數組運算而設計的語言,因此在程序設計中要注意充分利用這一優點來加快運算速度。
本文從以下三個方面展開:
程序語法分析 :Code Analyzer(M-Lint)
程序性能分析 :Profiler
運算性能提升 :向量化、預分配
1.程序語法分析
關于Matlab的程序語法分析,我們要充分利用Code Analyzer的各種提示,修改出現的各種warning,來改善程序。
所謂的Code Analyzer就是在m文件編輯器右邊的一欄warning提示,當程序出現warning時,它附帶地提供了一些可參考的方法。
在下圖中,我們可見到兩個warning,一個是沒有分號結束符,這樣會使代碼結果直接輸出,有過編程經驗的人都知道,在代碼的運行過程中不斷輸出中間結果,會大大增加程序的運行時間;另一個warning是沒有對其中的變量進行初始化,這樣會讓程序在運行過程中不斷重復初始化變量,同時也會大大消耗內存。
一個簡單的例子如下所示:
當我們沒有去掉warning時,程序的運行時間是:5.570289s,而當我們添加了代碼的分號結束符后,程序的運行時間是:0.008179s,對比發現程序提速非常明顯。
2.程序性能分析
對程序的性能分析我們主要利用Profiler來深度了解代碼的性能,找出瓶頸代碼,然后做出修改以提升性能。
在Matlab中打開Profiler只要點擊Run and Time即可,位置如下圖所示:
我們從Profiler可以得到
函數調用的總次數
每次函數調用耗時狀況
然后根據各個函數的調用情況,結合實際情況,把可以替換的函數直接替換,不能替換的高調用函數盡量優化。
3.運算性能提升
運算性能提升主要利用兩種方法:內存預分配和向量化。
首先我們來看看內存預分配的必要性:
需要明白,當你未進行內存預分配時,比如執行如下的代碼:
>> x=4;
>> x(2)=7;
>> x(3)=12;
它在內存中的過程是這樣的:
從上圖我們可以發現,改變數組大小是很耗費內存的,因此最好進行內存預分配,同時它能夠減少存儲器碎片。
接下來,我們來看看向量化,所謂向量化即是將for循環和while循環轉換為等價的向量或矩陣運算,它可以大大加速運算,還增強了代碼的可讀性。
我們從一個簡單的例子開始:
原程序:
A=1;
for x=1:10000000
f(x)=A*sin((x-1)/(2*pi));
end
運行時間:12.714 s
向量化后:
A=1;
x=0:10000000-1;
f=A*sin(x/(2*pi));
運行時間:0.544 s
可以發現,向量化后,程序的運行速度提高了23倍左右。
雖然一維的向量化很簡單,但是,當被評估的函數有兩個變量時,優化的方法可能就會復雜一些。
MATLAB使用meshgrid來實現對二維函數的評估,該函數的語法為
[C, R] = meshgrid(c, r)
該函數將由行向量c和r指定的域變換成數組C和R,這兩個數組能用來評估有著兩個變量的函數和三維表面圖(注意,在meshgrid的輸入和輸出中,列總是首先列出)。
輸出數組C是向量c的副本,R是r的副本。例如,假設我們想形成一個二維函數,該函數的元素是坐標向量x和y的值的平方和,其中x=0, 1, 2; y=0, 1。向量r由坐標的行向量構成:r=[0, 1, 2];類似的,c由坐標的列向量構成:c=[0 1](注意,此處的r和c均為行向量)。將這兩個向量代入meshgrid可得到如下數組:
>> [C,R]=meshgrid(c,r)
C =
0 1
0 1
0 1
R =
0 0
1 1
2 2
我們感興趣這個函數的實現:
>> h=R.^2+C.^2
h =
0 1
1 2
4 5
例子:
tic
u0=1/(4*pi);
v0=1/(4*pi);
for r=1:1000
u0x=u0*(r-1);
for c=1:1000
v0y=v0*(c-1);
f(r,c)=sin(u0x+v0y);
end
end
t1=toc
運行時間:?2.4337 s
向量化后:
tic
u0=1/(4*pi);
v0=1/(4*pi);
r=0:1000-1;
c=0:1000-1;
[C,R] = meshgrid(c,r);
g=sin(u0*R+v0*C);
t2=toc
運行時間:?0.0590s
向量后快了41倍。
OTHER TIPS:
以列向量存儲:以列作為雙重for循環的外循環會比以行作為外循環運算速度更快
邏輯索引運算性能更好:例子如下
%%
N=2000;
A=magic(N);
A1=magic(N);
A2=magic(N);
myRef=1e6;
%%
tic
ix=1;
vals=zeros(size(A(:)));
for jj=1:N
for ii=1:N
if A(ii,jj)>myRef
vals(ix) = A(ii,jj);
ix=ix+1;
end
end
end
% vals(ix:end)=[];
toc
%%
運行時間:Elapsed time is 5.466597 seconds.
tic
vals=A2(A2>myRef);
toc
運行時間:Elapsed time is 0.084450 seconds.
In-place操作 :減少臨時變量的使用
N=3e3;
x=rand(N);
tic;
y=x*1.2;
toc;
%Elapsed time is 0.073008 seconds.
%% In-place 操作
tic;
x=x*1.2;
toc;
%Elapsed time is 0.037856 seconds.
MATLAB并行計算
關于Matlab并行計算,這一塊我實際的經驗較少,只做一點淺顯的介紹,更多相關的資料見下文的參考資料。
1、Matlab并行計算原理
Matlab的并行計算實質還是主從結構的分布式計算。當你初始化Matlab并行計算環境時,你最初的Matlab進程自動成為主節點,同時初始化多個Matlab計算子節點。Parfor的作用就是讓這些子節點同時運行Parfor語句段中的代碼。Parfor運行之初,主節點會將Parfor循環程序之外變量傳遞給計算子節點。子節點運算過程時互不干擾,運算完畢,則應該有相應代碼將各子節點得到的結果組合到同一個數組變量中,并返回到Matlab主節點。當然,最終計算完畢應該手動關閉計算子節點。
2、初始化Matlab并行計算環境
這里講述的方法僅針對多核機器做并行計算的情況。設機器的CPU核心數量是CoreNum雙核機器的CoreNum2,依次類推。CoreNum以不等于核心數量,但是如果CoreNum小于核心數量則核心利用率沒有最大化,如果CoreNum大于核心數量則效率反而可能下降。因此單核機器就不要折騰并行計算了,否則速度還更慢。
下面一段代碼初始化Matlab并行計算環境:
%Initialize Matlab Parallel Computing Enviornment by Xaero | Macro2.cn
CoreNum=2; %設定機器CPU核心數量,我的機器是雙核,所以CoreNum=2
if matlabpool('size')<=0 %判斷并行計算環境是否已然啟動
matlabpool('open','local',CoreNum); %若尚未啟動,則啟動并行環境
else
disp('Already initialized'); %說明并行環境已經啟動。
end
運行成功后會出現如下語句:
Starting?matlabpool?using?the?'local'?configuration?...?connected?to?2?labs.
如果運行出錯,按照下面的辦法檢測:
首先運行:
matlabpool?size
如果出錯,說明你沒有安裝Matlab并行工具箱。確認安裝了此工具箱后,運行:
matlabpool?open?local?2;
如果出錯,證明你的機器在開啟并行計算時設置有問題。
3、終止Matlab并行計算環境
用上述語句啟動Matlab并行計算環境的話,在你的內存里面有CoreNum個Matlab進程存在,每個占用內存都在百兆以上。(可以用Windows任務管理器查看),故完成運行計算后可以將其關閉。關閉的命令很簡單:
matlabpool?close
Reference:
[1] ?Rafael C. Gonzalez. Digital Image Processing Using MATLAB.
[2]?mathworks ?webinars
[3] Matlab Help
[4]?Matlab并行編程方法?Rachel Zhang的專欄
本文地址:http://blog.csdn.net/linj_m/article/details/9730717
更多資源請關注 博客:LinJM-機器視覺微博:林建民-機器視覺
總結
以上是生活随笔為你收集整理的matlab充分利用性能,Matlab高性能编程——代码优化和并行计算的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: led显示原理(led显示屏接线图解)
- 下一篇: 上海那个装修公司好