将__m256i的前N个或后N个位设置为1,其余为0的有效方法 [英] Efficient way to set first N or last N bits of __m256i to 1, the rest to 0

查看:100
本文介绍了将__m256i的前N个或后N个位设置为1,其余为0的有效方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用AVX2有效设置为1

How to set to 1 efficiently with AVX2

  1. 第一个N
  2. 最后N
  1. first N bits
  2. last N bits

中的

,将其余部分设置为0?

当范围可能在__m256i值的中间开始和结束时,这是2个单独的操作,用于位范围的尾部和头部.范围内全部__m256i值的部分都使用all- 0或all- 1掩码进行处理.

These are 2 separate operations for tail and head of a bit range, when the range may start and end in the middle of __m256i value. The part of the range occupying full __m256i values is processed with all-0 or all-1 masks.

推荐答案

AVX2移位指令vpsllvdvpsrlvd具有移位计数的不错的属性 大于或等于32会导致ymm寄存器中的零整数. 换句话说:相比之下,班次计数没有被屏蔽 x86标量移位指令的移位计数.

The AVX2 shift instructions vpsllvd and vpsrlvd have the nice property that shift counts greater than or equal to 32 lead to zero integers within the ymm register. In other words: the shift counts are not masked, in contrast to the shift counts for the x86 scalar shift instructions.

因此,代码非常简单:

/*
gcc -O3 -m64 -Wall -mavx2 -march=broadwell avx2_bit_mask.c
*/
#include <immintrin.h>
#include <stdio.h>

__m256i bit_mask_avx2_msb(unsigned int n)      
{           
    __m256i ones       = _mm256_set1_epi32(-1);
    __m256i cnst32_256 = _mm256_set_epi32(32,64,96,128, 160,192,224,256);

    __m256i shift      = _mm256_set1_epi32(n);   
            shift      = _mm256_subs_epu16(cnst32_256,shift);  
                  return _mm256_sllv_epi32(ones,shift);         
}


__m256i bit_mask_avx2_lsb(unsigned int n)               
{           
    __m256i ones       = _mm256_set1_epi32(-1);
    __m256i cnst32_256 = _mm256_set_epi32(256,224,192,160, 128,96,64,32);

    __m256i shift      = _mm256_set1_epi32(n);   
            shift      = _mm256_subs_epu16(cnst32_256,shift);  
                  return _mm256_srlv_epi32(ones,shift);
}


int print_avx2_hex(__m256i ymm)
{
    long unsigned int x[4];
        _mm256_storeu_si256((__m256i*)x,ymm);
        printf("%016lX %016lX %016lX %016lX\n", x[3],x[2],x[1],x[0]);

    return 0;
}


int main()
{
    unsigned int i;

    for (i=0;i<259;i++){
        printf("bit_mask_avx2_lsb(%3d) ",i);
        print_avx2_hex(bit_mask_avx2_lsb(i));
    }
    printf("\n");

    for (i=0;i<259;i++){
        printf("bit_mask_avx2_msb(%3d) ",i);
        print_avx2_hex(bit_mask_avx2_msb(i));
    }
    printf("\n");


    return 0;
}

结果是:

$ ./a.out
bit_mask_avx2_lsb(  0) 0000000000000000 0000000000000000 0000000000000000 0000000000000000
bit_mask_avx2_lsb(  1) 0000000000000000 0000000000000000 0000000000000000 0000000000000001
bit_mask_avx2_lsb(  2) 0000000000000000 0000000000000000 0000000000000000 0000000000000003
bit_mask_avx2_lsb(  3) 0000000000000000 0000000000000000 0000000000000000 0000000000000007
bit_mask_avx2_lsb(  4) 0000000000000000 0000000000000000 0000000000000000 000000000000000F
bit_mask_avx2_lsb(  5) 0000000000000000 0000000000000000 0000000000000000 000000000000001F
bit_mask_avx2_lsb(  6) 0000000000000000 0000000000000000 0000000000000000 000000000000003F
bit_mask_avx2_lsb(  7) 0000000000000000 0000000000000000 0000000000000000 000000000000007F
bit_mask_avx2_lsb(  8) 0000000000000000 0000000000000000 0000000000000000 00000000000000FF
bit_mask_avx2_lsb(  9) 0000000000000000 0000000000000000 0000000000000000 00000000000001FF
bit_mask_avx2_lsb( 10) 0000000000000000 0000000000000000 0000000000000000 00000000000003FF
bit_mask_avx2_lsb( 11) 0000000000000000 0000000000000000 0000000000000000 00000000000007FF
...
bit_mask_avx2_lsb(124) 0000000000000000 0000000000000000 0FFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(125) 0000000000000000 0000000000000000 1FFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(126) 0000000000000000 0000000000000000 3FFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(127) 0000000000000000 0000000000000000 7FFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(128) 0000000000000000 0000000000000000 FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(129) 0000000000000000 0000000000000001 FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(130) 0000000000000000 0000000000000003 FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(131) 0000000000000000 0000000000000007 FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(132) 0000000000000000 000000000000000F FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
...
bit_mask_avx2_lsb(248) 00FFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(249) 01FFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(250) 03FFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(251) 07FFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(252) 0FFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(253) 1FFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(254) 3FFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(255) 7FFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(256) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(257) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_lsb(258) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF



