我对跨几个编译器(GCC、MSVC、Clang)编写性能代码很感兴趣。我看到了将函数作为编译时参数传递的两种模式,我很好奇编译器通常是否足够聪明地识别这两者是等价的,还是要求太多了。下面是STL样式,传递一个函子对象:
template<class InputIterator, class Predicate>
InputIterator find_if ( InputIterator first, InputIterator last, Predicate pred )
{
for ( ; first!=last ; first++ ) if ( pred(*first) ) break;
return first;
}这是另一种风格:
template<class InputIterator, class Predicate, class PredData>
InputIterator find_if ( InputIterator first, InputIterator last, PredData data )
{
for ( ; first!=last ; first++ ) if ( Predicate::eval(*first, data) ) break;
return first;
}在STL样式中,谓词类通常包含它所需的任何数据作为成员,并调用operator()来计算谓词。在另一种样式中,您从来没有谓词对象,而是包含一个接受要检查的项的静态方法,并且数据作为参数传递,而不是作为谓词上的成员存储。
我对使用STL风格有些担心:
如果谓词是一个单词或更小的
因此,我的直觉是,替代风格应该更快,但也许我低估了现代优化。
发布于 2012-02-23 19:25:02
根据我在gcc (g++)的个人经验,现代编译器绝对能够优化函子。有一种情况可能不是这样,那就是函子在不同的编译单元中。
也就是说,这不应该让你望而却步,C++库和方向通过使用现代风格来奖励你,它是一种使用抽象的更易于管理的语言。
我运行了一个实验,比较了使用for、std::for_each (函数)、std::for_each (与函子)和std::for_each (与lambda)的循环。编译器能够看到所有内联的指令的过去,每个编译器都有相同的执行时间和指令数量(尽管指令的结构略有不同)。
最后,Herb在他的一次演讲中(在build,我认为)说,C++风格比C风格只增加了3%的开销,与其更高的安全性相比,这一点都不算什么。
发布于 2012-02-23 19:28:15
编译器可以执行许多优化,但要记住的一点是,不同的编译器会有不同的优化,而对一个编译器最有效的优化可能不会对另一个编译器产生影响。
在C++11中,有一些移动语义可以优化谓词对象的副本。由于这是在标准中,所有编译器都应该实现相同的优化,第一种风格将具有与第二种相似的性能。
支持STL风格的另一点是,作为一种常见的模式,您可能有更多的机会进行编译器优化,因为编译器供应商将针对这些使用模式。
此外,您应该使用分析器来评估性能提高,因为程序员通常不善于猜测代码中的瓶颈是什么和瓶颈在哪里。
https://stackoverflow.com/questions/9419589
复制相似问题