一种计算矩阵乘法的快速算法

Posted

技术标签:

【中文标题】一种计算矩阵乘法的快速算法【英文标题】:a fast algorithm to compute matrix multiplication 【发布时间】:2011-06-05 23:29:24 【问题描述】:

在c++代码eclipse的中间,我需要计算矩阵A和B的乘积,大小为2400*3600(所以尺寸不一样)。矩阵存储在浮点二维数组中。它们不是稀疏的,没有限制。

每次乘法都需要很长时间(几分钟),我真的需要减少它,因为我有一个重复 5000 万次的循环。并且每次新的 A 和 B 应该相乘。 欢迎任何形式的建议以降低时间复杂度。 (甚至更改存储数据的结构,如果您认为这可能会有所帮助)。例如,如果我将数据存储到一维数组中怎么办?还是用向量代替数组?

在一种特殊情况下,第一列始终为 1,其值为 1、-1 或零。这个案子有什么想法吗? 在其他情况下,值可以是任何东西。 ** 这些乘法之一是 X 乘以其转置。对这个具体的有什么建议吗?

【问题讨论】:

在 O(n^3) 中进行一般矩阵乘法的朴素算法,但有一些方法可以将其降低到 O(n^(2.7ish))。如果您不能在开始之前减少一些工作,这只是一个非常大的计算。如果大量来自一组一致的转换,也许您可​​以每行做一个并找到 deltas。或某事 你的矩阵大部分是零吗?如果是这样,那么也许您可以找到一种在稀疏矩阵上运行的乘法算法。稀疏矩阵本质上是一个(i,j)->value 映射。 【参考方案1】:

我不会胡乱尝试自己编写:Google for LAPACK 或 BLAS,两个经过时间考验的数值计算包,都优化到 N 级。两者都有您可以使用的 C API。

【讨论】:

+1:这两个库不仅使用优化算法,还使用依赖 SSE 指令的优化实现。【参考方案2】:

存储您的第二个矩阵转置肯定会有所帮助,以便列与缓存行而不是行匹配。 L2缓存和主存的访问时间相差10倍左右。

【讨论】:

虽然看起来很明显,但我没有明白你的意思。你能再解释一下吗?如果我真的想将 A 乘以它的转置怎么办? @Pegah:如果您查看矩阵乘法算法,您会发现内部循环类似于:sum = 0; for( int k = 0; k < n; ++k ) sum += a[i][k] * b[k][j]; c[i][j] = sum;。连续迭代访问a[i][0]a[i][1]a[i][2],这很好,因为它们在内存中彼此相邻存储,因此缓存可以一次从主内存中读取一大块。但是你还要访问b[0][j]b[1][j]b[2][j],它们的局部性很差,而且缓存要从主存进行多次单独的传输,非常浪费。【参考方案3】:

你可以试试Eigen。

【讨论】:

【参考方案4】:

如果您谈论的是数百万次乘法,我要做的第一件事就是使用 CUDA 或 DirectCompute 将工作卸载到 GPU,这更适合这类东西。这就是 MATLAB 所做的,即使 GPU 加速是可选的。

有无数的 GPU 加速矩阵乘法示例,因此您的工作应该不会太难。

【讨论】:

其实我需要在一个c++代码中间做,它的结果被其余的代码使用。所以这不是一个独立的工作。据我了解(我刚刚在网上搜索过),GPU 是基于硬件的实现,而 Directcompute 是一个单独的应用程序。我错了吗?还是我仍然可以在我的代码中使用 GPU? 我不知道你在说什么。CUDA 和 DirectCompute 是让你在 GPU 上执行算术的 API。基于硬件的实现是什么?在 C++ 代码中间?与什么相反?.. @Pegah 是的,您的 GPU 可能是基于硬件的实现 :) @Pegah:GPU 只是指显卡上的处理器芯片。它非常擅长一次执行许多相同的操作,但不擅长复杂的分支。矩阵乘法是很多相同的操作,所以它在 GPU 上运行得非常快。 DirectCompute、CUDA 和 OpenCL 是允许 C++ 程序向您的视频卡发出指令并来回移动数据的库。

以上是关于一种计算矩阵乘法的快速算法的主要内容,如果未能解决你的问题,请参考以下文章

疯子的算法总结 矩阵乘法 (矩阵快速幂)

快速幂矩阵

CUDNN入坑指南(0)卷积算法实现类型

矩阵计算矩阵乘法其一:基础符号和算法

算法矩阵列乘法 | 动态规划

矩阵计算矩阵乘法其一:基础符号和算法