Байт C# [] сравнение без проверок принадлежности к диапазону

Я ищу производительность эффективные способы сравнить два байта [] для равенства. Размеры выше 1 МБ, таким образом, издержки для каждого элемента массива должны быть минимизированы.

Я стремлюсь побеждать скорости SequenceEqual или кодированный рукой для цикла по каждому объекту, путем предотвращения повторяющихся проверок принадлежности к диапазону на оба массива. Таким же образом это Array.Copy мог привести к быстро memcpy, что приведет к a memcmp?

6
задан Community 23 May 2017 в 12:13
поделиться

2 ответа

Если производительность действительно имеет значение, то самый быстрый способ сделать это, используя библиотеку CRT, включенной с каждой версией Windows. Этот код занимает ~ 51 мсек на моем ноутбуке Poky, работает на 64-битных машинах:

using System;
using System.Runtime.InteropServices;
using System.Diagnostics;

class Program {
  static void Main(string[] args) {
    byte[] arr1 = new byte[50 * 1024 * 1024];
    byte[] arr2 = new byte[50 * 1024 * 1024];
    var sw = Stopwatch.StartNew();
    bool equal = memcmp(arr1, arr2, arr1.Length) == 0;
    sw.Stop();
    Console.WriteLine(sw.ElapsedMilliseconds);
    Console.ReadLine();
  }
  [DllImport("msvcrt.dll")]
  private static extern int memcmp(byte[] arr1, byte[] arr2, int cnt);
}
12
ответ дан 8 December 2019 в 03:26
поделиться

Для выполнения операций с указателями можно использовать небезопасный код. Можно одновременно сравнивать байты четыре как целые числа:

public static bool ArrayCompare(byte[] a, byte[] b) {
  if (a.Length != b.Length) return false;
  int len = a.Length;
  unsafe {
    fixed(byte* ap = a, bp = b) {
      int* aip = (int*)ap, bip = (int*)bp;
      for (;len >= 4;len-=4) {
        if (*aip != *bip) return false;
        aip++;
        bip++;
      }
      byte* ap2 = (byte*)aip, bp2 = (byte*)bip;
      for (;len>0;len--) {
        if (*ap2 != *bp2) return false;
        ap2++;
        bp2++;
      }
    }
  }
  return true;
}

A проверили это на простом цикле, и это примерно в шесть раз быстрее.

Как предложил Джош Эйнштейн, long можно использовать на 64-битной системе. На самом деле, похоже, что оно почти в два раза быстрее как на 32-битных, так и на 64-битных системах:

public static bool ArrayCompare64(byte[] a, byte[] b) {
  if (a.Length != b.Length) return false;
  int len = a.Length;
  unsafe {
    fixed (byte* ap = a, bp = b) {
      long* alp = (long*)ap, blp = (long*)bp;
      for (; len >= 8; len -= 8) {
        if (*alp != *blp) return false;
        alp++;
        blp++;
      }
      byte* ap2 = (byte*)alp, bp2 = (byte*)blp;
      for (; len > 0; len--) {
        if (*ap2 != *bp2) return false;
        ap2++;
        bp2++;
      }
    }
  }
  return true;
}
16
ответ дан 8 December 2019 в 03:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: