0%

缺少指令集pclmulqdq导致无法运行crc32c的问题

问题

之前跑程序一直在intel/amd的CPU上,最近要适配一款国产cpu -中科海光 Hygon C86 7151 16-core Processor。突然发现计算crc32的程序跑不起来了,是啥原因呢?

这是用到的crc32的库https://github.com/htot/crc32c/。

  • 编译 cd crc32c/crc32c; make all
  • 跑test程序 ./crc32c_test
1
2
3
4
5
[root@store-11-14 crc32c]# ./crc32c_test 
Testing CRC32C functions
CRC32C:
CPUDetection: PASSED.
KnownValues: Illegal instruction

调试

用gdb汇编调试,

1
2
3
4
gdb ./crc32c_test 
(gdb) layout asm
(gdb) run
(gdb) m received signal SIGILL, Illegal instruction.

在执行机器指令pclmullqlqdq的时候,出现了Illegal instruction的错误,即改指令不支持。

该指令的支持,需要cpu支持pclmulqdq指令。该指令有助于实现高效的多项式的乘法。
查看Hygon C86 7151的处理器。确实没有该指令,所以无法运行crc32c_test。

而在用的一款intel cpu上有该pclmulqdq指令,所以可以运行crc32c_test。

再看crc32c中https://github.com/htot/crc32c/blob/master/crc32c/crc32intelc.cc的描述,也提到了依赖使用pclmulqdq instruction,进一步佐证了上面的分析过程。

/* Use hardware CRC instruction on Intel SSE 4.2 processors. This computes a
CRC-32C, not the CRC-32 used by Ethernet and zip, gzip, etc. Where efficient
3 crc32q instructions are used which a single core can execute in parallel.
This compensates for the latency of a single crc32q instruction. Combining the
3 CRC-32C bytes is done using the pclmulqdq instruction
, which has overhead of
its own, and makes this code path only efficient for buffer sizes above 216 bytes.
All code requiring a crc32q instruction is done inside a macro, for which alternative
code is generated in case of a 32 bit platform.*/