即使使用SSE,GCC也会模拟__int128_t算术吗?

时间:2013-05-15 13:31:30

标签: c gcc sse int128

我听说GCC提供的128位整数数据类型(如__int128_t)是模拟的,因此很慢。但是,据我所知,各种SSE指令集(SSE,SSE2,...,AVX)至少引入了一些128位寄存器的指令。我不太了解SSE或汇编/机器代码,所以我想知道是否有人可以向我解释使用现代版本的GCC是否模拟使用__int128_t的算术。

我之所以这样问是因为我想知道在不同版本的GCC之间预期__int128_t性能差异是否有意义,具体取决于SSE指令的优势。

那么,GCC会模拟__int128_t算术的哪些部分,以及哪些部分是用SSE指令实现的(如果有的话)?

3 个答案:

答案 0 :(得分:12)

我在问题中混淆了两件不同的事情。

首先,正如PaulR在评论中所解释的那样:“SSE或AVX中没有128位算术运算(除了按位运算)”。考虑到这一点,必须在现代基于x86-64的处理器(例如AMD Family 10或Intel Core架构)上模拟128位算术。这与GCC无关。

问题的第二部分是GCC中的128位算术仿真是否受益于SSE / AVX指令或寄存器。正如PaulR的评论所暗示的那样,SSE / AVX中没有太多可以让你更容易地进行128位算术;最有可能的x86-64指令将用于此目的。我感兴趣的代码无法使用-mno-sse进行编译,但它与-mno-sse2 -mno-sse3 -mno-ssse3 -mno-sse4 -mno-sse4.1 -mno-sse4.2 -mno-avx -mno-avx2编译良好,性能不受影响。所以我的代码没有受益于现代SSE指令。

答案 1 :(得分:5)

SSE2-AVX指令适用于8,16,32,64位整数数据类型。它们主要用于将打包数据一起处理,例如,128位寄存器可能包含四个32位整数,依此类推。

答案 2 :(得分:5)

虽然SSE / AVX / AVX512 /等。没有128位模式(它们的向量元素严格是64位,操作只会溢出),如Paul R has implied,主CPU 通过使用一对寄存器支持有限的128位操作。

  • 当两个常规64位数相乘时,MUL / IMUL可以在RAX / RDX寄存器对中输出其128位结果。
  • 相反,当分割DIV / IDIV时,可以从RAX / RDX对中获取输入,将128位数除以64位除数(并输出64位商+ 64位模数)

当然CPU的ALU是64位,因此 - as implied Intel docs - 这些更高的额外64位是以微代码中的额外微操作为代价的。这对于已经需要处理大量微操作的分区(> 3倍以上)来说更为显着。

仍然这意味着在某些情况下(比如使用三个规则来扩展值),编译器可能会发出常规CPU指令而不关心自己做任何128位仿真

这已经有很长一段时间了:

  • 自80386以来,32位CPU可以使用EAX进行64位乘法/除法:EDX对
  • 自8086/88以来,16位CPU可以使用AX:DX对进行32位乘法/除法

(至于添加和减法:感谢对carry的支持,对任何可以填充存储空间的任意长度的数量进行添加/替换是完全无足轻重的。)