如何避免Matlab中的大型矩阵乘法

时间:2013-12-04 16:46:06

标签: matlab matrix matrix-multiplication enumerate large-scale

我的代码中有两个大型矩阵,它们具有相同的列数和不同的行数。与A(20000X4000)B(30000X4000)一样。两者都是0-1稀疏。

我应该用A的所有行检查A的每一行,并计算公共1的数量。例如,如果A(1,:)=[0 1 0 1 1]B([1 2],:)=[1 1 1 1 1;0 0 0 1 1],我需要将结果设为32

假设有一个大的0-1矩阵C(50000X4000),其行被标记为类型A或类型B。我应该将AB的所有行进行比较并枚举1。如果A和B的每一行中的1的数量大于某些边界,那么我在剩下的计算中使用了A和B的那些行。所以,我甚至不需要存储AB,我只需要一系列行索引列表。类似[(3,2),(3,5),...]的内容显示我应该使用A的第三行和B的第二行,A的第三行和B的第五行等等。

我想到的第一件事是A*B',它给出了正确的结果,但实际上它是非常昂贵的,在某些情况下不可能进行这种乘法。

我将矩阵转换为单一数据类型,它变得更快一点。稀疏没有帮助。

任务看起来很简单,只计算每行A的常见1和B的所有行,但不容易实现。考虑到代码应该执行1000次这样的任务,那么实际上是不可能的。

任何想法如何在没有乘法的情况下枚举常见的? (顺便说一句,循环也没有用)。

感谢。

4 个答案:

答案 0 :(得分:2)

我不知道这是否真的比你拥有的更好,因为它仍然有一个for循环,但如果有人能弄清楚如何删除for循环你应该很高兴。

%  create temp data
A = rand(20000,4000) < 0.5;
B = rand(30000,4000) < 0.5;
counts = zeros(size(A,1),size(B,1),'uint8');
for i = 1:size(A,1)
    counts(i,:) = sum(bsxfun(@eq,A(i,:),B),2);
end

无论哪种方式,该过程都需要很长时间,因为您要比较30000行,每行4000个元素,20000次或大约2.4e+12个比较。这是一项艰巨的任务,肯定需要很长时间。如果你需要更快的话,可能会尝试使用并行计算。

答案 1 :(得分:1)

我做了一些基准测试;在我的机器上(i7-3770 @ 3.40GHz),无论内容如何,​​将大小为30000 x 4000和4000 x 20000的完整矩阵相乘大约需要55秒,与Dennis Jaheruddin发现的相同。但是使用稀疏矩阵可以使计算更快,具体取决于稀疏性。如果我将稀疏程度r定义为1 s与矩阵元素之间的比率,我得到以下结果:

r      time / s 
0.001   0.07
0.002   0.3
0.005   2.1
0.01    8.3
0.02   25

以下是用于确定这些数字的代码:

m = 20000;
n = 4000;
o = 30000;

r = 0.001;

N = round(r * m * n);
A = sparse(randi(m, N, 1), randi(n, N, 1), 1, m, n);

N = round(r * n * o);
B = sparse(randi(o, N, 1), randi(n, N, 1), 1, o, n);

tic
C = A * B';
toc

答案 2 :(得分:0)

如果不能完成整个矩阵的乘法,一个想法是一次处理一个垂直条纹。对于每个条带,您计算所需的结果,并将其与前面的条带累加:

A = double(rand(5,300)<.5); %// random data
B = double(rand(4,300)<.5); %// random data

S = 10; %// stripe size
result = zeros(size(A,1),size(B,1)); %// initialize to 0
for s = 1:10:size(A,2) %// each vertical stripe, of width S
    ind = s+(0:S-1);
    result = result +  A(:,ind)*(B(:,ind)).';
end

检查:

>> result

result =

    73    72    62    72
    84    70    79    71
    83    84    76    77
    77    80    77    74
    71    71    70    74

>> A*B.'

ans =

    73    72    62    72
    84    70    79    71
    83    84    76    77
    77    80    77    74
    71    71    70    74

答案 3 :(得分:0)

您尝试的解决方案是最佳或接近最佳的。

当我尝试这个时,需要不到一分钟的时间:

A = round(rand(30000,4000));
B = round(rand(20000,4000));
tic,A*B';toc;

如果你真的需要这样做几千次,我只能想象两种情景:

  1. 你不需要经常这样做,在这种情况下,只需让它运行,它将在明天完成
  2. 你想经常这么做并加快速度,找到一个更快的解决方案根本就不会发生。除非你有一些关于矩阵的非常有用的信息,否则你将成倍增加。
  3. 如果您发现此样本乘法超过一分钟(例如超过10分钟),则可能无法有效地使用内存。在这种情况下,尝试获得更多的ram。