快速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 >> 1) ^ (POLY & (0 - (crc & 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算法?的主要内容,如果未能解决你的问题,请参考以下文章