【问题标题】:C++ eigen3 linear algebra library, odd performance resultsC++ eigen3 线性代数库,奇怪的性能结果
【发布时间】:2012-04-09 23:24:53
【问题描述】:

我在 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;
}

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

$ 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

这是我的相关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

我知道当我不使用编译器选项-march=native 时不会进行向量化,因为当我不使用它时,我永远不会因为向量化而出现分段错误或错误结果,而不是我使用它的情况(-NDEBUG)。

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

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

【问题讨论】:

  • 你用的是哪个g++版本?
  • 在我的平台(英特尔 Q9550)上,无论我是否使用 March=native,我都能获得相同的速度。但是,-O3 会导致激进的内联、使用 SSE 和展开。添加 -mss3 会导致组装略有不同,但运行时性能完全相同。我真的不明白你对段错误的看法,你有一组编译器标志会导致你的程序崩溃吗?
  • @KillianDS 我的 gcc 版本:gcc --versiongcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2
  • @Bob 我已经尝试通过在 Vector2d 成员之前定义一个带有 char 成员的类来故意设置一个矢量化问题,没有 EIGEN_MAKE_ALIGNED_OPERATOR_NEW 然后创建一个带有 new 并编译的对象-NDEBUG 绕过断言。如果没有-march=native,我会从计算中得到正确的结果,并且有了它,我会遇到分段错误。这告诉我,没有 -march 就不会使用矢量化。

标签: c++ performance gcc vectorization eigen


【解决方案1】:

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

在我的平台上,没有-march=native 时我得到大约 9 毫秒,而使用 -march=native 时我得到大约 39 毫秒。但是,如果我将返回上方的行替换为

std::cout<<accumulator<<"\n";

然后在没有-march=native 的情况下时间更改为 78 毫秒,在-march=native 情况下更改为大约 39 毫秒。

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

如果您输出整个矩阵,从而迫使编译器计算所有条目,那么向量化会按照预期以因子 2 加速程序(尽管我很惊讶地发现它恰好是我的因子 2时间)。

【讨论】:

  • 不错的收获!编译器确实比我想象的要聪明。仅供参考,我已经运行了相同的测试,我在Intel(R) Core(TM) i3 CPU M 350 @ 2.27GHz 上得到了 42 毫秒与 112 毫秒,明天我将尝试使用问题中提到的 CPU 进行相同的测试,看看它是如何运行的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-22
  • 1970-01-01
  • 2017-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多