用于快速求解线性系统的 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++ 更快。
- 我运行它在配置管理器上处于活动发布模式
- 项目属性 - C/C++ - 优化 - /O2 处于活动状态
- 尝试使用增强指令(SSE 和 SSE2)。 SSE 实际上让它变慢了,而 SSE2 几乎没有任何区别。
- 我正在使用 Visual Studio 的社区版本,如果这有什么不同的话
首先,对于这种操作,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 线程数减少到物理内核数。
所以我想测试 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++ 更快。
- 我运行它在配置管理器上处于活动发布模式
- 项目属性 - C/C++ - 优化 - /O2 处于活动状态
- 尝试使用增强指令(SSE 和 SSE2)。 SSE 实际上让它变慢了,而 SSE2 几乎没有任何区别。
- 我正在使用 Visual Studio 的社区版本,如果这有什么不同的话
首先,对于这种操作,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 线程数减少到物理内核数。