測試
利用MATLAB 2013b我和英特爾至強3.6GHz的+ 16GB RAM我跑到下面的代碼來分析。我區分了3種方法,只考慮了1D陣列,即矢量。已經使用列向量和行向量(即(n,1)和(1,n))對方法1和2進行了測試。
方法1(M1R,M1C)
a = zeros(1,n);
方法2 M2R,M2C
a = NaN(1,n);
方法3(M3)
a(n) = 0;
結果
定時結果和元素數已繪製在圖時間間隔d的可變對數尺度。
如圖所示的第三方法具有幾乎分配獨立矢量的大小,而另一穩定地增加暗示矢量的隱式定義。
討論
MatLab的不使用JIT(準時)大量的代碼優化,即優化代碼在運行時。因此,提出運行速度更快的代碼是否由於編程(無論優化是否相同)還是優化,都是一個有效的問題。要測試此優化可以通過使用功能('accel','off')關閉。運行代碼的結果再次是相當有趣:
結果表明,現在方法1是最優的,既爲行和列向量。方法3的行爲與第一個測試中的其他方法相似。
結論
優化內存預分配是無用的,MATLAB自浪費時間,無論如何都會優化爲您服務。
請注意,應該預先分配內存,但是您的操作方式並不重要。預分配內存的性能在很大程度上取決於MatLab的JIT編譯器是否選擇優化代碼。這完全依賴於.m-file的所有其他內容,因爲編譯器當時會考慮代碼塊,然後嘗試優化(它甚至有一個內存,因此多次運行文件可能會導致執行更低)時間)。考慮到性能與後來執行的計算相比,內存預分配通常是非常短的過程
在我看來,內存應該通過使用方法1或方法2來預先分配,以保持可讀代碼並使用函數MatLab幫助建議,因爲這些將來最有可能得到改進。
代碼使用
clear all
clc
feature('accel','on')
number1D=30;
nn1D=2.^(1:number1D);
timings1D=zeros(5,number1D);
for ii=1:length(nn1D);
n=nn1D(ii);
% 1D
tic
a = zeros(1,n);
a(randi(n,1))=1;
timings1D(1,ii)=toc;
fprintf('1D row vector method1 took: %f\n',timings1D(1,ii))
clear a
tic
b = zeros(n,1);
b(randi(n,1))=1;
timings1D(2,ii)=toc;
fprintf('1D column vector method1 took: %f\n',timings1D(2,ii))
clear b
tic
c = NaN(1,n);
c(randi(n,1))=1;
timings1D(3,ii)=toc;
fprintf('1D row vector method2 took: %f\n',timings1D(3,ii))
clear c
tic
d = NaN(n,1);
d(randi(n,1))=1;
timings1D(4,ii)=toc;
fprintf('1D row vector method2 took: %f\n',timings1D(4,ii))
clear d
tic
e(n) = 0;
e(randi(n,1))=1;
timings1D(5,ii)=toc;
fprintf('1D row vector method3 took: %f\n',timings1D(5,ii))
clear e
end
logtimings1D = log10(timings1D);
lognn1D=log10(nn1D);
figure(1)
clf()
hold on
plot(lognn1D,logtimings1D(1,:),'-k','LineWidth',2)
plot(lognn1D,logtimings1D(2,:),'--k','LineWidth',2)
plot(lognn1D,logtimings1D(3,:),'-.k','LineWidth',2)
plot(lognn1D,logtimings1D(4,:),'-','Color',[0.6 0.6 0.6],'LineWidth',2)
plot(lognn1D,logtimings1D(5,:),'--','Color',[0.6 0.6 0.6],'LineWidth',2)
xlabel('Number of elements (log10[-])')
ylabel('Timing of each method (log10[s])')
legend('M1R','M1C','M2R','M2C','M3','Location','NW')
title({'Various methods of pre-allocation in 1D','nr. of elements vs timing'})
hold off
注
含有c(randi(n,1))=1
的線;除了賦值給預分配數組中的一個隨機元素之外,不要做任何事情,以便數組用於挑戰JIT編譯器。這些線路不會顯着影響預分配測量,即它們不可測量,不會影響測試。
這很有趣。我認爲也許MATLAB不會初始化零,直到矩陣的修改完成(類似於matlab如何複製矩陣),而是「抽象的; a = NaN(1e4); a(1)= 1; toc'確實比'tic慢; a =零(1e4); a(1)= 1; toc'在我的機器上。就像剛纔那樣,我真的只看到用'零'完成的預分配,所以我很肯定沒有一種方法可以在沒有初始化的情況下進行預分配,除非你要製作一個mex例程,但也許這裏的其他人會知道。 – Justin
這正在快速成爲一個Matlab常見問題,這個問題的各個方面已經在這裏介紹了。其他地方,比如在無價的Matlab博客 - http:// undocumentedmatlab上。com/blog/allocation-performance-take-2 /#more-4086隨着Matlab的發展,各種方法的相對速度似乎會改變。 –
@Shai這是關於預分配方法的性能,而不是關於預分配的需要。請停止關閉這樣的問題。 – EJG89