x86 - 在 AVX2 中广播高位字
问题描述
AVX2 中引入的vpbroadcastw
指令方便地 (?) 将低 16 位 WORD 广播到 32 字节ymm
寄存器中的所有位置。
因为我是一个逆势者,所以我想将 AVX2 寄存器的高位字(位 255:240)广播给所有元素。
我能想到的最好的办法是交叉洗牌,然后是逐pshufb
字节洗牌,如下所示:
inline __m256i bcast_mse(__m256i v) {
__m256i temp = _mm256_permute2x128_si256(v, v, 0x11);
__m256i ctrl = _mm256_set_epi8( // clang-format off
15, 14, 15, 14, 15, 14, 15, 14,
15, 14, 15, 14, 15, 14, 15, 14,
15, 14, 15, 14, 15, 14, 15, 14,
15, 14, 15, 14, 15, 14, 15, 14
); // clang-format on
return _mm256_shuffle_epi8(temp, ctrl);
}
有更好的吗?显然我更喜欢单指令,但假设这不会发生,可能涉及到需要这个 32 字节的随机播放控制。
解决方案
AVX512BWvpermw
可以在 SKX 及更高版本上执行此操作。在 SKX 上为 2 uop,但在后来的 Intel 上降至 1 uop。
使用 AVX2,您可以分 2 步进行广播,并立即进行两次随机播放,无需控制 vec:
- 使用in-lane填充高qword
vpshufhw ymm
_mm256_shufflehi_epi16(v, _MM_SHUFFLE(3,3,3,3))
- 立即广播
vpermq
。
_mm256_permute4x64_epi64
或者_mm256_permutex_epi64(v2, _MM_SHUFFLE(3,3,3,3))
我认为至少需要 2 个非洗牌指令(如vpsrld
/ vpblendw
)来设置一个vpermd
(带有控制向量)来广播高位 dword。但这无济于事,因为vpblendw
即使在 SKL/SKX 上也只有 p5。
如果 shuffle 吞吐量是瓶颈,例如高一半的瓶颈,那么存储/重新加载也是一个选项vextracti128
,然后从高位广播负载。(但广播负载比 dword 窄仍然需要 shuffle uop)。
推荐阅读
- python - 如何将每行分成两个字符串并在没有逗号的情况下打印?
- ios - 当方法参数为协议时,如何在 SwiftUI / Xcode 中轻松确定可以传递哪些类型?
- python-3.x - 对齐 QGridLayouts
- javascript - 设计游戏时的奇怪行为,猫消失了,游戏并没有停止
- keyboard-shortcuts - Firefox 开发者工具中关闭选项卡的快捷键
- android - 无法确定任务“:app:countFirebaseDebugDexMethods”的依赖关系
- javascript - 数据表中的排序图标问题
- swift - 无法以编程方式快速更改 UIBarItem 的颜色
- javascript - 画布:在不更改坐标的情况下使绘图适合画布大小
- python - 如何将 Python 解释器添加到 InteliJ?