【问题标题】:Why instrumented C program runs faster?为什么检测的 C 程序运行得更快?
【发布时间】:2012-09-22 03:33:30
【问题描述】:

我正在开发一个(相当大的)现有单线程 C 应用程序。在这种情况下,我修改了应用程序以执行一些非常少的额外工作,包括每次调用特殊函数时递增计数器(此函数被调用约 80.000 次)。该应用程序在 Ubuntu 12.04 上编译,运行 64 位 Linux 内核 3.2.0-31-generic,带有 -O3 选项。

令人惊讶的是,经过检测的代码版本运行速度更快,我正在调查原因。我使用 clock_gettime(CLOCK_PROCESS_CPUTIME_ID) 测量执行时间并获得具有代表性的结果,我报告了超过 100 次运行的平均执行时间值。此外,为了避免来自外界的干扰,我尽可能尝试在没有任何其他应用程序运行的系统中启动应用程序(附带说明,因为 CLOCK_PROCESS_CPUTIME_ID 返回进程时间而不是挂钟时间,其他应用程序“应该”在理论上只影响缓存而不直接影响进程执行时间)

我怀疑“指令缓存效应”,也许稍微大一点(几个字节)的检测代码在缓存中的适应方式不同且更好,这个假设可以想象吗?我尝试使用 valegrind --tool=cachegrind 进行一些缓存调查,但不幸的是,检测后的版本比初始版本有更多的缓存未命中(似乎合乎逻辑)。

欢迎任何有关此主题的提示和想法,可能有助于找出检测代码运行速度更快的原因(某些 GCC 优化在一种情况下可用,而在另一种情况下不可用,为什么?,...)

【问题讨论】:

  • 在不知道任何代码的情况下,很难对您的问题给出明确的答案。
  • @FUZxxl:我认为这就是为什么问题是“我在做我的工作时可以考虑哪些因素”,而不是通常的 SO 格式,“请为我做我的工作”;-)
  • @FUZxxl 正如史蒂夫·杰索普所说,在这里提供代码很困难,因为它很大,我正在寻求有关方向的帮助而不是答案,说“问题就在这里文件 mem.c 的 345”。如果您有任何提示,请随时添加答案。
  • @ArjunShankar ~5% 执行约 7 秒。
  • @ManuelSelva - Inlining isn't always a win。有时它会降低性能。无论如何,我的评论大多是疯狂的猜测。

标签: c linux performance gcc


【解决方案1】:

由于问题的细节不多,我只能推荐一些在调查问题时需要考虑的因素。

很少有额外的工作(例如递增计数器)可能会改变编译器关于是否应用某些优化的决定。编译器并不总是有足够的信息来做出完美的选择。它可能会尝试优化瓶颈是代码大小的速度。当没有太多数据需要处理时,它可能会尝试自动矢量化计算。编译器可能不知道要处理什么样的数据,或者执行代码的 CPU 的确切型号是什么。

  1. 增加计数器可能会增加某些循环的大小并阻止循环展开。这可能会减少代码大小(并改善代码局部性,这对于指令或微码缓存或循环缓冲区很有用,并允许 CPU 快速获取/解码指令)。
  2. 增加计数器可能会增加某些函数的大小并阻止内联。这也可能会减少代码大小。
  3. 增加计数器可能会阻止自动矢量化,这又可能会减小代码大小。

即使此更改不影响编译器优化,它也可能会改变 CPU 执行代码的方式。

  1. 如果您在适当位置插入计数器递增代码,其中充满了分支目标,这可能会降低分支目标的密集度并改进分支预测。
  2. 如果您在某个特定的分支目标前插入计数器递增代码,这可能会使分支目标的地址更好地对齐并加快代码获取速度。
  3. 如果您在写入某些数据之后但在再次加载相同数据之前放置计数器递增代码(并且由于某种原因存储到加载转发不起作用),加载操作可能会更早完成。
  4. 插入计数器递增代码可以防止两次冲突的加载尝试到 L1 数据缓存中的同一存储区。
  5. 插入计数器递增代码可能会改变某些 CPU 调度程序的决策,并使某些执行端口可及时用于某些性能关键指令。

要研究编译器优化的效果,您可以比较在添加反递增代码之前和之后生成的汇编代码。

要调查 CPU 影响,请使用允许检查处理器性能计数器的分析器。

【讨论】:

  • +1 用于比较汇编代码。那也是我要调查的第一个地方。
【解决方案2】:

根据我对嵌入式编译器的经验猜测,编译器中的优化工具会寻找递归任务。也许额外的代码迫使编译器看到更多递归的东西,并且它以不同的方式构造了机器代码。编译器为优化做了一些奇怪的事情。在某些语言中(我认为是 Perl?),“不是”条件比“真”条件执行得更快。您的调试工具是否允许您单步执行代码/程序集比较?这可以增加一些关于编译器决定如何处理额外任务的见解。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-31
    • 2014-10-09
    • 1970-01-01
    • 2012-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多