作者:貓叔來源:科學計算Tech微信公眾號
用過Matlab的同學應該都知道,Matlab的慢是出了名的,但是再慢也有優(yōu)化的方式,下面我們給出幾個Matlab編程中常用的優(yōu)化技巧。
在講優(yōu)化方法之前,首先要說的就是Matlab中用tic toc的方式來計算運行時間,這是個常識。當然,想統(tǒng)計具體的耗時,可以用profile工具。
1. 向量化操作
這個應該是用過Matlab的同學都清楚的一點,Matlab中操作向量和矩陣的速度要比使用for循環(huán)的速度快很多,是因為其底層調(diào)用了高性能線性代數(shù)庫BLAS庫和LAPACK庫。這個就不多說了。
2. 內(nèi)存預分配
在Matlab中我們可以定義一個空矩陣
mtx = [];
然后后面再給它加入一些數(shù)據(jù),而且這個矩陣大小可以隨著我們填入數(shù)據(jù)的多少而變化。像下面這個程序
tic n = 1000; mtrx = []; init = 1.0; for i = 1:n for j=1:n mtrx(i,j) = init + 1.0; end end toc
這個程序的運行時間是多久呢?在我電腦上是0.2秒。
那這個程序有什么問題呢?就是我們沒有為這個矩陣分配一個內(nèi)存空間,而且在循環(huán)中,矩陣大小是變化的,這就導致每次循環(huán)時都浪費額外的時間去尋找滿足需求的內(nèi)存空間,將改變大小后的矩陣整體移動到這個新的內(nèi)容空間中,并釋放原來的內(nèi)存空間,這除了會影響代碼的運行效率,還容易形成內(nèi)存碎片,讓程序越來越難找到滿足條件的內(nèi)存。
因此在循環(huán)前給矩陣預分配內(nèi)存是很一個良好的習慣,如果沒有這個習慣,你還可以通過Matlab自帶的代碼檢查器來查看是否存在類似問題。
所以,我們應該把程序修改如下:
tic n = 1000; mtrx = zeros(n,n); init = 1.0; for i = 1:n for j=1:n mtrx(i,j) = init + 1.0; end end toc
這個程序只用了0.007秒的時間就運行完成了,可見它們的差距有多大。
3. 按列存儲
Matlab中默認是按列存儲的,也就是說,列向量在內(nèi)存中是連續(xù)排列的,對連續(xù)的數(shù)據(jù)做處理肯定是要快的,所以我們在定義向量時一般都會使用列向量。下面對比矩陣中對行做操作和對列做操作花費的時間。
n = 10000; mtrx = rand(n,n); mcol = zeros(n,1); mrow = zeros(1,n); tic for i=1:n mcol(i) = sum(mtrx(:,i)); end toc
我們對矩陣中的每一列都求和,總共用了0.17秒。
tic for i=1:n mrow(i) = sum(mtrx(i,:)); end toc
再對矩陣中的每一行求和,用了0.8秒。
可以看出,對列操作比對行操作速度要快很多。
4. 數(shù)據(jù)類型
在Matlab中,數(shù)據(jù)類型默認是double型,對使用者來說,無需太多關心數(shù)據(jù)類型當然是省心省力的,但這也帶來了一個問題就是double型占用的內(nèi)存較多,還有可能拖慢程序的運行速度。所以,在適當?shù)那闆r下,我們可以把數(shù)據(jù)類型選擇為邏輯型、字符型、整型等。但這樣還需要注意的一點是,一個變量在改變數(shù)據(jù)類型時會消耗額外的時間,因此還不如重新建一個新變量。
高效編程的內(nèi)容就先寫這么多,后面還會繼續(xù)補充。下面說一個Matlab調(diào)試中斷點設置問題。在一個for循環(huán)中,比如for i=1:n,我們想在i=100的進入斷點,這個時候應該怎么用?以前的時候我們都會這么寫。
for i=1:n if(i==100) pass end end
把斷點設置在pass處,但其實不用這么弄。Matlab中提供了條件斷點的設置方式。在循環(huán)中右鍵選擇設置條件斷點。
Figure 1. 條件斷點設置1
在下面的窗口中填入條件即可,比如i==100。
Figure 2. 條件斷點設置2
這樣,當程序運行到i==100時就會進入斷點,不需要自己再寫額外的語句。
審核編輯:何安
-
matlab
+關注
關注
181文章
2960瀏覽量
230034
發(fā)布評論請先 登錄
相關推薦
評論