为何Eigen对称矩阵特征值求解器的运行速度慢于Julia的对应实现?
可尝试的优化点
- 修正特征值求解配置,避免多余计算
你当前Eigen代码默认同时计算特征值和特征向量,而Julia的eigvals仅计算特征值,这是两者性能差异的核心原因之一。将compute调用修改为仅求解特征值即可大幅降低开销:eg.compute(m, Eigen::EigenvaluesOnly); - 强制Eigen调用dsyevr接口和Julia对齐
在Eigen头文件引入前添加宏定义#define EIGEN_LAPACKE_USE_DSYEVR,即可让Eigen优先调用性能更优的dsyevr而非默认的dsyev,和Julia LinearAlgebra的底层实现保持一致。 - 移除编译期的性能剖析开销
你当前CMake配置中的-pg参数是用于gprof性能剖析的,会引入额外的运行时开销,正式性能测试时需要删除该编译选项。 - 减少循环内的重复开销
将SelfAdjointEigenSolver对象的构造移到循环外部,避免每次迭代重复分配、释放内部缓存内存:void compute_eigenvalues_symmetric(const MatrixXd & m) { SelfAdjointEigenSolver<MatrixXd> eg; for (int i = 0; i < 500; i++) { eg.compute(m, Eigen::EigenvaluesOnly); Eigen::VectorXd evals = eg.eigenvalues(); } } - 保证两边测试条件对齐
- 移除Julia代码中循环内的
println(i)语句,IO操作会引入不可控的开销,导致Julia的测试结果偏慢,无法公平对比核心计算性能 - 显式设置两边BLAS库的线程数一致,比如在C++中调用
openblas_set_num_threads(N)/mkl_set_num_threads(N),在Julia中调用BLAS.set_num_threads(N),避免默认线程配置差异带来的性能误差
- 移除Julia代码中循环内的
- MKL后端的额外配置
如果使用MKL后端,除了定义EIGEN_USE_MKL外,需要确保链接完整的MKL依赖库,仅定义宏但链接不完整会导致Eigen fallback到自带实现,无法发挥MKL的性能优势。
内容的提问来源于stack exchange,提问作者Praharsh Suryadevara
相关产品推荐
相关产品推荐

