【问题标题】:Will I get a performance boost when compiling with a C++14 compiler instead of C++11?使用 C++14 编译器而不是 C++11 编译时,我会获得性能提升吗?
【发布时间】:2015-07-09 01:43:51
【问题描述】:

我知道在使用 C++11 编译器而不是 C++03 编译器进行编译时,您可以获得性能提升(请参阅question)。

但是,从 C++11 编译器升级到 C++14 编译器时,我可以期待性能提升吗?

如果是这样,您能否向我展示一个使用 C++14 而不是 C++11 编译时会更快的代码示例。

【问题讨论】:

  • 这取决于你的代码。
  • 我不认为这取决于语言标准,而是取决于更现代编译器的更好优化能力。
  • 我在这里看到了很多程序示例,这些示例将所有时间都花在调用库函数或 I/O 上,人们想知道编译器是否可以使它们更快。如果 0.01% 的时间花在编译器看到的代码上,那么该时间可能会缩减到 0,而您永远不会注意到。
  • @πάνταῥεῖ 好吧,有时相同的语法会使用更新的语义和相关机制,它们(或可能)更快。我认为这是问题的前提。从这个意义上说,较新的标准“可以提高性能”,尽管我这样说有点苦涩 =)。
  • 我能想到至少有一个 post-C++11 core language tweak 应该会提高相同代码的性能,但那个是通过 DR 完成的。

标签: c++ performance c++11 c++14


【解决方案1】:

C++14 中的核心语言更改允许实现合并内存分配,请参阅N3664。如果您的编译器/优化器利用了这一优势,您可能会看到性能提升。

【讨论】:

    【解决方案2】:

    解决了所有缺陷的完全兼容的 C++14 编译器至少有一段代码被强制要求比 C++11 版本更高效。

    struct one_byte { char x = 7; };
    struct cheap_move {
      std::vector<one_byte> state{1000000}; // 1 mb of state, cheap to move
    };
    struct test_type {
      test_type(test_type const&)=default;
      test_type(test_type &&)=default;
    
      // can construct from a cheap_move via either copy or move:
      test_type(cheap_move const&y):x(y){}
      test_type(cheap_move &&y):x(std::move(y)){}
    
      cheap_move x;
    };
    
    test_type test_func() {
      cheap_move m;
      return m;
    }
    

    符合 C++11 的编译器中的 return m; 将复制 1 兆字节的内存。在实现 defect 1579 的 C++14 编译器中,它将复制 3 个指针(嗯,移动 1 个向量)。

    这是因为在 C++11 中,仅当类型完全匹配时才会发生隐式转换为右值。根据上述缺陷报告(列为 C++14),如果存在匹配的右值消耗构造函数,则会发生这种情况。所以 C++14 移动到返回值,而 C++11 复制到返回值。

    (@T.C. 追踪到了上面的缺陷报告)。

    请注意,并非所有 C++14 编译器都实现了对该缺陷的修复。在这一点上,http://coliru.stacked-crooked.com/ 的 clang 和 gcc 都没有在 C++14 或 C++1z 模式下实现该缺陷的修复。

    一个不太人为的例子是:

    struct modulate {
      std::vector<double> state;
      double operator()(double x)const{
        double r = 0;
        for (double v:state) {
          r*=x;
          r+=v;
        }
        return r;
      }     
    };
    std::function< double(double) > f( std::vector<double> state ) {
      auto m = modulate{std::move(state)};
      return m;
    }
    

    返回值在 C++14 中隐式移动,并在 C++11 中复制。

    请注意,一个简单的std::move(m) 会使 C++11 做与 C++14 相同的事情,但是“你不 move 返回局部变量”的规则导致人们避免这种情况(因为它块省略):根据一般规则,这样的“错误”很常见。

    在 C++11 中,这个“错误”导致上述效率低下,但在 C++14 中不再是错误。

    【讨论】:

    • 但是由于 DR1579 是 DR,编译器也可能会在 C++11 模式下实现它; GCC 5.1 就是这样做的。
    • @T.C.即使它是 C++14 状态 DR?或者这是否意味着它是在 C++14 发布之前发现的缺陷?
    • 后者。 “C++14”状态表示该解析符合 C++14 标准,而不是针对 C++14 的 DR。
    【解决方案3】:

    不是天生的。

    随着时间的推移,随着编译器在代码生成方面变得更好,您可能会期望性能通常会提高,因此与旧编译器相比,新编译器通常被认为“更好”并且更有可能在优化方面表现出色。

    但是你会通过在 C++11 和 C++14 模式之间切换来自动获得更快的程序吗?没有。

    【讨论】:

    • 所以没有类似于移动语义的更改会导致语言级别的加速?
    • Ummm...没有新的语义和机制可以让程序更快吗?我的意思是,从 03 到 11,您可以编写具有相同语法的代码,并将在 c++11 中使用 move 语义。那么编写一个得到“提升”的代码就相当容易了。答案是一个强有力的声明,从 11 到 14 没有这样的变化。
    • 我想知道,从 C++11 到 C++14 发生了什么变化,为什么没有提高性能?我记得读过一些关于现在编译器可以在比 C++11 中更多的地方移动而不是复制的东西,但忘记了细节。编译器是否也在其 C++11 模式下实现该行为?是否还有更多这样的案例,它如何影响答案?您的答案是特定于核心语言的还是它也考虑了库的演变?谢谢。
    猜你喜欢
    • 2019-03-18
    • 2015-08-21
    • 2013-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-18
    相关资源
    最近更新 更多