关于simd:avx2-使用vpshufb指令做字符分类
最近看到simdjson的论文,其中应用vpshufb指令做的字符匹配和分类,感觉这个办法很有播种,想分享以下。 先说simdjson中为啥用这个指令,它须要从字符数组中提取出6种控制字符(‘:’, \’, ‘:’, ‘"’, ‘{’, ‘}’),以及空格换行等4种无实际意义的字符(‘\r’,‘\n’,‘\t’,‘ ’)。 vpshufb是汇编指令,在C++中能够用__m256i _mm256_shuffle_epi8 (__m256i a, __m256i b)。 __m256i _mm256_shuffle_epi8 (__m256i a, __m256i b)算法过程:FOR j := 0 to 15 i := j*8 IF b[i+7] == 1 dst[i+7:i] := 0 ELSE index[3:0] := b[i+3:i] dst[i+7:i] := a[index*8+7:index*8] FI IF b[128+i+7] == 1 dst[128+i+7:128+i] := 0 ELSE index[3:0] := b[128+i+3:128+i] dst[128+i+7:128+i] := a[128+index*8+7:128+index*8] FIENDFORdst[MAX:256] := 0简略解释一下, __m256i能够当做有256个bit位,假如i=8,那么b[i+3:i]就是b[11:8],也就是第8到11bit,这四个bit组成一个无符号整数。四个比特最大是1111,也就是十六进制的f。 _mm256_shuffle_epi8能够当作是一种查表形式,然而只能用每个字节的低四位去查。从b中获取每个字节的低四位。其值只能是0-15中的一种,把这个值当作索引,而后从a中找这个索引对应的值。总之,能够认为_mm256_shuffle_epi8是一种映射关系,将一个数映射到另一个数。 下边是_mm256_shuffle_epi8的两个应用例子。 如果有一个字节数组,存的都是ascii,你须要从中找到小写字母。a-z对应的十六进制示意是:61-6f , 70-7a (这里没写成61-7a是因为后边解决须要) 将61-6f分成一组,是因为它们高四位都是6,70-7a高四位都是7。因为高四位一样的数能够被分到一个组里边。 算法思路是将一个字节的高四位,低四位别离应用_mm256_shuffle_epi8做映射,两个映射后的后果做与运算,最终后果不为0,就代表是须要的字符。 ...