国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
從Matlab的for循環(huán)說開…… - Vistb's Tiny IT Space - 博...
因?yàn)閷W(xué)習(xí)和工作的原因,最近又開始使用已經(jīng)許久沒有接觸的Matlab。在沒有什么特殊考慮的情況下,信手寫下了下面的m代碼片段:
 1 for i=1:1:(imgHeight-tmpHeight+1)
 2     for j=1:1:(imgWidth-tmpWidth+1)
 3         temp=0;
 4         for m=1:1:tmpHeight
 5             for n=1:1:tmpWidth
 6                 temp=temp+img(i+m-1,j+n-1)*template(m,n);
 7             end
 8         end
 9         if temp>0
10             tmpRst(i+floor(tmpHeight/2),j+floor(tmpWidth/2))=temp;
11         end;
12     end
13 end

  

  外層循環(huán)的2個變量長度為300和400,內(nèi)層的兩個為9。出乎我的意料的是,這樣一段代碼在我的機(jī)器上(T5750@2GHz, 2GB DDRII667)竟然要跑1分多鐘,而這段代碼轉(zhuǎn)換為C++后是準(zhǔn)備要在一個實(shí)時圖像識別系統(tǒng)上跑的。換言之,時間至少必須下降到1/25以內(nèi)!雖然可以指望C++的效率,但Matlab這樣的速度也太離譜了!況且我在Matlab中還要不斷的實(shí)驗(yàn),跑一遍就要1、2分鐘,實(shí)在令人難以接受。下午和師兄們討論時,無意談到了這個問題,他們立即對我說,想辦法轉(zhuǎn)換為矩陣操作什么的,Matlab中for循環(huán)的效率是很低的!

   回寢室后,試驗(yàn)了一下,結(jié)果令人乍舌,我把代碼改成了下面的樣子(注意第三行代碼實(shí)際上代替了內(nèi)層for循環(huán),其他的改動我想沒什么本質(zhì)影響):

1 for i=1:1:(imgHeight-tmpHeight+1)
2     for j=1:1:(imgWidth-tmpWidth+1)
3         temp=img(i:(i+tmpHeight-1),j:(j+tmpWidth-1)).*template;
4         temp=sum(sum(temp));
5         tmpRst(i+floor(tmpHeight/2),j+floor(tmpWidth/2))=(temp+abs(temp))/2;
6     end
7 end

  

  結(jié)果時間呢,只要了2秒左右!這么一改,效率提升了幾十倍!我是學(xué)過一些編譯原理的,但這種差距實(shí)在令我感到很不解。求助Google后,算是得到了滿意的答復(fù)。


  首先,看看Improving the Speed of MATLAB Calculations這篇文章中怎么說的。

  在前言中,文章中有兩段話:

   MATLAB programs are interpretted. This would seem to make it inapproapriate for large scale scientific computing. The power of MATLAB is realized with its extensive set of libraries which are compiled or are carefully coded in MATLAB to utilize "vectorization". The concept of vectorization is central to understanding how to write efficient MATLAB code.
  Vectorized code takes advantage, wherever possible, of operations involving data stored as vectors. This even applies to matrices since a MATLAB matrix is stored (by columns) in contiguous locations in the computer's RAM. The speed of a numerical algorithm in MATLAB is very sensitive to whether or not vectorized operations are used.

  其核心大意就是說為了彌補(bǔ)Matlab程序是解釋執(zhí)行所帶來效率問題,我們應(yīng)該盡量使用“向量化”(vectorization)的命令。Matlab程序執(zhí)行的效率,對于是否使用了“向量化”命令是非常(very)敏感的!

  其后,文章給出了兩條實(shí)用的建議。

  第一條,使用向量操作代替循環(huán)。 以下舉例說明。

