Java 获取2字节[]数组之间数值差的更快方法?

Java 获取2字节[]数组之间数值差的更快方法?,java,algorithm,lambda,java-stream,array-difference,Java,Algorithm,Lambda,Java Stream,Array Difference,我正在做一个程序,我有两个字节的数组,需要计算它们之间的差异。例如,如果第一个数组是{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]); }

我正在做一个程序,我有两个字节的数组,需要计算它们之间的差异。例如,如果第一个数组是{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;
}
public long calculateDifference(字节[]a,字节[]b){
长差=0;
for(int i=0;i
但是,该程序需要能够处理多达5000000个元素的字节数组,因此使用当前方法会太慢

因为我有16个线程,所以我将并行流视为一个选项。但是由于没有ByTestStream,如果没有拆箱和装箱,就不可能使用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;
}
public long calculateDifference(字节[]a,字节[]b,int start,int end){
长差=0;
for(int i=start;i
并从多个线程调用此方法,并组合结果:

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();
}
ExecutorService线程池=Executors.newFixedThreadPool(2);
公共长计算器差异(字节[]a,字节[]b)引发异常{
Future diff1=threadPool.submit(()->calculatediffice2(a,b,0,a.length/2));
Future diff2=threadPool.submit(()->calculatediffice2(a,b,a.length/2,a.length));
返回diff1.get()+diff2.get();
}

您可以尝试将数据分成两个或多个区域,每个区域在单独的线程中处理。它可能对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;
}
public long calculateDifference(字节[]a,字节[]b,int start,int end){
长差=0;
for(int i=start;i
并从多个线程调用此方法,并组合结果:

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();
}
ExecutorService线程池=Executors.newFixedThreadPool(2);
公共长计算器差异(字节[]a,字节[]b)引发异常{
Future diff1=threadPool.submit(()->calculatediffice2(a,b,0,a.length/2));
Future diff2=threadPool.submit(()->calculatediffice2(a,b,a.length/2,a.length));
返回diff1.get()+diff2.get();
}

如果第一个数组是
{1,2,3}
而第二个数组是
{0}
,该怎么办?另外,
5000000
添加所需的时间可能比您所能测量的要少。计算机每秒可以执行数百万次操作。在3.5GHz的6个内核中,有289Gigaflops。@ElliottFrisch我实际上在做一个遗传算法,并将持续运行,所以即使速度提高20%,也可以节省数小时。@Joni请参阅我上面的评论。注意289Gigaflops是~28900000000浮点运算(每秒)。你把500万比作近3000亿。小时?它不应该需要几秒钟。@ElliottFrisch我实际上不知道时钟速度与每秒浮点运算的速度不同!但是,对于我的程序来说,吞吐量越大越好。如果第一个数组是
{1,2,3}
,第二个数组是
{0}
,会怎么样?另外,
5000000
添加所需的时间可能比您所能测量的要少。计算机每秒可以执行数百万次操作。在3.5GHz的6个内核中,有289Gigaflops。@ElliottFrisch我实际上在做一个遗传算法,并将持续运行,所以即使速度提高20%,也可以节省数小时。@Joni请参阅我上面的评论。注意289Gigaflops是~28900000000浮点运算(每秒)。你把500万比作近3000亿。小时?它不应该需要几秒钟。@ElliottFrisch我实际上不知道时钟速度与每秒浮点运算的速度不同!不过,对于我的程序来说,吞吐量越大越好。谢谢你的回答!只有两个问题:改用threadPool.invokeAll()会有不同吗?threadPool可以重用吗?
invokeAll
不会对计算性能产生影响,但如果您觉得方便,可以使用它。当然,您可以重用线程池,但如果您这样做,可能会造成瓶颈,例如,如果从不同的线程调用
calculateDifference
本身。谢谢您的回答!只有两个问题:改用threadPool.invokeAll()会有不同吗?threadPool可以重用吗?
invokeAll
不会对计算性能产生影响,但如果您觉得方便,可以使用它。当然,您可以重用线程池,但如果您这样做,可能会造成瓶颈,例如,如果从不同的位置调用
calculateDifference
本身