Profile(分析) 在加速你的matlab程序之前,你需要知道你的代碼哪一部分運行最慢。matlab提供個簡單的機制,讓你能夠知道你的代碼的某一部分運行所占用CPU時間。通過在代碼段開始添加tic,及在結束添加toc;matlab就能計算出這一代碼段的運行時間。 Tic和toc方法存在兩個問題: (1)顯示的時間是運行時間“wall clock”。這個時間受你在運行你的代碼時,你的計算機是否同時運行其它別的程序。 (2)你需要不斷地壓縮計時范圍來查找你代碼運行最慢的位置。
一個最好的方法是利用matlab 內(nèi)嵌的代碼分析器。在你的程序前面通過添加命令profile on;及在程序結束添加profile viewer;并運行你的程序。當程序正常運行結束時,代碼分析器窗口將彈出,并顯示分析結果。它包含的信息有: Function Name :函數(shù)名; Calls :函數(shù)被調(diào)用次數(shù); Total Time :執(zhí)行該函數(shù)的CPU總用時,包含任何其它被它調(diào)用的函數(shù)的CPU時間。 Self Time :執(zhí)行該函數(shù)的CUP總用時,不包含任何其它被它調(diào)用的函數(shù)的CUP時間。 Total Time Plot :時間用時的曲線圖。 以上信息可進行各種排序和詳細查看。 注意:當你完成你的代碼分析后,請刪除profile on和profile viewer,因為嵌入代碼分析器會使用的程序運行變慢。
標準提示 ☆有問題找?guī)椭臋n。學會使用幫助文檔,學會針對待解決的問題檢索文檔資料。 ☆性能 查看MATLAB->Programming->Improving Performace and Memory Usage;或MATLAB->Programming Fundamentals->Performace->Techniques for Improveing Performace。 多線程 如果你使用的是多核心的計算機,那么你就可以讓Matlab同時運行多個線程,Matlab 程序中一些底層的函數(shù)(Low-level function)就有可能采用并行計算的方法。打開多線程的方法:File->Preferences選擇 General->Multithreading??圻xEnable multihread computation box。如果不限制使用核心的數(shù)目,可以保留使用Automatic。 注意:Matlab R2008a之前的版本在AMD處理器上是不支持多線程的。
向量化循環(huán) Matlab的運算是針對向量(矢量)和矩陣進行設計的,因此它在向量和矩陣上的運算速度比采用循環(huán)的方式更快。 例如: index=0; for time=0:0.001:60; index=index+1; waveForm(index)=cos(time); end; 采用以下代碼可加快速度。 Time=0:0.01:60; waveForm=cos(time); 一些有用的,可用于代替循環(huán)的函數(shù): any();size();find();cumsum();sum();
向量預分配 Matlab采用內(nèi)存中一塊連續(xù)的空間來存儲向量和矩陣數(shù)據(jù),而不是用鏈表。這就意味著你每 給向量或矩陣增加一元素,Matlab需要尋找一塊足夠大的內(nèi)存區(qū)域來存儲這個擴大后的向量或矩陣,然后復制現(xiàn)有的數(shù)據(jù)到新的內(nèi)存區(qū)域。在循環(huán)中增加向量 或矩陣元素的元數(shù)是允許的,但并不是明智之舉,而應該是一次性分配向量或矩陣的大小,或一次性重定義尺寸。 Results=0; for index=2:1000; results(index)=results(index-1)+index; end 上述代碼將比以下代碼速度慢: results=zeros(1,1000); for index=2:1000; results(kindex)=results(kindex-1)+index; end; 注意:當你需要用zeros()來創(chuàng)建一個指定數(shù)據(jù)類型的向量或矩陣時,你可以使用創(chuàng)建參數(shù) 來指定類型,而不是“重鑄”。results=int8(zeros(1,1000));將創(chuàng)建一個有1000個元素的double型零向量,然后把它轉(zhuǎn) 換成int8類型。如果我們使用results=zeros(1,1000,'int8'); Matlab將支持建立1000個int8類型的向量,在創(chuàng)建可實現(xiàn)性及速度上將更具有優(yōu)勢。
不要改變數(shù)據(jù)類型 Matlab為了能夠支持寬松的數(shù)據(jù)類型(例如一個變量能夠存儲不同類型的數(shù)據(jù),而不是指定 它為特定的數(shù)據(jù)類型),則Matlab除了存儲單純的數(shù)據(jù)之外,還需要伴隨數(shù)據(jù)存儲一定數(shù)量的頭信息(header),這就意味著需要內(nèi)存空間支存儲數(shù)據(jù) 類型,同時意味需要在數(shù)據(jù)類型轉(zhuǎn)換上支付額外的計算機資源開支。 對于實數(shù)據(jù)使用 real...函數(shù)。 Matlab中的一些函數(shù)能夠同時適用于實類型數(shù)據(jù)和復類型數(shù)據(jù)。如果你只使用實數(shù)據(jù),那么采用特定的版本的,非復數(shù)據(jù)函數(shù),那么它運行的速度將變得更快。這些函數(shù)如:reallog(), realpow(),realsqrt()。 使用“短路”邏輯操作 Matlab的“短路”邏輯操作可以在判斷條件達到充分條件后就停止計算處理,而不需要知道 判斷所有條件。例如:if(index>=3)&&(data(index)==5); 當index小于3時,第二個條件判斷將不被處理,這樣就少了去判斷data(index)==5)的時間,提高速度。 使用函數(shù)指針 Matlab的一些函數(shù)使用函數(shù)名作用參數(shù),常用一個變量支保存這個函數(shù)名字符串()如:func='tan';然后用這個變量作為函數(shù)的參數(shù):fzero(func,0))。這種方法對于簡單的函數(shù)調(diào)用是很好的,但是對于在循環(huán)中的重復調(diào)用就存在兩個問題: (1)在每一個循環(huán)中,Matlab需要去搜索這個函數(shù)的路徑(如tan),這需要花費時間。 (2)在循環(huán)過程中,路徑可能會改變。這會保證在這一次循環(huán)中,某個版本的函數(shù)(如tan)被首先調(diào)用,而下一次循環(huán)中這個版本的函數(shù)又被首先調(diào)用,最終會造成結果不一致。 解決的辦法是使用文件指針(func=@tan;或func=@sin),它能返回函數(shù)唯一的識別碼。調(diào)用方式同上。 文件I/O 通常高級輸入輸出操作(load()和save())比一般的低級操作(fread()和fwrite())快。
☆內(nèi)存使用 關于內(nèi)存的使用可查看幫助文檔Using Menory Efficently??刹榕cMemory Usage相關的信息。 一定記注:可以使用whos()來查看數(shù)據(jù)變量占有用的內(nèi)存空間大小。 復制數(shù)組 當你復制一個數(shù)組時,Matlab開始只復制一個指向數(shù)據(jù)的一個指針,僅當你隨后對任一版本進行修時,數(shù)據(jù)的復制才真正的執(zhí)行。這種操作包括數(shù)組作為函數(shù)參數(shù)進行傳遞的情況-作為值傳遞的參數(shù)傳遞,而不是作為參考的傳遞。因此,你應該盡量避開對大數(shù)組進行小改動的操作。 數(shù)據(jù)不用時,釋放內(nèi)存 如果一個變量以后已經(jīng)不再使用,那么你可以刪除它clear VariableName;則這個小塊的數(shù)據(jù)將可以重用。 注意:如果各變量在內(nèi)存是連續(xù)的,則Matlab很容易重用這些大塊的內(nèi)存,因此最好是先建立大的變量,后再建立小的變量,并且把它們組合起來。 結構體存儲 上文已經(jīng)提到,在Matlab中的變量包含有描述數(shù)據(jù)類型的頭信息。對于一個結構體,則有一個描述整個結構的頭信息,及每個元素也分別有一個頭信息。為了最小化地使用內(nèi)存,我們應該小心地使用混合數(shù)據(jù)類型的數(shù)組和結構。 例如: pixel.red(1:600,1:400) pixel.grn(1:600,1:400) pixel.blu(1:600,1:400) 則我們就需要存儲4個頭信息。而: pixel(1:600,1:400).red pixel(1:600,1:400).grn pixel(1:600,1:400).blu 我們就有720001個頭信息。
使用最小的合適的數(shù)據(jù)類型 為了減小內(nèi)存使用量,對于特定的運算經(jīng)常使用最小的數(shù)據(jù)類型。例如: (1)對于虛部為零的數(shù)據(jù),最好不要用complex去存儲。 (2)如果精度足夠,可采用single變量,而不用double。 (3)使用uint16來進行計數(shù)操作,它能存儲值為0到65535。但它比默認的double型省一半的內(nèi)存。 使用稀疏矩陣 如果矩陣絕大多的數(shù)據(jù)為零值,可以把它轉(zhuǎn)化成稀疏形式(使用sparse()函數(shù))。它將只存儲非零數(shù)據(jù)的數(shù)值和索引。因為需要額外的存儲數(shù)據(jù)的索引,因此只有二維數(shù)據(jù)的零值大約超過75%時,這種方法才是有效的,否則稀疏形式反而需要更多的內(nèi)存空間。
☆并行循環(huán) 如果從一個for循環(huán)的外部看,for循環(huán)滿足以下標準: (1)循環(huán)的計數(shù)是整數(shù); (2)每次循環(huán)都是獨立的; (3)計算循環(huán)先后順序無關。 那么這個for循環(huán)就有可能可以替換成parfor循環(huán)(matlab2008a中可用優(yōu)化算打開并行通信池:parfor循環(huán)包含于matlabpool open 和matlabpool close之間)。 注意:打開一個并行工作池worker pool大約需要10-15秒鐘,關閉一個工作池大概需要5秒鐘。計算這個時間在內(nèi),這個方法對于循環(huán)時間超過30秒的情況才是值得的。 |
|