性能测试-Armadillo(OpenBLAS),Eigen3,numpy,QR分解

微信公众号:科文路。转发须注明出处。

想一窥两个 C++ 矩阵库的性能,写了个程序,对比测试了下两个库在 QR 分解上的计算时间。

为了不让错误的结论影响他人,诚邀勘误。

声明:请勿将此文作为严肃文章参考!Notice: This article is not rigorous!

1 环境

  • 某不方便透露的比较强的服务器。
  • GCC 7.5.0
  • CentOS 6

2 版本

  • numpy,1.19.2
  • Armadillo 10.7.3,动态库
  • OpenBLAS 0.3.18,动态库
  • Eigen 3.4.0,头文件

3 数据

4 个随机数矩阵

1
2
3
4
5
6
7
8
import numpy as np

np.random.seed(30)

m10 = np.random.randint(10000, size=(10, 10))
m100 = np.random.randint(10000, size=(100, 100))
m1000 = np.random.randint(10000, size=(1000, 1000))
m10000 = np.random.randint(10000, size=(10000, 10000))

4 代码

加载数据

  • numpy,使用 loadtxt
  • Armadillo,使用 arma::mat 和它的 load() 函数
  • Eigen3,使用 fstream 写入 Eigen::MatrixXd

QR 分解

  • Armadillo,使用 arma::qr_econ() 计算后取得 R 矩阵
  • Eigen3,使用 HouseholderQR<MatrixXd> 构造初始化后,由 matrixQR().triangularView<Upper>() 取得 R 矩阵

计时

  • numpy,使用 %%timeit
  • Armadillo,使用 std::chrono 计时,各跑 5 次后计算平均数
  • Eigen3, 使用 std::chrono 计时,各跑 5 次后计算平均数

5 结果

  • QR 分解平均时间,单位(除特别说明外,µs),四舍五入到个位
  • R 矩阵末行末列数,作为判断计算结果正确性依据

numpy

  • 10x10,846 µs ± 793 µs
  • 100x100,3.96 ms ± 2.93 ms
  • 1000x1000,60.1 ms ± 3.68 ms
  • 10000x10000,6.78 s ± 7.94 ms

Armadillo

  • 10x10,95
  • 100x100,11 867
  • 1000x1000,8 451 469
  • 10000x10000,154254133(计算错误)

Eigen3

  • 10x10,145
  • 100x100,17 508
  • 1000x1000,7 898 760
  • 10000x10000,7 402 371 332

Eigen3,采取 -O2 编译选项

  • 10x10,10
  • 100x100,402
  • 1000x1000,118 003
  • 10000x10000,119 083 247

Eigen3,采取 -O2 -march=native 编译选项

感谢知乎评论区 @插地魔 指导

  • 10x10,15
  • 100x100,316
  • 1000x1000,35 439
  • 10000x10000,31 657 171

6 结论

  • numpy 快,不知具体原因(可能 C++ 这边受运行时库拖累了?)
  • Armadillo 在矩阵较小时,对 Eigen3 有微弱优势;但当矩阵较大时,不能得出结果
  • Eigen3 仅使用头文件就能运行;能在矩阵较大时得出正确结果;采取 -O2 -march=native 编译选项后,Eigen3 速度得到大幅提升,但仍比 numpy 慢很多。

Eigen3,棒!

性能测试-Armadillo(OpenBLAS),Eigen3,numpy,QR分解

https://xlindo.com/kewenlu2022/posts/e3d07952/

Author

xlindo

Posted on

2022-01-07

Updated on

2023-05-10

Licensed under

Comments