【问题标题】:Will modern c++ compiler optimize immutable temporary variable?现代 c++ 编译器会优化不可变的临时变量吗?
【发布时间】:2019-01-10 10:53:32
【问题描述】:

例如我有这样的代码:

void func(const QString& str) 
{
    QString s = str.replace(QRegexp("[abc]+"), " ");
    ......
 }

编译器是否会优化 var QRegep("[abc]+"),只构造一次而不是每次调用 func 时构造?或者换句话说,我是否需要像这样重新实现性能编码:

void func(const QString& str) 
{
    static const QRegexp sc_re("[abc]+");
    QString s = str.replace(sc_re, " ");
    ......
 }

将 QRegexp 设为静态 const 变量。

【问题讨论】:

  • 我看不出编译器如何优化它以只构造一次QRegexp,因为它不知道构造函数可能有什么副作用。但是,您可以随时检查生成的 asm 以供自己查看 - Compiler Explorer 对此非常棒
  • "..我是否需要像这样重新实现性能编码:"..无论您问题第一部分的答案是什么,这部分的答案都是明确的。不要做过早的优化,为了清晰和可读性而编写代码,然后才测量和分析(我非常怀疑你的分析器会将该行识别为热点)
  • 你希望调用这个数百万次吗?如果是,您可能想要优化,如果不是,您可能不想优化。
  • @JesperJuhl 如果编译器也在编译 QRegep,那么理论上它可以确定副作用(现代编译器在他们的工作中确实令人惊叹)。不是说这种情况会,但不是不可能想象它可以
  • 他们可能会在编译时进行一些计算,但我不知道有一个编译器会自动按照您的建议进行缓存。

标签: c++ gcc optimization


【解决方案1】:

编译器是否会优化 var QRegep("[abc]+"),只构造一次而不是每次调用 func 时构造?

您假设每次调用func 都会构造一个相同的QRegexp 对象,但是您怎么知道呢?例如,您如何知道这些对象不包含序列号,即设置为先前构造的QRegexp 对象数量的整数成员?如果使用这样的序列号,编译器只构造一次临时变量是错误的。

好的,我们可以合理地猜测没有发生类似的事情。不过,关键是我们在猜测,编译器是不允许猜测的。所以编译器考虑这种优化的先决条件是构造函数的定义是可用的(这是该类的实现细节,你不应该让你的代码依赖它)。

如果构造函数的定义可用,并且如果该定义在给定相同输入的情况下可证明产生相同的结果(可能还有一些其他的技术限制,目前我还没有想到),那么编译器将是允许的 em> 进行此优化。

我不知道是否有任何编译器在允许和有益(您做出的另一个假设)的情况下选择提供这种优化。启用和未启用优化的两个候选者的性能测试应该可以揭示您的特定编译器是否可能利用这一点。

或者换句话说,我是否需要像这样重新实现性能编码:

您几乎从不需要重新实现性能。 (一个例外是如果你的代码效率太低,需要几个世纪才能完成。我很确定我们不在那个范围内。)一个更好的问题是“应该”。我会同意的。

在这种特定情况下,我猜“不,这看起来像是过早的优化”。不过,这只是一个猜测,所以我将继续介绍您可以应用的一般准则。

只有在以下情况下,您才应该重新实现性能: 1) 性能提升对最终用户来说是显而易见的,或者 2) 新代码更容易让程序员阅读和理解。 在其他情况下,依赖编译器进行适当的优化。

在您的情况下,我看到变量名称 sc_re 并认为 “那是什么?” 所以第 2 点已经结束。这就留下了显着性能提升的问题。这通常不是一个人可以通过简单地四处询问来确定的。通常,它涉及性能测试,可能至少有两种类型。一项测试将在一个人为的繁重循环中对两个候选者进行计时,以查看性能增益有多大(如果有的话)。另一个测试将分析您的实际程序,以查看是否经常调用此代码以使最终用户注意到增益。一个好的第三个测试是将实际程序提供给最终用户,看看他们是否注意到差异。

在这些测试中,分析可能是最有效地利用您的时间。 (程序员在没有分析器帮助的情况下识别真正的性能障碍是出了名的差。)如果你每 5 分钟在这个函数上花费 2 毫秒,为什么还要花时间试图改进它呢?另一方面,如果你每次调用这个函数都花 1 秒时间,那么分析器可能会告诉你这个构造函数是否是罪魁祸首。

【讨论】:

    猜你喜欢
    • 2020-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多