快速CRC算法?

Posted

技术标签:

【中文标题】快速CRC算法?【英文标题】:Fast CRC algorithm? 【发布时间】:2015-03-12 10:56:46 【问题描述】:

我想用 ASCII 字符串创建一个 32 位数字。 CRC32 算法正是我正在寻找的,但我不能使用它,因为它需要的表太大(它适用于资源非常稀缺的嵌入式系统)。

那么:对快速而精简的 CRC 算法有什么建议吗?与原始 CRC32 相比,何时更可能发生冲突并不重要。

【问题讨论】:

CRC32 可以在没有查找表的情况下实现,或者如果必须的话,可以使用 1k 字节的查找表来实现,与 256k 的查找表变体相比,不会有很大的速度损失。 wiki.osdev.org/CRC32 的示例。如果您确实必须保存字节,请使用 adler32。 ressources are VERY rare 是什么意思?小于 64MB、小于 8KB 还是小于 512byte? 也许只是修复该代码并将表格放入闪存中。大多数链接器将常量变量放在闪存中,如今即使是低端 CPU-s 也带有 OTP 的下降量。只需将 table 定义为 const。 如果您对哈希/校验和/其他的质量没有任何特殊要求,那么像boost::hash_combine 这样非常简单的东西,甚至只是 XOR,可能就足够了。 这个问题不是题外话。 *** 警察显然不知道算法和实现之间的区别。询问存在哪些算法来完成特定任务完全是一个主题。 【参考方案1】:

CRC 实现使用表格来提高速度。它们不是必需的。

这是一个简短的 CRC32,使用 Castagnoli 多项式(与 Intel crc32 指令使用的相同)或以太网多项式(与 zip、gzip 等中使用的相同)。

#include <stddef.h>
#include <stdint.h>

/* CRC-32C (iSCSI) polynomial in reversed bit order. */
#define POLY 0x82f63b78

/* CRC-32 (Ethernet, ZIP, etc.) polynomial in reversed bit order. */
/* #define POLY 0xedb88320 */

uint32_t crc32c(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) ^ POLY : crc >> 1;
    
    return ~crc;

初始crc 值应为零。可以使用数据块连续调用该例程以更新 CRC。您可以展开内部循环以提高速度,尽管您的编译器可能会为您执行此操作。

【讨论】:

crc = (crc &gt;&gt; 1) ^ (POLY &amp; (0 - (crc &amp; 1))); 在使用 GCC/ICC/CLANG 为 x86 编译时快了约 33%(104 MB/s 与 134 MB/s)。在同一系统上,slice-8 是 2040 MB/s,而 Intel CRC32C 是 8 GB/s,所以最后可能没有太大区别。 @SnappleLVR Faster 仍然是按字节或按字的表实现。请参阅crcany,它将生成此类例程。 使用与上述相同的机器进行基准测试结果:1430 MB/s,不错,但 slice-8 仍然快 30%,CRC32C 指令快 450%。我只是指出,简单的按位版本可以通过对源代码进行小的手术修改来优化为快 33%。使用 -O3 使用 CLANG 和 GCC 将原始代码编译成“test/cmov”。更快的变体使用直接的 NEG/XOR/AND,正如从源代码中可以预期的那样。 (0 - n) 只是允许对无符号整数求反的技巧。所以要明确一点,我并没有声称这是最快的例程。 xD【参考方案2】:

显然,最大的查找表将带来最佳性能,但您可以使用任何(较小的)表进行 16,8 或 4 位查找。

所以表格大小是针对 crc32 的:

16bit-lookup: 4*2^16=256k  
 8bit-lookup: 4*2^8=1k  
 4bit-lookup: 4*2^4=64byte  

4 位表比 16 位表慢四倍。 您应该使用什么取决于您的速度要求。

正如 Luka Rahne 所说,将表放入闪存是个好主意,但在许多平台上,使用 const 关键字是不够的。 大多数情况下,您需要通过修改链接器命令文件将表放入闪存中的部分。

【讨论】:

另请参阅 Fast CRC32,Stephan Brumme 的网页提供了不同表格大小的比较。

以上是关于快速CRC算法?的主要内容,如果未能解决你的问题,请参考以下文章

CRC 算法C代码

Modbus总线CRC16效验算法C语言

C语言实现CRC32算法

CRC32加密算法的识别

crc16校验的c语言程序

CRC32算法