Java 获取2字节[]数组之间数值差的更快方法?
我正在做一个程序,我有两个字节的数组,需要计算它们之间的差异。例如,如果第一个数组是{1,2,3},而第二个数组是{2,3,4},则差值为3 我当前执行此操作的方法如下所示: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]); }
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
本身