我有以下for循环,我想要矢量化。但是,在for-loop里面我使用了circshift。有没有办法使用矢量化执行for循环,或至少优化它?它运行得很慢,因为strt,stop和M会增加它们的大小。
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
答案 0 :(得分:2)
将2D
数组M
与circshift
一起转移肯定会很昂贵。因此,一个技巧可能是转移到1D
数组v
而不是另一个方向,并保持M
不变。因此,我们只需要一个编辑来替换:
circshift(M, [0 ii])*v
与M*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.
答案 1 :(得分:2)
当您增加M
的大小时,函数circshift
将成为代码中最耗时的部分。这个时间随着规模的增加而增加。
一个有用的步骤是将circshift(M, [0 ii])*v
更改为M*circshift(v,-ii)
。请注意,它们会生成相同的tmp
,但第二个会处理v
,这只是M
的一列。
答案 2 :(得分:1)
这可以表示为2D卷积,因此此代码在Octave中进行了测试,对于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)])