遇到以下问题时,我正在分析代码以获得更好的性能。
以下代码将两个矩阵随机化,然后将它们相乘,以不同的方式和不同的性能获得相同的结果。
#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机器
答案 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
然后将RowVectorXf
,VectorXf
,A
,C1
(分别为{{1 }},A_rm
),然后删除无用的C3
,我得到:
C2
编辑:使用了已编辑的问题(例如C4
)后,即使像问题中那样使用gcc-5,我仍然无法复制:
transposeInPlace