bit_mask_avx2_msb(  0) 0000000000000000 0000000000000000 0000000000000000 0000000000000000
bit_mask_avx2_msb(  1) 8000000000000000 0000000000000000 0000000000000000 0000000000000000
bit_mask_avx2_msb(  2) C000000000000000 0000000000000000 0000000000000000 0000000000000000
bit_mask_avx2_msb(  3) E000000000000000 0000000000000000 0000000000000000 0000000000000000
bit_mask_avx2_msb(  4) F000000000000000 0000000000000000 0000000000000000 0000000000000000
bit_mask_avx2_msb(  5) F800000000000000 0000000000000000 0000000000000000 0000000000000000
bit_mask_avx2_msb(  6) FC00000000000000 0000000000000000 0000000000000000 0000000000000000
bit_mask_avx2_msb(  7) FE00000000000000 0000000000000000 0000000000000000 0000000000000000
bit_mask_avx2_msb(  8) FF00000000000000 0000000000000000 0000000000000000 0000000000000000
bit_mask_avx2_msb(  9) FF80000000000000 0000000000000000 0000000000000000 0000000000000000
bit_mask_avx2_msb( 10) FFC0000000000000 0000000000000000 0000000000000000 0000000000000000
bit_mask_avx2_msb( 11) FFE0000000000000 0000000000000000 0000000000000000 0000000000000000
...
bit_mask_avx2_msb(124) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFF0 0000000000000000 0000000000000000
bit_mask_avx2_msb(125) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFF8 0000000000000000 0000000000000000
bit_mask_avx2_msb(126) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFC 0000000000000000 0000000000000000
bit_mask_avx2_msb(127) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFE 0000000000000000 0000000000000000
bit_mask_avx2_msb(128) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 0000000000000000 0000000000000000
bit_mask_avx2_msb(129) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 8000000000000000 0000000000000000
bit_mask_avx2_msb(130) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF C000000000000000 0000000000000000
bit_mask_avx2_msb(131) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF E000000000000000 0000000000000000
bit_mask_avx2_msb(132) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF F000000000000000 0000000000000000
...
bit_mask_avx2_msb(248) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFF00
bit_mask_avx2_msb(249) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFF80
bit_mask_avx2_msb(250) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFC0
bit_mask_avx2_msb(251) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFE0
bit_mask_avx2_msb(252) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFF0
bit_mask_avx2_msb(253) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFF8
bit_mask_avx2_msb(254) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFC
bit_mask_avx2_msb(255) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFE
bit_mask_avx2_msb(256) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_msb(257) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
bit_mask_avx2_msb(258) FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF

对于值为n且具有256 <= n <= 65535的值,所有位都设置为1,这可能是我们所期望的. 65535的上限是由于_mm256_subs_epu16()的16位饱和算术引起的. 当n = 65536时,位掩码(输出值)为零.可以修改代码,以便将所有位都设置为1 对于256 <= n< = INT_MAX的范围. 这可以通过替换来实现 shift = _mm256_subs_epu16(cnst32_256,shift);

For a value n, with 256<=n<=65535, all bits are set to one, as one might expect. The upper limit of 65535 is due to the 16-bit saturated arithmetic of _mm256_subs_epu16(). With n=65536 the bitmask (the output value) is zero. It is possible to modify the code such that all bits are set to one for the range of 256<=n<=INT_MAX. This can be achieved by replacing shift = _mm256_subs_epu16(cnst32_256,shift); with

    __m256i mask       = _mm256_cmpgt_epi32(cnst32_256,shift);
            shift      = _mm256_sub_epi32(cnst32_256,shift);
            shift      = _mm256_and_si256(shift,mask);

这三个内在函数或多或少地模仿了_mm256_subs_epu32(cnst32_256,shift),这是不存在的.

These three intrinsics more or less emulate _mm256_subs_epu32(cnst32_256,shift), which doesn't exist.

这篇关于将__m256i的前N个或后N个位设置为1,其余为0的有效方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