简体   繁体   English

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

[英]How to add two arrays in Java in parallel manner?

For example, there are two huge (length 2-3 million) of the array float [] or double [] . 例如,数组float []double []有两个巨大的数组(长度为2-3百万)。 Need them very quickly add up. 需要他们很快加起来。 How to do it? 怎么做? Are there any libraries for this? 有图书馆吗?

Employ a fixed thread-pool with the number of threads equaling the number of processor cores. 使用一个固定的线程池,该线程池的线程数等于处理器内核的数量。 Submit as many tasks as there are threads. 提交与线程数一样多的任务。 Each task receives its index range it needs to sum. 每个任务接收其需要求和的索引范围。 In the main thread collect the results from all Future s returned to you from ExecutorService.submit and sum them up to the final result. 在主线程中,收集从ExecutorService.submit返回给您的所有Future的结果,并将其加和为最终结果。

One approach can be to decide a splitting of the array, and let N threads read specified parts of array and find individual sums. 一种方法可以是确定数组的拆分,然后让N个线程读取数组的指定部分并查找各个和。 A final thread can then add up all these individual sums for final output. 然后,最终线程可以将所有这些总和相加,以最终输出。

I've not had to do much truly high-performance coding but there isn't really a lot of room for optimization here (unless I'm being naive) except to divide the list into n segments (1 for each core) and have each core come up with a subtotal and add the subtotals up. 我不必做很多真正的高性能编码,但这里实际上没有太多优化空间(除非我天真),只是将列表分成n个段(每个核心1个)并具有每个核心提供一个小计,然后将小计加起来。 Now if you were being asked to multiply the values, as soon as a worker encounters a 0, you have your answer. 现在,如果要求您将值相乘,则当工人遇到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; }
    }
}

You might want to store the subtotals and total as a BigDecimal depending on how large you expect the values to be. 您可能希望将小计和总计存储为BigDecimal具体取决于您期望值的大小。 Of course, unless you need an exact answer, adding them up as ints/longs would be much faster - obviously you'd want to round and not just cast or just cast (which may be faster) and assume you answer will be low by ~ array.length / 2 as half the time, the cast will "round" it in the incorrect direction. 当然,除非您需要确切的答案,否则将它们加为整数/多位数会更快得多-显然,您想舍入而不是仅进行强制转换或仅强制转换(可能会更快),并假设您的答案会降低array.length / 2一半,强制转换将以错误的方向“四舍五入”。

在Java7中使用Fork / Join框架。

Another possible optimisation might be to try to use the superscalar abilities of your CPU by partially unrolling your loop. 另一个可能的优化可能是通过部分展开循环来尝试使用CPU的超标量功能。

For instance, on an architecture (and if the JVM is intelligent) with a pipeline size of four ints, you could write : 例如,在具有四个int的管道大小的体系结构(如果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];
}

But you have to write different code for every different architecture pipeline size. 但是您必须为每个不同的体系结构管道大小编写不同的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM