【发布时间】: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 单元中的域交叉,它实际上可能会更慢。 -
在受影响的处理器上,“跨域”问题在性能方面比从输出中获取两个值所看到的任何无限小的惩罚都方式登记。如果您想避免任何形式的惩罚,只需将寄存器用于所有操作数。看来您正在尝试解决一个发明的问题。您使用的哪些测量值告诉您
PSHUFD比SHUFPS快?至于您要求的参考资料,最终的参考资料是Agner Fog's online resources。请参阅第 112 和 129 页 agner.org/optimize/microarchitecture.pdf。
标签: c++ assembly vectorization sse intrinsics