1

搜索了一下,但我并没有真正找到我要找的东西。

我必须每秒验证大约 100 字节 [16384](+许多其他任务..)。看起来拐角处最大的问题是速度。

你们知道 C#.NET 中有什么好的校验和算法非常快吗?它不必非常精确,但如果一个位发生变化,校验和也应该(通常..)改变。

字节存储在内存中,所以没有 IO 东西会减慢它的速度。

谢谢!

4

2 回答 2

5

扩展 C.Evenhuis 的答案,这里有一些变化应该会更快一些。我不确定他们的正确性,有更多经验的人想帮助我吗?我知道他们给出的校验和与每字节的校验和不同,但我确实认为他们给出的校验和与每字节的校验和一样(不是很好,但显然足够)。

正如我在评论中所说,您可以通过不比较每个字节的字节数来大大提高速度,而是将数组视为小 4 倍的整数数组或小 8 倍的长数组。将其视为long[]仅可在 64 位上提供性能优势。

static unsafe uint ChecksumInt(byte[] array)
{
  unchecked
  {
    uint checksum = 0;
    fixed (byte* ptr = array)
    {
      var intPtr = (uint*)ptr;

      var iterations = array.Length / 4;
      var remainderIterations = array.Length % 4;

      for (var i = 0; i < iterations; i++)
      {
        var val = intPtr[i];
        checksum += val;
      }

      while (remainderIterations >= 0) // no more than 3 iterations
      {
        checksum += ptr[array.Length - remainderIterations];
        remainderIterations--;
      }
      return checksum;
    }
  }
}

static unsafe ulong ChecksumLong(byte[] array)
{
  unchecked
  {
    ulong checksum = 0;
    fixed (byte* ptr = array)
    {
      var intPtr = (ulong*)ptr;

      var iterations = array.Length / 8;
      var remainderIterations = array.Length % 8;

      for (var i = 0; i < iterations; i++)
      {
        var val = intPtr[i];
        checksum += val;
      }

      while (remainderIterations >= 0) // no more than 7 iterations
      {
        checksum += ptr[array.Length - remainderIterations];
        remainderIterations--;
      }
      return checksum;
    }
  }
}

我在 64 位(Core 2 Duo 3 GHz)上对 100,000 个项目的阵列进行了 10,000 次迭代的性能测量:

  • 每 1 个字节:00:00:00.7052533
  • 每 4 个字节:00:00:00.1761491
  • 每 8 个字节:00:00:00.0856880

所以速度要快一些。

但是,就像我说的,我不确定这是否提供了同样好的校验和。

于 2012-04-27T22:32:51.367 回答
1

如果每一个比特都很重要,那么校验和算法就必须处理每一个字节。一个简单的算法是简单地添加每个值并忽略溢出:

    static unsafe uint GetChecksum(byte[] array)
    {
        unchecked
        {
            uint checksum = 0;
            fixed (byte* arrayBase = array)
            {
                byte* arrayPointer = arrayBase;
                for (int i = array.Length - 1; i >= 0; i--)
                {
                    checksum += *arrayPointer;
                    arrayPointer++;
                }
            }
            return checksum;
        }
    }

当然,您可能无法检测到所有更改并获得重复项,但它可能会为您提供有关快速算法执行情况的指示。

于 2012-04-26T14:20:06.283 回答