将两个矩阵逐行相乘
multiply two matrices row by row
在 MATLAB 中,我想将一个 Nx4 矩阵乘以一个 4xN 矩阵,并从中得到一个 Nx1 向量。我还将结果按元素除以另一个向量。
在循环中,它将是:
A=rand(10,4);
B=rand(4,10);
L=rand(10,1);
for i=1:10
result(i)=A(i,:)*B(:,i)/L(i);
end
我能想到的唯一非循环方法是:
A=rand(10,4);
B=rand(4,10);
L=rand(10,1);
result=diag(A*B)./L
但这会做很多不必要的乘法运算。有没有更好的方法?
矢量化方法
您可以在 A
和 B
的转置之间进行矩阵乘法,然后沿 dim-2
求和,最后使用 L
-
执行逐元素除法
result = sum(A.*B.',2)./L
基准测试
本节涵盖 proposed approach
与问题前半部分列出的 loop-based approach
的运行时和加速测试。请注意
问题第二部分中建议的其他基于 diag
的方法未包含在这些测试中,因为使用它的运行时相对非常多
大数字。
基准代码
N_arr = 4000:4000:100000; %// Datasizes
timeall = zeros(2,numel(N_arr)); %// Array to store runtimes
for iter = 1:numel(N_arr)
%// Create random inputs
N = N_arr(iter);
A=rand(N,4); B=rand(4,N); L=rand(N,1);
%// Time the approaches
f = @() mult_twomat_loopy(A,B,L);
timeall(1,iter) = timeit(f); clear f
f = @() mult_twomat_vect(A,B,L);
timeall(2,iter) = timeit(f); clear f
end
%// Plot speedups
figure,hold on,grid on
plot(N_arr,timeall(1,:)./timeall(2,:),'-bo')
xlabel('Datasize, N(Rows in A)'),ylabel('Speedup Factor (x)')
title('Speedup Plot')
相关功能代码
mult_twomat_loopy.m:
function result = mult_twomat_loopy(A,B,L)
N = size(A,1);
result = zeros(N,1);
for i=1:N
result(i)=A(i,:)*B(:,i)/L(i);
end
mult_twomat_vect.m:
function result = mult_twomat_vect(A,B,L)
result = sum(A.*B.',2)./L;
提出的方法相对于循环方法的加速
结论
从加速图中可以看出,所提出的方法似乎是解决问题的一个很好的选择。从图中再次观察到有趣的是,针对 32K+ datasizes
的循环方法,所提出的方法的性能突然下降。这种下降背后的原因很可能是系统内存带宽限制了如此大的数据量下的性能,但值得庆幸的是,即使对于这样的数据量,加速仍然保持在 20x
以上。
在 MATLAB 中,我想将一个 Nx4 矩阵乘以一个 4xN 矩阵,并从中得到一个 Nx1 向量。我还将结果按元素除以另一个向量。
在循环中,它将是:
A=rand(10,4);
B=rand(4,10);
L=rand(10,1);
for i=1:10
result(i)=A(i,:)*B(:,i)/L(i);
end
我能想到的唯一非循环方法是:
A=rand(10,4);
B=rand(4,10);
L=rand(10,1);
result=diag(A*B)./L
但这会做很多不必要的乘法运算。有没有更好的方法?
矢量化方法
您可以在 A
和 B
的转置之间进行矩阵乘法,然后沿 dim-2
求和,最后使用 L
-
result = sum(A.*B.',2)./L
基准测试
本节涵盖 proposed approach
与问题前半部分列出的 loop-based approach
的运行时和加速测试。请注意
问题第二部分中建议的其他基于 diag
的方法未包含在这些测试中,因为使用它的运行时相对非常多
大数字。
基准代码
N_arr = 4000:4000:100000; %// Datasizes
timeall = zeros(2,numel(N_arr)); %// Array to store runtimes
for iter = 1:numel(N_arr)
%// Create random inputs
N = N_arr(iter);
A=rand(N,4); B=rand(4,N); L=rand(N,1);
%// Time the approaches
f = @() mult_twomat_loopy(A,B,L);
timeall(1,iter) = timeit(f); clear f
f = @() mult_twomat_vect(A,B,L);
timeall(2,iter) = timeit(f); clear f
end
%// Plot speedups
figure,hold on,grid on
plot(N_arr,timeall(1,:)./timeall(2,:),'-bo')
xlabel('Datasize, N(Rows in A)'),ylabel('Speedup Factor (x)')
title('Speedup Plot')
相关功能代码
mult_twomat_loopy.m:
function result = mult_twomat_loopy(A,B,L)
N = size(A,1);
result = zeros(N,1);
for i=1:N
result(i)=A(i,:)*B(:,i)/L(i);
end
mult_twomat_vect.m:
function result = mult_twomat_vect(A,B,L)
result = sum(A.*B.',2)./L;
提出的方法相对于循环方法的加速
结论
从加速图中可以看出,所提出的方法似乎是解决问题的一个很好的选择。从图中再次观察到有趣的是,针对 32K+ datasizes
的循环方法,所提出的方法的性能突然下降。这种下降背后的原因很可能是系统内存带宽限制了如此大的数据量下的性能,但值得庆幸的是,即使对于这样的数据量,加速仍然保持在 20x
以上。