MATLAB中代码优化的两种方法
MATLAB中的代碼優化
MATLAB中的代碼優化有兩種重要的方法:預分配組和向量化循環。
我們舉一個簡單的例子來看,創建一個MATLAB函數來計算f(x) = sin(x / 100π):
function y = sinfun1(M) x = 0: M - 1; for k = 1: numel(x)y(k) = sin(x(k) / (100 * pi)); end這里 我們使用函數timeit來計算調用函數所需的時間。(timeit可用于得到函數調用的可靠的、可重復的時間測量。)
此時我們得到M數量級為20000時的時間測量,如圖1所示:
圖1 函數sinfun1在M=20000的時間測量我們在編寫完函數sinfun1后可以看到MATLAB編輯器給出了一個提示:變量’y’似乎會隨迭代次數而改變,請預分配內存以獲得更高的運算速度。
為什么會出現這樣的情況?那是因為在sinfun1這個函數中,輸出變量y每經過一次循環后都會增長一個元素大小,它必須重新分配新的存儲空間,并且在每次數組生長時都要復制前一組數組元素。這種頻繁的內存重新分配和復制的開銷非常大,與sin本身的計算相比需要更多的時間。
此時我們采用預分配數組的辦法進行嘗試:
預分配組:是指在進入一個計算數組元素的for循環之前,初始化數組。預分配就意味著咋循環開始之前把它初始化為所希望的輸出大小。
function y = sinfun2(M) x = 0: M - 1; y = zeros(1, numel(x)); for k = 1: numel(x)y(k) = sin(x(k) / (100 * pi)); end在這里我們使用了zeros生成一個矩陣來預分配存儲空間,然后調用timeit計算M=20000時候的時間測量,如圖2:
圖1 函數sinfun2在M=20000的時間測量通過對比可以得出,在M=20000的數量級下,使用預分配數組的辦法,要比不使用運行快4倍。
接下來我們在M的數量級為200000和2000000下對兩種方法進行比較,得出的結果如圖3,圖4所示: 圖3 兩種方法在M=200000下的時間測量
圖4 兩種方法在M=2000000下的時間測量
我們通過計算可以得出,函數sinfun1基本維持了所要求的的時間與M成正比,sinfun2則在數量級到了一定程度后維持正比。另外比較兩個函數在200000和2000000下的速度比,可見在這兩個數量級下預分配數組的方法大約要比sinfun1快6倍。
向量化循環是指使用矩陣/向量運算符、索引技術和現有的MATLAB或工具箱函數來完全消除循環的一種技術。
我們使用向量化循環對矩陣的輸入進行逐元素的操作來消除循環:
function y = sinfun3(M) x = 0: M - 1; y = sin(x ./ (100 * pi)); end此時我們再用timit在M=20000時進行時間測量,如圖5:
由圖可知我們使用向量化時,在M=20000時要比預分配數組快3倍。接下來測量M的數量級為200000和2000000的時間。如圖6所示:
由此可見,不帶循環sinfun3的執行速度和帶一個循環的sinfun2的執行速度大致相同,但又略快于sinfun2。
在教材中為了為了更好地說明這個比較兩種優化方法,給出了下面這個例子。
這個例子是基于公式f(x) = Asin(u0x + v0y)創建一幅合成圖像,首先使用嵌套的for循環來計算f:
function f = twodsin1(A, u0, v0, M, N) %f = zeros(M, N); for c = 1 : Nv0y = v0 * (c - 1);for r = 1 : Mu0x = u0 * (r - 1);f(r, c) = A * sin(u0x + v0y);end end不使用預分配和使用后的執行時間如圖7所示:
我們在這里發現使用預分配前后,執行時間的差距并沒有很大。接下來來看向量化后的結果。
在實驗中使用一個meshgrid的MATLAB函數將函數重寫為沒有for循環的形式。
function f = twodsin2(A, u0, v0, M, N) r = 0 : M - 1; c = 0 : N - 1; [C, R] = meshgrid(c, r); f = A * sin(u0 * R + v0 * C);繼續用timeit測試,得到的結果如圖8:
可見使用向量化后,比使用預分配快了30%,比不使用任何優化方法快了50%。
小結
綜合以上兩個實驗表明,兩種代碼優化方法(預分配數組和向量化循環)在具體的使用中的差別并不是很大,都可以提升循環運行的速度。我們可以在遇到具體問題后,根據具體情況選擇具體的方法:若是循環存在沒有預分配內存的問題,那我們可以考慮采用預分配的方法,這樣對代碼的改動不大,更直觀,也更容易表示我們代碼得到實際工作機理;若是確定沒有預分配的問題,就可以選擇向量化循環的辦法,這樣與基于循環的代碼相比,向量化后的代碼更易于閱讀,更為簡潔。
總結
以上是生活随笔為你收集整理的MATLAB中代码优化的两种方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 博易大师 行情服务器文件,博易大师目录
- 下一篇: 数字图像处理——第三章 空间域图像增强(