【问题标题】:C# fast crc32 calculation :C# 快速 crc32 计算:
【发布时间】:2010-12-23 22:57:18
【问题描述】:

我使用 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#。
  • 请注意,x86 CRC 指令使用 CRC32C 多项式(例如 iSCSI 和某些文件系统)而不是经典 CRC32(以太网、gzip、bzip2 等)en.wikipedia.org/wiki/…。 CRC32C 可能是任何新用例的最佳选择,因为它往往具有更好的 CPU 加速支持。

标签: c# performance crc32 intrinsics


【解决方案1】:

您可以使用 PInvoke(和纯 c#)或创建 C++/CLI 项目并围绕这些函数编写包装器。

你看到msdn上的例子了吗?要计算字符串的 CRC,您只需遍历它即可。

嗯,它们是内在函数。这意味着您只有一个选择:创建 C++/CLI 包装器。

【讨论】:

    【解决方案2】:

    不确定您是否必须使用这些方法来替换您的自制啤酒。为 calculating CRC-32 in C# here 找到了一个很好的实现。

    【讨论】:

      【解决方案3】:

      围绕它的 C# 包装器可能是目前处理体面大小数据的最佳解决方案。

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

      Crcutil 库提供高效的 CRC 算法实现。它包括 Andrew Kadatch 和 Bob Jenkins 在 2007 年初发明的新型多字 CRC 算法的参考实现。新算法针对现代 Intel 和 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,因为它不是一个有效的答案。
      【解决方案4】:

      多年来,CRC32 计算速度越来越快。部分是因为实现优化,也因为新的处理器指令变得可用。因此,这个近十年前的问题的新答案!

      Stephan Brumme's CRC32 page 概述了最后一个 2016 年的优化。FastCRC by Yuri Babich 是 Stephan Brumme 和 Bulat Ziganshin 的快速 C++ CRC32 算法“Slicing-by-16”的 2019 C# 实现。他声称他的版本只比原生 CLI C++ 快速 CRC32 实现慢一点(大约 10%)。此算法是较旧的 CRC-32-IEEE。

      如果您有能力选择其他变体,请选择CRC-32C (Castagnoli)。这在 Crc32C.NET 包中可用。

      CRC-32C 中的多项式被证明具有更好的错误检测 属性,这是它在较新的标准中采用的原因 (iSCSI、SCTP、ext4)。除了更高的可靠性之外,CRC-32C 现在还具有 专用指令在较新的 Intel 处理器上的优势。 这就是为什么它被选择用于高性能应用,因为 Snappy 压缩算法示例。

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

      这个库包含对托管代码的优化,所以,它确实是 比其他 Crc32 实现更快。如果您正好需要 Crc32, 这个库是最好的选择。对此实施进行了调查 从不同的变体中最快。此外,它适用于 x64 和 x86,所以,看起来,做两种不同的实现是没有意义的。

      我不知道上述两个 .NET 实现中的哪一个对于经典的 CRC-32-IEEE 算法来说是最快的。 performance comparison table 没有引用第一个实现。

      Anonymous Coward 的答案指向crcutil,这是 Andrew Kadatch 和 Bob Jenkins 在 2007 年初发明的新型多字 CRC 算法的高性能 CRC 参考实现。新算法针对现代英特尔和 AMD 处理器和比几乎所有其他软件 CRC 算法都要快得多。他们 2010 年的论文 Everything we know about CRC but afraid to forget 已在下载中列出。本文展示了一些可用于避免重新处理某些数据范围的技巧:

      • 增量 CRC 计算
      • 更改初始 CRC 值
      • CRC 的串联
      • 就地修改 CRC 消息
      • 在消息后存储 CRC 值

      因此,一旦数据量变得足够大或环境有限,就需要聪明地计算需要计算的内容。

      【讨论】:

      • 值得更明确地指出,x86 CRC 指令仅加速 CRC32C。您的一个引述是这样说的,但这是支持将其用于将在 x86 上运行的软件的一个重要原因。不过,您的回答并不清楚这些 .NET 库中的任何一个是否真正利用了 x86 CRC 指令(如果可用)。您首先要讨论位切片,如果您可以将数据以 8 字节块的形式提供给 CRC 指令,那么它是无关紧要的。