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

NoS*_*tAl 2 c++ sse crc intrinsics

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

 #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;
    }
Run Code Online (Sandbox Code Playgroud)

输出是:

ee00d08c

a6679b4b

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

Pet*_*des 5

Mark Adler 对Implementing SSE 4.2's CRC32C in software 的回答表明您需要以 开始0 ^ 0xffffffff,并以 结束 来crc0 ^ 0xffffffff;进行预处理和后处理。(或者像~在 SW 版本中那样使用运算符)。

Mark 的答案使用 GNU C 内联汇编,但内部函数端口会很简单。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';
}
Run Code Online (Sandbox Code Playgroud)

(请注意,这std::endl比换行符慢得多,除非您实际上需要强制刷新,以防流被全缓冲而不是行缓冲。)