# [Risolto] march, mtune e CPU variabile (!!!)

## hujuice

Salve a tutti,

torno - temo per l'ennesima volta - su un argomento trito e ritrito, che però non ho mai mandato giù fino in fondo, in quanto "analfabeta"   :Crying or Very sad:   in gcc.

So che il mondo è pieno di ragionamenti sull'argomento, ma probabilmente soffro di sovraccarico di informazioni.

Dunque faccio il dummy   :Embarassed:   e ci torno su, in italiano, chiedendo a tutti voi.

Ho un caso in cui il mio sistema potrebbe cambiare CPU inaspettatamente (è un contesto di virtualizzazione).

Parto dal manuale gcc e mi sembra di capire che in caso del genere posso impostare le mie CFLAGS come segue:

```
CFLAGS="-march=generic -mtune=native altro-che-ora-non-importa"
```

Quello che spero di ottenere è che il processo di compilazione sia gestito al meglio, ma il set di istruzioni della CPU utilizzato dai binari risultanti non sia specifico.

Ho capito bene?

Non ho capito nulla?   :Confused: 

Grazie a tutti,

HUjuice

----------

## xdarma

 *hujuice wrote:*   

> 
> 
> ```
> CFLAGS="-march=generic -mtune=native altro-che-ora-non-importa"
> ```
> ...

 

 *Quote:*   

> There is no -march=generic option because -march indicates the instruction set the compiler can use, and there is no generic instruction set applicable to all processors. In contrast, -mtune indicates the processor (or, in this case, collection of processors) for which the code is optimized.

 

Sembra che non sia corretto -march=generic.

Se posso darti un consiglio (magari sbagliato ;-): visto che difficilmente userai archittetture obsolete potresti impostare -march con il "minimo comun installabile" nel senso che potresti usare -march=i686 per i 32bit e -march=k8 per i 64bit. O qualcosa del genere in base all'architettura che hai in mente di usare.

Curiosità: stai virtualizzando con Virtualbox o usi qualcosaltro?

----------

## hujuice

 *xdarma wrote:*   

>  *Quote:*   There is no -march=generic option because -march indicates the instruction set the compiler can use, and there is no generic instruction set applicable to all processors. In contrast, -mtune indicates the processor (or, in this case, collection of processors) for which the code is optimized. 
> 
> Sembra che non sia corretto -march=generic.

 

La pratica spesso è più facile della teoria...

Perciò partiamo dalla teoria  :Smile: 

Caro xdarma, dove hai letto quella frase?

Io sono attaccato con i denti alla già citata fonte di casa GCC, che non è molto generosa in materia di march:

 *Intel 386 and AMD x86-64 Options wrote:*   

> -march=cpu-type
> 
> Generate instructions for the machine type cpu-type. The choices for cpu-type are the same as for -mtune. Moreover, specifying -march=cpu-type implies -mtune=cpu-type. 

 

Alla lettera, posso usare generic anche per march.

La mia perplessità, semmai, riguarda il fatto che se prendo alla lettera quella affermazione il tuning con mtune potrebbe essere vano. Boh   :Embarassed:   fa parte dei miei dubbi.

Nella pratica, sto utilizzando un servizio commerciale di VPS OpenVZ. So che le CPU con cui a che fare sono tutte Xeon e il supporto mi ha assicurato che non cambieranno marchio a breve termine, quello che cambia è la generazione.

Il pasticcio mi si è prodotto quando ho cercato di produrre binari (quickpkg) su una macchina più potente a beneficio di un'altra davvero "mini". Il tutto dopo aver utilizzato march=native.

Ho preparato proprio gcc e ora la "mini" fallisce alcune compilazioni.

Secondo il supporto, dovrei cavarmela con:

```
-march=core2
```

E questo mi lascia di nuovo perplesso: core2 è il tipo più potente tra quelli elencati. Ma allora il tipo native è ancora più raffinato? Di nuovo "boh"   :Embarassed: 

Per chiudere, trovo molto interessanti queste forniture, che per pochi dollari al mese ti danno "piccole" macchine dalle prestazioni a volte eccellenti. Le consiglio a tutti quelli che hanno bisogno di una presenza in rete di piccolo taglio (e anche non troppo piccolo).

Saluti,

HUjuice

----------

## ciro64

Si; native è ancor più "raffinato" di core2.

native attiva la flags specifiche delle cpu in uso.

Con un Bulldozer attiverà le avx e quale altra diavoleria chissà (Slurp..... chissà come compilerà un mostro del genere  :Mr. Green:  )

Con core2 arriverà ad usare le SIMD fino ad ssse3 (supplementary streaming SIMD extensions 3).

