我一直试图在支持AVX512的计算机上以及先前针对AVX2优化的代码上使用_mm256_popcnt_epi64。
[不幸的是,我遇到了找不到该功能的问题。但是,找到了相应的__m512i
等效项。 __m256i
功能是否已弃用?
_mm512_popcnt_epi64
是_mm512_popcnt_epi64
的一部分。 256和128位版本还要求AVX512VL使用带有128位或256位向量的AVX512指令。
主流AVX512 CPU均具有AVX512-VL。 Xeon Phi CPU没有AVX512-VL。
也许您忘记启用必需的编译器选项(例如,GCC AVX512-VPOPCNTDQ来启用正在编译的计算机可以执行的所有操作),或者您正在为没有两个功能的目标进行编译。如果是这样,则编译器将没有对-march=native
的定义作为内在函数,因此在C中它将假定其未声明的功能并发出对其的调用。这会导致您似乎在谈论链接器错误。
目前很少有CPU带有AVX512-VPOPCNTDQ(_m256_popcnt_epi64
):
__m512i
。除非数据布局对256完美地起作用并且对512位进行额外的改组,否则您肯定应该在Xeon Phi上使用512位向量。但是请注意,对于没有512位版本的某些AVX / AVX2指令,它的运行速度很慢,例如元素小于32位的改组。 (无AVX512 BW)gcc -O3 -march=knm
,例如_mm256_popcnt_epi64
。 (假设编译器的头文件正确)。[在Ice Lake上选择256位和512位向量之间的选择与在Skylake-x上一样是一个折衷:当512位向量oups在飞行中时,端口1上的向量ALU不会被使用。并且最大涡轮时钟速度可能会降低。 gcc -O3 -march=icelake-client
。因此,如果从较宽的向量中得不到太多的加速(例如,由于内存瓶颈,或者您的SIMD循环只是较大程序的一小部分),则在一个循环中使用512位向量可能会损害整体性能。
其他CPU根本不支持硬件SIMD popcnt,并且没有SIMD instructions lowering CPU frequency形式可用。
即使您只有AVX2,也没有AVX512,SIMD popcnt还是标量_mm512_popcnt_epi64
胜过具有快速popcnt
(vpshufb
)的现代CPU上的小型阵列。 [_mm256_shuffle_epi8
具有使用https://github.com/WojciechMula/sse-popcount/进行Harley-Seal累积的AVX2和AVX512版本,以减少用于弹出计数的SIMD LUT查找数量。
也在堆栈溢出vpternlogd
中显示了几年前从该存储库复制的一些代码。
如果需要分别计算单独元素的数量,则只需将Counting 1 bits (population count) on large data using AVX-512 or AVX-2和vpshufb
的标准解包与零向量相对应即可将hsum合并为64位qword块。
如果需要位置弹出计数(每个位位置的和,请参见vpsadbw
。