如何在 Eigen C++ 中加速 LU 分解?
Posted
技术标签:
【中文标题】如何在 Eigen C++ 中加速 LU 分解?【英文标题】:How to speed up LU decomposition in Eigen C++? 【发布时间】:2020-05-09 15:45:02 【问题描述】:我是 C++ 和 Eigen 库的新手。我想对具有复杂条目的大小为1815 X 1815
的矩阵执行 LU 分解(部分旋转)。但是,我的代码性能很差,LU 分解需要 77.2852
秒,而 MATLAB 只需要 0.140946
秒。请找到随附的代码。关于如何改进代码的任何建议?请注意,在代码的第一部分,我从一个包含以下条目的文件中导入矩阵:a + bi
,其中a
和b
是复数。矩阵文件是从 MATLAB 生成的。谢谢。
#include <iostream>
#include <Eigen/Dense>
#include <fstream>
#include <complex>
#include <string>
#include <chrono>
using namespace std;
using namespace std::chrono;
using namespace Eigen;
int main()
int mat_sz = 1815; // size of matrix
MatrixXcd c_mat(mat_sz,mat_sz); // initialize eigen matrix
double re, im;
char sign;
string entry;
ifstream myFile("A_mat"); // format of entries : a + bi. 'a' and 'b' are complex numbers
//Import and assign matrix to an Eigen matrix
for (int i = 0; i < mat_sz; i++)
for (int j = 0; j < mat_sz; j++)
myFile >> entry;
stringstream stream(entry);
stream >> re >> sign >> im;
c_mat(i,j) = re, (sign == '-') ? -im : im; // Assigning matrix entries
// LU Decomposition
auto start = high_resolution_clock::now();
c_mat.partialPivLu(); // Solving equation through partial LU decomposition
auto stop = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(stop - start);
double million = 1000000;
cout << "Time taken by function: " << duration.count()/million << " seconds" << endl;
【问题讨论】:
你是在打开优化的情况下编译它吗? 大部分是一般建议,但仍然:eigen.tuxfamily.org/… Eigen 模板很重,因此需要打开优化以使其内联。请添加您的编译器和标志以及您正在运行它的硬件。 @user253751 我不认为优化已打开。我该如何检查?我正在使用 codelite 作为 IDE。 @AviGinsburg 我在 ubuntu 上使用 gcc 版本 7.4.0。硬件:Intel i7-8550U CPU @ 1.80GHz × 8。我不确定标志,如何检查?您能否还建议我如何启用优化?我在终端上输入了 g++ -Q --help=optimizers 并得到了一个很长的列表,例如falign-loops [禁用]。这是在正确的方向吗? 【参考方案1】:我会将 cmets 总结为一个答案。
当您觉得 Eigen
运行缓慢时,会列出需要验证的事项。
-
优化是否开启?
Eigen 是一个模板繁重的库,它会进行大量编译时检查,应该对其进行优化。如果未启用优化,则不会进行内联,并且会进行许多无意义的函数调用。即使开启最低级别的优化通常也能缓解大部分问题(gcc/clang 中的
-O1
或更高级别,MSVC 中的/O1
或更高级别)。关于优化的一般说明可以是found here。
我是否使用了所有硬件选项?
如果允许,可以对 Eigen 中的许多代码进行矢量化。确保使用打开 SSE/AVX/等的标志启用此功能。如果目标硬件支持它。如果可用,也启用 FMA。有一个占位符doc here。
启用多线程
如果您的流程/硬件允许,请考虑 enabling OpenMP 以允许 Eigen 将多个内核用于某些操作。
使用正确的精度
在许多应用程序中,只有前几个数字很重要。如果您的应用中出现这种情况,请考虑使用单精度而不是双精度。
链接到经过微调的库
最后,Eigen 吐出了一些精心构建的 C++ 代码,并依靠编译器自己处理大部分优化。在某些情况下,更精细调整的库(例如 MKL)可能会提高性能。 Eigen can link to MKL 以提高硬件速度。
【讨论】:
以上是关于如何在 Eigen C++ 中加速 LU 分解?的主要内容,如果未能解决你的问题,请参考以下文章