Warum macht das Umkehren einer Schleife es langsamer?

8

Ich habe den folgenden Code, der eine kreisförmige Verschiebung der Bits im Array bewirkt:

%Vor%

Dann dachte ich, es ist einfacher und lesbarer, so rückwärts zu gehen:

%Vor%

Aber ich habe gemerkt, dass der zweite (method2) langsamer ist als der erste (method1)! Ich habe den Unterschied bemerkt, weil ich die Methode tausende Male anrufe. Also habe ich einen Test gemacht, um sicherzugehen, und hier ist das durchschnittliche Ergebnis von 20 Tests, die jede Methode 3000 mal aufrufen (und die Anzahl der Bytes ist 1 Million):

%Vor%

Meine Frage ist also: Warum ist der erste schneller als der zweite?

Hier ist der Testcode, um sicherzustellen, dass ich mit meinen Tests nichts falsch mache:

%Vor%

Aktualisierung:

Sieht so aus, als ob ich in der zweiten Methode auf zwei verschiedene Indizes in jeder Schleife zugreife, während ich in der ersten Methode nur auf einen Index zugreife. Es hat also nichts damit zu tun, die Schleife umzukehren.

Danke @ rm5248 und @Ben, ich würde beide Antworten wählen, wenn ich könnte, aber ich habe den früheren gewählt.

    
Motasim 09.03.2012, 20:09
quelle

2 Antworten

7

Ich habe einen schnellen Test gemacht, und es scheint, als ob der Grund dafür, dass die zweite Methode langsamer läuft, der etwas veränderte Algorithmus ist. Im ersten Fall behalten Sie einen Wert in einer lokalen Variablen, während Sie nicht in der zweiten Variablen sind. Aus diesem Grund muss Java zweimal zum Array gehen, um die Variable zu entfernen. Theoretisch sollte das nicht anders sein, aber ich denke, das hat damit zu tun, wie Arrays in Java implementiert sind (ich vermute, dass wenn du es in C probiert hast, die Zeiten viel näher liegen würden).

Als Referenz, hier ist meine Implementierung (ich denke, dass es dasselbe tut, aber vielleicht nicht):

%Vor%

Hier waren die durchschnittlichen Zeiten, die ich bekam:

%Vor%     
rm5248 09.03.2012, 21:15
quelle
3

Es könnte Cache-Verhalten sein, aber die wahrscheinlichere Erklärung ist, was Peter in seinen Kommentaren gesagt hat - der JIT ist besser für den ersten Code optimiert.

Insbesondere ist es wahrscheinlich, dass das JIT erkennt, dass die erste Schleife niemals über die Grenzen des Arrays hinaus indexiert, und vermeidet somit eine gebundene Überprüfung. Die zweite Schleife ist komplizierter und enthält wahrscheinlich Begrenzungen für jeden Zugriff.

Außerdem liest Ihre erste Schleife nur einen Wert aus dem Array und den anderen aus einer temporären lokalen Variablen, die registriert wird. Die zweite Version liest zwei verschiedene Elemente aus dem Array.

Um das herauszufinden, sollten Sie sich die Demontage des vom JIT erzeugten Maschinencodes für beide Fälle ansehen.

    
Ben Voigt 09.03.2012 20:51
quelle

Tags und Links