使用行主矩阵的本征矩阵乘法性能

时间:2018-08-11 21:38:31

标签: c++ eigen

遇到以下问题时,我正在分析代码以获得更好的性能。
以下代码将两个矩阵随机化,然后将它们相乘,以不同的方式和不同的性能获得相同的结果。

#include <iostream>
#include "Eigen/Dense"
#include <chrono>

using namespace Eigen;
using namespace std;

class Timer {
protected:
  std::chrono::high_resolution_clock::time_point t1_;
  string message_;

public:
  Timer(){t1_ = chrono::high_resolution_clock::now();}
  virtual ~Timer() {}

  void time(const char* msg) {
    auto t2 = chrono::high_resolution_clock::now();
    cerr << msg << ": "
              << chrono::duration_cast<chrono::milliseconds>(t2 - t1_)
                         .count() << " ms\n";
    t1_ = t2;

  }
};

typedef Matrix<float, -1, -1, RowMajor> MatrixXRMf;

int main(int argc, char** argv) {
  Timer timer;

  MatrixXf A = MatrixXf::Random(10, 4096);
  MatrixXf B = MatrixXf::Random(4096, 10000);
  timer.time("random");

  MatrixXf C1 = A * B;
  timer.time("col-maj 1");

  MatrixXf C2 = (B.transpose() * A.transpose());
  C2.transposeInPlace();
  timer.time("col-maj 2");


  MatrixXRMf A_rm = A;
  MatrixXRMf B_rm = B;
  timer.time("assignment");

  MatrixXRMf C3 = A_rm * B_rm;
  timer.time("row-maj 1");

  MatrixXRMf C4 = (B_rm.transpose() * A_rm.transpose());
  C4.transposeInPlace();
  timer.time("row-maj 2");

  cout << "C3 == C1: " << C3.isApprox(C1) << endl;

  return 0;
}

打印结果是

random: 352 ms
col-maj 1: 130 ms
col-maj 2: 72 ms
assignment: 981 ms
row-maj 1: 62 ms
row-maj 2: 80 ms
C3 == C1: 1

为什么C1乘法比C3慢? 如果将C1乘法几次,可能会导致严重的性能损失。

本征:3.3.4
编译器:GCC 5.4
操作系统:Ubuntu16

编辑: 编译标志:-O3 -mavx -mfma -fopenmp

编辑: 我有两个重现此行为的ubuntu16机器 和另一台无法复制的ubuntu16机器

1 个答案:

答案 0 :(得分:0)

我得到了完全不同的结果,OSX,2.6Ghz Haswell(关闭了推升):

# gcc-7 -O3  -mavx -mfma
random: 498 ms
col-maj 1: 26 ms
col-maj 2: 69 ms
assignment: 674 ms
row-maj 1: 50 ms
row-maj 2: 57 ms

# Apples's clang 8 -O3  -mavx -mfma
random: 478 ms
col-maj 1: 25 ms
col-maj 2: 66 ms
assignment: 666 ms
row-maj 1: 55 ms
row-maj 2: 75 ms

然后将RowVectorXfVectorXfAC1(分别为{{1 }},A_rm),然后删除无用的C3,我得到:

C2

编辑:使用了已编辑的问题(例如C4)后,即使像问题中那样使用gcc-5,我仍然无法复制:

transposeInPlace