Matlab:元素3D矩阵乘法

时间:2013-02-27 00:55:14

标签: matlab

我有两个矩阵:大小为B的{​​{1}}和大小为9x100x51的{​​{1}}。我想将K的所有34x9x100乘以K(34)中的每一个,以便得到一个大小为B(9)的最终矩阵G

例如:元素34x9x100x51的组成如下

G(:,5,60,25)

我希望这个例子有助于理解我想要做的事情。 谢谢

2 个答案:

答案 0 :(得分:3)

每当你发现自己在matlab中编写嵌套循环时,你很有可能使用内置的矢量化函数来加速。代码最终通常也会缩短(但读者通常不太清楚,所以请注释您的代码!)。

在这种情况下,避免嵌套循环会有所作为吗?绝对!让我们开始工作吧。 @slayton提供了一个3循环解决方案。我们可以加快速度。

稍微重述一下问题,B有51 9x100个矩阵,K有34 9x100个矩阵。对于51x34的每个组合,您希望以元素方式乘以9x100B的相应K矩阵。

元素乘法对bsxfun来说是一个很好的工作,因此我们可以从概念上将此问题简化为沿着两个维度(B的第三维,K的第一维)。 :

初始,双循环解决方案:

B = rand(9,100,51);
K = rand(34,9,100);
G = nan(34,9,100,51);

for b=1:size(B,3)
    for k=1:size(K,1)
        G(k,:,:,b) = bsxfun(@times,B(:,:,b), squeeze(K(k,:,:)));
    end
end

好的,两个循环正在取得进展。我们可以做得更好吗?好吧,让我们认识到矩阵BK可以沿着适当的维度进行复制,然后逐个元素倍增。

B = rand(9,100,51);
K = rand(34,9,100);

B2 = repmat(permute(B,[4 1 2 3]), [size(K,1) size(B)]);
K2 = repmat(K, [size(K) size(B,3)]);

G = bsxfun(@times,B2,K2);

那么,解决方案如何快速比较?我测试了八度音阶在线实用程序,但没有包括生成初始BK矩阵的时间。我确实包含了为需要预分配的解决方案预分配G矩阵的时间。代码如下。

3个循环(@ slayton的答案):4.024471 s
2循环解决方案:1.616120 s
0循环repmat / bsxfun解决方案:1.211850 s
0循环repmat / bsxfun解,没有临时值:0.605838 s

警告:时机可能在很大程度上依赖于您的机器,我不相信在线实用程序可以进行精确的时序测试。改变循环执行的顺序(甚至注意不重用变量和分配时间)确实改变了一些事情,即2循环解决方案有时和存储临时值的无循环解决方案一样快。但是,你可以得到的矢量化越多,你就会越好。

以下是速度测试的代码:

B = rand(9,100,51);
K = rand(34,9,100);

tic
G1 = nan(34,9,100,51);

for ii = 1:size(B,1)
  for jj = 1:size(B,2);
    for kk = 1:size(B,3)
      G1(:, ii, jj, kk) = K(:,ii,jj) .* B(ii,jj,kk);
    end
  end
end
t=toc;
printf('Time for 3 loop solution: %f\n' ,t)

tic
G2 = nan(34,9,100,51);

    for b=1:size(B,3)
        for k=1:size(K,1)
            G2(k,:,:,b) = bsxfun(@times,B(:,:,b), squeeze(K(k,:,:)));
        end
    end
t=toc;
printf('Time for 2 loop solution: %f\n' ,t)
tic

B2 = repmat(permute(B,[4 1 2 3]), [size(K,1) 1 1 1]);
    K2 = repmat(K, [1 1 1 size(B,3)]);

    G3 = bsxfun(@times,B2,K2);
t=toc;
printf('Time for 0-loop repmat/bsxfun solution: %f\n' ,t)

tic

    G4 = bsxfun(@times,repmat(permute(B,[4 1 2 3]), [size(K,1) 1 1 1]),repmat(K, [1 1 1 size(B,3)]));
t=toc;
printf('Time for 0-loop repmat/bsxfun solution, no temporaries: %f\n' ,t)


disp('Are the results equal?')
isequal(G1,G2)
isequal(G1,G3)

Time for 3 loop solution: 4.024471
Time for 2 loop solution: 1.616120
Time for 0-loop repmat/bsxfun solution: 1.211850
Time for 0-loop repmat/bsxfun solution, no temporaries: 0.605838
Are the results equal?
ans =  1
ans =  1    

答案 1 :(得分:0)

您可以使用嵌套循环执行此操作,但它可能不会非常快:

B = rand(9,100,51);
K = rand(34,9,100);

G = nan(34,9,100,51)

for ii = 1:size(B,1)
  for jj = 1:size(B,2);
    for kk = 1:size(B,3)
      G(:, ii, jj, kk) = K(:,ii,jj) .* B(ii,jj,kk);
    end
  end
end

这是漫长的一天,我的大脑有点油腻,对任何可以改善这一点的人都感到荣幸!