如何加速 Eigen C++ 中的 LU 分解?
How to speed up LU decomposition in Eigen C++?
我是 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
是 运行 慢时,这里有一个清单应该验证。
- 优化是否开启?
Eigen 是一个模板繁重的库,它会进行大量编译时检查,应该对其进行优化。如果未启用优化,其中 none 将被内联并进行许多无意义的函数调用。即使是最低级别的优化通常也能缓解大部分问题(-O1
或 gcc/clang 或更高级别,/O1
或更高级别的 MSVC)。关于优化的一般说明可以是 found here.
- 我是否利用了所有硬件选项?
如果允许,Eigen 中的很多代码都可以向量化。确保启用标志并打开 SSE/AVX/etc。如果目标硬件支持它。如果可用,也启用 FMA。有一个占位符 doc here.
- 启用多线程
如果您的 process/hardware 允许,请考虑 enabling OpenMP 以允许 Eigen 在某些操作中使用多个内核。
- 使用正确的精度
在许多应用程序中,只有前几位数字很重要。如果您的应用程序属于这种情况,请考虑使用单精度而不是双精度。
- Link 到微调库
最后,Eigen 吐出一些精心构建的 C++ 代码,并依靠编译器自行处理大部分优化。在某些情况下,更精细调整的库(例如 MKL)可能会提高性能。 Eigen can link to MKL 从硬件中榨取更多的速度。
我是 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
是 运行 慢时,这里有一个清单应该验证。
- 优化是否开启?
Eigen 是一个模板繁重的库,它会进行大量编译时检查,应该对其进行优化。如果未启用优化,其中 none 将被内联并进行许多无意义的函数调用。即使是最低级别的优化通常也能缓解大部分问题(-O1
或 gcc/clang 或更高级别,/O1
或更高级别的 MSVC)。关于优化的一般说明可以是 found here. - 我是否利用了所有硬件选项?
如果允许,Eigen 中的很多代码都可以向量化。确保启用标志并打开 SSE/AVX/etc。如果目标硬件支持它。如果可用,也启用 FMA。有一个占位符 doc here. - 启用多线程
如果您的 process/hardware 允许,请考虑 enabling OpenMP 以允许 Eigen 在某些操作中使用多个内核。 - 使用正确的精度
在许多应用程序中,只有前几位数字很重要。如果您的应用程序属于这种情况,请考虑使用单精度而不是双精度。 - Link 到微调库
最后,Eigen 吐出一些精心构建的 C++ 代码,并依靠编译器自行处理大部分优化。在某些情况下,更精细调整的库(例如 MKL)可能会提高性能。 Eigen can link to MKL 从硬件中榨取更多的速度。