Wie funktioniert mtune eigentlich?

8

Es gibt diese verwandte Frage: GCC: Wie unterscheidet sich march von mtune?

Die vorhandenen Antworten gehen jedoch nicht viel weiter als das GCC-Handbuch selbst. Höchstens erhalten wir:

  

Wenn Sie -mtune verwenden, generiert der Compiler Code, der funktioniert   jeder von ihnen, aber wird Befehlssequenzen bevorzugen, die am schnellsten laufen   die spezifische CPU, die Sie angegeben haben.

und

  

Die Option -mtune=Y stimmt den generierten Code so ab, dass er schneller auf Y ausgeführt wird   auf anderen CPUs könnte es laufen.

Aber genau wie favorisiert der GCC eine bestimmte Architektur, wenn er building ist, während er trotzdem in der Lage ist, den Build auf anderen (normalerweise älteren) Architekturen auszuführen, wenn auch langsamer?

Ich kenne nur eine Sache (aber ich bin keine Informatikerin), die das könnte, und das ist ein CPU-Dispatcher. Es scheint jedoch nicht (für mich), dass mtune hinter den Kulissen einen Dispatcher generiert und stattdessen ein anderer Mechanismus wahrscheinlich ist.

Ich fühle mich aus zwei Gründen so:

  1. Die Suche nach "gcc mtune cpu dispatcher" findet nichts Relevantes; und
  2. Wenn es auf Dispatcher basiert, könnte es intelligenter sein (selbst wenn es eine andere Option als mtune ist) und für cpuid testen, um unterstützte Anweisungen zur Laufzeit zu erkennen, anstatt sich auf eine benannte Architektur zu verlassen zur Erstellungszeit bereitgestellt.

Wie funktioniert es wirklich?

    
Marc.2377 12.06.2017, 01:42
quelle

1 Antwort

11

-mtune erstellt keinen Dispatcher, er benötigt keinen. Wir teilen dem Compiler bereits mit, auf welche Architektur wir abzielen.

Aus den GCC-Dokumenten :

  

-mtune = CPU-Typ

     

Tune to cpu-type alles, was für den generierten Code gilt, außer ABI und dem
  Satz von verfügbaren Anweisungen.

Dies bedeutet, dass GCC keine Anweisungen verwendet, die nur auf CPU-Typ 1 verfügbar sind, aber es wird Code generieren, der optimal auf CPU-Typ .

Um diese letzte Aussage zu verstehen, ist es notwendig, den Unterschied zwischen Architektur und Mikroarchitektur zu verstehen Die Architektur beinhaltet eine ISA (Instruction Set Architecture), die nicht von -mtune beeinflusst wird.
Die Mikroarchitektur ist, wie die Architektur in Hardware implementiert wird. Für einen gleichen Befehlssatz (gelesen: Architektur) kann eine Codefolge aufgrund der internen Details der Implementierung optimal auf einer CPU (Lese-Mikroarchitektur), aber nicht auf einer anderen laufen. Dies kann so weit gehen, dass eine Codesequenz nur auf einer Mikroarchitektur optimal ist.

Beim Generieren des Maschinencodes hat GCC oft einen Freiheitsgrad bei der Auswahl der Anweisungen und der zu verwendenden Variante.
Es wird eine Heuristik verwenden, um eine Folge von Anweisungen zu generieren, die schnell auf den gebräuchlichsten CPUs laufen, manchmal wird es eine 100% optimale Lösung für CPU x opfern, wenn das CPUs bestraft y , z und w .

Wenn wir -mtune=x verwenden, optimieren wir die Ausgabe von GCC für CPU x und erzeugen damit einen Code, der auf der CPU 100% optimal ist (aus der GCC-Perspektive).

Betrachten Sie als konkretes Beispiel , wie dieser Code zusammengestellt wird :

%Vor%

% ce_de% wird beim Targeting einer Skylake oder eines Core2 vektorisiert (wenn sich die Vektoren nicht überschneiden):

Himmelslake

%Vor%

Core2

%Vor%

Der Hauptunterschied besteht darin, wie ein a[i] += b[i]; -Register geladen wird, auf einem Core2 wird es mit zwei Ladevorgängen geladen, die xmm und movlps verwenden, anstatt einen einzelnen movhps zu verwenden.
Der Ansatz mit zwei Lasten ist bei einer Core2-Mikroarchitektur besser. Wenn Sie sich die Agnator Fog-Befehlstabellen ansehen, sehen Sie, dass movups in 4 Ups dekodiert wird und eine Latenz von 2 Zyklen hat, während jeder movups ist 1 Uop und 1 Latenzzyklus.
Dies ist wahrscheinlich darauf zurückzuführen, dass 128-Bit-Zugriffe zu diesem Zeitpunkt in zwei 64-Bit-Zugriffe aufgeteilt wurden.
Auf Skylake ist das Gegenteil der Fall: movXps ist besser als 2 movups .

Also müssen wir eins holen.
Im Allgemeinen greift GCC auf die erste Variante zurück, weil Core2 eine alte Mikroarchitektur ist, aber wir können dies mit movXps überschreiben.

1 Befehlssatz wird mit anderen Schaltern ausgewählt.

    
Margaret Bloom 12.06.2017, 13:49
quelle