2011-04-08 88 views
2

當我在MatLab中執行這些等效操作時,第一個運行時間爲24.158371秒(for循環)。第二次運行在0.004976秒(邏輯索引)。 MatLab可能會做些什麼讓這個運行速度更快?這仍然是O(n)時間,對吧?這爲什麼這麼快?

t = linspace(-2*pi,2*pi,100000); 
fd = 1e3; 
tau = 1e-6; 


% Calculate arbitrary function using a loop 
tic 
for tind = 1:length(t) 
    tester(tind) = cos(2*pi*fd*t(tind))/(2*pi*fd.*t(tind)); 
end 
toc 

pause; disp('Press a key'); 
% Same calculation with logical indexing 
tic 
tester2 = cos(2*pi*fd.*t)./(2*pi*fd.*t); 
toc 
+1

您的第一個循環代表了與第二個循環相同的更高層次的方法;即腳本看起來並不是最優化的。 – ThomasRS 2011-04-08 01:02:25

+0

這證實了Matlab循環吸吮的事實,如果有任何使用矩陣的方法,應該避免像瘟疫一樣。 – Reinderien 2011-04-08 01:10:25

+3

@Reinderien - 不,你錯了。循環中的問題是,tind從未被預分配。所以發生的每一次都是通過循環,數組tind必須在內存中重新分配。 – 2011-04-08 11:10:58

回答

5

您的第一個循環中最大的成本實際上來自動態調整數組大小tester。每次通過循環時,Matlab必須將現有陣列複製到內存中的新位置,並留出額外元素的空間。所以,對於循環的每次迭代來說,這是一個O(n)操作。如果您預先分配數組,它將運行得更快,例如

tic 
tester = zeros(100000,1); 
for tind = 1:length(t) 
    tester(tind) = cos(2*pi*fd*t(tind))/(2*pi*fd.*t(tind)); 
end 
toc 

在我的系統,我得到11.3秒原始循環,0.0013秒的矢量版本0.010秒,以用於預分配爲tester內存循環。值得一提的是,其他許多具有可調整大小的數組的語言會根據數組的當前大小分配額外的空間塊,因此通過每次追加一個元素來構建數組的成本僅爲O(n log n) ,所以這是Matlab的一個特殊缺陷。

5

MATLAB的R2011a版本使得這種事情更快(什麼?你還沒有得到該版本嗎?下載!),請參閱release note。在我的機器上,第一個循環需要0.02秒,第二個循環需要0.004秒。所以,預先分配仍然是一個好主意,但如果你不能做到這一點,你就不會處在一個非常糟糕的地方。