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