【发布时间】:2017-03-01 20:41:44
【问题描述】:
我有一个 __m256i 寄存器,我想从每个 64 位组中提取 4 个低 32 位,将它们打包并连续存储到内存中。即,如果__m256i寄存器包含8个32位字:{a0,a1,a2,a3,a4,a5,a6,a7},我想将四个字连续存储到内存中{a0,a2,a4,a6}
我想出了以下代码:
void mystore(uint32 *dst, const __m256i& src)
{
__m256 ps256 = _mm256_castsi256_ps(src);
__m128 lo128 = _mm256_extractf128_ps(ps256, 0);
__m128 hi128 = _mm256_extractf128_ps(ps256, 1);
__m128 pack128 = _mm_shuffle_ps(lo128, hi128, 0 + (2<<2) + (0<<4) + (2<<6));
__m128i r = _mm_castps_si128(pack);
_mm256_storeu_si256( reinterpret_cast<__m128i*>(dst), r )
}
如果我是正确的,强制转换操作只是为了满足编译器类型检查,但它们实际上是等效的无操作,因此 shuffle 指令和 2 个提取指令的总延迟成本为 3,加上未对齐商店的成本。
有更快的方法吗?
谢谢
【问题讨论】:
-
_mm256_extractf128_ps(ps256, 0);也只是一个演员表。每个 YMM 寄存器的低半部分都可以作为相应的 XMM 寄存器访问,幸运的是编译器知道这一点,并且不会因为我们编写 extract(v, 0) 而不是正确的_mm_castintrinsic 更直接地表达最佳 asm 来惩罚我们。 (类似地,编译器在您编写_mm_extract_epi32(v, 0)时使用 MOVD 而不是实际的 PEXTRD)。 -
有趣,我不知道。
标签: vectorization simd intrinsics avx2