【发布时间】:2021-06-02 13:46:19
【问题描述】:
我在一个 AVX 值 __m256i 中有 8 个整数值,它们的上限都是 0xffff,所以高 16 位都是零。
现在我想将这 8 个值存储为 8 个连续的 uint16_t 值。
我怎样才能以这种方式将它们写入内存?我可以以某种方式将 8 个打包整数的 __m256i 值转换为包含 8 个打包短裤的 __m128i 值吗?
我的目标是 AVX2 内在函数,但如果它可以在 AVX 内在函数中完成,那就更好了。
【问题讨论】:
-
使用
_mm256_packus_epi32可以将2 个__m256i寄存器合并为一个,但结果会被打乱。或者,提取一个寄存器的上半部分并使用_mm_packus_epi32。 -
当您说“lane”时,您是指 32 位 SIMD 元素吗?不是 AVX / AVX2 向量的两个 128 位一半之一?在 AVX 术语中,这是“车道”的常用用法,如“vpermilps 是车道内随机播放,但 vpermd 是车道交叉”。并且“在 AVX-512 之前,没有比 32 位更窄的车道交叉洗牌”。我知道在 ARM NEON 和其他一些 SIMD 上下文中,“lane”用于表示“元素”,但通常不适用于 x86。
-
对于 AVX2,使用
_mm256_packus_epi32+_mm256_permutex_epi64来修复打包的通道内行为,就像@chtz 说的那样。使用 AVX1,提取一个向量的高半部分并打包成一个__m128i。这将花费相同的 2 次 shuffle 微指令,但会产生一半的数据输出宽度。 (尽管在 Zen1 上 YMM 寄存器被视为 2x 128 位的一半是很好的。)
标签: intrinsics avx avx2 narrowing