获取 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();
}
我正在开发一个程序,其中有 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();
}