GCC: Wie unterscheidet sich der Marsch von mtune?

87

Ich habe versucht, die GCC-Manpage dafür zu bereinigen, verstehe es aber immer noch nicht.

Was ist der Unterschied zwischen -marchund -mtune?

Wann verwendet man nur -marchgegen beide? Ist es jemals möglich, nur -mtune?

Jameson
quelle

Antworten:

97

Wenn Sie verwenden, kann -marchGCC Anweisungen generieren, die auf der angegebenen CPU funktionieren, jedoch (normalerweise) nicht auf früheren CPUs in der Architekturfamilie.

Wenn Sie nur verwenden -mtune, generiert der Compiler Code, der auf jedem von ihnen funktioniert, bevorzugt jedoch Befehlssequenzen, die auf der von Ihnen angegebenen CPU am schnellsten ausgeführt werden. zB Einstellen der für diese CPU geeigneten Heuristik zum Abrollen von Schleifen.


-march=fooimpliziert, es -mtune=foosei denn, Sie geben auch eine andere an -mtune. Dies ist ein Grund, warum die Verwendung -marchbesser ist, als nur Optionen zu aktivieren, -mavxohne etwas gegen die Optimierung zu tun.

Vorsichtsmaßnahme: -march=nativeAuf einer CPU, die GCC nicht speziell erkennt, werden weiterhin neue Befehlssätze aktiviert, die GCC erkennen kann, die jedoch verlassen werden -mtune=generic. Verwenden Sie ein ausreichend neues GCC, das sich mit Ihrer CPU auskennt, wenn Sie möchten, dass sie guten Code erstellt.

James Youngman
quelle
10
Antwortet nicht, ob es sinnvoll ist, beide zu verwenden, oder ob mtune redundant ist, wenn derselbe Wert festgelegt wird.
Pavel Šimerda
12
@ PavelŠimerda Intuitiv ist die Antwort in der Definition der beiden Merkmale enthalten. Außerdem heißt es in der Dokumentation ausdrücklich, dass dies marchimpliziert mtune. Die Antworten auf Ihre Einwände lauten also Nein bzw. Ja.
underscore_d
Danke, dass du das so elegant erklärt hast! Sie machen es leicht zu verstehen.
Rahim Khoja
5
Leute brauchen ein tl; dr: Verwenden Sie -march, wenn Sie es NUR auf Ihrem Prozessor ausführen, und verwenden Sie -mtune, wenn Sie möchten, dass es für andere Prozessoren sicher ist.
j riv
3
Benutzer müssen auch verstehen, dass ältere Compiler (die veröffentlicht wurden, bevor eine CPU nicht vorhanden war) zu unterschiedlichen Optimierungen mtuneund marchKombinationen führen können. Dieser Blog-Beitrag beleuchtet diesen Punkt mit den anderen: lemire.me/blog/2018/07/25/…
qneill
52

Das habe ich gegoogelt:

Die -march=XOption verwendet einen CPU-Namen Xund ermöglicht es GCC, Code zu generieren, der alle Funktionen von verwendet X. Das GCC-Handbuch erklärt genau, welche CPU-Namen welche CPU-Familien und -Funktionen bedeuten.

Da Funktionen normalerweise hinzugefügt, aber nicht entfernt werden, -march=Xläuft eine mit erstellte Binärdatei auf der CPU X, hat eine gute Chance, auf CPUs ausgeführt zu werden, die neuer als sind X, aber fast sicher nicht auf etwas älterem als X. Bestimmte Befehlssätze (3DNow!, Denke ich?) Sind möglicherweise spezifisch für einen bestimmten CPU-Hersteller. Wenn Sie diese verwenden, erhalten Sie wahrscheinlich Binärdateien, die nicht auf konkurrierenden CPUs, neueren oder anderen, ausgeführt werden.

Die -mtune=YOption optimiert den generierten Code so, dass er schneller ausgeführt wird Yals auf anderen CPUs, auf denen er möglicherweise ausgeführt wird. -march=Ximpliziert -mtune=X. -mtune=Ywird nicht überschrieben -march=X, so macht es zum Beispiel wahrscheinlich keinen Sinn -march=core2und -mtune=i686- Ihr Code wird auf nichts älter als core2sowieso ausgeführt, weil -march=core2warum sollten Sie also für etwas älteres (weniger funktionsfähiges) als core2 optimieren? -march=core2 -mtune=haswellSinnvoller: Verwenden Sie keine Funktionen, die über das hinausgehen core2(was immer noch viel mehr ist als das, -march=i686was Sie bieten!), sondern optimieren Sie den Code für viel neuere haswellCPUs, nicht für core2.

Es gibt auch -mtune=generic. genericLässt GCC Code produzieren, der auf aktuellen CPUs am besten läuft (dh genericÄnderungen von einer Version von GCC zu einer anderen). Es gibt Gerüchte in Gentoo-Foren, -march=X -mtune=genericdie Code produzieren, der schneller läuft Xals Code, der von do produziert wird -march=X -mtune=X(oder einfach -march=X, wie -mtune=Ximpliziert). Keine Ahnung, ob das stimmt oder nicht.

Wenn Sie nicht genau wissen, was Sie benötigen, scheint es im Allgemeinen am besten zu sein, -march=<oldest CPU you want to run on>und anzugeben -mtune=generic( -mtune=genericum dem Impliziten entgegenzuwirken -mtune=<oldest CPU you want to run on>, da Sie wahrscheinlich nicht für die älteste CPU optimieren möchten). Oder einfach -march=native, wenn Sie jemals nur auf demselben Computer ausgeführt werden, auf dem Sie aufbauen.

LRN
quelle
4
Aber wenn Sie verwenden -march=native, möchten Sie möglicherweise angeben -mtune=X, da der Standard immer noch ist -mtune=generic, wie hier beschrieben: lemire.me/blog/2018/07/25/…
Roland Weber
@ RolandWeber: Das passiert nur, wenn Sie einen GCC verwenden, der zu alt ist, um über Ihre CPU Bescheid zu wissen. -march=nativeDies ist in tune=nativeOrdnung, wenn Sie einen GCC verwenden, der sich mit Ihrer CPU auskennt. Dieser Artikel präsentiert nur den schlimmen Fall. Neuere GCC-Versionen bieten im Allgemeinen besseren Code, insbesondere wenn neue Anweisungen wie AVX2 und AVX-512 verwendet werden. Und Optimierungseinstellungen (wie z. B. Heuristiken zum Abwickeln von Schleifen) für Ihre CPU sind ein klares Plus. Wenn Sie sich also genug um die Leistung kümmern, um diese Optionen nutzen zu können, verwenden Sie einen neuen GCC, mindestens einen, der Ihre CPU kennt, vorzugsweise die aktuelle stabile Version.
Peter Cordes
Es ist schade, dass GCC nichts Besseres tun kann als tune=genericein neueres Mitglied derselben Mikroarchitekturfamilie, insbesondere etwas wie Kaby Lake, das buchstäblich mit der Mikroarchitektur von Skylake identisch ist. Aber ich denke, es hat immer noch eine andere Familie / Stufe, so dass ein GCC, der nur über Skylake und älter Bescheid wusste, es möglicherweise nicht für die Abstimmung erkennt.
Peter Cordes