8

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

在某些情况下,我可以在函数指针的帮助下将条件语句替换为对函数的调用。类似这样的事情。(对于类似类型的场景,您可以考虑基于组件的编程而不是继承)

     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();
        } 
     }

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

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

PS:即使在汇编代码中,我也不介意有人详细概述“分支预测有多糟糕”。

更新:分析后(类似上述代码),
如果条件在这种情况下成功。有人可以给出原因吗?功能调用代码可以预取,因为没有分支代码,对吧?但在这里它看起来是另一种方式..分支代码获胜!:O 在 Intel Mac Osx、GCC O3/Os 优化上进行了分析。

4

3 回答 3

10

您用间接替换了 if 语句。

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

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

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

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

请分享你的结果!

于 2011-10-01T09:51:02.063 回答
3

您需要对此类代码进行概要分析,以便能够针对特定环境(编译器、编译器版本、操作系统、硬件)做出特定声明,并且您需要在特定应用程序中进行测量,以便能够了解这对于该应用程序是否重要。除非您正在编写库代码,否则不要打扰,除非分析表明这是您应用程序中的热点。

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

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

于 2011-10-01T09:30:32.800 回答
3

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

但是如果你调用函数而只实现一个分支(if在你的情况下使用),CPU 更有可能应用它的魔力,即重新排序指令、预取事物等。如果大多数 CPU 之间有函数调用,很可能会“刷新”它们的管道,并且 CPU 优化将不可能。

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

尝试自己测量。调用它 1M 次。在 C++11 中使用<chrono>, monothonic_clock::now().

更新:我的经验是:不要过度优化你的代码——你很可能会让它变得更糟。让编译器完成这项工作,并为此尽可能多地使其可见代码。如果你这样做了,你肯定需要一个分析器,尝试替代方案,使用其中一些为你提供的提示。但不要忘记:这必须非常仔细地微调。只有一种性能衡量标准是速度。还有可读性可测试性和可重用性等等。并引用 Donald Knuth 的话:“过早的优化是万恶之源。”

于 2011-10-01T09:59:15.617 回答