標籤:

MATLAB裡面有哪些加快程序運行速度的方法呢,求分享?

MATLAB裡面有哪些加快程序運行速度的方法呢,求分享?


各位答主說的很好,我補充一個最方便的方法:

安裝最新版本的MATLAB!

MATLAB的運算速度越來越快了, 特別是R2015b以後換了新的運算引擎。

舉一個面向對象編程的例子:

classdef myclass
properties
Prop1 = 20;
end
methods
function out = method1(obj)
out = obj.Prop1 * 10;
end
end
end

測試腳本

tic;
for i = 1:10^5
m = myclass;
end
toc;
tic;
for i = 1:10^5
method1(m);
end
toc;
tic;
for i = 1:10^5
m.method1();
end
toc;

分別在R2013a,R2016a, R2016b上測試:

R2013a
Elapsed time is 3.016981 seconds.
Elapsed time is 1.144438 seconds.
Elapsed time is 1.649474 seconds.

R2016a
Elapsed time is 4.020194 seconds.
Elapsed time is 0.083297 seconds.
Elapsed time is 0.088005 seconds.

R2016b
時間已過 0.801935 秒。
時間已過 0.069980 秒。
時間已過 0.074639 秒。

速度提升明顯!


1. 向量化。養成看到for就渾身不舒服的本能反應。

2. 矩陣如果太大了會爆內存則千萬別向量化,老老實實用循環吧。有些3-4緯的矩陣,用循環處理起來甚至快一些。

3. 循環豎著走比橫著走快。

4. 不少內置函數都有大量的error check。直接用profiler找出真正幹活的。

5. 不少內置函數在網上都有人提供了更快的版本的,當然功能弱一些,正好符合提速的需求。

6. 視情況,有時可以把變數強行變成single,速度暴增。

7. 利用copy on write的特點,丟進函數的變數能不對其修改就不要修改。

8. matlab就是個高級計算器,不要拿干來處理文件,往資料庫里塞數據這種活。eval, object之類的東西能別碰就別碰,盡量保持著every is an array of double的模式。

9. 不要把代碼全塞到一行。不但難看有時候還慢一些。


1. 減少循環的使用

有很多for循環都可以用矩陣操作簡化,比如下例:

a = rand(1, 100);
b = zeros(1, 100);
for n = 1:100
if n == 1
b(n) = a(n);
else
b(n) = a(n-1) + a(n);
end
end

可以用矩陣操作

a = rand(1, 100);
b = [0 a(1 : end-1)] + a;

非常簡單實現。

相關官方文檔:Vectorization

2. 預先定義好變數的維度

類似於數組的變數都是連續存放在內存里,如果每次賦值時都要change size的話,MATLAB只好重新找一塊連續的內存放這些數據,增加了數據在內存里不必要的讀取存儲。

3. 並行處理

這部分我還不是太懂,等用熟練了回來填坑。

4. 使用函數句柄

(2016.03.22 更新修正:這個說法是以前在一個博客看到的 感謝@高樹華指出並沒有權威依據支持。剛才我查了一下官方文檔,的確沒有提到function handle可以提高運行速度的優點,所以此條存疑,可信度不大。謝謝指出! )

對於經常需要調用的函數,使用句柄可以提高運行速度。因為MATLAB每次對函數的調用都要搜索所有的路徑。

例如,我們需要經常調用如下函數:

% f.m
function y=f(x)
y=acos(x);

可以使用句柄,寫成

f=@(x)acos(x)

5. 其它

剩下還有一些小細節,想到或者遇到隨時更新。

5.1

對於矩陣方程 Ax=b

如果方程有唯一解,不要使用

x = inv(A) * b

使用

x = A b

速度遠快於第一種方法,尤其在矩陣規模較大時。(多謝 @芷菡 提醒改正了一個typo)

5.2

矩陣中如果有很多0,請一定使用sparse,將會大大提高運行速度。

具體參見官方文檔:Computational Advantages of Sparse Matrices

有錯誤歡迎指正討論~


別寫循環,固定維度,善用稀疏(spdiags騷的一比),善用算重載(自帶的)。

對Q系:使用更好的離散化方案,使用方差縮減,動態規劃寫矩陣形式,學習各種騷氣的矩陣生成法(像什麼對數三角,泊松三角,卡方替換,布朗橋,都是最騷的,我才不會告訴你們呢~)

