【问题标题】:How to add two arrays in Java in parallel manner?如何在Java中以并行方式添加两个数组?
【发布时间】:2013-05-22 08:10:13
【问题描述】:

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

【问题讨论】:

  • 使用多线程...,只是为了模拟
  • 除非我错过了什么,不是真的。
  • 你想要多快?我刚刚写了一个 for 循环,它遍历 200 万 double 值并对它们求和。花了不到一秒钟。你需要比这更快吗?

标签: java arrays vector parallel-processing add


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      我不需要做太多真正高性能的编码,但这里并没有太多的优化空间(除非我很天真),除了将列表分成 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,具体取决于您期望值的大小。当然,除非您需要一个确切的答案,否则将它们添加为整数/长整数会快得多 - 显然您想要四舍五入而不是仅仅投射或只是投射(这可能更快)并假设您的答案会低~ array.length / 2 有一半时间,演员会朝错误的方向“环绕”它。

      【讨论】:

        【解决方案4】:

        在 Java7 中使用 Fork/Join 框架。

        【讨论】:

          【解决方案5】:

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

          例如,在具有四个整数的管道大小的体系结构(如果 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];
          }
          

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

          【讨论】:

            猜你喜欢
            • 2016-12-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-08-23
            • 1970-01-01
            • 1970-01-01
            • 2018-02-13
            • 1970-01-01
            相关资源
            最近更新 更多