按行相乘两个矩阵

3
在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

但这样做会进行很多不必要的乘法运算。有更好的方法吗?
1个回答

7

向量化方法

你可以对矩阵 A 和转置的矩阵 B 进行矩阵乘法,然后沿着 dim-2 求和,最后执行元素级别的除法运算,使用 L - 进行。

result = sum(A.*B.',2)./L

基准测试

本部分涵盖了针对问题早期提到的“基于循环的方法”的建议方法与之进行的运行时和加速测试。请注意,第二部分中建议的“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;

提议方法相较于循环方法的加速

enter image description here

结论

从加速图中可以看出,提议方法似乎是解决该问题的一个很好选择。再次观察到的有趣现象是,在数据大小达到32K+时,提议方法对循环方法的性能突然下降。这种下降的原因很可能是系统内存带宽在大数据量情况下限制了性能,但值得庆幸的是,即使在如此大的数据量下,速度提升仍然保持在20倍以上的水平。


1
@user61290 我认为这样会更好,因为需要进行的乘法和加法运算数量要少得多。 - Divakar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接