函数调用C ++中可感知的开销?

时间:2012-10-10 11:52:26

标签: c++ performance function-call

在我的项目中,我有一个类,执行时间是第一个目标。对于它我不太关心维护,订单等。至少我直到昨天才关心......现在我处于一种情况,我也有点担心它。

我有一个类,比如A,它对来自相机的图像执行多次扫描,即可变宽度窗口实时扫描它们。



    class A{  
    // methods and attributes of A:  
    ...  
    void runiterator(){  
      ...  
    for{    // change window’s dimension  
      for{  // rows  
       for{ // columns  
          // many lines of code of operations to be executed for each window at each position  
          ...      
       }  
      }   
     }  
    }  
    }; 

性能显示已有一点延迟,但我可以解决它跳过图像的有限区域。此外,我有第二个函数,比如B,它与A具有完全相同的方案,并且在每次扫描时执行不同的操作(幸运的是比A快得多)。

嗯,现在是时候加入所有行动,以显着提高整体效果。只有代码真的变得混乱,巨大并混合真正不同的东西。我想定义一个执行迭代的类X,并且在每次扫描时执行对A_new中的一个函数和B_new中的一个函数的函数调用。但我担心每张图像大约200000x2函数调用会导致性能下降。

你有什么建议?

EDIT
对于只调用Anew的X类(因此它只能与现在的A进行比较),我得到了平均值,多次重复:

在一系列56张图像上执行X的时间= 6.15秒 在相同系列的56张图像上执行A的时间= 5.98秒

我的嫌疑人似乎并不那么天真 差异大约是3%,不是很多,但仍然感到抱歉。

对于X,__ forceinline时间也是5.98秒,但我不想依赖它。

我认为代码已经过优化,进一步改进的利润很少 事实上,它在相对较短的时间内在图像上做了很多事情 在A类中不可能顺序处理数据,因为它基于来自图像的值是不可预测的。这就是为什么B级(设法做到这一点)要快得多的原因。

3 个答案:

答案 0 :(得分:1)

你必须先测量它是否会导致性能问题,然后再担心它。

如果 出现问题,请尝试使用模板进行操作。编写函数的两个变体,然后在函数模板中将它们用作函数,进行迭代。您将实例化两个版本,并调用适当的版本。编译器应该内联调用(但最好验证一下)。

我将它用于医学图像处理,它就像一个魅力。

答案 1 :(得分:1)

函数调用开销很大程度上取决于您调用的函数类型。在汇编程序级别(假设没有偷偷摸摸的OS页面错误处理),现代Intel处理器上的call address指令需要0个周期(jmp address指令也是如此)。如果从某些数据源计算函数地址,则会引入开销,例如vtbl查找,对外部DLL的调用(如果您使用的是Win32)或者涉及条件。这些涉及访问内存和污染缓存。这将我们带到了大人物。

等待数据进入CPU时,大多数性能都会丢失。 CPU的速度远远大于从RAM读取数据的速度。这就是为什么每个级别有几个级别的缓存通常比前一个级别更大和更慢。函数调用(即使是复杂函数调用)的成本也低于在数据读取时丢失缓存所花费的时间。

这类事情属于标题:微优化。

通常,避免随机数据访问,按顺序处理数据,即执行n项,然后是n + 1,n + 2等,而不是n,n + 100,n + 200等,n + 1,n + 101,n + 201等

此外,让编译器有机会内联函数 - 这样,如果结果产生更快的代码就会完成内联(并且编译器非常了解什么时候有用)。

另请注意,大函数可能比许多小函数慢(这与CPU本地缓存的uops缓冲区有关)。多次迭代数据可能比一次性完成所有操作更快。只分析代码会告诉你哪一个更快。

最后,更好的算法通常是提高性能的方法。你的算法是最优的吗?

答案 2 :(得分:0)

你必须衡量效果,因为很难说出编译器真正产生了什么 - 特别是在O3。当然,如果编译器没有内联函数,函数调用会产生开销。如果可以内联函数,请尝试向编译器提供inline提示。