Matlab中如何避免大矩阵乘法

Matlab中如何避免大矩阵乘法,matlab,matrix,matrix-multiplication,enumerate,large-scale,Matlab,Matrix,Matrix Multiplication,Enumerate,Large Scale,我的代码中有两个大矩阵,它们的列数相同,行数不同。比如A(20000X4000)和B(30000X4000)。两者都是0-1稀疏的 我应该检查A的每一行和B的所有行,并计算公共1的数量。例如,如果A(1,:)=[011]和B([12],:)=[1111;0011],我需要得到3和2的结果 假设存在一个大的0-1矩阵C(50000X4000),其行被标记为typea或typeB。我应该将A和B的所有行一起进行比较,并枚举1。如果A和B的每一行中的1的数量大于某个界限,那么我在剩下的计算中使用了A和

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

我应该检查A的每一行和B的所有行,并计算公共1的数量。例如,如果
A(1,:)=[011]
B([12],:)=[1111;0011]
,我需要得到
3
2
的结果

假设存在一个大的0-1矩阵
C(50000X4000)
,其行被标记为type
a
或type
B
。我应该将
A
B
的所有行一起进行比较,并枚举1。如果A和B的每一行中的1的数量大于某个界限,那么我在剩下的计算中使用了A和B的这些行。因此,我甚至不需要存储
A
B
,我所需要的只是一组成对的行索引。类似于
[(3,2),(3,5),…]
的内容显示我应该使用
A
的第三行和
B
的第二行,以及
A
的第三行和
B
的第五行,依此类推

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

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

这项任务似乎很简单,只需计算
A
的每一行和
B
的所有行的公共1,但并不容易实现。考虑到代码应该执行1000次这样的任务,那么这实际上是不可能的

你知道如何不用乘法来列举常见的数吗?(顺便说一句,循环也没有帮助)


谢谢。

我不知道这是否真的比你拥有的更好,因为它仍然有一个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
%创建临时数据
A=兰特(200004000)<0.5;
B=兰特(300004000)<0.5;
计数=零(大小(A,1),大小(B,1),'uint8');
对于i=1:尺寸(A,1)
计数(i,:)=和(bsxfun(@eq,A(i,:),B),2);
结束

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

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

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

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

当我尝试此操作时,只需不到一分钟:

A = round(rand(30000,4000));
B = round(rand(20000,4000));
tic,A*B';toc;
如果你真的需要做上千次,我只能想象两种情况:

  • 你不需要经常这样做,在这种情况下,让它运行,它将在明天完成
  • 如果你想经常这样做,而且速度很重要,那么找到一个更快的解决方案是不可能的。除非你有一些非常有用的信息,关于你要乘的矩阵

  • 如果您发现此示例乘法远远超过一分钟(比如超过10分钟),则可能是内存使用效率低下。在这种情况下,尝试获得更多的ram。

    我做了一些基准测试;在我的机器(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
    

    谢谢然而,矩阵的大小不允许任何循环;这会花费更多的时间,我无法运行代码。@如果我不确定您是否理解这样一个事实,即无论哪种方式,这都将是一个巨大的比较。至少需要30000*4000*20000=2.4e12比较。这是巨大的。即使你可以“优化”它,同样数量的比较也需要发生——这是正确的,这就是为什么我被卡住了。我一直在试图重新解释这个问题,或者重新表述它,但仍然没有任何进展。我主要关心的是,我想可能有一些枚举方法可以应用于我不知道的特定问题(0-1矩阵)。我真的不认为有任何简单的方法可以解决这个问题。很抱歉我的意思是它会运行,只需要一段时间。如果你真的很不耐烦,或者内存有问题,你可以把矩阵分解成更小的块。在我的笔记本电脑上运行这个程序大约需要一个小时。我的笔记本电脑只有一个Intel i5 CPU。但一旦完成,您就可以保存结果,并且不再需要再次运行该程序。或者你也可以通过使用parfor和并行计算工具箱来加速这个过程谢谢你的建议,但这对我的情况不起作用!这个问题现在让我很恼火。我的意思是,它比我在Matlab中从正则矩阵乘法中得到的要花更多的时间。这种方法当然是正确的,但对速度没有帮助。谢谢你,伙计!矩阵有多稀疏,即大约有多少个?一般来说,一个矩阵不能在
    A*B'
    上改进。甚至切换到C++也不会有很大的改进。所以,你唯一的希望就是1。以不同的方式解决问题,或2。使用更多有用的信息。事实上,它是一个逻辑矩阵,这是一种信息,但不幸的是,这是不够的。你可以问自己,矩阵有多稀疏,它们是否有特定的结构?你的成果矩阵有多稀疏?
    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