Stapelzuweisungsfunktion (Leistung)

8

Während meiner kleinen Untersuchung zu Leistungsproblemen bemerkte ich eine interessante Stapelzuweisungsfunktion, hier ist es eine Vorlage für die Zeitmessung:

%Vor%

Jetzt geht es nur noch um foo() Implementierung, in jeder Implementierung wird insgesamt 500000 ints zugewiesen:

  1. Wird in one Chunk zugewiesen:

    %Vor%

    Ergebnis: 7,3 Sekunden ;

  2. Wird in zwei Chunks zugewiesen:

    %Vor%

    Ergebnis: 3,5 Sekunden ;

  3. Wird in vier Chunks zugewiesen:

    %Vor%

    Ergebnis: 1,8 Sekunden .

und etc ... Ich teile es in 16 Brocken und erhalte die Ergebniszeit 0,38 Sekunden .

Erklären Sie es mir bitte, warum und wie das passiert?
Ich habe MSVC 2013 (v120), Release Build verwendet.

UPD:
Meine Maschine ist x64-Plattform. Und ich kompilierte es mit Win32-Plattform.
Wenn ich es mit x64-Plattform kompiliere, dann ergibt es in allen Fällen ungefähr 40ms.
Warum Plattformwahl so sehr beeinflussen?

    
MrPisarik 09.08.2016, 00:47
quelle

2 Antworten

8

Bei der Disassemblierung von VS2015 Update 3, in der 2 und 4 Array-Versionen von foo , optimiert der Compiler die nicht verwendeten Arrays, so dass er nur Stack-Platz für 1 Array in jeder Funktion reserviert. Da die späteren Funktionen kleinere Arrays haben, dauert dies weniger Zeit. Die Zuweisung zu x liest den gleichen Speicherort für beide / alle 4 Arrays. (Da die Arrays nicht initialisiert sind, ist das Lesen von ihnen ein nicht definiertes Verhalten.) Ohne den Code zu optimieren, gibt es 2 oder 4 verschiedene Arrays, aus denen gelesen wird.

Die lange Zeit, die für diese Funktionen benötigt wird, ist auf Stack-Tests zurückzuführen, die von __ chkstk als Teil der Stapelüberlauferkennung (erforderlich, wenn der Compiler mehr als eine Seite Speicherplatz für alle lokalen Variablen benötigt).

    
1201ProgramAlarm 09.08.2016 04:03
quelle
1

Sie sollten sich den resultierenden Assembler-Code ansehen, um zu sehen, was Ihr Compiler wirklich mit dem Code macht. Für gcc / clang / icc können Sie Matt Godbolts Compiler Explorer verwenden.

kling optimiert alles wegen UB und das Ergebnis ist ( foo - erste Version, foo2 - zweite Version:

%Vor%

icc behandelt beide Versionen sehr ähnlich:

%Vor%

und gcc erstellt verschiedene Assembler-Codes für verschiedene Versionen. Version 6.1 erzeugt Code, der ein ähnliches Verhalten wie Ihre Experimente zeigt:

%Vor%

Der einzige Weg, den Unterschied zu verstehen, besteht darin, sich den Assembler-Code anzusehen, der von Ihrem Compiler erstellt wurde, alles andere ist nur raten.

    
ead 09.08.2016 13:29
quelle

Tags und Links