在JAVA中循环两次但成本相同

时间:2017-07-13 07:26:07

标签: java performance loops

我有一个这样的循环:

  double[][] ED = new double[n][m];
  for(int k = 0; k < 20000; k++)
   for (int i = 0; i < 200; i++) 
    for (int j = 0; j < 200; j++)
     ED[i][j] = dis(qx[k][i], qy[k][i], dx[k][j], dy[k][j]);

“dis”是计算(x1,y1)和(x2,y2)之间的距离的函数。不介意。问题是当我在循环中添加另一个布尔赋值时,就像这样:

  double[][] ED = new double[n][m];
  boolean[][] bool = new boolean[n][m];
   for(int k = 0; k < 20000; k++)
   for (int i = 0; i < 200; i++) 
    for (int j = 0; j < 200; j++)
     {
       ED[i][j] = dis(qx[k][i], qy[k][i], dx[k][j], dy[k][j]);
       bool[i][j] = ED[i][j] > 5000;
     }

新循环比第一个循环花费1.5倍。我觉得它花了太多钱。为了测试,我将2个分配分成2个循环。奇怪的是,两个时间成本相同。有时,代码3比代码2花费更少的时间

    double[][] ED = new double[n][m];
    boolean[][] bool = new boolean[n][m];
    for(int k = 0; k < 20000; k++)
    {
      for (int i = 0; i < 200; i++) 
       for (int j = 0; j < 200; j++)
        {
         ED[i][j] = dis(qx[k][i], qy[k][i], dx[k][j], dy[k][j]);
        }
      for (int i = 0; i < 200; i++) 
       for (int j = 0; j < 200; j++)
        {
         bool[i][j] = ED[i][j] > 5000;
        }
    }

我的目标是使用更少的时间来计算bool [i] [j],我该怎么做。

1 个答案:

答案 0 :(得分:1)

引入新的大数组bool [] []可能比看起来更具影响力。 当仅使用单个arrayED [i] [j]时,可以减轻L1处理器缓存的压力。 对于第二个数组,您有两倍的数据,因此缓存将更频繁地失效。

你能尝试,而不是使用两个数组(bool和arrayED)使用同时包含double和boolean的单个数组吗?对象数组会有很大的开销,但是(也许)编译器会足够智能地去构造对象。

使用单个数组,您将拥有更好的数据位置。

另外,正如评论中所建议的那样,请确保正确进行微基准测试。 使用http://openjdk.java.net/projects/code-tools/jmh/并阅读其文档如何正确使用它。

另一种有助于多核系统的解决方案是使用并行处理。您可以创建ThreadPoolExecutor(池大小等于您拥有的核心数),然后将每个操作作为任务提交给执行程序。操作可能是最内层循环(带有计数器j),甚至可能是两个最内层循环(带有计数器ij)。 协调工作会有一些开销,但如果你有4或8个核心,执行时间应该快得多。

另一个想法是改变输入数据结构。你可以使用单个数组,而不是在4个二维数组(qx,qy,dx,dy)上运行吗?它可以使dis功能更快。