如何以Java并行方式在Java中添加两个数组?

例如,有两个巨大的(长度2-3百万)数组float []double [] 。 需要他们很快加起来。 怎么做? 这有什么图书馆吗?

使用一个固定的线程池,其线程数等于处理器核心数。 提交与线程一样多的任务。 每个任务都会收到它需要求和的索引范围。 在主线程中收集来自ExecutorService.submit返回给你的所有Future的结果,并将它们汇总到最终结果。

一种方法可以是决定分裂数组,让N个线程读取数组的指定部分并找到各个总和。 然后,最终的线程可以将所有这些单独的总和相加以用于最终输出。

我不需要做太多真正的高性能编码,但这里没有太多的优化空间(除非我天真)除了将列表分成n个段(每个核1个)并且每个核心都会提供一个小计并添加小计。 现在,如果要求您将这些值相乘,一旦工人遇到0,您就会得到答案。

 public class ArrayAdder { public double getTotal(double[] array) { Worker workers[] = new Worker[Runtime.getRuntime().availableProcessors()]; for (int i = 0; i < workers.length - 1;i++) { workers[i] = new Worker(array, i * array.length / workers.length, (i + 1) * array.length / workers.length); } workers[workers.length - 1] = new Worker(array, (workers.length - 1) * array.length / workers.length,array.length); double total = 0; for (int i = 0;i < workers.length;i++) { try { workers[i].join(); total += workers[i].getSum(); } catch (InterruptedException e) { i--; //retry the wait for worker[i] } } return total; } static class Worker extends Thread { public Worker(double[] array, int start, int end) { super(); this.array = array; this.start = start; this.end = end; start(); } private double[] array; private int start; private int end; private double sum; @Override public void run() { for (int i=start;i < end;i++) { sum += array[i]; } } public double getSum() { return sum; } } } 

您可能希望将小计和总计存储为BigDecimal具体取决于您期望值的大小。 当然,除非你需要一个确切的答案,否则将它们添加为int / long会更快 - 显然你想要舍入而不仅仅是强制转换或者只是强制转换(这可能更快)并且假设你的回答很低~ array.length / 2作为时间的一半,演员将在不正确的方向“圆”。

在Java7中使用Fork / Join框架。

另一种可能的优化可能是通过部分展开循环来尝试使用CPU的超标量function。

例如,在管道大小为四个整数的体系结构(如果JVM是智能的)上,您可以编写:

 for(int i = 0; i < array.size(); i += 4) { c[i] = a[i] + b[i]; c[i+1] = a[i+1] + b[i+1]; c[i+2] = a[i+2] + b[i+2]; c[i+3] = a[i+3] + b[i+3]; } 

但是您必须为每个不同的体系结构管道大小编写不同的代码。