2012-11-19 106 views
2

我已經在matlab中編寫了一個小循環來生成一個隨機NxN矩陣。循環是for循環中的計算速度

tic 
for i=1:10000 
    u=rand(1,10000); 
    tau(i,:)=d.*(u(1,:)-0.5); 
end 
toc 

我第一次嘗試循環程序只有一次,

u=rand(1,10000); 
    tau=d.*(u(1,:)-0.5); 

這給了我頭在0.000169秒。我認爲循環將花費大約1.69s。它沒有,它花了555.018280s與球迷瘋狂。

有沒有
a)速度與迭代次數沒有線性關係的原因是什麼?
b)原因爲什麼它需要所以更長的時間做很多次例程
c)一種方法來加速這一個(我實際上想生成更大的矩陣),例如一個更好的循環或方式比如說給我一個同樣類型的1'000'000x1'000'000的矩陣?

+2

嘗試預先分配'tau'。 – Junuxx

+1

有一個名爲「加速MATLAB應用程序」的網絡研討會。有關於大矩陣的一些信息以及如何處理它們。 https://www.mathworks.com/company/events/webinars/wbnr49643.html?id=49643&p1=961666025&p2=961666043 – HebeleHododo

回答

7

你必須先預分配的矩陣tau,即

tau = zeros(10000,10000); 

否則MATLAB將繼續在地區哪裏有足夠的可用內存(重新分配它=>找到足夠自由的空間區域+硬拷貝)。

一般情況下,你會獲得更好的性能矢量化的全過程:

u=rand(10000,10000); 
tau=d.*(u-0.5); 

編輯:首先,聽羅迪的在下面的評論中明智的建議。 (在任何情況下,我想假設rand(a,b)將運行比a連續執行rand(1,b)快一點)。

+1

更好地防止雙內存分配(注意,「u」是800兆字節):'tau = d *(蘭特(10000)-0.5)'。或者,如果size(d)== [1 10000]',使用'tau = bsxfun(@times,d,rand(10000)-0.5)'。峯值內存仍然相同,但是,在分配之後,釋放了800MB的1.6GB峯值。或者:之後只需發出一個清晰的u。 –

+0

@RodyOldenhuis因此,重點是做'tau = d。*(rand(10000,10000)-0.5);',對嗎?順便說一句,是'bsxfun'版本更快嗎? – Acorbe

+0

可能不會更快,但它適用於'd'的大小隻適用於循環解決方案('size(d)== [1 10000]') –

0

一個明顯的可能性是內存訪問量。測試循環的內存可能完全處於高速緩存中,但由完整循環寫入的內存需要大量內存訪問。

這是一個可測試的假設:編寫整個矩陣的時間,而不是算術。

如果我理解Matlab索引,可能會更快地切換維度,以便寫入同一列中的塊而不是同一行中的塊。將u轉換爲循環外的列向量也可能有所幫助。一般來說,應儘可能按記憶順序進行大矩陣訪問。