【问题标题】:Intel C++ Compiler understanding what optimization is performed英特尔 C++ 编译器了解执行了哪些优化
【发布时间】:2011-02-05 06:10:56
【问题描述】:

我有一个简单的代码段:

for( int i = 0; i < n; ++i)
{
  if( data[i] > c && data[i] < r )
  {
    --data[i];
  }
}

这是一个大型功能和项目的一部分。这实际上是对不同循环的重写,这被证明是耗时的(长循环),但我对两件事感到惊讶:

当 data[i] 像这样临时存储时:

for( int i = 0; i < n; ++i)
{
  const int tmp = data[i];
  if( tmp > c && tmp < r )
  {
    --data[i];
  }
}

它变得更慢了。我不认为这应该更快,但我不明白为什么它应该这么慢,编译器应该能够确定是否应该使用 tmp。

但更重要的是,当我将代码段移到一个单独的函数中时,它的速度大约慢了四倍。我想了解发生了什么,所以我查看了 opt-report,在这两种情况下,循环都是矢量化的,并且似乎做了相同的优化。

所以我的问题是什么可以对一个没有被调用一百万次但本身很耗时的函数产生如此大的影响?在 opt-report 中寻找什么?

我可以通过保持它内联来避免它,但为什么困扰着我。

更新:

我应该强调,我主要关心的是理解为什么它在移动到一个单独的函数时变得更慢。使用 tmp 变量给出的代码示例,只是我在此过程中遇到的一个奇怪示例。

【问题讨论】:

  • 只是一个强制性问题:您对所有构建都有最大优化?
  • 尝试查看生成的程序集。
  • 是的,都是用 O3 编译的。我还没有看过程序集,只是因为它是一个大型项目的一部分(也因为我不是程序集专家)。

标签: c++ optimization compiler-construction intel


【解决方案1】:

您可能是寄存器匮乏,编译器不得不加载和存储。我很确定本机 x86 汇编指令可以使用内存地址来操作 - 即编译器可以保持这些寄存器空闲。但是通过将其设为本地,您可能会改变行为。别名和编译器可能无法证明更快的版本具有相同的语义,特别是如果这里有某种形式的多线程,允许它更改代码。

函数在新段中的速度较慢,可能是因为函数调用不仅会破坏管道,而且还会导致指令缓存性能不佳(参数推送/弹出/等有额外的代码)。

教训:让编译器做优化,它比你聪明。我不是说这是侮辱,它也比我聪明。但实际上,尤其是英特尔编译器,这些人知道他们在针对自己的平台时在做什么。

编辑:更重要的是,您需要认识到编译器的目标是优化未优化的代码。它们的目标不是识别半优化代码。具体来说,编译器将为每个优化设置一组触发器,如果​​您碰巧编写代码时它们不会被命中,您可以避免执行优化即使代码在语义上是相同的。

您还需要考虑实施成本。并非所有适合内联的函数都可以内联——因为内联该逻辑太复杂,编译器无法处理。我知道 VC++ 很少会内联循环,即使内联会带来好处。您可能会在 Intel 编译器中看到这一点——编译器编写者只是认为不值得花时间来实现。

我在处理 VC++ 中的循环时遇到过这种情况——编译器会为两个格式略有不同的循环生成不同的程序集,即使它们都实现了相同的结果。当然,他们的标准库使用了理想的格式。您可以通过使用std::for_each 和函数对象来观察加速。

【讨论】:

  • 我同意这个教训,但我不想比编译器更聪明,只是为了理解和学习改进代码以更好地适应编译器。实际的问题是理解为什么移动到另一个文件时它会变慢。
  • @Bo Jensen:这是因为由于 C++ 的设计方式,许多编译器无法跨翻译单元执行内联。我相信最新版本的 VC++ 可以做到这一点,也许 GCC 也可以,但我不认为英特尔可以。
  • 感谢您的回复。但函数在同一个文件中。
【解决方案2】:

您是对的,编译器应该能够将其识别为未使用的代码并将其删除/不编译。这并不意味着它确实会识别并删除它。

最好的办法是查看生成的程序集并检查到底发生了什么。请记住,仅仅因为聪明的编译器能够弄清楚如何进行优化,并不意味着它可以。

如果您检查并发现代码没有被删除,您可能需要向英特尔编译器团队报告。听起来他们可能有错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-30
    • 1970-01-01
    • 2014-08-29
    • 2016-03-22
    • 1970-01-01
    • 2011-02-14
    • 2017-10-07
    • 1970-01-01
    相关资源
    最近更新 更多