我正在尝试以“矢量化”方式将大型 (2x2m) 矩阵的 (2x2) 子矩阵相乘,以消除循环并提高速度。目前,我 reshape 为 (2x2xm),然后使用 for 循环来执行此操作:
for n = 1:1e5
m = 1e4;
A = rand([2,2*m]); % A is a function of n
A = reshape(A,2,2,[]);
B = eye(2);
for i = 1:m
B = A(:,:,i)*B; % multiply the long chain of 2x2's
end
end
函数目标类似于@prod,但使用矩阵乘法而不是逐元素标量乘法。 @multiprod 看起来很接近,但将两个不同的 nD 矩阵作为参数。我想象一个解决方案,它使用一个非常大的二维数组的多个子矩阵,或一个 2x2m{xn} 数组来消除一个或两个 for 循环。
提前致谢,乔
最佳答案
我认为您必须以不同的方式 reshape 矩阵才能进行矢量化乘法,如以下代码所示。这段代码也使用循环,但我认为应该更快
MM = magic(2);
M0 = MM;
M1 = rot90(MM,1);
M2 = rot90(MM,2);
M3 = rot90(MM,3);
MBig1 = cat(2,M0,M1,M2,M3);
fprintf('Original matrix\n')
disp(MBig1)
MBig2 = zeros(size(MBig1,2));
MBig2(1:2,:) = MBig1;
for k=0:3
c1 = k *2+1;
c2 = (k+1)*2+0;
MBig2(:,c1:c2) = circshift(MBig2(:,c1:c2),[2*k 0]);
end
fprintf('Reshaped original matrix\n')
disp(MBig2)
fprintf('Checking [ M0*M0 M0*M1 M0*M2 M0*M3 ] in direct way\n')
disp([ M0*M0 M0*M1 M0*M2 M0*M3 ])
fprintf('Checking [ M0*M0 M0*M1 M0*M2 M0*M3 ] in vectorized way\n')
disp( kron(eye(4),M0)*MBig2 )
fprintf('Checking [ M0*M1*M2*M3 ] in direct way\n')
disp([ M0*M1*M2*M3 ])
fprintf('Checking [ M0*M1*M2*M3 ] in vectorized way\n')
R2 = MBig2;
for k=1:3
R2 = R2 * circshift(MBig2,-[2 2]*k);
end
disp(R2)
输出是
Original matrix
1 3 3 2 2 4 4 1
4 2 1 4 3 1 2 3
Reshaped original matrix
1 3 0 0 0 0 0 0
4 2 0 0 0 0 0 0
0 0 3 2 0 0 0 0
0 0 1 4 0 0 0 0
0 0 0 0 2 4 0 0
0 0 0 0 3 1 0 0
0 0 0 0 0 0 4 1
0 0 0 0 0 0 2 3
Checking [ M0*M0 M0*M1 M0*M2 M0*M3 ] in direct way
13 9 6 14 11 7 10 10
12 16 14 16 14 18 20 10
Checking [ M0*M0 M0*M1 M0*M2 M0*M3 ] in vectorized way
13 9 0 0 0 0 0 0
12 16 0 0 0 0 0 0
0 0 6 14 0 0 0 0
0 0 14 16 0 0 0 0
0 0 0 0 11 7 0 0
0 0 0 0 14 18 0 0
0 0 0 0 0 0 10 10
0 0 0 0 0 0 20 10
Checking [ M0*M1*M2*M3 ] in direct way
292 168
448 292
Checking [ M0*M1*M2*M3 ] in vectorized way
292 168 0 0 0 0 0 0
448 292 0 0 0 0 0 0
0 0 292 336 0 0 0 0
0 0 224 292 0 0 0 0
0 0 0 0 292 448 0 0
0 0 0 0 168 292 0 0
0 0 0 0 0 0 292 224
0 0 0 0 0 0 336 292
关于MATLAB - 在单个矩阵内矩阵乘子矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17227005/