warum ist std :: gleich viel langsamer als eine hand gerollte Schleife für zwei kleine std :: array?

8

Ich habe ein kleines Stück Code erstellt, das Teil einer größeren Simulation ist, und zu meiner Überraschung ist die STL-Funktion gleich (std :: equal) viel langsamer als eine einfache for-Schleife und vergleicht die beiden Arrays Element für Element. Ich habe einen kleinen Testfall geschrieben, von dem ich glaube, dass er ein fairer Vergleich zwischen beiden ist, und der Unterschied, g ++ 6.1.1 aus den Debian-Archiven zu verwenden, ist nicht unbedeutend. Ich vergleiche zwei Arrays mit vier Elementen mit Vorzeichen mit Vorzeichen. Ich testete std :: equal, operator == und eine kleine for-Schleife. Ich habe nicht std :: chrono für ein genaues Timing verwendet, aber der Unterschied kann explizit mit der Zeit gesehen werden ./a.out.

Meine Frage lautet, warum Operator == und die überladene Funktion std :: equal (die den Operator == Ich glaube) etwa 40 Sekunden braucht, um den Vorgang abzuschließen, und die handgeschriebene Schleife braucht nur 8 Sekunden. Ich benutze einen sehr aktuellen Intel basierten Laptop. Die For-Schleife ist auf allen Optimierungsebenen, -O1, -O2, -O3 und -Ofast schneller. Ich habe den Code mit zusammengestellt g++ -std=c++14 -Ofast -march=native -mtune=native

Führen Sie den Code aus

Die Schleife läuft sehr oft, nur um den Unterschied mit bloßem Auge zu verdeutlichen. Die Modulo-Operatoren stellen eine billige Operation auf einem der Array-Elemente dar und dienen dazu, den Compiler daran zu hindern, außerhalb der Schleife zu optimieren.

%Vor%     
KBentley57 01.09.2016, 03:59
quelle

1 Antwort

1

Hier ist die generierte Assembly der for -Schleife in main() , wenn die Funktion are_equal_manual(left,right) verwendet wird:

%Vor%

Und hier ist was generiert wird, wenn die Funktion are_equal_alg(left,right) verwendet wird:

%Vor%

Ich bin mir nicht ganz sicher, was im generierten Code für den ersten Fall passiert, aber es ruft eindeutig nicht memcmp() auf. Es scheint nicht zu sein, den Inhalt der Arrays überhaupt zu vergleichen. Während die Schleife immer noch 5000000000 Mal wiederholt wird, ist sie darauf optimiert, nicht viel zu tun. Die Schleife, die are_equal_alg(left,right) verwendet, führt jedoch weiterhin den Vergleich durch. Grundsätzlich ist der Compiler immer noch in der Lage, den manuellen Vergleich viel besser zu optimieren als die Vorlage std::equal .

    
Michael Burr 01.09.2016 04:42
quelle

Tags und Links