Ho provato a pulire la pagina man di GCC per questo, ma ancora non l'ho capito, davvero.
Qual è la differenza tra -march
e -mtune
?
Quando si usa solo -march
, contro entrambi? È mai possibile solo -mtune
?
Risposte:
Se si utilizza, -march
GCC sarà libero di generare istruzioni che funzionano sulla CPU specificata, ma (in genere) non sulle CPU precedenti nella famiglia di architetture.
Se usi solo -mtune
, il compilatore genererà codice che funziona su uno qualsiasi di essi, ma favorirà le sequenze di istruzioni che vengono eseguite più velocemente sulla CPU specifica che hai indicato. es. impostare l'euristica di srotolamento del ciclo in modo appropriato per quella CPU.
-march=foo
implica a -mtune=foo
meno che non specifichi anche un diverso -mtune
. Questo è uno dei motivi per cui usare -march
è meglio che abilitare semplicemente opzioni come -mavx
senza fare nulla per l'ottimizzazione.
Avvertenza: -march=native
su una CPU che GCC non riconosce in modo specifico, abiliterà comunque nuovi set di istruzioni che GCC può rilevare, ma lascerà -mtune=generic
. Usa un GCC abbastanza nuovo che conosca la tua CPU se vuoi che faccia un buon codice.
march
implica mtune
. Quindi, le risposte alle tue obiezioni sono rispettivamente no e sì.
mtune
e diversa march
. Questo post del blog illumina questo punto con gli altri: lemire.me/blog/2018/07/25/…
Questo è quello che ho cercato su Google:
L' -march=X
opzione prende un nome di CPU X
e consente a GCC di generare codice che utilizza tutte le funzionalità di X
. Il manuale di GCC spiega esattamente quali nomi di CPU significano quali famiglie e caratteristiche di CPU.
Poiché le funzionalità vengono solitamente aggiunte, ma non rimosse, un binario compilato con -march=X
verrà eseguito su CPU X
, ha buone possibilità di funzionare su CPU più recenti di X
, ma quasi sicuramente non verrà eseguito su qualcosa di più vecchio di X
. Alcuni set di istruzioni (3DNow !, immagino?) Potrebbero essere specifici per un particolare fornitore di CPU, utilizzarli probabilmente ti consentirà di ottenere binari che non funzionano su CPU concorrenti, più recenti o meno.
L' -mtune=Y
opzione ottimizza il codice generato per essere eseguito più velocemente Y
rispetto ad altre CPU su cui potrebbe essere eseguito. -march=X
implica -mtune=X
. -mtune=Y
non sovrascriverà -march=X
, quindi, ad esempio, probabilmente non ha senso -march=core2
e -mtune=i686
- il tuo codice non verrà eseguito su qualcosa di più vecchio di core2
comunque, a causa di -march=core2
, quindi perché sulla Terra vorresti ottimizzare per qualcosa di più vecchio (meno ricco di funzionalità) di core2? -march=core2 -mtune=haswell
ha più senso: non utilizzare alcuna funzionalità oltre a ciò che core2
fornisce (che è ancora molto di più di ciò che -march=i686
ti dà!), ma ottimizza il codice per haswell
CPU molto più recenti , non per core2
.
C'è anche -mtune=generic
. generic
fa in modo che GCC produca il codice che funziona meglio sulle attuali CPU (significato delle generic
modifiche da una versione di GCC a un'altra). Ci sono voci sui forum Gentoo che -march=X -mtune=generic
producono codice che gira più velocemente X
del codice prodotto da -march=X -mtune=X
(o semplicemente -march=X
, come -mtune=X
è implicito). Non ho idea se questo sia vero o no.
Generalmente, a meno che tu non sappia esattamente di cosa hai bisogno, sembra che la soluzione migliore sia specificare -march=<oldest CPU you want to run on>
e -mtune=generic
( -mtune=generic
è qui per contrastare l'implicito -mtune=<oldest CPU you want to run on>
, perché probabilmente non vuoi ottimizzare per la CPU più vecchia). O semplicemente -march=native
, se mai funzionerai solo sulla stessa macchina su cui costruisci.
-march=native
, potresti volerlo specificare -mtune=X
, perché l'impostazione predefinita è ancora -mtune=generic
, come discusso qui: lemire.me/blog/2018/07/25/…
-march=native
implica tune=native
che va bene se usi un GCC che conosce la tua CPU. Quell'articolo presenta solo il caso negativo. Le versioni più recenti di GCC migliorano il codice in generale, specialmente quando si usano nuove istruzioni come AVX2 e AVX-512. E avere impostazioni di ottimizzazione (come l'euristica di srotolamento del ciclo) progettate per la tua CPU è un vantaggio decisivo. Quindi, se ti interessano abbastanza le prestazioni da utilizzare queste opzioni, usa un nuovo GCC, almeno uno che conosca la tua CPU, preferibilmente l'attuale versione stabile.
tune=generic
per un nuovo membro della stessa famiglia di microarchitettura, specialmente qualcosa come Kaby Lake che è letteralmente identico alla microarchitettura Skylake. Ma penso che abbia ancora una famiglia / un passo diverso, quindi un GCC che conosceva solo Skylake e anziani potrebbe non riconoscerlo per la messa a punto.