【问题标题】:Compile time optimization given constant function arguments给定常量函数参数的编译时间优化
【发布时间】:2018-06-29 04:47:32
【问题描述】:

我有两个函数void f(int x){...}void g(int x){f(x);}。我知道 99% 的时间 g() 收到 3 或 5。在 f() 中,x 永远不会更改并监督大量循环和条件分支。以下会比我的原始代码更快吗?

void g(int x)
{
  if(x == 3) f(3);
  else if(x == 5) f(5);
  else f(x);
}

编译器 (g++ -Ofast) 是否会与 f(x) 分别编译 f(3)f(5),类似于编译两个模板参数?我还应该怎么做才能让编译器更容易地确认优化机会?声明void f(const int &x){...} 有用还是有必要?

【问题讨论】:

  • 如果xf() 和/或g() 中没有变化,最好将其作为const 传递。不确定它是否有助于提高性能,但它肯定会通知编译器x 的非可变状态。
  • 检查程序集,它有可能编译成完全相同的东西。如果您需要提示,请参阅 __bulitin_expect 之类的内容

标签: c++ compiler-optimization


【解决方案1】:

这些问题的答案最终会产生误导,因为它们不仅取决于您使用的确切环境,还取决于您的项目将链接的其他代码(如果使用链接时优化)。此外,编译器可以生成多个版本——一些更“最优”,然后“最优”取决于谁在调用g()。如果g() 是 constexpr - 让它如此,编译器可以使用该事实来指导优化。

无论如何:您需要查看编译器的输出;将代码编译到您的项目中。只有这样你才能说出来。作为前奏,您应该前往编译器资源管理器https://godbolt.org,并在一个孤立的环境中亲眼看看。

【讨论】:

    【解决方案2】:

    如果这是一个性能关键函数,并且 99% 的时间 f(3) 或 f(5) 被调用,并且您正在尝试优化,则应该测量此类调用的差异。如果 f() 是内联函数,优化器可能能够比变量更好地处理常量,以使其某些功能在编译时进行评估(例如常量折叠、强度降低等)。这可能很有用Godbolt.org 查看装配,看看是否有任何明显的改进。即使没有内联,LTO 也可能有所帮助,尽管不同的人报告了不同程度的成功。

    如果您没有看到太多改进但认为可能提前知道 x,您还可以考虑编写 f() 的不同专用版本,例如针对这些情况进行了优化的 f3() 和 f5() (尽管您最终可能会得到更大的指令并遇到 icache 问题。这一切都归结为衡量您尝试的内容并查看好处(和损失)在哪里。最重要的是衡量。让代码变得复杂并不有趣没有收获(或者更糟的是,以优化的名义减慢速度。)

    【讨论】:

      猜你喜欢
      • 2012-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-13
      相关资源
      最近更新 更多