使用 SIMD 提取位

Extract bits with SIMD

我想从寄存器变量 __mm256i src 中提取 8 位,其中 8 个位置由另一个由 8 个整数组成的 __mm256i offset 指定。 例如:如果 offset[1,3,5,21,100,200,201,202],我想从 src 中获取第 1、3、5、100、200、201、202 位并将它们打包到 int8 .

这个问题类似于Extracting bits using bit manipulation,但我想要一个使用 SIMD 指令的解决方案,因为它要快得多。

  1. Select 每个元素中的高 3 位和 select 需要使用内部 _mm256_permutevar8x32_epi32().
  2. 的 32 位元素
  3. Select vector 的每个元素中的低 5 位,并使用内部 _mm256_sllv_epi32().
  4. 创建位掩码
  5. 使用 _mm256_movemask_ps() 将结果打包为 int8(将 __m256i 转换为 __m256)。

下面有一个例子:

uint8_t Select(__m256i offset, __m256i src)
{
    __m256i permutedSrc = _mm256_permutevar8x32_epi32(src, _mm256_srli_epi32(offset, 5));
    __m256i shift = _mm256_and_si256(offset, _mm256_set1_epi32(31));
    __m256i bitmask = _mm256_sllv_epi32(_mm256_set1_epi32(1), shift);
    __m256i mask = _mm256_cmpeq_epi32(_mm256_and_si256(permutedSrc, bitmask), _mm256_setzero_si256());
    return ~_mm256_movemask_ps(_mm256_castsi256_ps(mask));
}