Col native se hai un "Penryn" o successivi "attiverà" anche sse4.1 nel I caso, sse4.2 nel 2° e coi futuri (anzi 1°Q 2011 usciranno i "Sandy Bridge") le avx ecc ecc.

Se in un terminale dai

```

echo 'int main(){return 0;}' > test.c && gcc -v -Q -march=native -O2 test.c -o test && rm test.c test

```

Potrai leggerti il "papiro" delle flags attivate con

```

CFLAGS="-march=native -O2"
```

prova a lanciare lo stesso mettendo al posto di "native" che so.... x86_64 , i686 (se usi 32) , core2 o altro e vedi le differenze.

----------

## xdarma

 *hujuice wrote:*   

> Caro xdarma, dove hai letto quella frase?

 

Proprio lì:

 *Quote:*   

> -mtune=cpu-type
> 
>     Tune to cpu-type everything applicable about the generated code, except for the ABI and the set of available instructions. The choices for cpu-type are:
> 
>     generic
> ...

 

 *hujuice wrote:*   

> Alla lettera, posso usare generic anche per march.

 

Per quello che ho capito io "generic" è usabile solo per -mtune

 *hujuice wrote:*   

> Il pasticcio mi si è prodotto quando ho cercato di produrre binari (quickpkg) su una macchina più potente a beneficio di un'altra davvero "mini".

 

Non ho capito: vuoi usare gli Xeon con OpenVZ (macchina virtuale a noleggio) per creare dei binari per il "mini" server di rete (macchina fisica in ufficio)?

Visto che i binari finiranno nella "mini" forse è il caso di sapere meglio cosa supporta il processore della "mini".

Se rimani in casa Intel, magari valuta una combinazione tipo "-march=core2 -mtune=generic".

Voci di corridoio dicono che anche se usi -march=k8 su Intel funziona lo stesso, ma non ci metto la mano sul fuoco  ;-)

Ciao

----------

## ago

 *ciro64 wrote:*   

> Col native se hai un "Penryn" o successivi "attiverà" anche sse4.1 nel I caso, sse4.2 nel 2° e coi futuri (anzi 1°Q 2011 usciranno i "Sandy Bridge") le avx ecc ecc.

 

Se non erro sse4 va specificato manualmente, e non viene attivato automaticamente da native.

Personalmente non ho mai trovato migliorie in native, anche perché abilita poco più di quando setti il -march esatto.

```
gcc -march=native -E -v - </dev/null 2>&1 | sed -n 's/.* -v - //p'
```

----------

## ciro64

@ Ago

con gcc 4.3.x effettivamente dovevo specificarlo.

Con il 4.4.x lo include.

Anche un mio amico che ha un "Clarkdale" gli rileva senza dover specificare altro anche le sse4.2 e le AESNI

----------

## hujuice

Ehm, bello, da dove comincio?   :Very Happy: 

Intanto... buongiorno a me!

Ero talmente intento, xdarma, a cercare significati reconditi in quella frase su march, che continuavo a leggere in fretta mtune.

E grazie a ciro64, quel -Q è illuminante ed effettivamente native ci mette molto di più.

```
$ echo 'int main(){return 0;}' > test.c && gcc -v -Q -march=native -O2 test.c -o test && rm -f test.c test

...

/usr/libexec/gcc/x86_64-pc-linux-gnu/4.4.4/cc1 -v test.c -D_FORTIFY_SOURCE=2 -march=core2 -mcx16 -msahf -mpopcnt -msse4.2 --param l1-cache-size=32 --param l1-cache-line-size=64 --param l2-cache-size=256 -mtune=core2 -dumpbase test.c -auxbase test -O2 -version -o /tmp/ccgIU7jV.s

...

$ echo 'int main(){return 0;}' > test.c && gcc -v -Q -march=core2 -O2 test.c -o test && rm -f test.c test

...

/usr/libexec/gcc/x86_64-pc-linux-gnu/4.4.4/cc1 -v test.c -D_FORTIFY_SOURCE=2 -dumpbase test.c -march=core2 -auxbase test -O2 -version -o /tmp/cc6xBO5w.s

...

```

@xdarma

Non sto compilando in VPS per una macchina fisica e locale... no...  :Smile: 

Ho tre VPS (di cui uno minuscolo, per i test) il problema è sorto tentando di compilare da uno all'altro.

Contattando il supporto, poi, mi hanno annunciato che gli upgrade di hardware non verranno annunciati, quindi il problema si è generalizzato.

Si fa un po' di luce, nelle mie tenebre, grazie a tutti  :Smile: 

