获取 2 byte[] 数组之间数值差异的更快方法?

Faster way to get the numerical difference between 2 byte[] arrays?

我正在开发一个程序,其中有 2 个字节数组,需要计算它们之间的差异。例如,如果第一个数组为 {1, 2, 3},第二个数组为 {2, 3, 4},则差值为 3。

我目前的方法是这样的:

public long calculateDifference(byte[] a, byte[] b) {
  long difference = 0;
  for(int i = 0; i < a.length; i++) {
    difference += Math.abs(a[i] - b[i]);
  }
  return difference;
}

但是,该程序需要能够处理最多包含大约 5,000,000 个元素的字节数组,因此使用当前方法会太慢。

因为我有 16 个线程,所以我看到了并行流作为一个选项。但是因为没有 ByteStream,所以如果不拆箱和装箱就无法使用 reduce 和 collect 操作。

另一种选择是使用 IntStream.range(0, byteArrayLength) 创建并行流并使用 int 访问索引。但是,要做到这一点,需要一个 LongAdder 或 AtomicLong,它们在我的基准测试中都慢得多。 (LongAdder内部好像用了一个数组,最后总结一下)

有没有更有效的方法来实现这个?我不介意添加外部依赖项。谢谢!

您可以尝试的一件事是将数据分成两个或多个区域,每个区域在单独的线程中处理。对于 10 亿个项目的数组来说,这可能足以让它物有所值,但对于只有 500 万个项目,可能就不值得了。

接下来是一个非常粗略的概念验证,您可以用它来评估这个想法是否有任何价值。

制作一个为区域计算的方法:

public long calculateDifference(byte[] a, byte[] b, int start, int end) {
    long difference = 0;
    for(int i = start; i < end; i++) {
        difference += Math.abs(a[i] - b[i]);
    }
    return difference;
}

并从多个线程调用此方法,并合并结果:

ExecutorService threadPool = Executors.newFixedThreadPool(2);

public long calculateDifference(byte[] a, byte[] b) throws Exception {
    Future<Long> diff1 = threadPool.submit(() -> calculateDifference2(a, b, 0, a.length / 2));
    Future<Long> diff2 = threadPool.submit(() -> calculateDifference2(a, b, a.length / 2, a.length));
    return diff1.get() + diff2.get();
}