has*_*san 11 c++ algorithm optimization stl
我有两个用C++编写的算法.据我所知,通常使用
-O0 -NDEBUG(g ++)进行编译,同时比较两种算法的性能(无症状地相同).但我认为优化级别对其中一个是不公平的,因为它在每种情况下都使用STL.使用普通数组的程序在使用-O0选项编译时,速度比STL重算法快5倍.但是当我使用-O2 -NDEBUG编译它们时,性能差异并没有太大的不同.
有没有办法在优化级别-O0中充分利用STL(我在vector []运算符中获得了很高的性能)?
在比较两种算法时,您使用了哪些优化级别(以及可能的变量,如-NDEBUG)?
如果有人能够对比较C++编写的算法性能的学术研究趋势有所了解,那将会很有帮助吗?
好的,为了隔离优化级别的问题,我现在使用一种算法但两种不同的实现.
我用原始指针(int和boolean)将其中一个函数改为std :: vector和std :: vector ...使用-O0 -NDEBUG,性能为5.46s(原始指针)和11.1s(std :: vector) ).使用-O2 -NDEBUG,性能为2.02s(原始指针)和2.21s(std :: vector).相同的算法,一个实现使用int和boolean的4/5动态数组.另一个是使用std :: vector和std :: vector代替.在其他所有情况下都是一样的
你可以看到-O0 std :: vector的性能比指针速度快了两倍.在-O2中,它们几乎相同.
但我真的很困惑,因为在学术领域,当他们在运行时发布算法结果时,他们用-O0编译程序.
我缺少一些编译器选项吗?
这取决于您想要优化的内容.
我建议使用-O2 -NDEBUG -ftree-vectorize,如果您的代码专门设计为在x86或x86_64上运行,请添加-msse2.这将让您对GIMPLE的表现有一个广泛的了解.
我相信你应该用-Os -fno-rtti -fno-exceptions -fomit-frame-pointer.这将最小化可执行文件的大小到一定程度(假设C++).
在这两种情况下,算法的速度都不依赖于编译器,但是如果编译器可以"证明"它可以,则编译器可以大大改变代码的行为方式.
GCC检测"公共"代码,例如手动编码min(),max()并将它们转换为一条SSE指令(在x86/x86_64上,当设置了-msse时)或在i686可用时使用cmov(SSE具有更高的优先级).GCC还可以自由地重新排序循环,展开和内联函数,如果它想要,甚至删除无用的代码.
至于你最新的编辑:
你可以看到-O0 std :: vector的性能比指针速度快了两倍.在-O2中,它们几乎相同.
那是因为std::vector仍然有代码抛出异常并可能使用rtti.尝试比较-O2 -NDEBUG -ftree-vectorize -fno-rtti -fno-exceptions -fomit-frame-pointer,你会发现std :: vector会比你的代码略好一些.GCC知道什么是"内置"类型以及如何在现实世界中使用它们并且很乐意这样做 - 就像它知道什么memset()和memcpy()做什么以及如何在知道复制大小时相应地进行优化.
编译器优化通常不会改变算法的复杂度顺序,只会改变常量和线性比例因子.编译器相当聪明,但它们并不那么聪明.
你打算用-O0编译你的代码以便发布吗?可能不是.您可以在编译时使用您实际打算使用的任何编译标志来比较算法的性能.