无符号整数存储的 MMX 寄存器速度与堆栈
MMX Register Speed vs Stack for Unsigned Integer Storage
我正在考虑在纯汇编中实现 SHA3。 SHA3 具有 17 个 64 位无符号整数的内部状态,但由于它使用的转换,如果我在寄存器中有 44 个这样的整数可用,则可以实现最佳情况。可能加上一个暂存器。在这种情况下,我将能够在寄存器中完成整个转换。
但这是不现实的,优化甚至可以优化到几个寄存器。不过,越多越好,具体取决于此问题的答案。
我正在考虑至少使用 MMX 寄存器进行快速存储,即使我需要换成其他寄存器进行计算。但我担心那是古建筑。
MMX 寄存器和 RAX 之间的数据传输是否比在堆栈上索引 u64 并从可能是 L1 缓存访问它们更快?或者即使是这样,除了我应该注意的速度考虑之外,是否还有隐藏的陷阱?我对一般情况感兴趣,所以即使在我的计算机上一个比另一个快,它可能仍然没有定论。
- 这不是性能的胜利。 MMX 也不会。用例是为了完全避免可能会干扰微基准的内存访问。
高效的存储转发和快速的 L1d 缓存命中使得使用常规 RAM 非常好。 x86 允许内存操作数,例如 add eax, [rdi]
,现代 CPU 可以将其解码为单个 uop。
使用 MMX,您需要 2 微指令,例如 movd edx, mm0
/ add eax, edx
。所以这是更多的微指令和更多的延迟。 movd
或 movq
延迟 to/from MMX 或 XMM 寄存器比典型现代 CPU 上的 3 到 5 个周期存储转发延迟更差。
但如果您不需要经常来回移动数据,您可以将一些数据保留在 MMX / XMM 寄存器中 并使用 pxor mm0, mm1
等等。
如果您可以安排算法,那么使用 movd/movq
(int<->XMM 或 int<->MMX)和 movq2dq
/[=18= 的总指令数/微指令数会更少] (MMX->XMM / XMM->MMX) 指令而不是存储和内存操作数或加载,那么它可能是一个胜利。
但在 Haswell 之前的 Intel 上,只有 3 个 ALU 执行端口,因此 4 宽超标量流水线可能会遇到比前端吞吐量更窄的瓶颈(ALU 吞吐量),如果你离开 store/load端口空闲。
(参见 https://agner.org/optimize/ and other performance links in the x86 tag wiki。)
我正在考虑在纯汇编中实现 SHA3。 SHA3 具有 17 个 64 位无符号整数的内部状态,但由于它使用的转换,如果我在寄存器中有 44 个这样的整数可用,则可以实现最佳情况。可能加上一个暂存器。在这种情况下,我将能够在寄存器中完成整个转换。
但这是不现实的,优化甚至可以优化到几个寄存器。不过,越多越好,具体取决于此问题的答案。
我正在考虑至少使用 MMX 寄存器进行快速存储,即使我需要换成其他寄存器进行计算。但我担心那是古建筑。
MMX 寄存器和 RAX 之间的数据传输是否比在堆栈上索引 u64 并从可能是 L1 缓存访问它们更快?或者即使是这样,除了我应该注意的速度考虑之外,是否还有隐藏的陷阱?我对一般情况感兴趣,所以即使在我的计算机上一个比另一个快,它可能仍然没有定论。
高效的存储转发和快速的 L1d 缓存命中使得使用常规 RAM 非常好。 x86 允许内存操作数,例如 add eax, [rdi]
,现代 CPU 可以将其解码为单个 uop。
使用 MMX,您需要 2 微指令,例如 movd edx, mm0
/ add eax, edx
。所以这是更多的微指令和更多的延迟。 movd
或 movq
延迟 to/from MMX 或 XMM 寄存器比典型现代 CPU 上的 3 到 5 个周期存储转发延迟更差。
但如果您不需要经常来回移动数据,您可以将一些数据保留在 MMX / XMM 寄存器中 并使用 pxor mm0, mm1
等等。
如果您可以安排算法,那么使用 movd/movq
(int<->XMM 或 int<->MMX)和 movq2dq
/[=18= 的总指令数/微指令数会更少] (MMX->XMM / XMM->MMX) 指令而不是存储和内存操作数或加载,那么它可能是一个胜利。
但在 Haswell 之前的 Intel 上,只有 3 个 ALU 执行端口,因此 4 宽超标量流水线可能会遇到比前端吞吐量更窄的瓶颈(ALU 吞吐量),如果你离开 store/load端口空闲。
(参见 https://agner.org/optimize/ and other performance links in the x86 tag wiki。)