【问题标题】:Why is there no floating point intrinsic for `PSHUFD` instruction?为什么“PSHUFD”指令没有浮点内在?
【发布时间】:2017-09-15 15:52:39
【问题描述】:

我面临的任务是洗牌 一个 _m128 向量并将结果存储在另一个中。

在我看来,有两种基本方法可以对打包的浮点 _m128 向量进行洗牌:

  • _mm_shuffle_ps,它使用 SHUFPS 指令,如果您只需要一个向量中的值,这不一定是最佳选择:它从目标操作数中获取两个值,这意味着额外的移动。
  • _mm_shuffle_epi32,它使用 PSHUFD 指令,似乎完全符合这里的预期,并且可以比 SHUFPS 具有更好的延迟/吞吐量。

然而,后者的内在函数适用于整数向量 (_m128i),并且似乎没有浮点对应物,因此将其与 _m128 一起使用将需要一些丑陋的显式转换。此外,没有这样的对应物这一事实可能意味着有一些正当的理由,我不知道。

问题是为什么没有内在的东西来洗牌一个浮点向量并将结果存储在另一个中?
如果_mm_shuffle_ps(x,x, ...)能生成PSHUFPD,能保证吗?
如果PSHUFD 不应该用于浮点值,那是什么原因?

谢谢!

【问题讨论】:

  • 标题和问题的其余部分似乎有些不匹配,顺便说一句 _mm_shuffle_pd 确实存在
  • __m128 y = _mm_shuffle_ps(x, x, shuf_mask); 有什么问题?洗牌非常快;他们只接受一个输入就不会提高性能。如果代码的外观让您感到困扰,那么您可以编写一个内联包装函数或宏。 AVX 引入了_mm_permute_ps(),它可以根据您的需要接受一个输入。
  • 我从未见过编译器从_mm_shuffle_ps() 调用生成PSHUFD 指令。你能举个例子吗?此外,根据Intel's intrinsics guide,这两条指令在所有最新架构上具有相同的吞吐量和延迟(禁止在 FP 和整数域之间移动的任何绕过延迟)。
  • 为什么要PSHUFD?您没有引用任何可验证的理由说明您认为它更好的原因。由于 SIMD 单元中的域交叉,它实际上可能会更慢。
  • 在受影响的处理器上,“跨域”问题在性能方面比从输出中获取两个值所看到的任何无限小的惩罚都方式登记。如果您想避免任何形式的惩罚,只需将寄存器用于所有操作数。看来您正在尝试解决一个发明的问题。您使用的哪些测量值告诉您PSHUFDSHUFPS 快?至于您要求的参考资料,最终的参考资料是Agner Fog's online resources。请参阅第 112 和 129 页 agner.org/optimize/microarchitecture.pdf

标签: c++ assembly vectorization sse intrinsics


【解决方案1】:

内在函数应该与指令一一对应。 _mm_shuffle_ps 生成 PSHUFD 是非常不可取的。它应该始终生成 SHUFPS。该文档并未表明存在其他情况。

将数据转换为单精度或双精度浮点时,某些处理器会降低性能。这是因为处理器使用包含数据的 FP 分类的内部寄存器来扩充 SSE 寄存器,例如零或 NaN 或无穷大或正常。切换类型时,您会在执行该步骤时遇到停顿。我不知道现代处理器是否仍然如此,但您可以查阅英特尔架构优化手册以获取该信息。

在现代处理器上,SHUFPS 并不比 PSHUFD 慢很多。根据 Agner Fog 的指令表 (http://www.agner.org/optimize/instruction_tables.pdf),它们在 Haswell(第 4 代 Core i7)上具有相同的延迟和吞吐量。在 Nehalem(第一代 Core i7)上,它们具有相同的延迟,但 PSHUFD 的吞吐量为 2/周期,而 SHUFPS 的吞吐量为 1/周期。因此,即使您忽略与切换类型相关的性能损失,您也不能说在所有处理器中都应该优先使用一条指令。

还有一种在 __m128、__m128d 和 __m128i 之间进行转换的方法:_mm_castXX_YY (https://software.intel.com/en-us/node/695375?language=es) 其中 XX 和 YY 分别是 ps、pd 或 si128 之一。例如,_mm_castps_pd()。这确实是一个坏主意,因为 PSHUFD 速度更快的处理器会遭受与之后切换回 FP 相关的性能损失。换句话说,除了做 SHUFPS 之外,没有其他更快的方法来做 SHUFPS。

【讨论】:

  • pshufd 的好处是它是一个复制和随机播放。如果以后仍需要原始输入,pshufd 会避免使用movaps 指令来复制shufps 的寄存器以进行就地修改。 使用它的真正原因不是任何管道的停顿,它是 SIMD 整数和 FP 转发网络之间的旁路延迟:在 Nehalem 上单程 2 个周期,在 Sandybridge 上不存在洗牌 -家庭。 (不是 FP 格式信息;当 add/mul/fma 指令消耗相同单元的结果时,您将它与 AMD 特定的 float-vs-double 大惩罚和低 1 个周期的延迟混合在一起)
  • 查看 Agner Fog 的 microarch pdf 以了解有关绕过延迟和 AMD 效应的详细信息。
猜你喜欢
  • 2021-09-26
  • 1970-01-01
  • 1970-01-01
  • 2012-08-10
  • 1970-01-01
  • 2013-04-24
  • 2010-10-05
  • 2012-08-21
  • 1970-01-01
相关资源
最近更新 更多