“_mm256_cvtepi16_epi32”的反义词是什么
What is the inverse of "_mm256_cvtepi16_epi32"
我想要一个 AVX2(或更早版本)内在函数,它将一个 8 宽 32 位整数向量(总共 256 位)转换为 8 宽 16 位整数向量(总共 128 位)[丢弃高 16 -每个元素的位]。
这应该是“_mm256_cvtepi16_epi32”的倒数。
如果没有直接说明,我应该如何使用一系列说明最好地做到这一点?
在 AVX512F 之前没有 single-instruction 逆。 __m128i _mm256_cvtepi32_epi16(__m256i a)
(VPMOVDW
),也可用于 512->256 或 128->low_half_of_128。 (输入小于 512 位 ZMM 寄存器的版本也需要 AVX512VL,因此只有 Skylake-X,而不是 Xeon Phi KNL)。
该 AVX512 指令有 signed/unsigned 个饱和版本,但只有 AVX512 有一个打包指令 t运行cates(丢弃每个元素的高位字节)而不是饱和。
或者使用 AVX512BW,您可以使用 vpermi2w
模拟 lane-crossing 2 输入包,从两个 512 位输入向量生成 512 位结果。在 Skylake-AVX512 上,它解码为多个 shuffle uops,但 VPMOVDW
也是如此,这也是粒度小于 dword(32 位)的 lane-crossing shuffle。 http://instlatx64.atw.hu/ 有一个 SKX 微指令/端口的电子表格。
像_mm256_packus_epi32
(vpackusdw
)这样的SSE2/AVX2打包指令做有符号或无符号饱和,以及在每个128位通道内运行.这与 vpmovzxwd
的 lane-crossing 行为不同。
不过,您可以 _mm256_and_si256
在打包之前清除高字节。如果您有多个输入向量,那可能会很好,因为 packs_epi32
采用 2 个输入向量并产生 256 位输出。
a = H G F E | D C B A 32-bit signed elements, shown from high element to low element, low 128-bit lane on the right
b = P O N M | L K J I
_mm256_packus_epi32(a, b) 16-bit unsigned elements
P O N M H G F E | L K J I D C B A
elements from first operand go to the low half of each lane
如果你能有效地利用 2x vpand
/ vpackuswd ymm
/ vpermq ymm
得到一个 256 位向量,所有元素都按正确的顺序排列,那可能是最好的在英特尔 CPU 上。每 256 位结果只有 2 个 shuffle uops(总共 4 个 uops),并且您将它们放在一个向量中。
或者你可以使用 SSSE3 / AVX2 vpshufb
(_mm256_shuffle_epi8
) 从单个输入中提取你想要的字节,并将另一半归零每个 128 位通道(通过设置该元素的 shuffle-control 值来设置符号位)。然后使用 AVX2 vpermq
将两个通道的数据洗牌到低 128。
__m256i trunc_elements = _mm256_shuffle_epi8(res256, shuffle_mask_32_to_16);
__m256i ordered = _mm256_permute4x64_epi64(trunc_elements, 0x58);
__m128i result = _mm256_castsi256_si128(ordered); // no asm instructions
所以这是每 128 位结果 2 微指令,但这两个微指令都是 运行 仅在支持 AVX2 的主流英特尔 CPU 上的端口 5 上的随机播放。作为一个循环的一部分,这很好,它做了很多工作,可以让 port0 / port1 忙碌,或者如果你需要单独的每个 128 位块。
对于Ryzen/Excavator,lane-crossing vpermq
是昂贵的(因为他们将256位指令拆分为多个128位指令,并且没有真正的 lane-crossing 洗牌单元:http://agner.org/optimize/)。所以你想 vextracti128
/ vpor
结合起来。或者 vpunpcklqdq
,这样您就可以使用 set1_epi64
加载相同的洗牌掩码,而不是需要一个完整的 256 位向量常量来将上层通道中的元素洗牌到该通道的上层 64 位。
我想要一个 AVX2(或更早版本)内在函数,它将一个 8 宽 32 位整数向量(总共 256 位)转换为 8 宽 16 位整数向量(总共 128 位)[丢弃高 16 -每个元素的位]。 这应该是“_mm256_cvtepi16_epi32”的倒数。 如果没有直接说明,我应该如何使用一系列说明最好地做到这一点?
在 AVX512F 之前没有 single-instruction 逆。 __m128i _mm256_cvtepi32_epi16(__m256i a)
(VPMOVDW
),也可用于 512->256 或 128->low_half_of_128。 (输入小于 512 位 ZMM 寄存器的版本也需要 AVX512VL,因此只有 Skylake-X,而不是 Xeon Phi KNL)。
该 AVX512 指令有 signed/unsigned 个饱和版本,但只有 AVX512 有一个打包指令 t运行cates(丢弃每个元素的高位字节)而不是饱和。
或者使用 AVX512BW,您可以使用 vpermi2w
模拟 lane-crossing 2 输入包,从两个 512 位输入向量生成 512 位结果。在 Skylake-AVX512 上,它解码为多个 shuffle uops,但 VPMOVDW
也是如此,这也是粒度小于 dword(32 位)的 lane-crossing shuffle。 http://instlatx64.atw.hu/ 有一个 SKX 微指令/端口的电子表格。
像_mm256_packus_epi32
(vpackusdw
)这样的SSE2/AVX2打包指令做有符号或无符号饱和,以及在每个128位通道内运行.这与 vpmovzxwd
的 lane-crossing 行为不同。
不过,您可以 _mm256_and_si256
在打包之前清除高字节。如果您有多个输入向量,那可能会很好,因为 packs_epi32
采用 2 个输入向量并产生 256 位输出。
a = H G F E | D C B A 32-bit signed elements, shown from high element to low element, low 128-bit lane on the right
b = P O N M | L K J I
_mm256_packus_epi32(a, b) 16-bit unsigned elements
P O N M H G F E | L K J I D C B A
elements from first operand go to the low half of each lane
如果你能有效地利用 2x vpand
/ vpackuswd ymm
/ vpermq ymm
得到一个 256 位向量,所有元素都按正确的顺序排列,那可能是最好的在英特尔 CPU 上。每 256 位结果只有 2 个 shuffle uops(总共 4 个 uops),并且您将它们放在一个向量中。
或者你可以使用 SSSE3 / AVX2 vpshufb
(_mm256_shuffle_epi8
) 从单个输入中提取你想要的字节,并将另一半归零每个 128 位通道(通过设置该元素的 shuffle-control 值来设置符号位)。然后使用 AVX2 vpermq
将两个通道的数据洗牌到低 128。
__m256i trunc_elements = _mm256_shuffle_epi8(res256, shuffle_mask_32_to_16);
__m256i ordered = _mm256_permute4x64_epi64(trunc_elements, 0x58);
__m128i result = _mm256_castsi256_si128(ordered); // no asm instructions
所以这是每 128 位结果 2 微指令,但这两个微指令都是 运行 仅在支持 AVX2 的主流英特尔 CPU 上的端口 5 上的随机播放。作为一个循环的一部分,这很好,它做了很多工作,可以让 port0 / port1 忙碌,或者如果你需要单独的每个 128 位块。
对于Ryzen/Excavator,lane-crossing vpermq
是昂贵的(因为他们将256位指令拆分为多个128位指令,并且没有真正的 lane-crossing 洗牌单元:http://agner.org/optimize/)。所以你想 vextracti128
/ vpor
结合起来。或者 vpunpcklqdq
,这样您就可以使用 set1_epi64
加载相同的洗牌掩码,而不是需要一个完整的 256 位向量常量来将上层通道中的元素洗牌到该通道的上层 64 位。