有谁知道MATLAB用于矩阵乘法的算法是什么,它的时间复杂度是多少?
答案 0 :(得分:19)
为了完整性 - 如this thread中所述,Matlab使用DGEMM
(基本线性代数子程序)中的BLAS(双通用矩阵乘法)例程。
请注意,BLAS没有一个单独的实现 - 它针对特定的处理器体系结构进行了调整。因此,如果没有找到正在使用的BLAS版本,您无法绝对确定您的计算机上使用了哪种算法。
BLAS规范规定了每个子程序的输入和输出,并为每个子程序的输出提供了可接受的误差范围。实现可以随意使用他们喜欢的任何算法,只要它们遵循规范。
BLAS的参考实现使用DGEMM
中的block matrix multiplication algorithm,其时间复杂度为O( n ^ 3),用于乘以两个 n x n 矩阵。我认为假设大多数BLAS实现或多或少都遵循参考实现是合理的。
请注意,它不使用朴素矩阵乘法算法
for i = 1:N
for j = 1:N
for k = 1:N
c(i,j) = c(i,j) + a(i,k) * b(k,j);
end
end
end
这是因为通常整个矩阵不适合local memory。如果数据不断地移入和移出本地存储器,算法将减慢速度。块矩阵算法将操作分解为小块,这样每个块都足够小以适应本地存储器,从而减少了进出内存的移位次数。
存在渐近更快的矩阵乘法算法,例如Strassen algorithm或Coppersmith-Winograd algorithm,其速率略快于O( n ^ 3)。但是,它们通常不会识别缓存并忽略局部性 - 这意味着数据不断需要在内存中分流,因此对于大多数现代架构而言,整体算法实际上比优化的块矩阵乘法算法慢。
维基百科指出,Strassen算法可以在单个核心CPU上为大于几千的矩阵提供加速,但是加速可能大约为10%左右,BLAS的开发人员可能认为不值得对于这种罕见的情况(说,this paper从1996年开始宣称,对于 n 超过DGEMM
的速度增加约10% - 虽然我不知道如何过时了)。另一方面,Coppersmith-Winograd算法“只为矩阵提供了一个优势,使得它们无法被现代硬件处理”。
所以答案是Matlab使用一种天真但有效的缓存感知算法来获得快速的矩阵乘法。
我通过创建一些演示块矩阵乘法算法的局部性的视频来更新这个答案,与天真算法相比较。
在以下每个视频中,我们都可视化两个8x8矩阵 A 和 B 的乘法,以创建产品 C = < strong> A x B 。黄色突出显示表示在算法的每个步骤中正在处理每个矩阵 A , B 和 C 中的哪个元素。您可以看到块矩阵乘法一次只对矩阵的小块有效,并且多次重复使用这些块中的每一个,以便最小化数据必须移入和移出本地存储器的次数