执行GCC和Clang之间的性能差距

我有以下简单的代码,当我在GCC和Clang中编译它们时,它们的执行时间之间存在巨大的性能差异,因为您可以看到下面的结果和编译器的版本。

char* strchr_x(register const char* s,int c) {
  do {
    if (*s == c) {
      return (char*)s;
    }
  } while (*s++);

  return 0;
}
char* get(char* value,const char separator) {
  int separator_index = strchr(value,separator) - value;
  char* result = malloc(separator_index);
  memcpy(result,value,separator_index);
  result[separator_index] = '\0';

  return result;
}
int main() {
  const char separator = ',';
  clock_t t = clock();

  for (size_t i = 0; i < 100000000; ++i) {
    free(get("127.0.0.1,127.0.0.2:1111",separator));
  }

  float elapsed_seconds = (((double)(clock() - t)) / CLOCKS_PER_SEC);
  printf("%f seconds.\n",elapsed_seconds);

  return 0;
}
gcc version 8.1.0 (Ubuntu 8.1.0-5ubuntu1~16.04)
# gcc main.c -O3 -o gcc-main
# 1.968750 seconds.

clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
# clang main.c -O3 -o clang-main
# 0.000000 seconds.

此外,“ strchr_x”实现与原始GCC实现完全相同。您可以在https://github.com/gcc-mirror/gcc/blob/master/libiberty/strchr.c

上看到它

当我在标准库中使用'strchr'方法时; GCC的运行时间减少到0.015625秒。

所以,我的问题是:

  1. 在GCC中,为什么我的'strchr_x'与标准库的'strchr'在性能上有巨大差异?
  2. 为什么在GCC和Clang之间存在巨大的性能差距?
liyinjie86 回答:执行GCC和Clang之间的性能差距

如果将代码插入https://godbolt.org/,您会发现Clang将优化整个for循环,这说明了为什么它会在0秒内执行。之所以这样做,是因为get的唯一副作用是malloc,结果立即被释放。

编辑: GCC确实对您的代码不太好,似乎... 我再次检查了生成的汇编程序,不仅是它未能删除空的for循环(对于strchr()),而且它也未能删除循环主体中的函数调用(用于strchr_x())。

因此,最后归结为一些非常奇怪的优化行为,而您最慢的示例实际上是唯一一个完全不执行任何操作的示例。我不知道 为什么 在您的示例中GCC如此失败,但是我绝对同意您应该将此作为错误提交(也许已经是两个单独的错误,因为它已经存在了)使用strchr()时很难失败,使用strchr_x()时甚至更难,即使两者应该相同)

,

似乎gcc无法删除循环,即使它删除了循环中的调用也是如此。这是上面提到的代码与Godbolt的链接: https://godbolt.org/z/5wamhm

main:
        push    rbx
        call    clock
        mov     rbx,rax
        mov     eax,100000000
.L5:
        sub     rax,1 // <<-------- loop which does nothing.
        jne     .L5
        call    clock

这绝对值得在gcc bugzilla中提交错误。我在这里提交错误: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92638

,

问题二的简短答案-clang(LLVM)在运行时具有更好的代码和链接优化。

现在,我将首先从经验中提出一个例子。我从事的项目适合在树莓派pi-3设备上进行所需的测试。当我使用clang++进行编译时,大约花费了15分钟,而当使用gcc进行了40多分钟的等待编译之后,恰好在链接过程的最后,构建就用光了内存!为什么?同样,clang提供了更好的编译时代码优化和后台链接。

但是,此取决于,您在不同的Ox含量下可能不会得到相同的差异(尝试使用O2,您会看到)。为了获得更多参考,我认为这两篇文章提供了一些详细的解释。

https://medium.com/@alitech_2017/gcc-vs-clang-llvm-an-in-depth-comparison-of-c-c-compilers-899ede2be378

https://clang.llvm.org/comparison.html

本文链接:https://www.f2er.com/3139420.html

大家都在问