【发布时间】:2014-10-28 11:20:49
【问题描述】:
我有两个数组A 和B 具有相同的维度1000 x 3 x 20 x 20。我想生成维度为3 x 3 x 20 x 20 的第三个数组C,这将是A 和B 的对应切片矩阵相乘的结果,即C(:,:,i,j) = A(:,:,i,j)'*B(:,:,i,j)。然后我需要通过反转相应的3 x 3 矩阵,即D(:,:,i,j) = inv(C(:,:,i,j)),将数组C 转换为新数组D。同样,很清楚如何使用循环来做到这一点。有没有办法避免循环遍历 400 项目?
编辑:比较不同解决方案性能的基准代码是 -
%// Inputs
n1 = 50;
n2 = 200;
A = rand(n1,3,n2,n2);
B = rand(n1,3,n2,n2);
%// A. CPU loopy code
tic
C = zeros(3,3,n2,n2);
for ii = 1:n2
for jj = 1:n2
C(:,:,ii,jj) = A(:,:,ii,jj)'*B(:,:,ii,jj); %//'
end
end
toc
%// B. Vectorized code (using squeeze)
tic
C1 = squeeze(sum(bsxfun(@times,permute(A,[2 1 5 3 4]),permute(B,[5 1 2 3 4])),2));
toc
%// C. Vectorized code (avoiding squeeze)
tic
C2 = sum(bsxfun(@times,permute(A,[2 5 3 4 1]),permute(B,[5 2 3 4 1])),5);
toc
%// D. GPU vectorized code
tic
A = gpuArray(A);
B = gpuArray(B);
C3 = sum(bsxfun(@times,permute(A,[2 5 3 4 1]),permute(B,[5 2 3 4 1])),5);
C3 = gather(C3);
toc
运行时结果 -
Elapsed time is 0.287511 seconds.
Elapsed time is 0.250663 seconds.
Elapsed time is 0.337628 seconds.
Elapsed time is 1.259207 seconds.
【问题讨论】:
-
哇!这是一些有用且有趣的运行时结果。谢谢!
-
另外,我忘了提到的另一件事是您需要在基准测试之前“预热”GPU。因此,实现这一目标的最简单方法是按原样运行基准测试代码并再次运行它并观察第二次运行的运行时。对 GPU 代码进行基准测试的可靠方法是使用
gputimeit,但这会使代码复杂化,因此暂时不要这样做。
标签: arrays matlab vectorization matrix-multiplication