- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想要一个 AVX2(或更早版本)内在函数,它将 8 宽 32 位整数向量(总共 256 位)转换为 8 宽 16 位整数向量(总共 128 位)[丢弃高 16 位每个元素]。这应该是“_mm256_cvtepi16_epi32”的逆。如果没有直接指令,我应该如何通过一系列指令最好地做到这一点?
最佳答案
直到 AVX512F 才出现单指令逆。 __m128i _mm256_cvtepi32_epi16(__m256i a)
(VPMOVDW
) ,也可用于 512->256 或 128->low_half_of_128。 (输入小于 512 位 ZMM 寄存器的版本也需要 AVX512VL,因此只有 Skylake-X,而不是 Xeon Phi KNL)。
该 AVX512 指令有有符号/无符号饱和版本,但只有 AVX512 具有截断(丢弃每个元素的高字节)而不是饱和的 pack 指令。
或者使用 AVX512BW,您可以使用 vpermi2w
模拟车道交叉 2 输入包,从两个 512 位输入向量生成 512 位结果。在 Skylake-AVX512 上,它解码为多个 shuffle uops,但 VPMOVDW
也是如此,它也是粒度小于 dword(32 位)的跨车道 shuffle。 http://instlatx64.atw.hu/有一个 SKX uops/端口的电子表格。
SSE2/AVX2 包指令(例如 _mm256_packus_epi32
(vpackusdw
))执行有符号或无符号饱和,以及在每个 128 位 channel 内运行。这与 vpmovzxwd
的车道交叉行为不同。
不过,您可以_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 位向量如果顺序正确,那么这在 Intel CPU 上可能是最好的。每 256 位结果只有 2 个 shuffle uops(总共 4 个 uops),并且您可以在单个向量中获得它们。
或者您可以使用 SSSE3/AVX2 vpshufb
(_mm256_shuffle_epi8
) 从单个输入中提取所需的字节,并将其他输入归零每个 128 位 channel 的一半(通过设置该元素的随机控制值来设置符号位)。然后使用 AVX2 vpermq
将两个 channel 中的数据混洗到低 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 个 uops,但这两个 uops 都是随机播放,仅在支持 AVX2 的主流 Intel CPU 上的端口 5 上运行。作为循环的一部分,它可以做大量的工作,使 port0/port1 保持忙碌,或者如果您无论如何都需要单独的每个 128 位 block ,这很好。
<小时/>对于 Ryzen/Excavator,跨线 vpermq
成本高昂(因为它们将 256 位指令拆分为多个 128 位微指令,并且没有真正的车道交叉洗牌单元: http://agner.org/optimize/ )。因此,您需要将 vextracti128
/vpor
组合起来。或者可能是 vpunpcklqdq,这样您就可以使用 set1_epi64 加载相同的洗牌掩码,而不需要完整的 256 位向量常量将上部 channel 中的元素洗牌到上部 64 位那条车道。
关于x86 - "_mm256_cvtepi16_epi32"的倒数是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49721807/
我是一名优秀的程序员,十分优秀!