C++ eigen3线性代数库,性能奇怪

eno*_*ram 4 c++ performance gcc vectorization eigen

我已经在c ++中使用了eigen3线性代数库一段时间了,我一直试图利用矢量化性能优势.今天,我决定测试多少矢量化真正加速我的程序.所以,我写了以下测试程序:

--- eigentest.cpp ---

#include <eigen3/Eigen/Dense>
using namespace Eigen;

#include <iostream>

int main() {
        Matrix4d accumulator=Matrix4d::Zero();
        Matrix4d randMat = Matrix4d::Random();
        Matrix4d constMat = Matrix4d::Constant(2);
        for(int i=0; i<1000000; i++) {
                randMat+=constMat;
                accumulator+=randMat*randMat;
        }
        std::cout<<accumulator(0,0)<<"\n"; // To avoid optimizing everything away
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

然后我用不同的编译器选项编译它后运行这个程序:(结果不是一次性的,很多运行给出类似的结果)

$ g++ eigentest.cpp  -o eigentest -DNDEBUG -std=c++0x -march=native
$ time ./eigentest
5.33334e+18

real    0m4.409s
user    0m4.404s
sys 0m0.000s
$ g++ eigentest.cpp  -o eigentest -DNDEBUG -std=c++0x
$ time ./eigentest 
5.33334e+18

real    0m4.085s
user    0m4.040s
sys 0m0.000s
$ g++ eigentest.cpp  -o eigentest -DNDEBUG -std=c++0x -march=native -O3
$ time ./eigentest 
5.33334e+18

real    0m0.147s
user    0m0.136s
sys 0m0.000s
$ g++ eigentest.cpp  -o eigentest -DNDEBUG -std=c++0x -O3
$time ./eigentest
5.33334e+18

real    0m0.025s
user    0m0.024s
sys 0m0.000s
Run Code Online (Sandbox Code Playgroud)

这是我的相关cpu信息:

model name  : AMD Athlon(tm) 64 X2 Dual Core Processor 5600+
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt rdtscp lm 3dnowext 3dnow extd_apicid pni cx16 lahf_lm cmp_legacy svm extapic cr8_legacy 3dn
Run Code Online (Sandbox Code Playgroud)

我知道当我不使用编译器选项-march=native时没有向量化,因为当我不使用它时,我从未得到分段错误,或者由于向量化而导致错误的结果,而不是我使用它的情况(与-NDEBUG).

这些结果让我相信,至少在我的CPU上使用eigen3进行矢量化会导致执行速度变慢.我应该责怪谁?我的CPU,eigen3还是gcc?

编辑:为了消除任何疑虑,我现在尝试添加-DEIGEN_DONT_ALIGN编译器选项,以便我尝试测量无向量化情况的性能,结果是相同的.此外,当我加-DEIGEN_DONT_ALIGN一起-march=native的结果变得非常接近,没有的情况下-march=native.

Jit*_*sen 9

似乎编译器比你想象的更聪明,并且仍然优化了许多东西.

在我的平台上,我得到-march=native大约9毫秒,大约39毫秒-march=native.但是,如果我将返回上方的行替换为

std::cout<<accumulator<<"\n";
Run Code Online (Sandbox Code Playgroud)

然后时间变为78毫秒,没有-march=native和大约39毫秒-march=native.

因此,似乎没有矢量化,编译器意识到您只使用矩阵的(0,0)元素,因此它只计算该元素.但是,如果启用了矢量化,则无法执行该优化.

如果你输出整个矩阵,从而迫使编译器计算所有条目,那么矢量化就像预期的那样以2倍加速程序(虽然我很惊讶地发现它在我的时间中恰好是2因素).