如何在 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,其中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.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 分解?的主要内容,如果未能解决你的问题,请参考以下文章

基于Eigen库的线性方程组/矩阵方程求解(方法汇总)

犰狳 C++ LU 分解

线性方程理论说明和Eigen解线性方程求解方法汇总

Eigen解线性方程组

Eigen学习之简单线性方程与矩阵分解

Eigen求矩阵行列式