C#快速计算CRC32:

3

我使用Ants对我的应用进行了分析,发现超过10%的时间用于CRC32计算。(该CRC32计算是在C#中完成的)

经过一些搜索,我了解到在Visual Studio 2008中有以下几个内置函数:

_mm_crc32_u8

_mm_crc32_u16

_mm_crc32_u32

_mm_crc32_u64

http://msdn.microsoft.com/en-us/library/bb514036.aspx

请问有人能告诉我如何使用这些内置函数来替换我的自制CRC32吗?


请注意,这些是C++内置函数,而不是C#。 - MSalters
请注意,x86 CRC指令使用CRC32C多项式(例如iSCSI和某些文件系统),而不是经典的CRC32(以太网,gzip,bzip2等)。https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Polynomial_representations_of_cyclic_redundancy_checks。CRC32C可能是任何新用例的最佳选择,因为它往往具有更好的CPU加速支持。 - Peter Cordes
4个回答

5
CRC32计算速度在多年来变得更快。部分原因是由于实现的优化,也由于新的处理器指令变得可用。因此,这个几乎十年前的问题有了新的答案! Stephan Brumme's CRC32 page提供了一个关于优化的概述,最后更新于2016年。Yuri Babich的FastCRC是一个2019年的C#实现,使用了快速C++ CRC32算法"Slicing-by-16",由Stephan Brumme和Bulat Ziganshin开发。他声称他的版本只比本地CLI C ++快速CRC32实现慢一点(约10%)。该算法是较旧的CRC-32-IEEE。
如果您有选择另一种变体的能力,请选择CRC-32C(Castagnoli)。这在Crc32C.NET包中提供。
CRC-32C中的多项式显示具有更好的错误检测属性,这就是为什么它被采用于新标准(iSCSI、SCTP、ext4)的原因。除了更高的可靠性,CRC-32C现在在新的英特尔处理器上拥有专用指令的优势。这就是为什么它被选择用于高性能应用程序,例如Snappy压缩算法。

Crc32.NET是Robert Važan的Crc32C.NET的.NET安全实现,但适用于Crc32算法。

此库包含托管代码的优化,因此真正比其他Crc32实现更快。如果您需要精确的Crc32,则此库是最佳选择。这个实现从不同的变体中进行了调查,发现它是最快的。而且,它对x64和x86都很好,所以,似乎没有必要做2个不同的实现。

我不知道上面两个.NET实现哪一个对于经典的CRC-32-IEEE算法来说是最快的。性能比较表没有提到第一个实现。

匿名用户的答案指向了crcutil,这是一种高性能的CRC参考实现,采用了Andrew Kadatch和Bob Jenkins在2007年初发明的新型多字节CRC算法。新算法针对现代英特尔和AMD处理器进行了大量调整,比几乎所有其他软件CRC算法都要快得多。他们2010年的论文我们所知道的关于CRC但害怕忘记的一切列在下载中。这篇论文展示了一些技巧,可以用来避免重新处理某些数据范围:

  • 增量CRC计算
  • 更改初始CRC值
  • CRC的连接
  • 就地修改CRC-ed消息
  • 在消息后存储CRC值

因此,当数据量足够大或环境受限时,请尝试聪明地计算需要计算的内容。


值得更明确地提到的是,x86 CRC指令只加速CRC32C。你的引用中已经提到了这一点,但这是支持在x86上运行的软件的重要原因。不过,你的回答并没有明确说明这些.NET库是否实际利用了x86 CRC指令(如果有的话)。你一开始谈论的是位切片,但如果你可以将数据以8字节块的形式输入CRC指令,那么这就与此无关了。 - Peter Cordes

3
一个C#包装器可能是目前处理大量数据的最佳解决方案。

http://code.google.com/p/crcutil/

Crcutil库提供了CRC算法的高效实现。它包括Andrew Kadatch和Bob Jenkins在2007年初发明的新型多字CRC算法的参考实现。这种新算法针对现代英特尔和AMD处理器进行了大量优化,并且比几乎所有其他软件CRC算法都要快得多。
硬件辅助CRC32C:每字节0.13个(Nehalem)CPU周期。64位及更小的CRC:每字节1.0个(Nehalem)- 1.2个(Core)CPU周期。128位CRC:每字节1.7个CPU周期。
如果Haswell的AVX2带来了一些指令,可能会进一步提高性能,如果可以的话,将其包含在此库中将非常不错。

虽然这很有趣,但它并没有回答“如何替换Pygmys自制的CRC32算法”的问题。解释如何包装所提到的库会更好。不能+1,因为它不是一个有效的答案。 - Sascha Hennig

2

不确定您是否必须使用这些方法来替换自己的自制品。在此处找到了一个好的C#实现,用于计算CRC-32


0
您可以使用 PInvoke(和纯 c#),或创建 C++/CLI 项目并编写这些函数的包装器。
您是否在 MSDN 上看到了示例?要计算字符串的 CRC,只需循环遍历即可。
好吧,它们是内置函数。这意味着您只有一种选择:创建 C++/CLI 包装器。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接