哪一个更快?函数调用或条件if语句?

时间:2011-10-01 09:23:47

标签: c++ optimization architecture compiler-optimization data-oriented-design

在回答这个问题之前,请考虑分支预测。

我有一些场景,我可以在函数指针的帮助下用函数调用替换条件语句。这样的事情。 (你可以想到基于组件的编程而不是类似类型的senario的继承)

     class Shape
     {
        float Area()
        {
            if(type == SQUARE)
             {
                return length*length;
             }
            else if(type == RECTANGLE)
            {
             return length*breadth;
            }
        } 
     }

同一个班级可以这样写。

       class Shape
     {
        void SetAreaFunction(void *funcptr)//this function is used to set the current AreaFunc
        {
             CurrentAreaFunc = funcptr ;//this holds the pointer to current area func
        }
        float SqauareArea();//this will return square area
        float RectangleArea();//this will return rectangle area 
        float Area()
        {
            currentAreaFunc();
        } 
     }

如果考虑上述情况,两者都会得到相同的结果。但是,我正在考虑性能开销。在第二种情况下,我通过函数调用避免了分支预测问题。

现在让我知道哪种更好的做法和'更优化的代码'在这种情况下。(顺便说一句,我不喜欢“早熟优化是万恶之源”的说法,因为,优化有它的好处所以我考虑优化我的代码!)

P.S:我不介意是否有人详细概述了“即使在汇编代码中分支预测有多糟糕”。

更新:分析后(类似上面的代码),
     如果条件在这种情况下成功了。任何人都可以说明理由吗? 功能调用代码可以预取,因为没有分支代码吗?但在这里它看起来是另一种方式..分支代码获胜! :o 详细介绍了Intel Mac Osx,GCC O3 / Os优化。

3 个答案:

答案 0 :(得分:9)

您使用间接替换了if语句。

你的if语句和间接都需要内存访问。

但是,if会导致短跳转 - 这可能不会使管道无效,而间接可能会使管道无效。

另一方面,间接是跳转,而if语句是条件跳转。分支预测器可能会错过。

如果不进行测试,很难说哪个更快。我预测if语句会赢。

请分享您的结果!

答案 1 :(得分:3)

您需要对这些代码进行分析,以便能够为特定环境(编译器,编译器版本,操作系统,硬件)创建特定语句,并且您需要在特定应用程序中进行测量,以便能够知道这是否对于那个申请。除非您正在编写库代码,否则不要打扰,除非分析表明这是您应用程序中的热点。

只需编写最易读的代码,这是最容易维护的。与修复错误优化代码相比,优化干净,无错误且易于阅读的代码总是更容易。

那就是说,我记得Lippman在他的 C ++对象模型中引用的研究发现,虚拟函数(基本上是函数指针)至少与在实际应用程序中切换类型一样快。我不知道细节,但它在书中的某个地方。

答案 2 :(得分:3)

优化器更有可能在if语句上应用他的魔法,然后在动态变化的函数指针上应用。只是一个猜测,从理论上讲,编译器可以做任何他可以证明不会改变语义的东西。

但是如果您调用一个函数但只实现一个分支(在您的情况下使用if),则CPU更有可能应用 em>魔术,即重新排序指令,预取事物等。如果在大多数CPU之间存在函数调用,很可能会“刷新”它们的管道,并且无法进行CPU优化。

也就是说,如果你把所有内容都放在头文件,调用者和被调用者中,编译器可能会取消函数调用,会自行重新排序等等。

尝试自己测量一下。称它为1M次。使用C ++ 11时,请使用<chrono>monothonic_clock::now()

更新:我的经验是:不要过度优化你的代码 - 你很可能会让它变得更糟。让编译器完成工作,为此,尽可能多地使代码可见。如果你这样做,你肯定需要一个分析器,尝试替代方案,使用其中一些提供给你的提示。但不要忘记:这必须非常仔细地进行微调。只有一次 还有可读性可测试性可重用性等等。引用唐纳德·克努特的话说:“过早优化是万恶之源。”