如何加快本征C++中的LU分解?

How to speed up LU decomposition in Eigen C++?

本文关键字:LU 分解 中的 C++ 何加快      更新时间:2023-10-16

我是 c++ 和 Eigen 库的新手。我想在大小为1815 X 1815的矩阵上执行 LU 分解(部分透视(,其中包含复杂的条目。但是,我的代码性能很差,LU 分解需要77.2852秒,而 MATLAB 只需要0.140946秒。请找到随附的代码。关于如何改进代码的任何建议?请注意,在代码的第一部分中,我从包含条目的文件导入矩阵:a + bi,其中ab是复数。矩阵文件是从 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运行缓慢时,会列出应该验证的内容。

  1. 优化是否已启用?
    Eigen 是一个模板密集型库,它执行大量编译时检查,应该进行优化。如果未启用优化,则不会内联任何优化,并且会进行许多毫无意义的函数调用。即使是最低级别的优化通常也能缓解大部分这种情况(gcc/clang 中为-O1或更高,MSVC 中为/O1或更高(。有关优化的一般说明,请参阅此处。
  2. 我是否使用了所有硬件选项?
    如果允许,特征中的许多代码都可以进行矢量化。如果目标硬件支持,请确保通过打开 SSE/AVX/等的标志启用此功能。如果可用,也启用 FMA。这里有一个占位符文档。
  3. 启用
  4. 多线程
    如果进程/硬件允许,请考虑启用 OpenMP 以允许 Eigen 利用多个内核进行某些操作。
  5. 使用正确的精度
    在许多应用中,只有前几位数字很重要。如果您的应用程序中是这种情况,请考虑使用单精度而不是双精度。
  6. 链接到微调库
    最后,Eigen 吐出一些精心构建的C++代码,并依靠编译器自己处理大多数优化。在某些情况下,更精细的库(如 MKL(可能会提高性能。Eigen可以链接到MKL,以从硬件中挤出更多的速度。