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

use*_*900 5 c++ benchmarking matlab visual-studio eigen

所以我想测试一下 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 !!!";
}
Run Code Online (Sandbox Code Playgroud)

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

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

tic
x = a\b;
toc
Run Code Online (Sandbox Code Playgroud)

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

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

可能我遗漏了一些东西,因为我认为 C++ 更快。

  • 我在配置管理器上以处于活动状态的发布模式运行它
  • 项目属性 - C/C++ - 优化 - /O2 处于活动状态
  • 尝试使用增强指令(SSE 和 SSE2)。SSE 实际上让它变慢了,而 SSE2 几乎没有任何区别。
  • 我正在使用 Visual Studio 的社区版本,如果这有什么不同的话

gga*_*ael 5

首先,对于这种操作,Eigen 不太可能击败 MatLab,因为后者会直接调用 Intel 的经过深度优化和多线程的 MKL。请注意,您还可以将 Eigen 配置为回退到 MKL,请参阅如何操作。如果这样做,您最终会获得类似的性能。

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