1

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

4

5 回答 5

2

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

于 2013-05-22T08:15:18.990 回答
0

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

例如,在管道大小为 4 个整数的架构(如果 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];
}

但是您必须为每种不同的架构管道大小编写不同的代码。

于 2013-07-25T07:20:03.327 回答
0

我不需要做太多真正的高性能编码,但这里没有太多优化空间(除非我很天真),除了将列表分成 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; }
    }
}

您可能希望将小计和总计存储为 a,BigDecimal具体取决于您期望值的大小。当然,除非您需要一个确切的答案,否则将它们添加为整数/长整数会快得多 - 显然您想要四舍五入而不是仅仅投射或只是投射(这可能更快)并假设您的答案会低~array.length / 2有一半的时间,演员会朝错误的方向“绕”它。

于 2013-05-22T08:52:05.437 回答
0

在 Java7 中使用 Fork/Join 框架。

于 2013-05-22T13:55:52.537 回答
0

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

于 2013-05-22T08:32:21.807 回答