1 dx = pi/30;
2 nx = 1 + 2*pi/dx;
3 for i = 1:nx
4   x(i) = (i-1)*dx;
5   y(i) = sin(3*x(i));
6 end


  這段代碼是很自然的從C語言的形式轉(zhuǎn)化而來的,但其效率很低!Matlab是實(shí)時為變量分配內(nèi)存的,在第一遍循環(huán)時(即i=1時),Matlab為x和y這兩個向量(長度均為1)分配內(nèi)存。以后每執(zhí)行一次循環(huán),Matlab都會在x和y的末尾附加新的元素。這不僅導(dǎo)致分配內(nèi)存的調(diào)用的增加,也使得x和y的各個元素在內(nèi)存中的分布不是連續(xù)的(就像數(shù)據(jù)結(jié)構(gòu)中數(shù)組和鏈表的區(qū)別)。由此,性能遭到了損失。

  相比之下,下面的代碼效率提高不少:

1 = 0:pi/30:2*pi
2 = sin(3*x);


  第一個語句分配了一個連續(xù)的內(nèi)存空間來存儲具有多個元素的向量x。類似的,第二個語句在分配內(nèi)存時,也是分配了一個連續(xù)的內(nèi)存空間來存儲具有多個元素的向量y。撇去計(jì)算sin的消耗不算,就內(nèi)存分配命令的執(zhí)行次數(shù)和對向量元素訪問的方便程度來說,高下立見。

  第二條,為矩陣和向量預(yù)先分配內(nèi)存。

  文章中指出,雖然Matlab會自動調(diào)整變量的大小,我們最好還是預(yù)先為變量分配內(nèi)存空間。因?yàn)檫@樣可以使調(diào)用內(nèi)存分配命令的次數(shù)降為1,也可以使變量在內(nèi)存中連續(xù)存儲(當(dāng)變量為矩陣時是按列在內(nèi)存中連續(xù)存儲)。

  而所謂“預(yù)先為變量分配內(nèi)存空間” ,是指在知道變量的大小的情況下,在變量中的任何一個元素都未被引用之前,創(chuàng)建一個大小和其一致的變量。

  下面是一個例子,代碼質(zhì)量從上至下逐漸提高:

 1 dx = pi/30;
 2 nx = 1 + 2*pi/dx;
 3 nx2 = nx/2;
 4 
 5 for i = 1:nx2
 6   x(i) = (i-1)*dx;
 7   y(i) = sin(3*x(i));
 8 end
 9 
10 for i = nx2+1:nx
11   x(i) = (i-1)*dx;
12   y(i) = sin(5*x(i));
13 end

 

 1 dx = pi/30;
 2 nx = 1 + 2*pi/dx;
 3 nx2 = nx/2;
 4 
 5 = zeros(1,nx);      % 為向量x預(yù)分配內(nèi)存
 6 = zeros(1,nx);      % 為向量y預(yù)分配內(nèi)存
 7 
 8 for i = 1:nx2
 9   x(i) = (i-1)*dx;
10   y(i) = sin(3*x(i));
11 end
12 
13 for i = nx2+1:nx
14   x(i) = (i-1)*dx;
15   y(i) = sin(5*x(i));
16 end


 1 = 0:pi/30:2*pi;     % 計(jì)算向量x的值
 2 nx = length(x);
 3 nx2 = nx/2;
 4 
 5 = x;                % 為向量y預(yù)分配內(nèi)存
 6 
 7 for i = 1:nx2
 8   y(i) = sin(3*x(i));
 9 end
10 
11 for i = nx2+1:nx
12   y(i) = sin(5*x(i));
13 end