高階(還沒去全會):學會玩兒四維以上方塊,學會對特定維度使用「二向箔」,巧用個各種維度的三角矩陣,巧用矩陣分解,巧用張量積,妙用@,巧用char和double之間的轉換,沒事別開table,沒事別開元胞(元胞是真尼瑪傷)

大招:下新版(逃@李海濤

最後跟我念:

矩陣邪教,滅世方塊,一統天下,文成武德


--(生產更高效的代碼)--

先說個奇技淫巧:除法的開銷比乘法大很多 所以常用的比如frac{1}{pi}  frac{1}{e} frac{1}{sqrt{2}}這些如果算的時候用到的多的話先算出來具體數要用到的時候直接乘上,會有明顯加速的,這種無痛加速不搞白不搞。

評論區有說有內部優化乘法除法速度差不多,本人一向專治各種不服:【MATLAB 2016a】

u2=rand(12000);
u1=rand(12000);

num_all=300;
r1=ones(1,num_all);
r2=ones(1,num_all);

for k=1:num_all
tic; u1.*u2.*u2; r1(k)=toc;
tic; u1./u2./u2; r2(k)=toc;
end

對於多次計算的時間統計一下分布情況結果是:

將近二倍的區別所以說 如果有些數字的除法真的很常用又在程序運行的關鍵節點上,做這一步優化還是非常有意義的

對於一個程序要找出關鍵節點進行重點優化,比如說一個程序里的某種矩陣操作,大部分運算都能用到,那麼這個就是關鍵節點,要重點優化。

matlab提供了一個叫做profile的函數,可以記錄程序在各個模塊消耗的時間統計出來給優化提供參考(如圖)

然後是優化的一個大殺器是並行

軟體本身是有個parallel computing toolbox 最簡單的並行parfor就是for循環如果前後耦合性不強的話可以通過分配給多個worker來實現概念上的並行,提高效率

GPU加速

有核彈當然要用(matlab僅僅支持NVIDIA顯卡的GPU加速)

其實這是最有效的(對於大矩陣的運算)還是GPU運算,(首先你得有個n卡),因為GPU的流處理器個數遠多於CPU核心數,所以並行如果可以放到顯卡里對運算的優化使顯而易見的

下圖是一個benchmark可見GPU在加速計算方面的效果是極其顯著的

而對於gpu優化計算,水就更深了

而對於gpu優化計算 水就更深了

可以幾行代碼就實現簡單的優化

也可以深度優化

一個栗子:

算分型的栗子:

% Setup
t = tic();
x = linspace( xlim(1), xlim(2), gridSize );
y = linspace( ylim(1), ylim(2), gridSize );
[xGrid,yGrid] = meshgrid( x, y );
z0 = xGrid + 1i*yGrid;
count = ones( size(z0) );

% Calculate
z = z0;
for n = 0:maxIterations
z = z.*z + z0;
inside = abs( z )&<=2; count = count + inside; end count = log( count ); % Show cpuTime = toc( t );

用cpu要算5.8s如果做一些微小的修改:

count = ones( size(z0), "gpuArray" );

就多了一句話 24倍優化,解釋一下,這個在聲明變數的時候加一個gpuarray就相當於是吧變數從host memory轉成gpu memory然後後面的計算都是GPU資辭的。所以大部分計算都是GPU內計算當然是比西方記者還快。

就多了一句話 24倍優化,解釋一下,這個在聲明變數的時候加一個gpuarray就相當於是吧變數從host memory轉成gpu memory然後後面的計算都是GPU資辭的。所以大部分計算都是GPU內計算當然是比西方記者還快。如果覺得這還不夠的可以用arrayfun加速:

count = arrayfun( @pctdemo_processMandelbrotElement, ...
xGrid, yGrid, maxIterations );

原理上就是host並行加gpu並行matlab支持cuda就當然會支持寫device碼編譯進GPU作為一個模塊調用(太麻煩但是效果極其顯著)

__device__
unsigned int doIterations( double const realPart0,
double const imagPart0,
unsigned int const maxIters ) {
// Initialize: z = z0
double realPart = realPart0;
double imagPart = imagPart0;
unsigned int count = 0;
// Loop until escape
while ( ( count &<= maxIters ) ((realPart*realPart + imagPart*imagPart) &<= 4.0) ) { ++count; // Update: z = z*z + z0; double const oldRealPart = realPart; realPart = realPart*realPart - imagPart*imagPart + realPart0; imagPart = 2.0*oldRealPart*imagPart + imagPart0; } return count; }

device碼是c在cuda的規範下寫的

540倍啊 啊啊啊 啊啊啊啊 是吧,別再說matlab慢了,會用就快了

【matlab本來已經很快】最後貼一個benchmark這個是julia官網的比較常用的幾個模塊的測試

matlab僅僅在parseint的過程中顯得很弱因為它數據轉換的形式的複雜性,從文本到數的轉換慢是可以理解的,在其他幾個計算的硬菜上matlab表現還都是非常出色的,甚至有超過fortran的,matlab對矢量化支持非常好,對於矢量元素操作是自動並行的,所以能用向量表示的就用向量表示,親眼見過搞圖像處理的matlab小白為了把兩段視頻疊加起來開了四層嵌套大循環跑了幾個小時然後大罵matlab慢的跟翔一樣。

matlab是解釋型的,相當於是編譯一句執行一句,所以循環是最坑的執行幾遍要編譯幾遍,當然現在也有優化,但是為了保證語言特性的靈活,沒有變成編譯語言。所以寫程序之前默念三句話【我不寫循環】【矢量化大法好】【GPU大法好】,這是最基礎的。沒有矢量化那簡直就是c的語言特性加python的速度


提前定義變數維度。


我講profiler里看不出來的

1.減少語句分析

matlab是解釋性語言,語法分析會耗時,生成目標文件p文件能加快好多

命令

pcode XXX.m

會生成XXX.p

運行時會自動調用p文件,不需要內存再把m文件逐句解釋一遍了,會大大提高運行速度

2.用句柄函數

搜索也很費事,所以多用句柄函數和內在函數

搜索速度如下:

句柄函數>內在函數>當前目錄函數>其它目錄函數

調用方法:

比如

ans=feval("@fun",傳入變數1,....)

ans=fun(args)

運行速度快的多

編譯的時候,句柄函數會直接把路徑給內存了,不會執行全路徑搜索

最近在數學建模,大家一起進步吧


多跟matlab內置的公開的m函數學習


1、盡量使用矩陣運算

2、某些部分考慮使用mex


向量化編程,少用或者不用for循環


福利歸納-任何引擎搜索:write fast matlab code。

有搜不到的聯繫我或留郵箱,直接發。


m語言中盡量少調用simulink,sim函數很費時間。

或者直接用c寫程序,用mex編譯之後在Matlab里調用。


新版本下並不是所有情況下的向量化都比循環快 要看具體問題 預分配內存 或者叫提前設定變數維度是可以提高速度 另外巧用嵌套函數和匿名函數很多時候有奇效


別用循環,用矩陣


少用find,多用logical

一個用logical幾秒完事的程序,我用find愣是跑到台式機掛,筆記本黑屏...

第一次體會到優化代碼效率的重要性


用c語言實現複雜循環部分,用SIMD進一步優化循環部分。


1. pre-allocation

2. 用build-in function而不是自己寫的function

3. 用最新版本

4. 向量化。但是其實新版本for loop已經差不多速度了

5. 演算法設計。其實for loop一點都不慢,但是你每一步都要引用一個很大的方程就很慢了(Regress, ARICH, etc.)慢可不能怪到for loop

6. parallel computing. eg, parfor

7. profiler analysis


feature jit off


1.向量化

2.無法向量化的,寫一小段c,mex編譯執行


用並行,矩陣,少用循環,可以看下這位作者的文章:

http://blog.163.com/cd_keanu/blog/static/31274952010730114358492/


避免符號運算,轉化為離散的數值運算,初學者最容易犯的錯誤


拿fortran或者c重寫,然後放到超級計算機上?


1. 能用矩陣的就用矩陣,用矩陣函數減少循環出現。

2. 改進演算法,估算內存使用量,避免太大的數據處理,MATLAB有些版本內存超過一定限制會導致死機 (e.g. GD-&>SGD)。

3. 少用simulink。

4. 某些領域追求速度請用C, (e.g. CV: MATLAB-&>opencv)


推薦閱讀:

為什麼很多計算機專業碩士生論文編程都是用MATLAB做的,僅僅是科學計算方面的優勢嗎?
Matlab 2018a 比2017b有哪些改進?
如何快速重寫一份你不了解 組織較差的代碼?(算是代碼整理吧)
為什麼同樣的C++函數,在matlab混合編程中調用,和直接在VS2010中調用,計算結果不一致?
用於數學建模 安裝matlab 2014 需要安裝哪些組件?

TAG:MATLAB |