Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在JAVA中的嵌套for循环中,为什么小循环中的大循环比大循环中的小循环快?_Java_Performance_For Loop_Nested - Fatal编程技术网

在JAVA中的嵌套for循环中,为什么小循环中的大循环比大循环中的小循环快?

在JAVA中的嵌套for循环中,为什么小循环中的大循环比大循环中的小循环快?,java,performance,for-loop,nested,Java,Performance,For Loop,Nested,当迭代次数相同时,我想知道外部“for循环”的较小迭代是否更快 这是我的java代码 循环迭代总数为1000亿次 public class Test { public static long run1() { final long start = System.nanoTime(); long cnt = 0; for(int i = 0; i<1000000000; i++) { for(int j = 0

当迭代次数相同时,我想知道外部“for循环”的较小迭代是否更快

这是我的java代码

循环迭代总数为1000亿次

public class Test {

    public static long run1() {
        final long start = System.nanoTime();
        long cnt = 0;
        for(int i = 0; i<1000000000; i++) {
            for(int j = 0 ; j<100 ; j++) {
                cnt++;
            }
        }
        final long end = System.nanoTime();

        System.out.println("run1 : "+(end-start)*1e-9+" sec");
        return start - end;
    }



    public static long run2() {
        final long start = System.nanoTime();
        long cnt = 0;
        for(int i = 0; i<100; i++) {
            for(int j = 0 ; j<1000000000 ; j++) {
                cnt++;
            }
        }
        final long end = System.nanoTime();

        System.out.println("run2 : "+(end-start)*1e-9+" sec");
        return start - end;
    }


    public static void main(String[] args) {

        for(int i = 0 ; i < 10 ; i++) {
            long test1 = run1();
            long test2 = run2();
            System.out.println("Time diff : "+(test1-test2)*1e-9+" sec\n");
        }
    }
}
像这样,

我想知道为什么会有这些结果


并且,通过三重嵌套循环编辑,得到了类似的结果。

简单的回答是:JIT和你的数学是错误的

让我们从run方法开始,它以这一行和一个返回结束

System.out.println("run1 : "+(end-start)*1e-9+" sec");
return start - end;
这里的问题是打印结束-开始,然后返回开始-结束。我没有在run方法中进行数学运算,而是将其转换为每次运行只负责运行和计时:

public class loops
{

  public static long run1()
  {
    final long start = System.nanoTime();
    long cnt = 0;
    for (int i = 0; i < 1000000000; i++)
    {
      for (int j = 0; j < 100; j++)
      {
        cnt++;
      }
    }
    final long end = System.nanoTime();
    return end - start;
  }

  public static long run2()
  {
    final long start = System.nanoTime();
    long cnt = 0;
    for (int i = 0; i < 100; i++)
    {
      for (int j = 0; j < 1000000000; j++)
      {
        cnt++;
      }
    }
    final long end = System.nanoTime();
    return end - start;
  }

  public static void main(String[] args)
  {

    for (int i = 0; i < 10; i++)
    {
      long test1 = run1();
      long test2 = run2();
      System.out.println("run1 : " + test1 + " ns");
      System.out.println("run2 : " + test2 + " ns");
      System.out.println("Time diff : " + (test1 - test2) + " ns\n");
    }
  }
}
公共类循环
{
公共静态长运行1()
{
最终长启动=System.nanoTime();
长cnt=0;
对于(int i=0;i<100000000;i++)
{
对于(int j=0;j<100;j++)
{
cnt++;
}
}
最终长端=System.nanoTime();
返回结束-开始;
}
公共静态长运行2()
{
最终长启动=System.nanoTime();
长cnt=0;
对于(int i=0;i<100;i++)
{
对于(int j=0;j<100000000;j++)
{
cnt++;
}
}
最终长端=System.nanoTime();
返回结束-开始;
}
公共静态void main(字符串[]args)
{
对于(int i=0;i<10;i++)
{
长test1=run1();
长test2=run2();
System.out.println(“run1:+test1+ns”);
System.out.println(“run2:+test2+ns”);
System.out.println(“时间差:+(test1-test2)+“ns\n”);
}
}
}
我还把数学题去掉了,因为。。那么,为什么要麻烦呢?将这些值视为纳秒有什么不对?这才是真正的

运行此命令,可以看到初始大值减小并接近零。在一些运行中,这两个版本甚至都达到了零

零纳秒?是的,即时计算。让量子计算去吸它吧! 好吧,这不是即时的。当您检查以下各项时,则不会:

该方法提供纳秒精度,但不一定 纳秒分辨率(即值更改的频率)

它只是比可行的测量速度快,因为JIT可能最终发现该方法实际上什么都不做。现在,为什么一种方法比另一种方法减少得更快,需要深入研究JIT,以及它如何决定优化一种方法和另一种方法,这是我所不知道的

最后,两者几乎没有区别。两种方法初始运行后,最大的时间差最多只有几毫秒。我不认为说一个版本比另一个版本快有什么意义

有趣的旁注: JDK-11的性能似乎不太好。。。

格拉尔文的表现似乎不太好。。。虽然,可能有一些标志可以改善它。。。
简单的回答是:JIT和你的数学是错误的

让我们从run方法开始,它以这一行和一个返回结束

System.out.println("run1 : "+(end-start)*1e-9+" sec");
return start - end;
这里的问题是打印结束-开始,然后返回开始-结束。我没有在run方法中进行数学运算,而是将其转换为每次运行只负责运行和计时:

public class loops
{

  public static long run1()
  {
    final long start = System.nanoTime();
    long cnt = 0;
    for (int i = 0; i < 1000000000; i++)
    {
      for (int j = 0; j < 100; j++)
      {
        cnt++;
      }
    }
    final long end = System.nanoTime();
    return end - start;
  }

  public static long run2()
  {
    final long start = System.nanoTime();
    long cnt = 0;
    for (int i = 0; i < 100; i++)
    {
      for (int j = 0; j < 1000000000; j++)
      {
        cnt++;
      }
    }
    final long end = System.nanoTime();
    return end - start;
  }

  public static void main(String[] args)
  {

    for (int i = 0; i < 10; i++)
    {
      long test1 = run1();
      long test2 = run2();
      System.out.println("run1 : " + test1 + " ns");
      System.out.println("run2 : " + test2 + " ns");
      System.out.println("Time diff : " + (test1 - test2) + " ns\n");
    }
  }
}
公共类循环
{
公共静态长运行1()
{
最终长启动=System.nanoTime();
长cnt=0;
对于(int i=0;i<100000000;i++)
{
对于(int j=0;j<100;j++)
{
cnt++;
}
}
最终长端=System.nanoTime();
返回结束-开始;
}
公共静态长运行2()
{
最终长启动=System.nanoTime();
长cnt=0;
对于(int i=0;i<100;i++)
{
对于(int j=0;j<100000000;j++)
{
cnt++;
}
}
最终长端=System.nanoTime();
返回结束-开始;
}
公共静态void main(字符串[]args)
{
对于(int i=0;i<10;i++)
{
长test1=run1();
长test2=run2();
System.out.println(“run1:+test1+ns”);
System.out.println(“run2:+test2+ns”);
System.out.println(“时间差:+(test1-test2)+“ns\n”);
}
}
}
我还把数学题去掉了,因为。。那么,为什么要麻烦呢?将这些值视为纳秒有什么不对?这才是真正的

运行此命令,可以看到初始大值减小并接近零。在一些运行中,这两个版本甚至都达到了零

零纳秒?是的,即时计算。让量子计算去吸它吧! 好吧,这不是即时的。当您检查以下各项时,则不会:

该方法提供纳秒精度,但不一定 纳秒分辨率(即值更改的频率)

它只是比可行的测量速度快,因为JIT可能最终发现该方法实际上什么都不做。现在,为什么一种方法比另一种方法减少得更快,需要深入研究JIT,以及它如何决定优化一种方法和另一种方法,这是我所不知道的

最后,两者几乎没有区别。两种方法初始运行后,最大的时间差最多只有几毫秒。我不认为说一个版本比另一个版本快有什么意义

有趣的旁注: JDK-11的性能似乎不太好。。。

格拉尔文的表现似乎不太好。。。虽然,可能有一些标志可以改善它。。。
您看到的性能差异是由于循环展开,JVM首先展开内部循环,但无法展开外部循环

展开意味着:

for (int i=0;i<MAX;i++) cnt++;

您看到的性能差异是由于循环展开,JVM首先展开内部循环,但无法展开外部循环

展开
run1: 1000000000 * (100 / 16 + 4) = 10 000 000 000 operations
run2: 100 * (1000000000 / 16)     =  6 250 000 000 operations