从两个二维矩阵中获取多个三维矩阵(逐列乘法)
Get many 3d matrices from two 2d matrices (column-wise multiplication)
有没有更快的方法可以不用循环执行下面的操作?
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
之间进行逐列矩阵乘法。然后我需要对这些矩阵进行矢量化。
您可以使用 repmat, kron and reshape 完全 向量化 或使用 Divakar 的 bsxfun
、permute
和 repmat
解决方案在速度方面给你另一个显着的改进。
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
Elapsed time is 0.117396 seconds.
tic
for j = 1:1000
C = zeros(n*n,m);
for i = 1 : m
tmp = A(:,i) * B(:,i)';
C(:,i) = tmp(:);
end
end
toc
Elapsed time is 5.751179 seconds.
因此,加速大约是 50 倍。然而,正如下面评论中所讨论的,加速比通常取决于矩阵的大小和任务执行的次数。
您基本上是对 A
中的所有列对所有列执行逐元素乘法,但在 B
中进行转置。您可以使用 bsxfun(@times,..)
的一种矢量化方法,基本上 killing/replacing 那些 讨厌的循环 具有 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.
有没有更快的方法可以不用循环执行下面的操作?
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
之间进行逐列矩阵乘法。然后我需要对这些矩阵进行矢量化。
您可以使用 repmat, kron and reshape 完全 向量化 或使用 Divakar 的 bsxfun
、permute
和 repmat
解决方案在速度方面给你另一个显着的改进。
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
Elapsed time is 0.117396 seconds.
tic
for j = 1:1000
C = zeros(n*n,m);
for i = 1 : m
tmp = A(:,i) * B(:,i)';
C(:,i) = tmp(:);
end
end
toc
Elapsed time is 5.751179 seconds.
因此,加速大约是 50 倍。然而,正如下面评论中所讨论的,加速比通常取决于矩阵的大小和任务执行的次数。
您基本上是对 A
中的所有列对所有列执行逐元素乘法,但在 B
中进行转置。您可以使用 bsxfun(@times,..)
的一种矢量化方法,基本上 killing/replacing 那些 讨厌的循环 具有 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.