假设在一个1千万长度的数组中,基本可以肯定只有几十个数小于4。如果要统计具体小于4的数有多少,是否有比较高效率的方法。
我现在的思路是,因为小于4的数很少,是否能减少if分支的数量,比如四个数为一组,因为即使四个位一组,if的结果也99%都为false,应该有利于分支预测,但是实际测试下来并没有一个提升。
if(pb[i]<4||pb[i+1]<4||pb[i+2]<4||pb[i+3]<4){
//在逐一判断一次,看具体有几个数小于4
}
现在我想通过avx2指令做类似上述的操作。
通过_mm256_cmpgt_epi64指令一次比较四个数,但是返回的也是__m256i类型,而且为true时,64个位填充的0xFFFFFFFFFFFFFFFF。
这样的话,问题就转变成判读__m256i中的每个数是否都含有1,但是我找了半天没发现有这样的指令。
我也不确定这样的做法是否有效率,只是想到了就想测试一下。求大家解惑。
确实可以用simd优化这个过程,下边这个函数,统计ms中小于5的数据有多少,假设数组中大概35个小于等于4的元素。
我用visiual studio 2019,分别使用msvc和llvm编译器,msvc编译出来的是循环展开成5,逐次判断是否小于等于4,大概耗时6毫秒。
用llvm编译出来的是使用通过avx2指令集版本,一次循环比较16个元素的大小。耗时4.5毫秒左右。
下边是循环体部分的汇编:
上边的内容可以看作下边的代码重复了四次:
xmm0,xmm2,xmm3,xmm4都保存的是部分结果,循环结束后,把xmm0,xmm2,xmm3,xmm4中数据相加就是结果了。