_mm_crc32给出与手动版本不同的结果

_mm_crc32 giving different results that manual version

本文关键字:版本 结果 mm crc32      更新时间:2023-10-16

我有以下代码(手动版本来自阿德勒的答案(

#include <iostream>
#include <nmmintrin.h>
#define POLY2 0x82f63b78  
uint32_t crc32c2(uint32_t crc, const unsigned char *buf, size_t len)
{
int k;
crc = ~crc;
while (len--) {
crc ^= *buf++;
for (k = 0; k < 8; k++)
crc = crc & 1 ? (crc >> 1) ^ POLY2 : crc >> 1;
}
return ~crc;
}
int main(int argc, char **argv)
{
const unsigned int val = 5;
std::cout << std::hex << crc32c2(0,(const unsigned char*)&val,4) << std::endl;   
std::cout << _mm_crc32_u32(0, 5) << std::endl;
}

输出为:

EE00D08C

A6679B4B

我的问题是为什么手动版本没有给出与内部版本相同的答案。

Mark Adler关于在软件中实现SSE 4.2的CRC32C的回答表明,您需要从0 ^ 0xffffffff开始,并以crc0 ^ 0xffffffff;结束,以预处理和后处理结束。 (或者像在 SW 版本中那样使用~运算符(。

Mark 的回答使用 GNU C 内联 asm,但内在移植会很简单。 (它与多个累加器一起展开,以隐藏crc32_u64在大缓冲区上的延迟。

此版本适用于我的系统。

int main(int argc, char **argv)
{
const unsigned int val = 5;
std::cout << std::hex << crc32c2(0,(const unsigned char*)&val,4) << 'n';   
std::cout << (_mm_crc32_u32(0^0xffffffff, 5) ^ 0xffffffffU) << 'n';
}

(请注意,std::endl比换行符慢毫无意义,除非您确实需要强制刷新,以防流是完全缓冲而不是行缓冲。