8

I've heard that the 128-bit integer data-types like __int128_t provided by GCC are emulated and therefore slow. However, I understand that the various SSE instruction sets (SSE, SSE2, ..., AVX) introduced at least some instructions for 128-bit registers. I don't know very much about SSE or assembly / machine code, so I was wondering if someone could explain to me whether arithmetic with __int128_t is emulated or not using modern versions of GCC.

The reason I'm asking this is because I'm wondering if it makes sense to expect big differences in __int128_t performance between different versions of GCC, depending on what SSE instructions are taken advantage of.

So, what parts of __int128_t arithmetic are emulated by GCC, and what parts are implemented with SSE instructions (if any)?

4

3 回答 3

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 指令中受益。

于 2013-05-15T17:18:11.063 回答
5

虽然 SSE/AVX/AVX-512/等。没有 128 位模式(它们的向量元素严格限制为 64 位最大值,并且操作将简单地溢出),正如 Paul R 所暗示的那样,主 CPU通过使用一对寄存器确实支持有限的 128 位操作。

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

当然,CPU 的 ALU 是 64 位的,因此 -正如英特尔文档所暗示的那样- 这些更高的额外 64 位是以微码中额外的微操作为代价的。对于已经需要处理大量微操作的部门(> 3 倍以上)来说,这更加引人注目。

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

这个已经很久了:

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

(至于加法和减法:由于对进位的支持,对可以填满存储空间的任意长度的数字进行加法/减法是完全微不足道的)。

于 2015-03-26T18:16:51.213 回答
5

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

于 2013-05-15T13:48:38.803 回答