x86 - 将数据放入 SIMD 寄存器需要多少个周期?

标签 x86 sse simd

我是一名学习 x86 和 ARM 架构的学生。

我想知道将多个数据放入 SIMD 寄存器需要多少个周期?

我知道 x86 SSE 的 xmms 寄存器有 128 位大小的寄存器。

如果我想通过 SIMD 指令集和汇编语言将 8 位数据中的 32 个放入堆栈中的一个 xmms 寄存器中,该怎么办,

通用寄存器的 PUSH/POP 是否具有相同的周期时间?

还是每 8 位数据需要 32 倍的时间?

感谢您的关注和关心!

最佳答案

简答:

如果您正在执行多次重复的 128 位加载,则可以使用 Sandy Bridge、Ivy Bridge 和 Haswell 实现每个时钟周期的 两个 128 位加载,或者使用 Nahelem 实现每个时钟周期的一个 128 位加载。 Nahelem 之前的处理器取决于您是执行对齐加载还是未对齐加载。

长答案:

Mystical 在 Agner Fog's Instruction Tables 为您提供了您需要的信息。但是让我为您(和我自己)详细说明。

你要查看的指令是:MOVDQUMOVDQA,操作数为 x、m128。它们都将在一次操作中将 128 位数据加载到 XMM/YMM 寄存器中。 MOVDQA 要求地址按 16 字节对齐。 MOVDQU 没有这样的限制。

您要查看的两个指标是 延迟和互惠吞吐量 (越低越好)。自 Nahelem 和 Sandy Bridge 以来,这些指标发生了两个重要变化:

  • Nahelem 之前的英特尔处理器具有更高的 MOVDQU 延迟和互惠吞吐量。 然而,由于 Nahelem MOVDQUMOVDQA 具有相同的延迟和互惠吞吐量。
  • 自 Sandy Bridge 以来的所有 Intel 处理器都可以同时执行两个 128 位加载。 这可以在 intels-haswell-architecture 中很好地看到。您可以看到,在 Nahelem 中,只有端口 2 可以执行 128 位加载,而在 Sandy Bridge 和 Haswell(以及 Ivy Bridge)中,它们可以使用端口 2 和 3 同时执行两个 128 位加载(这就是它们的工作方式)一个 AVX 负载)。因此,Nahelem 的倒数吞吐量为 1,而 Sandy Bridge 的倒数吞吐量为 0.5。

  • 然而,即使 MOVDQAMOVDQU 对于每个处理器具有相同的延迟和互惠吞吐量,这并不意味着它们会提供相同的性能。如果地址不是 16 字节对齐,则永久性可能会下降。你可以用 ScottD 在 Successful compilation of SSE instruction with qmake (but SSE2 is not recognized) 的代码测试这个,我得到了大约 4% 的下降。我认为这是由于地址跨越缓存行的情况(例如,一个缓存行中的前 64 位和另一个缓存行中的下一个 64 位),否则性能是相同的。这实际上意味着自 Nahelem 以来没有理由再使用 MOVDQA。唯一的区别是内存对齐。

    编辑:
    我说Haswell可以同时做两个128位的加载。事实上,它可以同时做两个 256 负载。

    编辑:
    事实证明,使用 SSE 未对齐的加载指令不能与另一个操作折叠。折叠允许CPU使用微操作融合(虽然这并不意味着它会融合但不折叠肯定不会融合)。
    所以说对齐加载指令自 Nehalem 以来已经过时并不完全准确。更准确地说,它们已被 AVX 淘汰(随英特尔的 Sandy Bridge 一起提供)。但是,在实践中,除非在某些特殊情况下,否则不折叠可能没什么区别。

    关于x86 - 将数据放入 SIMD 寄存器需要多少个周期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20648158/

    相关文章:

    c++ - opengl 位于何处(gpu 软件或操作系统)?

    c++ - SIMD 代码?

    c - 如何用GCC生成IP相对寻址指令

    compiler-errors - 如何在启用了SSE的情况下编译Linux内核?

    c++ - 适用于 GNU C++ 的 SSE SSE2 和 SSE3

    linux - 如何在 Ubuntu11.04 中使用 NASM 维护堆栈

    c++ - 任何种子在同一字符串上的CRC32哈希冲突

    c++ - 如何向量化 data_i16[0 到 15]?

    c - 使用 SSE/SSE2 对 2*Pi 取模

    c++ - SIMD:实现 _mm256_max_epu64_ 和 _mm256_min_epu64_