GCC -march e -mtune
As duas opções servem para otimizar a geração de código de máquina para determinada família de processadores.
O mínimo
Existe um
Cuidado com
Esta é a diferença de um mesmo código compilado em 64-bit com
Instruções SSE foram substituídas por equivalentes AVX. Ao rodar o binário num processador sem AVX:
-march
diz ao compilador qual conjunto de instruções será usado. -mtune
mexe na forma como o código será organizado para tentar manter o processador o mais ocupado possível, escolhe instruções mais adequadas àquela família e aplica outras técnicas similares, porém sem modificar o conjunto base de instruções definido em -march
.O mínimo
-march
em 64-bit é x86-64
, que é uma mescla de nocona
(Pentium 4 e Xeon derivados) e k8
(AMD Athlon 64 e Opteron). Comparado com o mínimo i386
de 32-bit, é um ponto de corte bem mais alto, que oferece ao compilador mais instruções. Hoje em dia as distribuições configuram seus toolchains para usarem por padrão i686
(Pentium Pro para cima) em 32-bit e x86-64
em 64-bit. Escolhas de certa forma conservadoras, mas necessárias, pois estamos falando do conjunto de instruções.Existe um
-march
especial: native
. -march=native
escolhe pelo CPU ID a família exata do processador em uso na máquina onde o GCC estiver rodando. Veja aí o que seria configurado com:$ gcc -march=native -E -v - </dev/null 2>&1 | sed -n 's/.* -v - //p'
-mtune
suporta as mesmas opções de -march
, com a adição de duas especiais: generic
e intel
. São diferentes pois variam com o tempo a cada nova versão do compilador. O GCC promete com -mtune=generic
otimizar para famílias de processadores atuais. No GCC 4.9, seus desenvolvedores consideram tais famílias as microarquiteturas Nehalem (Intel) e Bobcat (AMD). É o -mtune
padrão das distribuições. -mtune=intel
leva em conta apenas processadores da marca (Haswell e Silvermont no momento).Cuidado com
-march
. Quando o processador não suportar alguma instrução, o programa será terminado com erro "instrução ilegal". O mesmo não acontece com -mtune
porque não afeta o conjunto de instruções.Esta é a diferença de um mesmo código compilado em 64-bit com
-march=x86-64
e -march=sandybridge
:--- x86-64.s 2015-02-27 08:09:00.120616635 -0300 +++ sandybridge.s 2015-02-27 08:09:12.685131480 -0300 @@ -34,7 +34,7 @@ call clock_gettime imul rcx, QWORD PTR [rsp+32], 1000000000 imul rdx, QWORD PTR [rsp+16], 1000000000 - pxor xmm0, xmm0 + vxorpd xmm0, xmm0, xmm0 mov esi, ebx mov edi, OFFSET FLAT:.LC1 add ebx, 1 @@ -42,9 +42,9 @@ add rdx, QWORD PTR [rsp+24] mov rax, rcx sub rax, rdx - cvtsi2sdq xmm0, rax + vcvtsi2sdq xmm0, xmm0, rax + vdivsd xmm0, xmm0, QWORD PTR .LC0[rip] mov eax, 1 - divsd xmm0, QWORD PTR .LC0[rip] call printf cmp ebx, 6 jne .L2
Instruções SSE foram substituídas por equivalentes AVX. Ao rodar o binário num processador sem AVX:
$ ./sandybridge Instrução ilegal (imagem do núcleo gravada) $ journalctl -n2 -o cat traps: sandybridge[11853] trap invalid opcode ip:400555 sp:7fff552ac870 error:0 in sandybridge[400000+1000] Process 11853 (sandybridge) of user 1000 dumped core. Stack trace of thread 11853: #0 0x0000000000400555 main (sandybridge) #1 0x00007fae5550cfe0 __libc_start_main (libc.so.6) #2 0x00000000004005c0 _start (sandybridge)
Comentários
Postar um comentário