Matlab重复矩阵乘法 - 循环与内置性能

时间:2016-01-08 11:22:01

标签: performance matlab matrix matrix-multiplication memory-efficient

给定矩阵A,我需要与其他n向量Bi(即i=1...n)相乘。 A的大小可能类似于5000x5000,因此Bi的大小类似于5000x1

如果我按以下方式评估产品:

for i=1:n
    product=A*Bi;
    % do something with product
end

结果比计算产品的方式(数量级)慢:

%assume that S is a matrix that contains the vectors Bi as columns, i.e. S(:,i)=Bi, then:
results=A*S;   %stores all the products in matrix form
% do something with results

问题是向量n的数量Bi可能太大而无法存储在内存中,例如n=300000,所以我需要每次都使用循环方法我评估产品,使用它,然后丢弃向量Bi

为什么这种方法与直接乘法相比这么慢,有没有办法克服这个问题?

4 个答案:

答案 0 :(得分:4)

您可以尝试循环批量,例如

for i = 0:(n/k)-1
    product = A*S(:,(i*k+1):(i+1)*k)
end

并调整k以找到最佳的速度和记忆权衡。

MATLAB的循环很慢,因为它是一种解释型语言。所以它必须在运行中解决很多问题。由于JIT编译器,这些天的循环得到了极大的改进,但是与用C编写和编译的内置函数相比,它们仍然很慢。此外,它们使用真正尖端的超快速矩阵乘法算法,通过循环实现你相当天真的算法,这也有助于你所经历的加速。

答案 1 :(得分:3)

为简单起见,我的答案将采用n×n方阵A,但对于非正方形也是如此。

你的循环方法使用矩阵向量乘法。天真的解决方案也是最为人所知的,导致O(n ^ 2)的运行时间重复n次。最终总运行时间为O(n ^ 3)。

对于矩阵乘法,有一种更好的方法。最着名的算法只需要少于O(n ^ 2.4)的运行时间,这使得它对于大数字来说要快得多。

使用矩阵乘法一次乘以多个向量Bi时,您将获得更好的运行时间。这将无法实现纯矩阵乘法的性能,但使用较大的b片段可能是最快的内存有效解决方案。

针对不同讨论方法的一些代码:

n=5000;
k=100;
A=rand(n,n);
S=rand(n,n);
workers=matlabpool('size');
%for a parfor solution, the batch size must be smaller because multiple batches are stred in memory at once
kparallel=k/workers;
disp('simple loop:');
tic;
for i = 1:n
    product = A*S(:,n);
end
toc
disp('batched loop:');
tic;
for i = 1:(n/k)
    product = A*S(:,(i-1)*k+1:(i)*k);
end
toc
disp('batched parfor loop:');
tic;
parfor i = 1:(n/kparallel)
    product = A*S(:,(i-1)*kparallel+1:(i)*kparallel);
end
toc
disp('matrix multiplication:');
tic;
A*S;
toc

答案 2 :(得分:1)

除了@Dan's answer之外,您可以尝试并行,只要您有足够的内核和足够大的操作来使其盈利(有关this answer的内存消耗的更多详细信息,请参阅parfor) :

parfor ii = 0:(n/k)-1
    product = A*S(:,(ii*k+1):(ii+1)*k)
end

我无法在docs on mtimes*运算符)中看到它是否是隐式多线程的,但我认为它值得一试。

答案 3 :(得分:0)

为了将每个数组与矩阵进行乘法运算,只需将矩阵与一个矩阵相乘,该矩阵将所需的数组作为列。

所以,如果你想检查一下

如果

size(a)=3,3

然后

 a*b==horzcat(a*b(:,1),a*b(:,2),a*b(:,3)) 

是真的

通过这种方式,您可以节省大量的时间