2013-12-10 65 views
1

我能夠得到矢量化這個for循環的幫助,但如果我嘗試運行它時,array1/xfreq_orig有500,000行或t_rebuilt有500,000我跑了我跑出來的公羊我有16gig。加速循環,因爲我向量化時內存不足

array1=[xfreq_orig,yamp_orig,yamp_inv,phase_orig] %frequency, amplitudes, phases to use 
t_rebuilt=linspace(0,2*pi,44100) 


aa_sig_rebuilt_L=zeros(1,length(t_rebuilt)); 
aa_sig_combined_L=zeros(1,length(t_rebuilt)); 
sig_full_L=zeros(1,length(t_rebuilt)); 

for kk=1:1:numel(xfreq_orig); 

    aa_sig_rebuilt_L = array1(kk, 2)*cos ((array1(kk,1))*t_rebuilt+(array1(kk, 4))); 
    aa_sig_combined_L = aa_sig_combined_L + aa_sig_rebuilt_L; 

end 

sig_full_L=(aa_sig_combined_L/max(abs(aa_sig_combined_L))*.8); 

這裏是向量化版本,但我用完存儲器時ARRAY1/xfreq_orig行的是大像500000或者如果t_rebuilt是大陣列等t_rebuilt = linspace(0,2 * PI, 544100

a = array1; 
t = t_rebuilt; 

aa_sig_rebuilt_L = bsxfun(@times, a(:,2) , ... 
        cos(bsxfun(@plus, bsxfun(@times, a(:,1), t), a(:,4)))); 

aa_sig_combined_L = sum(aa_sig_rebuilt_L); 

這就是爲什麼從克里斯·泰勒答案的解釋。 「請記住,這將使用比循環更多的內存(它將使用numel(xfreq_orig)乘以更多的內存,因爲它在對它們進行求和之前計算aa_sig_rebuilt_L的每一行,而循環計算每一行,並將其添加到總和然後丟棄它)。「

vectorizing a matlab/octave FOR loop

有沒有人對如何加快for循環起來,因爲如果我vectorise它,我會用盡內存有什麼建議?有另一種方式來vectorise它,所以我不會出來的內存使用大量行的時獲得陣列1/xfreq_orig運行或t_rebuilt

回答

2

是的,這就是bsxfun(三次!)可能不是個例一個好主意。有時候人們對Matlab中循環的偏執看起來太過分了。他們是完美的罰款,如果在適當的情況下使用可以比其他選項在許多情況下更快(並有很好的可讀性)。更新方程和遞歸關係,就像系統一樣,這個系統可以更好地用for循環實現。如果你計算循環和較小輸入的代碼,你會發現它們非常相似。

您正在做的是在代碼中看起來像很多不必要的分配。例如,aa_sig_rebuilt_Lsig_full_L不需要預先分配。它們將在初始化時自動分配。您還從較小的陣列構建了一個大陣列array1,並在for循環的每次迭代中執行二維索引。那些人會清理你的代碼,也許會稍微加快速度,但實際上你會從擺脫臨時變量aa_sig_rebuilt_L並將所有內容放在一行中獲得最大的加速。這不應該與JIT編譯一起工作,但有時候確實如此。這裏是我的版本:

t_rebuilt = linspace(0,2*pi,544100); 
aa_sig_combined_L1 = zeros(1,length(t_rebuilt)); 
for i=1:length(xfreq_orig); 
    aa_sig_combined_L1 = aa_sig_combined_L1 + ... 
     yamp_orig(i)*cos(xfreq_orig(i)*t_rebuilt+phase_orig(i)); 
end 

它仍然需要一段時間來我的機器上運行,但你不應該耗盡內存,除非你的代碼的其他部分已經使用它(與whos檢查)。如果您確實內存不足,可以嘗試使用clearin Octave)明確清除大量未使用的變量。除此之外,您可以探索使用mex編寫代碼或使用codgen自動將函數輸出到可從Matlab調用的C代碼。在Octave中:Dynamically Linked Functions – Oct-Files and Mex-Files

2

一方面,您希望使用Matlab矢量化,即使用所有數據。另一方面,你不能這樣做,因爲你沒有足夠的內存。即使你有足夠的空間,分配大量的RAM也會導致你的計算速度變慢。

其中一個解決方案是將數據拆分成部分,從磁盤加載相關部分,並對其進行矢量化計算。你可以用這個參數來玩一下,看看什麼會產生最好的性能。