Alla fine dei giochi, affidandomi a quanto affermato dal supporto (resteranno comunque core2) mi assesto su un normalissimo

```
-march=core2
```

rinunciando alle raffinatezze di native.

EDIT: no, l'idea qua sotto non va bene, vedi il post successivo

In alternativa, se ho capito bene, potrei pignoleggiare usando

```
-march=core2 -mtune=native
```

ottenendo un codice ottimizzato per la CPU che compila e che gira, però, anche sulle altre della famiglia core2.

Ciao,

HUjuice

PS: marco il titolo come [SOLVED], anche se la conversazione è aperta e interessante.

----------

## ago

 *hujuice wrote:*   

> In alternativa, se ho capito bene, potrei pignoleggiare usando
> 
> ```
> -march=core2 -mtune=native
> ```
> ...

 

no.

-march=foo include -mtune=foo

----------

## djinnZ

prima cosa mi ricordo che c'era un metodo alternativo al compilare un eseguibile per verificare cosa passava in realtà --march=native se qualcuno la ricorda...

Quanto alle ottimizzazioni puoi pensare di usare gcc -Q -march=... --help=[target,oprimization] per capirci qualcosina di più.

Sarebbe interessante sapere come capire direttamente se attivare o meno -msse e compagnia e senza estenuanti richerche o ricorso alla memoria ma tant'è.

----------

## hujuice

Grazie ago.

Era quello che temevo, interpretando alla lettera il manuale.

Però ho visto molta gente fare così, annegando nel mare delle innumerevoli discussioni in rete.

In effetti, i due comandi seguenti hanno output identici:

```
$ echo 'int main(){return 0;}' > test.c && gcc -v -Q -march=athlon64-sse3 -O2 test.c -o test > march_tune 2>&1 && rm -f test.c test

$ echo 'int main(){return 0;}' > test.c && gcc -v -Q -march=athlon64-sse3 -mtune=native -O2 test.c -o test > march_tune 2>&1 && rm -f test.c test
```

(sono nel mio desktop, ora).

Mentre questo ha qualcosa in più:

```
$ echo 'int main(){return 0;}' > test.c && gcc -v -Q -march=native -O2 test.c -o test > march_tune 2>&1 && rm -f test.c test
```

Grazie ancora,

HUjuice

----------

## ago

 *ciro64 wrote:*   

> @ Ago
> 
> con gcc 4.3.x effettivamente dovevo specificarlo.
> 
> Con il 4.4.x lo include.
> ...

 

Ho appena testato ed effettivamente hai ragione.

OT:

che istruzioni intendi per aesni?

----------

## hujuice

 *djinnZ wrote:*   

> Sarebbe interessante sapere come capire direttamente se attivare o meno -msse e compagnia e senza estenuanti richerche o ricorso alla memoria ma tant'è.

 

Credo che abbiano introdotto native proprio per questo. No?

HUjuice

----------

## ago

 *hujuice wrote:*   

>  *djinnZ wrote:*   Sarebbe interessante sapere come capire direttamente se attivare o meno -msse e compagnia e senza estenuanti richerche o ricorso alla memoria ma tant'è. 
> 
> Credo che abbiano introdotto native proprio per questo. No?
> 
> HUjuice

 

O metti native, o spulci in 

```
/proc/cpuinfo
```

 e ti regoli  :Wink: 

----------

## ciro64

@ Ago

AES-NI per la crittografia.

Qui qualche benchmark

Penso dabba vedersi nelle flags abilitate -maes (non ho personalmente una cpu che le supporti).

----------

## djinnZ

