Originariamente inviato da /dev/null
Il compilatore GCC (ma forse anche altri) permette, pasandogli determinate opzioni, di scegliere per quale architettura compilare il programma in modo da sfruttare a pieno le sue potenzialita'...
Non penso comunque che sia possibile sfruttare funzioni avanzate di alcuni processori direttamente in C, per fare questo serve l'assembler...
Ehm, GCC consente tramite delle direttive di abilitare il supporto a funzioni che sfruttano le funzionalità avanzate delle CPU moderne, questo non significa che l'ottimizzazione è automatica (tranne nel caso della ver. x86_64 che utilizza per le operazioni floating point i registri SSE al posto della FPU classica degli x86, questo perchè è stato standardizzato nell'ABI).
Per esempio se compili con -msse abiliti solo all'uso delle funzioni definite nell'header xmmintrin.h
These switches enable or disable the use of built-in functions that allow direct
access to the MMX, SSE and 3Dnow extensions of the instruction set.
e in questo caso puoi scrivere cose tipo
codice:
void sum4_sse(__m128* a, __m128* b)
{
*a = _mm_add_ps(*a, *b);
}
In questo modo hai il diretto controllo delle funzioni che vuoi utilizzare.
To have SSE/SSE2 instructions generated automatically from floating-point
code, see ‘-mfpmath=sse’.
quindi usando -mfpmath=sse -msse sarà il compilatore a generare "automaticamente", esempio:
codice:
float dot4(float a[4], float b[4])
{
return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3];
}
gcc -S dot4.c -mfpmath=sse -msse -O2
codice:
.file "dot4.c"
.section .text
.p2align 4,,15
.globl _dot4
_dot4:
pushl %ebp
movl %esp, %ebp
pushl %eax
movl 12(%ebp), %eax
movl 8(%ebp), %edx
movss (%eax), %xmm1
movss 4(%eax), %xmm0
mulss (%edx), %xmm1
mulss 4(%edx), %xmm0
addss %xmm0, %xmm1
movss 8(%eax), %xmm0
mulss 8(%edx), %xmm0
addss %xmm0, %xmm1
movss 12(%eax), %xmm0
mulss 12(%edx), %xmm0
addss %xmm0, %xmm1
movss %xmm1, -4(%ebp)
flds -4(%ebp)
movl %ebp, %esp
popl %ebp
ret
.ident "GCC: (GNU) 3.3.2"
utilizza l'istruzione MOVSS, che è meno efficiente della MOVAPS, in quanto non ti obbliga ad allineare i dati alla linea dati della cache, invece la MOVAPS è più efficiente ma occorre dichiarare i dati in modo che siano allineati a 16 byte.
movss xmm, [mem|reg] = move (copy) a single 32-bit floating point
value to a single element of the xmm vector register
movaps xmm, [mem|reg] = copy a 4-element vector (of 32-bit floats, for
a total of 128 bits) from memory to an xmm vector register. the "a" in
movaps means that alignment (on a 128-bit boundary) is required, there's
also an unaligned load.
in asm x86 sarebbe così
codice:
float dot4_sse(float a[4], float b[4])
{
float r;
__asm
{
MOVAPS xmm0, [a]
MULPS xmm0, [b]
MOVAPS xmm0, xmm1, 0x78
ADDPS xmm0, xmm1
MOVAPS xmm1, xmm0 0xB1
ADDPS xmm0, xmm1
MOVSS [r], xmm0
}
return r;
}