用于快速求解线性系统的 C++ Eigen

C++ Eigen for solving linear systems fast

所以我想测试 C++ 与 Matlab 求解线性方程组的速度。为此,我创建了一个随机系统并测量了在 Visual Studio:

上使用 Eigen 求解它所需的时间
#include <Eigen/Core>
#include <Eigen/Dense>
#include <chrono>

using namespace Eigen;
using namespace std;

int main()
{
    chrono::steady_clock sc;   // create an object of `steady_clock` class
    int n;
    n = 5000;
    MatrixXf m = MatrixXf::Random(n, n);
    VectorXf b = VectorXf::Random(n);
    auto start = sc.now();     // start timer
    VectorXf x = m.lu().solve(b);
    auto end = sc.now();
    // measure time span between start & end
    auto time_span = static_cast<chrono::duration<double>>(end - start);
    cout << "Operation took: " << time_span.count() << " seconds !!!";
}

求解这个 5000 x 5000 的系统平均需要 6.4 秒。在 Matlab 中做同样的事情需要 0.9 秒。 matlab代码如下:

a = rand(5000);  b = rand(5000,1);

tic
x = a\b;
toc

根据这个反斜杠运算符的流程图:

鉴于随机矩阵不是三角形、置换三角形、厄米矩阵或上海森堡矩阵,Matlab 中的反斜杠运算符使用 LU 求解器,我相信它与我在 C++ 代码中使用的求解器相同,即是,lu().solve

可能我遗漏了什么,因为我认为 C++ 更快。

首先,对于这种操作,Eigen 打败 MatLab 的可能性很小,因为后者会直接调用 Intel 的 MKL,该 MKL 是高度优化和多线程的。请注意,您还可以配置 Eigen 以回退到 MKL,请参阅 how。如果这样做,您最终会获得相似的性能。

尽管如此,6.4s 已经足够了。 Eigen 的 documentation 报告 0.7s 分解 4k x 4k 矩阵。 运行 你在我的电脑上的例子(Haswell 笔记本电脑@2.6GHz)我得到了 1.6s(clang 7,-O3 -march=native),以及启用多线程的 1s(-fopenmp)。因此,请确保启用所有 CPU 的功能(AVX、FMA)和 openmp。使用 OpenMP,您可能需要明确地将 openmp 线程数减少到物理内核数。