```
 /usr/libexec/gcc/x86_64-pc-linux-gnu/4.4.4/cc1 -v help-dummy -D_FORTIFY_SOURCE=2 -march=amdfam10 -mcx16 -msahf -mpopcnt --param l1-cache-size=64 --param l1-cache-line-size=64 --param l2-cache-size=512 -mtune=amdfam10 -fno-strict-overflow -dumpbase help-dummy -auxbase help-dummy -O2 -version -fhelp=target -fPIE -fstack-protector-all -o /tmp/.private/root/ccdwO5v2.s

The following options are target specific:

  -m128bit-long-double                  [disabled]

  -m32                                  [disabled]

  -m3dnow                               [disabled]

  -m3dnowa                              [disabled]

  -m64                                  [enabled]

  -m80387                               [enabled]

  -m96bit-long-double                   [enabled]

  -mabm                                 [disabled]

  -maccumulate-outgoing-args            [disabled]

  -maes                                 [disabled]

  -malign-double                        [disabled]

  -malign-functions=          

  -malign-jumps=              

  -malign-loops=              

  -malign-stringops                     [enabled]

  -march=                               amdfam10

  -masm=                      

  -mavx                                 [disabled]

  -mbranch-cost=              

  -mcld                                 [disabled]

  -mcmodel=                   

  -mcx16                                [enabled]

  -mfancy-math-387                      [enabled]

  -mfma                                 [disabled]

  -mforce-drap                          [disabled]

  -mfp-ret-in-387                       [enabled]

  -mfpmath=                   

  -mfused-madd                          [enabled]

  -mglibc                               [enabled]

  -mhard-float                          [enabled]

  -mieee-fp                             [enabled]

  -mincoming-stack-boundary=  

  -minline-all-stringops                [disabled]

  -minline-stringops-dynamically        [disabled]

  -mintel-syntax                        [disabled]

  -mlarge-data-threshold=     

  -mmmx                                 [disabled]

  -mms-bitfields                        [disabled]

  -mno-align-stringops                  [disabled]

  -mno-fancy-math-387                   [disabled]

  -mno-fused-madd                       [disabled]

  -mno-push-args                        [disabled]

  -mno-red-zone                         [disabled]

  -mno-sse4                             [enabled]

  -momit-leaf-frame-pointer             [disabled]

  -mpc                        

  -mpclmul                              [disabled]

  -mpopcnt                              [enabled]

  -mpreferred-stack-boundary= 

  -mpush-args                           [enabled]

  -mrecip                               [disabled]

  -mred-zone                            [enabled]

  -mregparm=                  

  -mrtd                                 [disabled]

  -msahf                                [enabled]

  -msoft-float                          [disabled]

  -msse                                 [disabled]

  -msse2                                [disabled]

  -msse2avx                             [disabled]

  -msse3                                [disabled]

  -msse4                                [disabled]

  -msse4.1                              [disabled]

  -msse4.2                              [disabled]

  -msse4a                               [disabled]

  -msse5                                [disabled]

  -msseregparm                          [disabled]

  -mssse3                               [disabled]

  -mstack-arg-probe                     [disabled]

  -mstackrealign                        [enabled]

  -mstringop-strategy=        

  -mtls-dialect=              

  -mtls-direct-seg-refs                 [enabled]

  -mtune=                               amdfam10

  -muclibc                              [disabled]

  -mveclibabi=                

COLLECT_GCC_OPTIONS='-v' '-Q'  '-O2' '-fhelp=target' '-fPIE' '-pie'

 /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/../../../../x86_64-pc-linux-gnu/bin/as -V -Qy -o /tmp/.private/root/ccoDVt8w.o /tmp/.private/root/ccdwO5v2.s

GNU assembler version 2.20.1 (x86_64-pc-linux-gnu) using BFD version (GNU Binutils) 2.20.1.20100303
```

mi puzza un tantino di bug di gcc in effetti

```
flags           : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm 3dnowext 3dnow constant_tsc rep_good nonstop_tsc extd_apicid pni monitor cx16 popcnt lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs skinit wdt npt lbrv svm_lock nrip_save
```

come vedi non è così semplice (e meno male che ago te lo aveva indicato) e non è che uno può sempre andarsi a ricordare che pni corrisponde all'attivazione di -msse3 etc. o andarsi ogni volta a spulciare /usr/src/linux/arch/x86/include/asm/cpufeature.h per vedere le corrispondenze utili.

Per inciso, considerando il genere di cpu che potresti usare, un buon livello di ottimizzazione potrebbe essere -march=x86_64 -mtune=generic -mmmx -msse -msse3 -msse3

nulla di eccezionale ma dovrebbe andare su qualsiasi cpu sia intel che amd a 64 bit attualmente in commercio. potrest anche pensare di aggiungere un minimo comun denominatore tra le varie possibili e spingerti più avanti impostando i valori di cache opportuni etc.

Quanto al native, soprattutto se inizi a parlare di avere gentoo su macchine differenti o di ricompilare per una nuova cpu serve solo a creare casini, IMHO.

Quello che mi chiedevo è se c'era un metodo rapido come questo, non trovo molto utile sbattere la testa a fare confronti e non mi tengo a mente certe informazioni, sarà pure divertente la prima volta ma dopo diventa solo una seccatura.

Il perchè sse4 e compagnia non sono abilitate di default e vanno usate con cautela oltre ad essere filtrate da diversi ebuild te lo lascio indovinare.

per inciso il comando per capire cosa combina è 

```
echo "int main() { return 0; }" | gcc -march=native -v -[E|x|Q|Q --help=[target,optimizers]] -
```

----------

