为什么MATLAB在矩阵乘法中如此快?

206

我正在使用CUDA、C++、C#、Java进行一些基准测试,并使用MATLAB进行验证和矩阵生成。当我使用MATLAB进行矩阵乘法时,2048x2048甚至更大的矩阵几乎可以立即相乘。

             1024x1024   2048x2048   4096x4096
             ---------   ---------   ---------
CUDA C (ms)      43.11      391.05     3407.99
C++ (ms)       6137.10    64369.29   551390.93
C# (ms)       10509.00   300684.00  2527250.00
Java (ms)      9149.90    92562.28   838357.94
MATLAB (ms)      75.01      423.10     3133.90

只有CUDA具有竞争力,但我认为至少C++应该接近一些,而不是慢60倍。我也不知道如何评价C#的结果。该算法与C++和Java完全相同,但结果从1024跳到2048。

Matlab是如何实现如此快速的矩阵乘法的?

C++代码:

float temp = 0;
timer.start();
for(int j = 0; j < rozmer; j++)
{
    for (int k = 0; k < rozmer; k++)
    {
        temp = 0;
        for (int m = 0; m < rozmer; m++)
        {
            temp = temp + matice1[j][m] * matice2[m][k];
        }
        matice3[j][k] = temp;
    }
}
timer.stop();

14
可能是由于你使用的算法不同所导致的问题。 - Robert J.
26
确保Matlab没有缓存你的结果,它是一个棘手的东西。首先确保实际进行了计算,然后进行比较。 - rubenvb
29
LAPACK和向量化。http://www.mathworks.com/company/newsletters/news_notes/clevescorner/winter2000.cleve.htmlLAPACK是用于数值线性代数计算的软件库,它可以高效地求解线性方程组、特征值问题和奇异值分解等。向量化可以使这些计算更快速地执行,它指的是将代码重写为使用向量操作,以便充分利用现代处理器的并行能力。在Matlab中,向量化是一种常见的优化技巧,可以显著提高代码的执行速度。 - James
11
我认为这篇文章确实很有趣,但我想看到更适当的基准测试。例如,我知道Matlab R2011a会自动使用多线程,并且矩阵乘法是使用Intel的MKL / BLAS库实现的。因此,如果使用mkl调用来进行矩阵乘法,我猜c ++会更快。问题在于Matlab的开销是多少。我知道这取决于矩阵乘法的其他细节,但目前上述数字相当无意义。 - Lucas
1
你可以使用运行时间为O(n^2.81)的Strassen算法来进行大型矩阵乘法,这比原生乘法快10倍左右,原生乘法的运行时间为O(n^3)。此外,SSE/AVX可以帮助你实现8-20倍的代码执行速度提升。总体而言,你可以拥有一个比Matlab更快的C语言实现。 - DU Jiaen
显示剩余14条评论
12个回答

2

这种显著的对比不仅是由于Matlab惊人的优化(正如许多其他答案所讨论的),而且还在于您将矩阵构造为一个对象的方式。

看起来您将矩阵制作成了一系列列表? 一系列列表包含指向列表的指针,然后列表包含矩阵元素。 包含列表的位置是任意分配的。 当您正在遍历第一个索引(行号?)时,内存访问的时间非常重要。 相比之下,为什么不尝试使用以下方法将矩阵实现为单个列表/向量?

#include <vector>

struct matrix {
    matrix(int x, int y) : n_row(x), n_col(y), M(x * y) {}
    int n_row;
    int n_col;
    std::vector<double> M;
    double &operator()(int i, int j);
};

并且
double &matrix::operator()(int i, int j) {
    return M[n_col * i + j];
}

应使用相同的乘法算法,以便flop的数量相同。(对于大小为n的方阵,n^3)

我要求您计时,以便结果与之前的结果可比(在同一台机器上)。通过比较,您将确切地展示内存访问时间可以有多重要!


2

在C++中速度较慢是因为您没有使用多线程。实际上,如果A = B C,其中它们都是矩阵,则可以独立计算A的第一行与第二行等。如果A、B和C都是n乘以n的矩阵,则可以将乘法加速n^2倍,如下所示:

a_{i,j} = sum_{k} b_{i,k} c_{k,j}

如果您使用Eigen[http://eigen.tuxfamily.org/dox/GettingStarted.html],则多线程已经内置,并且可调整线程数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接