2011-05-10 23 views
3

我剛纔異形我的MATLAB代碼,有一個瓶頸,在本作循環:方法,以加快循環在MATLAB

for vert=-down:up 
    for horz=-lhs:rhs 
     y = y + x(k+vert.*length+horz).*DM(abs(vert).*nu+abs(horz)+1); 
    end 
end 

其中y,x和DM是我已經定義的向量。我通過書寫向量化了循環,

B=(-down:up)'*ones(1,lhs+rhs+1); 
C=ones(up+down+1,1)*(-lhs:rhs); 
y = sum(sum(x(k+length.*B+C).*DM(abs(B).*nu+abs(C)+1))); 

但是,這樣做的速度足夠慢。

有沒有關於如何加快這個循環的建議?

在此先感謝。

+0

什麼是「向下」,「向上」,「LHS」,「RHS」和「NU 「? ..與y,x,DM有任何關係嗎?或..你能給我更多的數學解釋你想做什麼? – Efrain 2011-05-10 12:30:25

+0

我很確定你的向量化操作不會和for循環做同樣的事情。你獲得了相同的結果嗎? – Phonon 2011-05-10 13:05:23

+0

@Efrain,我不確定我們在這裏需要更多的數學細節。問題只是關於代碼的計算複雜性,而不是其語義意義。 – Phonon 2011-05-10 13:06:21

回答

4

你所做的並不是真正的矢量化。在Matlab中爲圖像處理編寫適當的矢量化程序(我假定你正在做這些)是非常困難的,如果不是不可能的話。當我們使用術語矢量化的時,我們的意思是「矢量化,沒有額外的計算」。例如,該代碼

a = 1:1000000; 
for i = a 
    n = n+i; 
end 

將運行慢得多那麼這段代碼

a = 1:1000000; 
sum(a) 

更新:上面的代碼進行了修改,感謝@ RASMAN的敏銳建議。原因是在運行之前,Matlab不會將編譯爲您的代碼轉換爲機器語言,這就是導致它變慢的原因。像summean.*這樣的內置函數在幕後運行預編譯的C代碼。 For循環是一個非常好的代碼示例,它在未針對CPU寄存器進行優化時運行緩慢。

你做了什麼,並且請忽略我的第一條評論,正在用矢量操作重寫你的程序一些額外的操作。這些操作會佔用額外的CPU,因爲您要讓計算機執行更多計算,即使每次計算可能會(或不會)花費更少的時間。

如果你真的在加速你的代碼後,看看MEX files。它們允許您編寫和編譯C和C++代碼,編譯它並像Matlab函數一樣運行,就像那些快速內置函數一樣。無論如何,Matlab並不是一個快速的通用編程平臺,而是一個計算機模擬環境,儘管近些年來這種方法一直在發生變化。我的建議(從經驗)是,如果你做圖像處理,你會寫循環,而且很少有解決方法。矢量運算是爲線性代數問題的一種更直觀的方法而編寫的,我們很少將數字圖像視爲正則矩陣來處理它們。

我希望這會有所幫助。

+2

'sum(1:10000000)'實際上需要更長的時間,因爲Matlab首先分配內存。比較'sum(1:10000000)'到'sum(a)'的時間,其中'a'已經被預定義爲'a = 1:10000000',你會得到更接近你想要的東西的東西說 – Rasman 2011-05-10 14:05:48

+0

非常好的一點。謝謝。將更新我的迴應。 – Phonon 2011-05-10 14:16:08

0

我會用矩陣處理圖像時......你可以再嘗試提取小矩陣,像這樣:

X = reshape(x,height,length); 
kx = mod(k,length); 
ky = floor(k/length); 

xstamp = X([kx-down:kx+up], [ky-lhs:ky+rhs]); 
xstamp = xstamp.*getDMMMask(width, height); 
y = sum(xstamp); 

... 

function mask = getDMMask(width, height, nu) 
% I don't get what you're doing there .. return an appropriate sized mask here. 
return mask; 
end