执行GCC和Clang之间的性能差距
我有以下简单的代码,当我在GCC和Clang中编译它们时,它们的执行时间之间存在巨大的性能差异,正如您可以看到的结果和下面编译器的版本一样执行GCC和Clang之间的性能差距,c,gcc,clang,C,Gcc,Clang,我有以下简单的代码,当我在GCC和Clang中编译它们时,它们的执行时间之间存在巨大的性能差异,正如您可以看到的结果和下面编译器的版本一样 char*strchr\ux(寄存器常量char*s,int c){ 做{ 如果(*s==c){ 返回(字符*)s; } }而(*s++); 返回0; } char*get(char*value,常量字符分隔符){ int separator_index=strhr(值,分隔符)-值; char*result=malloc(分隔符索引); memcpy(结
char*strchr\ux(寄存器常量char*s,int c){
做{
如果(*s==c){
返回(字符*)s;
}
}而(*s++);
返回0;
}
char*get(char*value,常量字符分隔符){
int separator_index=strhr(值,分隔符)-值;
char*result=malloc(分隔符索引);
memcpy(结果、值、分隔符和索引);
结果[分隔符索引]='\0';
返回结果;
}
intmain(){
常量字符分隔符=',';
时钟t=时钟();
对于(尺寸i=0;i<100000000;++i){
免费(获取(“127.0.0.1127.0.0.2:1111”,分隔符));
}
浮点经过的秒数=((双精度)(时钟()-t))/CLOCKS\u/SEC);
printf(“%f秒。\n”,已用\u秒);
返回0;
}
此外,“strchr_x”实现与原始GCC实现完全相同。你可以在
当我在标准库中使用'strchr'方法时;GCC的运行时间减少到0.015625秒
因此,我的问题是:
如果您将代码插入其中,您可以看到Clang将优化整个for循环,这解释了为什么它在0秒内执行。它可能会这样做,因为get的唯一副作用是malloc,结果会立即被释放 编辑: GCC确实不能很好地处理您的代码,似乎。。。 我再次检查了生成的汇编程序,这不仅是因为它无法删除空for循环(对于strchr()),而且它也无法删除循环体中的函数调用(对于strchr\u x())
所以最后,这一切归结为一些非常奇怪的优化行为,而你最慢的例子实际上是唯一一个做任何事情的例子。我不知道为什么GCC在你的例子中失败得如此之难,但我绝对同意你应该将其作为一个bug进行归档(甚至可能是两个单独的bug,因为它在使用strchr()时已经很难失败,而在使用strchr_x()时更难失败,尽管两者应该是相同的)关于问题二的简短回答-
clang
(LLVM)在运行时具有更好的代码和链接优化
现在,我先从经验中举出一个例子。该项目适合我在raspberry pi-3设备上进行必要的测试。当我使用clang++
编译时,大约需要15分钟,而使用gcc
编译时,经过40多分钟的长时间等待编译,就在链接的最后,构建的内存就用完了!为什么?同样,clang
提供了更好的编译时代码优化和后台链接
然而,这取决于,在不同的Ox水平下,你可能不会得到相同的差异(试试O2,你会看到)。为了更多的参考,我认为这两篇文章提供了一些详细的解释
似乎
gcc
无法删除循环,即使它删除了循环中的调用。以下是指向godbolt的链接,代码如下:
main:
推送rbx
呼叫钟
mov-rbx,rax
mov eax,100000000
.L5:
sub-rax,1//clang显然优化了/*no-effect*/for循环。看看反汇编。当时间为零时,这意味着编译器完全优化了您试图测试的代码。它可以这样做,因为代码没有任何可观察的效果。您有未定义的行为(在result
末尾写入)。这可能不是导致性能差异的原因,但是.gcc将循环减少为for(无符号长x=10000000;x!=0;--x)代码>则无法删除此空循环。请在gcc的bugzilla中提交错误报告。在main上添加\uuuu attribute\uuuu((flatte))
,使gcc能够进行优化,但它确实能够在不作弊的情况下进行优化。实际上,我想知道这是否是gcc方面的错误,但@marc glisse已经回答了这个问题。你能回答我的第一个问题吗@felix-g?我已经再次检查了汇编程序,并相应地扩展了我的答案
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.
main:
push rbx
call clock
mov rbx, rax
mov eax, 100000000
.L5:
sub rax, 1 // <<-------- loop which does nothing.
jne .L5
call clock