在JAVA的嵌套循环中,为什 么小循环中的大循环比大循环中的小循环快? [重复]

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在JAVA的嵌套循环中,为什 么小循环中的大循环比大循环中的小循环快? [重复]相关的知识,希望对你有一定的参考价值。

当迭代次数相同时,我想知道外部“ 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");
        
    

这是结果

run1 : 4.5772473950000006 sec
run2 : 1.7155700900000002 sec
Time diff : -2.861677305 sec

run1 : 4.4107229420000005 sec
run2 : 1.6532413140000002 sec
Time diff : -2.7574816280000003 sec

run1 : 3.815836296 sec
run2 : 1.761153921 sec
Time diff : -2.054682375 sec

run1 : 3.913543021 sec
run2 : 1.752971717 sec
Time diff : -2.1605713040000003 sec

run1 : 3.851766485 sec
run2 : 1.7262416440000001 sec
Time diff : -2.1255248410000003 sec

run1 : 3.95305219 sec
run2 : 1.7323067330000002 sec
Time diff : -2.220745457 sec

run1 : 3.924869236 sec
run2 : 1.6953032440000002 sec
Time diff : -2.229565992 sec

run1 : 3.839871705 sec
run2 : 1.692300162 sec
Time diff : -2.147571543 sec

run1 : 3.93864626 sec
run2 : 1.704322469 sec
Time diff : -2.234323791 sec

run1 : 3.863758493 sec
run2 : 1.700392962 sec
Time diff : -2.163365531 sec

像这样,

我想知道为什么会出现这些结果。

并且由三重嵌套循环编辑,获得类似的结果。

答案

简短的答案是: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");
    
  

我也参加了数学考试,因为..那么,为什么要打扰?将值视为纳秒有什么问题?那才是真正的...

运行此命令,您会看到初始的大值减小并接近零。在某些运行中,这两个版本甚至都达到零。

Java 8 Run

零纳秒?是的,instant计算。让Quantum计算吸这一点!好吧,这不是really即时。当您检查nanoTime description时不是:

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

它比可测量的速度快,因为JIT可能最终发现该方法实际上没有任何作用。现在,为什么一个或另一个比另一个下降得更快,将需要更深入地研究JIT,以及JIT如何决定优化一种方法而不是另一种方法-这是我所知道的。

实际上,没有任何区别。两种方法初次运行后,最大时差最多只有几毫秒。我不认为说一个版本确实比另一个版本快要有意义。

有趣的旁注:JDK-11似乎表现不佳...Java 11 run

GraalVM的性能似乎不佳...尽管,可能有一些标志可以改善它...GraalVM

另一答案

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

展开表示:

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

被转换成类似:

int i=0;
for (;(i+16)<=MAX; i+=16) cnt+=16;
for (i<MAX; i++) cnt++; // handle case when MAX % 16 != 0

所以操作总数实际上是:

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

以上是关于在JAVA的嵌套循环中,为什 么小循环中的大循环比大循环中的小循环快? [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Java初学者,比较嵌套for循环中的字符串

小白学Java for循环3分钟学会Java的for循环,让看懂for循环嵌套再不是难事

java中for嵌套for循环的详细讲解?

打破嵌套循环[重复]

在java中,如何跳出当前的嵌套循环

面试在Java中如何跳出当前的多重嵌套循环?