首页 > 解决方案 > Lambda vs. 手动内联代码改变了 GCC 的优化器行为

问题描述

以下代码:

#include <vector>

extern std::vector<int> rng;

int main()
{
  auto is_even=[](int x){return x%2==0;};
  int res=0;
  for(int x:rng){
    if(is_even(x))res+=x;
  }

  return res;
}

由 GCC 11.1 (链接到 Godbolt ) 以一种非常不同的方式优化:

#include <vector>

extern std::vector<int> rng;

int main()
{
  int res=0;
  for(int x:rng){
    if(x%2==0)res+=x;
  }

return res;
}

链接到 Godbolt。)此外,第二个版本(其中 lambda 已被直接手动注入其主体替换为调用位置),比第一个版本快得多。

这是 GCC 错误吗?

标签: c++gccoptimizationlambda

解决方案


在 x64 架构中没有向量化积分模运算之类的东西。这意味着代码本身并不是固有的可矢量化的,需要事先进行转换才能完成。

在使用 SIMD 友好的均匀度测试的更简单的情况下,您可以看到矢量化在这两种情况下都工作得很好:https ://godbolt.org/z/hc5ffbePY

因此,如果有的话,可以说 GCC 设法对内联版本进行矢量化,并且 Clang 内联这两个版本实际上非常令人印象深刻。

话虽如此,由于我们知道 GCC 能够执行该转换,因此它似乎只在内联发生之前执行,这是不幸的,并且可能值得引起维护者的注意。


推荐阅读