Je ne suis pas un expert de montage mais j'ai réussi suivante. J'aurais des commentaires, mais il est trop grand:
cat test.s
.file "test.c"
.text
.p2align 4,,15
.globl f
.type f, @function
f:
.LFB0:
.cfi_startproc
testl %esi, %esi
jle .L4
leal -1(%rsi), %eax
pxor %xmm0, %xmm0
movss .LC1(%rip), %xmm1
leaq 8(%rdi,%rax,8), %rax
.p2align 4,,10
.p2align 3
.L3:
movaps %xmm1, %xmm4
movss (%rdi), %xmm3
movss 4(%rdi), %xmm2
mulss %xmm3, %xmm1
mulss %xmm2, %xmm4
addq $8, %rdi
mulss %xmm0, %xmm2
cmpq %rdi, %rax
mulss %xmm3, %xmm0
subss %xmm2, %xmm1
addss %xmm4, %xmm0
jne .L3
.L1:
movss %xmm1, -8(%rsp)
movss %xmm0, -4(%rsp)
movq -8(%rsp), %xmm0
ret
.L4:
movss .LC1(%rip), %xmm1
pxor %xmm0, %xmm0
jmp .L1
.cfi_endproc
.LFE0:
.size f, .-f
.section .rodata.cst4,"aM",@progbits,4
.align 4
.LC1:
.long 1065353216
.ident "GCC: (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005"
.section .note.GNU-stack,"",@progbits
Ma commande de compilation était gcc -S -O3 -ffast-math -ftree-vectorizer-verbose=3 -ftree-slp-vectorize -ftree-vectorize -msse3 test.c
vous n'avez pas besoin tous aussi peu obtient permis à -O3. Référez-vous à https://gcc.gnu.org/projects/tree-ssa/vectorization.html
Bien que je n'ai pas de réponse, j'ai essayé d'aider. Quand je mon architecture précise cpu (build) et je me suivant:
.file "test.c"
.text
.p2align 4,,15
.globl f
.type f, @function
f:
.LFB0:
.cfi_startproc
testl %esi, %esi
jle .L4
vmovss .LC1(%rip), %xmm1
leal -1(%rsi), %eax
vxorps %xmm0, %xmm0, %xmm0
leaq 8(%rdi,%rax,8), %rax
.p2align 4,,10
.p2align 3
.L3:
vmovss (%rdi), %xmm2
vmovss 4(%rdi), %xmm3
addq $8, %rdi
vmulss %xmm3, %xmm0, %xmm4
vmulss %xmm2, %xmm0, %xmm0
vfmadd231ss %xmm3, %xmm1, %xmm0
vfmsub132ss %xmm2, %xmm4, %xmm1
cmpq %rdi, %rax
jne .L3
.L1:
vmovss %xmm1, -8(%rsp)
vmovss %xmm0, -4(%rsp)
vmovq -8(%rsp), %xmm0
ret
.L4:
vmovss .LC1(%rip), %xmm1
vxorps %xmm0, %xmm0, %xmm0
jmp .L1
.cfi_endproc
.LFE0:
.size f, .-f
.section .rodata.cst4,"aM",@progbits,4
.align 4
.LC1:
.long 1065353216
.ident "GCC: (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005"
.section .note.GNU-stack,"",@progbits
La commande est maintenant gcc -S -O3 -ffast-math -msse4 -march=haswell test.c
où Haswell est mon cpu 4770HQ Core i7. Référez this pour votre cpu. Donc, comme vous voyez le jeu d'instructions AVX venir en image dans la deuxième version.
Un point de référence de l'échantillon de code ci-dessous:
$time ./a.out
0.000000
real 0m0.684s
user 0m0.620s
sys 0m0.060s
#include <stdio.h>
#include <complex.h>
complex float f(complex float x[], long n) {
complex float p = 1.0;
for (long i = 0; i < n; i++)
p *= x[i];
return p;
}
int main()
{
static complex float x[200000000] = {0.0, 1.0, 2.0, 4.0, 5.0, 6.0};
complex float p = f(x, 200000000);
printf("%f", creal(p));
return 0;
}
Le réseau est statique si la majeure partie est-à-dire sur le disque ssd disque dur. Vous pouvez l'allouer en mémoire pour un traitement encore plus rapide. C'est des boucles de 200M. Binaire est 1.5G donc la plupart du temps est IO. Le CPU l'éclaire même sans -msse3 et -march. Tout ce dont vous avez besoin est -fast-math. Cela provoque une grande différence.
J'ai changé le programme suivant:
#include <stdio.h>
#include <complex.h>
float f(float x[], long n) {
float p = 1.0;
for (long i = 0; i < 8; i++) {
p = p * x[i];
}
return p;
}
int main() {
float x[8] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
printf("%f\n", f(x, 8));
return 0;
}
et compilé avec gcc -S -O3 -ffast-math -msse3 -mfpmath=sse -mavx -march=haswell test.c
qui se traduit par:
f:
.LFB23:
.cfi_startproc
vmovups (%rdi), %ymm2
vxorps %xmm1, %xmm1, %xmm1
vperm2f128 $33, %ymm1, %ymm2, %ymm0
vmulps %ymm2, %ymm0, %ymm0
vperm2f128 $33, %ymm1, %ymm0, %ymm2
vshufps $78, %ymm2, %ymm0, %ymm2
vmulps %ymm2, %ymm0, %ymm0
vperm2f128 $33, %ymm1, %ymm0, %ymm1
vpalignr $4, %ymm0, %ymm1, %ymm1
vmulps %ymm1, %ymm0, %ymm0
vzeroupper
ret
.cfi_endproc
Alors ce qui semble me est que pour forcer gcc utiliser SSE3 vous noeud au code d'une certaine manière. http://sci.tuomastonteri.fi/programming/sse vous sera utile. Remarques finales: Si vous expérimentez avec différentes valeurs de limite supérieure pour i, vous verrez que différentes instructions sont produites. Je pense que la raison en est que gcc n'évalue pas les variables, donc vous pouvez utiliser des templates C++ capables de calculer le temps de compilation et de le faire.
Quelle est votre version de gcc? – user902384
@Bugbugbuggerbuggered J'utilise gcc 5.4.0 mais je peux mettre à niveau si nécessaire. (La version gcc est également au bas du code d'assemblage.) – eleanora
Il utilise l'instruction SSE comme évident de http://www.felixcloutier.com/x86/MULSS.html – user902384