【问题标题】:Can function overhead slow down a program by a factor of 50x?函数开销可以使程序减慢 50 倍吗?
【发布时间】:2011-12-06 03:03:41
【问题描述】:

我有一个正在为一个项目运行的代码。它是 O(N^2),对于我来说,N 是 200。有一种算法可以将此 O(N^2) 转换为 O(N logN)。这意味着,使用这种新算法,它应该快 100 倍左右。但是,我只得到了 2 倍的增长(也就是 2 倍快)。

我试图缩小范围,看看我是否搞砸了,或者这是否是我编写这个程序的方式所固有的。对于初学者,我在嵌套类中有很多函数开销。例如,我有很多这样的(在许多循环中):

energy = globals->pair_style->LJ->energy();

由于我在实际数据方面得到了正确的结果,只是错误的速度增加,我想知道函数开销是否实际上会导致 很大的速度减少多达 50 倍。

谢谢!

【问题讨论】:

  • 尝试在探查器下运行这两种方法,并查看每种方法花费的时间。
  • Big-O 表示法显示了某些东西的扩展方式,而不一定是它的执行方式。对于较小的 N 值,您可能根本看不到任何差异。
  • “它是 O(N^2),对于我来说 N 是 200”。你有它。您没有正确使用大哦符号。如果“对于 [您的] 案例,N 为 200”,则为 O(1)。
  • 天哪。首先,我很抱歉将性能与 Big-O 表示法混淆。其次,@Mankarse:您会建议使用探查器吗?第三,我真的很希望它不是函数开销,否则我将不得不将所有东西都塞进一个,使它非常非常难看并且非常工作密集
  • @Amit:在 OSX 上,我喜欢使用 Activity Monitor 内置的分析器(这是我唯一广泛使用的分析器)。在 Windows 上,Very Sleepy 取得了不错的效果。我没有在其他系统上做太多的分析,但请查看here 以获得更多建议。

标签: c++ overhead


【解决方案1】:

首先,您认为O(N logN)O(N^2) 对于N=200 快约100 倍的解释是不正确的。 big-Oh 表示法处理限制中的上限和行为,并且不考虑复杂性中的任何乘法常数。

其次,是的,在现代硬件上,由于管道中断,函数调用往往相对昂贵。要了解这对您的情况有多大影响,您必须提出一些微基准。

【讨论】:

    【解决方案2】:

    绝对最大的打击是缓存未命中。 L1 缓存未命中相对便宜,但是当您在 L2(或 L3,如果有)上未命中时,您可能会丢失数百甚至数千个周期到即将到来的停顿。

    虽然这可能只是问题的一部分。在对代码进行概要分析之前,不要优化您的代码。识别慢速区域,然后找出它们慢速的原因。一旦您了解了它运行缓慢的原因,您就有机会对其进行优化。

    顺便说一句,O 表示法非常方便,但不是全部和全部。我已经看到 O(n^2) 算法的工作速度明显快于 O(n log n),因为它们缓存的效率更高。

    【讨论】:

    • @Amit:vTune 可能是英特尔 x86 芯片中最好的,但它并不便宜。但是,30 天免费试用非常便宜 ;)
    【解决方案3】:

    Big O 表示法的重要之处在于它只指定执行时间的限制,随着数据集大小的增加 - 任何常量都会被丢弃。虽然 O(N^2) 确实比 O(N log N) 慢,但 实际 运行时间可能是 N^2 与 1000N log N - 即 O(N^2)在某些数据集上可能比 O(N log N)

    没有更多细节,很难说更多 - 是的,函数调用确实有相当多的开销,这可能就是为什么你没有看到更大的性能提升 - 或者可能只是这种情况您的 O(N log N) 在您大小的数据集上表现不佳。

    【讨论】:

    • 这真的很有趣。我没有意识到这一点!是否有可能的编译标志可以在一定程度上减少函数开销?我目前正在使用 -O3 编译并使用 intel 的 icpc 编译器
    • @Amit:我知道减少函数开销的唯一方法是通过内联完全避免它 - 而 can 确实会产生巨大的影响。同样,没有更多细节是不可能知道的。因此,如有必要,请通过分析器运行它。
    【解决方案4】:

    我研究过图像处理算法,每像素调用一个函数(即:对于 640x480 将是 307200)会显着降低性能。尝试将您的函数声明为内联,或将函数设为宏。这可以快速显示是否是因为函数调用。尝试查看一些分析工具。 VS 2010 自带了一些不错的工具,否则还有 Intel VTune、glowcode。他们可以帮助显示您在哪里花费时间。

    恕我直言,我认为 1600 次函数调用根本不会降低性能(200 log 200)

    【讨论】:

      【解决方案5】:

      我建议使用分析它

      关于分析的重要常见问题解答主题在这里:How can I profile C++ code running in Linux?

      • gprof(需要编译时检测)
      • valgrind --tool=callgrindkcachegrind;具有出色可视化效果的出色工具 - 此处为屏幕截图:

      【讨论】:

        猜你喜欢
        • 2015-04-21
        • 1970-01-01
        • 1970-01-01
        • 2011-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-28
        相关资源
        最近更新 更多