2016-09-20 150 views
3

我有以下for循環,我想矢量化。但是,在for循環中,我使用了circshift。有沒有辦法使用矢量化來執行for循環,或者至少優化它?它的運行速度非常緩慢,停止和M增加它們的大小。MATLAB:矢量化for循環包含circshift

indx = 0; 

M = magic(16); 
v = M(:,1); 

strt=-5; 
stop=+5; 

result = zeros(4, length(strt:stop), 4); 
for ii=strt:stop 
    tmp = circshift(M, [0 ii])*v; 
    tmp = tmp/norm(tmp); 

    indx = indx+1; 
    result(:, indx, :) = reshape(tmp(:,1), 4,4); 
end 
+1

其大概[-5; 5]正確? – Finn

+0

@Finn是的,我改變了它 – BillyJean

回答

2

搬那個巨大2D陣列,Mcircshift肯定是昂貴的。所以,一個技巧可能是改變1D陣列v而不是另一個方向並保持M原樣。所以,我們只需要一個編輯來替換:

circshift(M, [0 ii])*vM*circshift(v,-ii)

M(2500 x 2500)與我的目的原來和提出的方法大小的數組的運行時間分別爲 -

----------------------- With Original approach 
Elapsed time is 0.803823 seconds. 
----------------------- With Proposed approach 
Elapsed time is 0.137444 seconds. 
+0

嗯,我想我是遲了1分鐘;) – erfan

+0

@erfan是的,但我想我們都有好主意;) – Divakar

2

當你增加M大小,功能circshift成爲最耗時的部分代碼。這一次隨着大小而增加。

一個有用的步驟是將circshift(M, [0 ii])*v更改爲M*circshift(v,-ii)。請注意,它們產生相同的tmp,但第二個處理v,這只是M的一列。

1

這可以被表示爲2D卷積,所以該代碼在八度測試,Matlab的需要一些改變,在評論解釋:

%temp created however order of column reversed relative to your 'tmp' 
temp=conv2([M M(:,1:10)] , circshift(flipud(v).', [0 , 5]),'valid'); 
%only availabe in Octave. Norm of columns computed . In Matlab use for loop to compute norm of each column 
nrm=norm(temp,'cols'); 
%divide temp by norm 
temp = bsxfun(@rdivide,temp,nrm); 
% The result. Order of slices reversed 
result = reshape(temp,[4,4,size(temp,2)])