从两个2d矩阵中获取许多3d矩阵(逐列乘法)

时间:2015-12-05 10:52:39

标签: matlab matrix vectorization multiplication bsxfun

是否有更快的方法在没有循环的情况下执行以下操作?

n = 2;
m = 1000;
A = rand(n,m);
B = rand(n,m);

C = zeros(n*n,m);
for i = 1 : m
    tmp = A(:,i) * B(:,i)';
    C(:,i) = tmp(:);
end

基本上我需要获得m nxn矩阵,其中AB之间的列有矩阵乘法。然后我需要这种矩阵的矢量化。

2 个答案:

答案 0 :(得分:6)

您可以使用repmatkronreshape完全矢量化,或者使用Divakar的解决方案bsxfun,{ {1}}和permute在速度方面为您提供了另一项重大改进。

repmat
  

经过的时间是0.117396秒。

tic
for j = 1:1000
A1 = repmat(A, n, 1);
B1 = kron(B,ones(n,1));
D = reshape(A1(:).*B1(:), n*n, m);
end
toc
  

经过的时间是5.751179秒。

所以,加速大约是50倍。但是,正如下面的评论中所讨论的那样,加速通常取决于矩阵的大小和任务执行的次数。

答案 1 :(得分:2)

您基本上针对所有列对A中的所有列执行元素乘法,但转换为B。您可以使用bsxfun(@times,..)基本杀死/替换那些令人讨厌的循环并使用bsxfun强大的内部扩展功能进行一种矢量化方法。实施还将涉及重塑以使其与C具有相同的格式,并且看起来像这样 -

out = reshape(bsxfun(@times,permute(A,[1 3 2]),permute(B,[3 1 2])),n^2,[]) 

运行时测试

本节比较了目前为止列出的所有方法来解决问题。

基准代码 -

%// Inputs
n = 2;
m = 1000;
A = rand(n,m);
B = rand(n,m);

num_iter = 5000;

disp('-------------------- For loop NO fuN') %// From OP question
tic
for iter = 1:num_iter
    C = zeros(n*n,m);
    for i = 1 : m
        tmp = A(:,i) * B(:,i)';
        C(:,i) = tmp(:);
    end
end
toc

disp('-------------------- run run KRON') %'// @lhcgeneva's solution
tic
for iter = 1:num_iter
    A1 = repmat(A, n, 1);
    B1 = kron(B,ones(n,1));
    D = reshape(A1(:).*B1(:), n*n, m);
end
toc

disp('-------------------- fun fun BSXFUN') %// Proposed in this post
tic
for iter = 1:num_iter
    out = reshape(bsxfun(@times,permute(A,[1 3 2]),permute(B,[3 1 2])),n^2,[]);
end
toc

输出 -

-------------------- For loop NO fuN
Elapsed time is 28.101873 seconds.
-------------------- run run KRON
Elapsed time is 1.156337 seconds.
-------------------- fun fun BSXFUN
Elapsed time is 0.692433 seconds.