是否有更快的方法在没有循环的情况下执行以下操作?
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
矩阵,其中A
和B
之间的列有矩阵乘法。然后我需要这种矩阵的矢量化。
答案 0 :(得分:6)
您可以使用repmat,kron和reshape完全矢量化,或者使用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.