-fno-strict-aliasing的性能影响

30

是否有任何研究或基准测试集表明指定GCC中的-fno-strict-aliasing(或其他编译器中的等效选项)会导致性能下降?


1
严格的别名规则(Strict aliasing) - GManNickG
8
我在那个讨论中没有发现任何性能数字。我正在寻找一些测试结果/数据。我有所遗漏吗? - Carlos
1
顺便说一句,接受的答案中也没有性能数字。 - peterchen
4个回答

30

编译器之间的实现差异很大,不同编译器的实现级别也不一样。GCC非常积极:启用严格的别名规则会使它认为指针是“显然”等效的(如foo *a; bar *b = (bar *) a;),从而允许进行一些非常积极的转换,但可能会破坏未经精心编写的代码。出于这个原因,苹果的GCC默认禁用严格别名。

相比之下,LLVM甚至没有严格的别名规则,并且虽然计划实现它,但开发人员表示计划在什么都不能确定时将其实现为后备方案。在上面的示例中,它仍然会判断a和b是等效的。它只有在无法以其他方式确定它们之间的关系时才使用基于类型的别名。

根据我的经验,严格的别名规则对性能的影响主要与循环不变式代码移动有关,其中类型信息可用于证明循环内加载不能与正在迭代的数组别名,从而允许将它们提取出来。结果可能因人而异。


1
请注意,自从发布这个答案以来,clang现在也有-fstrict-aliasing选项。 - Keith Smiley

12

通过我的经验(在PS3上测试了一个大型项目,PowerPC是一种由于其很多寄存器而能够受益于SA的架构),我可以告诉你,你将看到的优化通常会非常局部(范围)和小。在一个20MB的可执行文件中,它仅削减了大约80kb的.text部分(=代码),而且这些都是在小范围和循环内进行的。

使用此选项可以使您生成的代码比现在更加轻量级和优化(考虑1到5%的范围内),但不要期望有任何大的成果。因此,使用-fno-strict-aliasing的影响可能对您的性能没有太大影响。尽管如此,编写需要-fno-strict-aliasing的代码通常是次优情况。


1
代码大小等于速度?你的PS3示例与此无关。它是如何运行的? - Eloff
2
我在哪里说它更快了?也许是 - 如果省略了潜在的负载/存储,这一点都不难想象 - 而且在任何情况下,在内存受限的机器上,更小的可执行文件更可取。所以它在这里,也在那里。 - nielsj
1
OP询问性能影响,而你只讨论了代码大小。然后你使用了ipso facto的论点来解释为什么你不会看到很大的性能差异。接着你称Linux内核为“最佳情况下的次优选择”。我想你可以理解为什么会被踩了。 - Eloff
2
在许多情况下,忽略严格别名规则的代码可能更易于阅读,并且即使在编译器上(可能由于配置)不会特别高效地优化memcpy(),也能产生良好的性能。如果严格别名不能带来有意义的性能提升,那么与编写可读性强的代码并禁用严格别名相比,编写丑陋繁琐的代码是否是次优的? - supercat

10

以下是一份2004年的研究报告链接:http://docs.lib.purdue.edu/cgi/viewcontent.cgi?article=1124&context=ecetr,其中探讨了严格别名对代码性能的影响等内容。图2.5显示相对提高了3%至10%的效果。

研究人员关于性能下降的解释:

通过检查汇编代码,我们发现性能下降是寄存器分配算法的影响。 GCC实现了一种图形着色寄存器分配器[2,3]。 由于存在严格别名,变量的生存期变得更长,导致寄存器压力过大而溢出。 相同的变量在更保守的别名方式下,也会在其(较短)生存期结束时发生内存转移。

[2] Peter Bergner、Peter Dahl、David Engebretsen和Matthew T.O’Keefe。 Spill code minimization via interference region spilling. In SIGPLAN Conference on Programming Language Design and Implementation, pages 287–295, 1997.

[3] Preston Briggs、Keith D.Cooper和Linda Torczon。 Improvements to graph coloring register allocation. ACM Transactions on Programming Languages and Systems, 16(3):428–455, May 1994.


你知道有没有研究探讨过通过严格别名可能实现的优化价值,而这些优化不能通过“restrict”限定符实现吗? - supercat
我不知道有没有,你知道任何满足这些要求的优化吗? - SzymonPajzert
1
restrict 限定符不能有效地告诉编译器静态持续时间对象不会别名,而且在某些情况下,程序可能有多个可能相关的指向相同类型的指针,它们可能会别名。基于类型的别名将允许在这些情况下进行一些优化,否则这些优化将不可用。在我看来,可以通过添加更好的限定符(例如,在对象可能暴露给外部代码但通过指针以外的方式访问时可能表现得好像它们获得了新地址时,允许 “register” 限定符)更好地处理这些情况。 - supercat

2
这个标志可以对循环向量化和性能产生影响,如下面的例子所示:
// a simple test code
#include<vector>
void add(double *v, double *b, double *c, int *idx, std::vector<int> &v1) {

    for(int i=v1[0];i<v1[2];i++){
        v[i]  = b[i] + c[i];
    }
}

如果您使用GCC11.2编译器以-O3 -ftree-vectorize -ftree-loop-vectorize -fopt-info-vec-missed -fopt-info-vec-optimized -fno-strict-aliasing标志在https://godbolt.org/上编译代码,您将会看到以下消息:
<source>:5:22: missed: couldn't vectorize loop
<source>:5:22: missed: not vectorized: number of iterations cannot be computed.

现在,如果您删除-fno-strict-aliasing或将其替换为-fstrict-aliasing,您会看到:
<source>:5:22: optimized: loop vectorized using 16 byte vectors
<source>:5:22: optimized:  loop versioned for vectorization because of possible aliasing

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接