1 = 0:pi/30:2*pi;                  % 計(jì)算向量x的值
2 nx = length(x);
3 nx2 = nx/2;
4 
5 = x;                             % 為向量y預(yù)分配內(nèi)存
6 
7 y(1:nx2) = sin(3*x(1:nx2));        % 計(jì)算y的第1部分的值
8 y(nx2+1:nx) = sin(5*x(nx2+1:nx));  % 計(jì)算y的第2部分的值



  然后,再來看看這個名為Improving Program Efficiency的PPT。

  除了上篇文章提到的那幾點(diǎn)以外,該ppt中還提出了以下幾點(diǎn)看法和建議。

  第一,選擇合適的數(shù)據(jù)類型。Matlab有多種數(shù)據(jù)類型,不同的數(shù)據(jù)類型可以帶來不同的精度,但處理速度也存在差別。double當(dāng)然可以比int8帶來更高的精度,但性能卻會下降。不過,我個人對這個建議持保留意見,主要在于有些操作對一些諸如int8類型的非標(biāo)準(zhǔn)類型不支持,而且有時候容易產(chǎn)生誤操作(例如相對uint8這樣的無符號整形變量)。

  第二,使用tic和toc來測試程序的執(zhí)行時間。這兩個命令配合使用可以測試一段m代碼的執(zhí)行時間。具體的就不多說了,大家可以去查看Matlab的幫助文件。另外,Matlab最近的版本(像R2009b)中出現(xiàn)了類似于性能測試工具的組件,大家可以在Matlab的幫助文件中搜索"Profiling for Improving Performance" 進(jìn)行進(jìn)一步了解。

  第三,類似于上一篇文章中提到的使用向量化命令,減少循環(huán)。但是,該ppt中還列出了一些常用的可以用來代替循環(huán)的向量化命令,列舉如下:

  • find        (find values that meet some criteria,尋找符合某些特定條件的矩陣中的元素)
  • sum, prod, diff   (sum 加, product 乘, difference 減)
  • .*, ./        (element by element matrix operations,矩陣間逐元素操作)
  • min, max       (find min or max values,求最小和最大值)
  • zeros, ones     (for initializing arrays,用于初始化變量)

  其中,我覺得find、prod、diff等都是比較少見的(可能由于我才疏學(xué)淺,呵呵),大家可以仔細(xì)研究一下。尤其是find,非常有用!


  最后,在一篇討論for循環(huán)的效率的帖子中,我也聽到了一些不同的意見。

  總的來說,就是對for循環(huán)不能一棒子打死,要區(qū)別對待(像對goto語句?)。

  在這個帖子中,名為Bruno Luong的作者總結(jié)道(本人英文不好,不敢打包票翻譯對了,故附上原文~~~):

  • if there is an equivalent vectorized stock function, always use it(如果有等價的向量化命令,毫不猶豫的使用后者)
  • avoid for-loop that call function with non negligible overhead(避免在for循環(huán)中調(diào)用計(jì)算量很大的函數(shù))
  • for loop is desirable when a nested IF condition can be used to save computation time(如果for循環(huán)中有if語句,并可以因此而帶來時間的節(jié)省,那么for語句是值得試試的)
  • for loop is attractive when the result of the preceding iteration(s) can be used to save computation effort of the current calculation(如果上一次的循環(huán)得出的結(jié)果對本次循環(huán)有幫助,可以節(jié)省計(jì)算量,那么for循環(huán)是比較吸引人的)
  • using for loop is not recommended when the large data need to be duplicated inside the loop(當(dāng)循環(huán)中存在大量的數(shù)據(jù)復(fù)制時,for循環(huán)是不值得推薦使用的)
  • time it, time it and time it(不停的測試,測試不用for和用for的區(qū)別,“唯利是圖”就可以了)
  • Read Matt Fig's post!(閱讀Matt Fig的帖子!【Matt Fig是哪位大神?我沒Google,大家看看他發(fā)表了什么高見,然后告訴我一聲啊~】)
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
matlab提速技巧(自matlab幫助文件)
MATLAB主要命令匯總 -- 愛數(shù)學(xué) -- 編程愛好者博客
matlab中多組變量繪圖:plot
MATLAB的使用
MATLAB基礎(chǔ)教程 | Essential MATLAB for Engineers and Scientists
Matlab代碼的分析、優(yōu)化和加速
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服