代码之家  ›  专栏  ›  技术社区  ›  gansub

使用内置popcount或其他内部函数来处理mm256 movemask比较位图的结果?

  •  2
  • gansub  · 技术社区  · 6 年前

    Adapting Tree Structures for Processing with SIMD Instructions

    #include <stdint.h>
    #include <immintrin.h>
    #include <assert.h>
    #include <limits.h>
    #include <math.h>
    #include <stdalign.h>
    
    int main(void)
    {
        __m256d avx_creg, res, avx_sreg;
        int bitmask;
        uint64_t key = 503;
    
        avx_sreg = _mm256_castsi256_pd(_mm256_set1_epi64x(key));
        alignas(32) uint64_t v[4]; 
        _mm256_store_pd((double*)v, avx_sreg);
        printf("v2_u64: %lld %lld %lld %lld\n", v[0], v[1],v[2],v[3]);
        uint64_t b[4]= {500,505,510,515};
        avx_creg = _mm256_castsi256_pd(
                       _mm256_loadu_si256((__m256i const *)&b));
        //
        alignas(32) uint64_t v1[4]; 
        _mm256_store_pd((double*)v1, avx_creg);
        printf("v2_u64: %lld %lld %lld %lld\n", v1[0], v1[1],v1[2],v1[3]);
    
        res      = _mm256_cmp_pd(avx_sreg, avx_creg, 30);
        bitmask  = _mm256_movemask_pd(res);
        int mmask = __builtin_popcount(bitmask);
        printf("mmask is %d\n",mmask);
    
        return 0;
    }
    

    mmask 作为1。这是我一点也不清楚的地方。我应该将数字“1”解释为数组索引,其中数组元素大于输入键,还是指设置的位数?

    例如,如果我将密钥更改为499,则mmask打印为0。

    1 回复  |  直到 6 年前
        1
  •  2
  •   Peter Cordes Steve Bohrer    6 年前

    movemask 通过从向量中获取每个元素的高位来生成整数位图。将其打印为十六进制或base-2以更好地查看。

    如果你只关心0和非零计数,那就检查一下 if(bitmask != 0)

    if(bitmask == 0x0f) 检查他们是否都是真的(4位表示4元素向量)。


    使用popcount找出有多少是真的。 __builtin_popcnt

    使用 __builtin_ctz 找到第一个元素的位置,在那里比较是正确的(从低到高的内存地址计数,如果向量是从内存加载的)。当心那个 __内置ctz 仅对非零输入有意义。e、 g.在a memchr ctz 只有在跳出搜索循环后 _mm256_movemask_epi8(cmp_result) == 0 来确定这个向量是否匹配(epi8因为我说的是字节搜索循环,不像你的压缩循环- double 比较)。

    _lzcnt_u32(bitmask) 如果您已经需要AVX2,则在bitmask=0上获得定义良好的结果(32个前导零)(因为我认为所有的AVX2 cpu都有BMI1。)


    迭代匹配项 ,您可以使用清除最低设置位操作,如果仍有任何位设置,则 找出哪一个。看到了吗 Clearing the lowest set bit of a number .

    x & (x-1) 将有效地编译为BMI1 blsr 指令,例如 -march=haswell

    (为了让这个工作顺利进行,你肯定需要一个 移动掩码 _pd 所以你可以用 _mm256_movemask_pd .)