编译器如何处理SSE(或任何)内置函数?

8

前段时间我在某处读到,SSE内置函数编译成高效的机器码,因为编译器对待它们与普通函数不同。我想知道编译器实际上是怎么做的,C程序员可以做些什么来促进这个过程。是否有任何指导方针,说明如何以一种使用内置函数的方式,使编译器生成高效的机器码变得更容易。

谢谢。

2个回答

7
与Necrolis所写的相反,内在函数可能会编译成它们所代表的指令,也可能不会。这对于复制或加载指令(例如_mm_load_pd)尤其如此,因为当使用内在函数时,编译器仍然负责寄存器分配和赋值。这意味着如果两个位置可以由同一个寄存器表示,则根本不需要将一个值从一个位置复制到另一个位置。在这种情况下,编译器可能选择删除复制。如果结果从未使用,它还可能选择删除其他指令。
请参阅{{link1:此博客文章}},其中比较了不同编译器的行为。它是从2009年开始的,因此细节可能已经过时。但是,新的编译器很可能会更多地优化您的代码,而不是减少。
至于实际有效地使用内在函数,答案与所有其他性能优化一样:测量,测量和测量。确保您实际上正在处理热点代码,找出它为什么变慢,然后改进它。您很可能会发现,改进内存访问模式比使用内在函数更重要。

我完全同意你的观点。一个简单的例子就是矩阵乘法,转置第一个矩阵可以大大增加内存访问。 - Trax

6
这些内置函数会编译成它们所代表的指令,效率高不高取决于使用方式。另外,每个编译器对内置函数的处理略有不同(即实现特定),但GCC是开源的,因此您可以看到它们如何处理SSE内置函数。Open Watcom*,LCC,PCC和TCC*都是开源C编译器,尽管它们没有SSE内置函数,但它们应该仍然有内置函数,并且您可以看到它们如何处理它们。我认为你读到的与代码自动向量化有关,这是GCC(参见this)和ICC擅长的领域,但它们还不如手动优化的代码效果好,至少目前还是这样。*可能已更新以支持SSE,最近没有检查过...

3
我是指_mm_blah_blah函数,而不是自动向量化。但愿我能阅读GCC的源代码。 - pic11
@pic11:那就忽略最后一部分吧。我确实同意你的看法,不幸的是,从读者的角度来看,gcc的源代码很混乱(这也是我建议使用更简单的c编译器的原因),你可能会发现LLVM(和clang)更容易理解。虽然Gcc和llvm有许多配套的论文,但你可能会发现一些与sse相关的论文(有一篇关于ssa寄存器分配的论文提到了sse的优化)。MSDN Visual Studio博客上有一些关于他们的simd内部函数的条目,但不幸的是它非常肤浅。 - Necrolis
尽管gcc很混乱,而且编译它真是一场苦难(编译编译器,而不是用编译器编译),但它是最令人惊叹的编译器之一。特别是在内置函数及其周围的优化方面,它比MSVC强得多。 - Damon
虽然它没有直接回答问题,但是已经被接受了。看起来了解编译器在内部的工作方式是理解内置函数如何工作的唯一方法。我希望有一本类似于“Effective C++” 的“Effective SSE”书籍,可以在不涉及晦涩的编译器内部知识的情况下解释SSE内置函数。 - pic11

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