CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

Optimisation : facteurs de temps

Fvirtman
Fvirtman
Niveau 10
13 janvier 2007 à 15:25:06

Salut !

Un petit topic pour se renseigner au sujet des optimisations :

le processeur calcule certaines opérations plus vite que d´autres.
Par exemple, la racine carré est un algo X fois plus lent qu´une simple multiplication.
Ma premiere question, que vaut X ?

Et plus généralement, une addition est elle plus rapide qu´une multiplication, qu´une division, quelle facteur de temps ?

Quelle facteur de temps entre les 2 syntaxes suivantes :

p = ma_struct->truc->bidule->chose->machin;

et

p2 = ma_struct->truc;
p3 = p2->bidule;
p4 = p3->chose;
p = p4->machin;

Bref, voici un topic pour parler d´optimisations processeur, et surtout de facteur de temps entre une opération et une autre...

deepblue
deepblue
Niveau 16
13 janvier 2007 à 16:16:42

En php, pour savoir quelle strcture de langage est plus rapide ou nom, on fait tout simplement des tests (1000, 10000) aevc le temps d´execution (microtime fin du script - microtime debut du script)

KouicKouic
KouicKouic
Niveau 6
13 janvier 2007 à 16:23:55

Bonjour,
J´avais effectué des recherches sur le sujet il y a quelques temps. Se que j´ai appris, pour faire simple, c´est que ta premiere question a autant de réponses que d´architecture de processeur. Ta seconde question a autant de réponse que de compilateur.

Pour parler d´optimisation processeur il faut spécifier la famille de processeur visée. Chaqu´une a ses jeux d´instruction permettant d´accélérer les calculs. MMX, 3DNOW, SS& et 2...
Ces nouvelle collection d´instruction oblige le developpeur a concevoir son code de facon a les utiliser le mieux possible. Pour avoir une vitesse d´execution maximum dans tout les cas il n´est commun de compiler le meme code autant de fois qu´il y a de famille de prosseur, le choix de l´implémentation étant faite par le programme en late-binding.

Fvirtman
Fvirtman
Niveau 10
13 janvier 2007 à 18:57:56

Je me suis fait un petit fichier de Bench qui illustre pas mal de choses.

http://rafb.net/p/u9ERMZ36.html

Mes résultats sont en dessous.
(CPU : Athlon T-bird, Visual C++ 6.0)

1) A ceux qui veulent essayer, avez vous globalement les memes resultats ? (ordre de facteur)
(essayez bien en release, et non en debug !! )

Mes remarques et questions :
pourquoi une telle différence quand je cast un int en (double), et en (double&). :question:

Les opérateurs trigo internes sont de vraies saletés...
La racine carrée est moins craignos que je le pensais, mais reste 6 fois plus lente que la multiplication...

godrik
godrik
Niveau 30
13 janvier 2007 à 19:58:36

"
Quelle facteur de temps entre les 2 syntaxes suivantes :

p = ma_struct->truc->bidule->chose->machin;

et

p2 = ma_struct->truc;
p3 = p2->bidule;
p4 = p3->chose;
p = p4->machin;
"
en principe c´est exactement pareil! Sauf si ton compilo est débile bien sur.

"le processeur calcule certaines opérations plus vite que d´autres.
Par exemple, la racine carré est un algo X fois plus lent qu´une simple multiplication.
Ma premiere question, que vaut X ?"
1/ Ca dépend complètement des processeurs et des algorithmes.
2/ ce n´est pas forcément linéaire. Parceque certaines fonctions sont calculées a partir de developpement limite. l´algorithme s´arrete quand l´erreur commise est inférieur au standard IEEE. et selon les algorithmes et les valeurs cela peut changer fortement

KouicKouic
KouicKouic
Niveau 6
13 janvier 2007 à 20:36:31

J´ai également fait tourner le test sur ma machine. C´est un Athlon 2000+. Rien de lourd (mis a par KDE) ne tournait sur ma machine lors du test. Les résultats sont a la fin des sources que j´ai modifiées pour fonctionner sous linux avec GCC 4.1.
http://rafb.net/p/XScgnj35.html

On ne peux pas dire que ce soit trés parlant comme résultats. Il serait interressant de comparer les instructions classiques et les vectioriels sur un meme processeur. La il y aurait des résultats plus interressant.

dnob700
dnob700
Niveau 10
14 janvier 2007 à 03:17:47

En optimisant violemment :
g++ essai.cpp -O3 -march=nocona -mfpmath=sse

je trouve 0 pour presque tout les tests sauf ceux qui suivent :

1M malloc(100), 1M free : 96 millisecondes
1M calloc(100,0), 1M free : 40 millisecondes
1M new char[100], 1M delete : 74 millisecondes
1M malloc(100), 1M free, 1M creation var interne : 64 millisecondes
100M += et 100M sqrt et 100M cast double: 2439 millisecondes

si ça ce trouve, il ne génère pas de code pour le reste car ça ne sers à rien. Mais je ne sais pas comment on regarde le code assembleur généré avec gcc donc je ne peut pas vérifier.

Il faut noter que les sin, cos, etc. sont des fonctions de lamachine (au moins pour le fpu x87) donc ne prennent à lalimite qu´une seule instruction, et il doit être facile au compilo de savoir qu´il faut les éliminer si on jette leur résultat. Pour la racine, je ne crois pas qu´il y ai d´instruction directement (je regarderais dans la doc intel).

J´ai testé aussi sur une grosse station de travail Sun, mais là, je trouve rigoureusement 0 milliseconde partout, même sans optimisation, je crois que c´est le GetTimeOfDay qui déconne dessus.

Je regarderais demain sous windows avec les compilo MS et Intel.

KouicKouic
KouicKouic
Niveau 6
14 janvier 2007 à 09:57:07

A partir de l´option -O1 la majeur partie des tests ne sont pas compilés.
Pour optenir le code ASM il suffit de compiler avec l´option -S.
Pour ce qui est des résultat sur la station Sun, cela dépend du compilateur (vérififier avec -S) et de la puissance du proc.
GetTimeOfDay renvoi des nanoseconde, pour un résultat plus précis tu peux utiliser la ligne suivante pour la fonction timeGetTime :
return ((unsigned long long)(tv1.tv_sec) *1000000) + (unsigned long long)(tv1.tv_usec);

dnob700
dnob700
Niveau 10
14 janvier 2007 à 12:34:40

j´ai un peu modifié le code pour que le tout soit toujours compilé (globalement, je récupère le résultat du calcul), car sous VS2005, dès qu´on est en release, il ne compilaitplus rien du tout (sauf malloc et Cie).

le code et les résultats sont là, avec la version VC++ sans vectorisation (ou pas trop en tout cas), et celle de ICC.

http://repository.sectionpc.info/C/bench.cpp

Là, je tourne en 32 bits. Mais dès qu´on manipule des float et des double, il peut être interessant de comparer surla même machine, le résultat en 64 bit (mais si possible avec le même compilo, hors je n´arrive pas à faire tourner icc sous linux) vu que là, les double en 80 bits tiennent dans un registre, ce qui améliore les choses.

godrik
godrik
Niveau 30
14 janvier 2007 à 12:37:54

a mon tour:
proc: P4 HT Ghz en 64 bit (os et binaire)
Les résultats des test sont en fin de post.
chez moi, -O1 -O2 -O3 ca ne change rien. En tout cas, tant que l´on ne vise pas le bon processeur.
Parcontre cibler le bon processeur, ca change tout! avec -O3 et -O2 on obtient une bonne proportion de 0ms. en -01, le compilo semble faire tout betement snas optimisation.

Au chapitre des curiosités...
dans l´assembleur les lignes d´initialisations sont différente en -02 et -O3 (avec processeur ciblé au moins)
movl $0, %eax (en -O1)
xorl %eax, %eax (en -O2)

plutot que de faire a=0; il fait a= a XOR a; ce qui en effet fait 0 aussi.
ceci semble etre la différence majeure entre les deux code binaire.
je fournit un diff des code en fin de post.

-------------------------------------

g++ /tmp/toto.cpp -o /tmp/toto (donc -O1)
100M += : 293 millisecondes
100M += ; 100M appels de fonction inline: 503 millisecondes
100M += ; 100M appels de fonction: 516 millisecondes
100M *= : 502 millisecondes
100M += et 100M + : 307 millisecondes
100M += et 100M * : 344 millisecondes
100M += float : 871 millisecondes
100M += double : 869 millisecondes
100M += float+cast : 870 millisecondes
100M += double+cast : 870 millisecondes
100M += float, 200M cast, 100M * : 875 millisecondes
100M += double, 200M cast, 100M * : 871 millisecondes
100M += float, 100M cast, 100M var temp, 100 * : 1506 millisecondes
100M += float, 100M cast, 100M var temp, 100 * : 1537 millisecondes
100M += float+cast& : 3075 millisecondes
100M += double+cast& : 2175 millisecondes
1M malloc(100), 1M free : 99 millisecondes
1M calloc(100,0), 1M free : 54 millisecondes
1M new char[100], 1M delete : 115 millisecondes
1K malloc(100000), 1M free : 0 millisecondes
1K new char[100000], 1M delete : 0 millisecondes
1M malloc(100), 1M free, 1M creation var interne : 102 millisecondes
100M 10 indirections : 1259 millisecondes
100M 2*5 indirections : 1427 millisecondes
100M += et 100M sqrt et 100M cast double: 3175 millisecondes
100M += et 100M sin et 100M cast double: 10876 millisecondes
100M += et 100M cos et 100M cast double: 10753 millisecondes
100M += et 100M tan et 100M cast double: 16911 millisecondes

les meme en -02:
godrik@skynet-ubuntu:~$ g++ -O2 /tmp/toto.cpp -o /tmp/tot
godrik@skynet-ubuntu:~$ /tmp/toto
100M += : 293 millisecondes
100M += ; 100M appels de fonction inline: 508 millisecondes
100M += ; 100M appels de fonction: 507 millisecondes
100M *= : 503 millisecondes
100M += et 100M + : 309 millisecondes
100M += et 100M * : 337 millisecondes
100M += float : 872 millisecondes
100M += double : 872 millisecondes
100M += float+cast : 874 millisecondes
100M += double+cast : 872 millisecondes
100M += float, 200M cast, 100M * : 880 millisecondes
100M += double, 200M cast, 100M * : 876 millisecondes
100M += float, 100M cast, 100M var temp, 100 * : 1509 millisecondes
100M += float, 100M cast, 100M var temp, 100 * : 1541 millisecondes
100M += float+cast& : 3058 millisecondes
100M += double+cast& : 2180 millisecondes
1M malloc(100), 1M free : 100 millisecondes
1M calloc(100,0), 1M free : 54 millisecondes
1M new char[100], 1M delete : 115 millisecondes
1K malloc(100000), 1M free : 1 millisecondes
1K new char[100000], 1M delete : 0 millisecondes
1M malloc(100), 1M free, 1M creation var interne : 103 millisecondes
100M 10 indirections : 1348 millisecondes
100M 2*5 indirections : 1534 millisecondes
100M += et 100M sqrt et 100M cast double: 3413 millisecondes
100M += et 100M sin et 100M cast double: 10970 millisecondes
100M += et 100M cos et 100M cast double: 10756 millisecondes
100M += et 100M tan et 100M cast double: 16891 millisecondes

puis en -O3:
godrik@skynet-ubuntu:~$ g++ -O3 /tmp/toto.cpp -o /tmp/tot
godrik@skynet-ubuntu:~$ /tmp/toto
100M += : 288 millisecondes
100M += ; 100M appels de fonction inline: 505 millisecondes
100M += ; 100M appels de fonction: 501 millisecondes
100M *= : 505 millisecondes
100M += et 100M + : 309 millisecondes
100M += et 100M * : 337 millisecondes
100M += float : 874 millisecondes
100M += double : 872 millisecondes
100M += float+cast : 873 millisecondes
100M += double+cast : 872 millisecondes
100M += float, 200M cast, 100M * : 881 millisecondes
100M += double, 200M cast, 100M * : 885 millisecondes
100M += float, 100M cast, 100M var temp, 100 * : 1505 millisecondes
100M += float, 100M cast, 100M var temp, 100 * : 1536 millisecondes
100M += float+cast& : 3072 millisecondes
100M += double+cast& : 2173 millisecondes
1M malloc(100), 1M free : 98 millisecondes
1M calloc(100,0), 1M free : 54 millisecondes
1M new char[100], 1M delete : 112 millisecondes
1K malloc(100000), 1M free : 0 millisecondes
1K new char[100000], 1M delete : 0 millisecondes
1M malloc(100), 1M free, 1M creation var interne : 98 millisecondes
100M 10 indirections : 1260 millisecondes
100M 2*5 indirections : 1427 millisecondes
100M += et 100M sqrt et 100M cast double: 3173 millisecondes
100M += et 100M sin et 100M cast double: 10885 millisecondes
100M += et 100M cos et 100M cast double: 10754 millisecondes
100M += et 100M tan et 100M cast double: 16888 millisecondes

et avec l´optimisation pour le processeur comme il faut:
godrik@skynet-ubuntu:~$ g++ -O3 -mtune=nocona /tmp/toto.cpp -o /tmp/toto
godrik@skynet-ubuntu:~$ /tmp/toto
100M += : 0 millisecondes
100M += ; 100M appels de fonction inline: 0 millisecondes
100M += ; 100M appels de fonction: 0 millisecondes
100M *= : 0 millisecondes
100M += et 100M + : 0 millisecondes
100M += et 100M * : 0 millisecondes
100M += float : 0 millisecondes
100M += double : 0 millisecondes
100M += float+cast : 0 millisecondes
100M += double+cast : 0 millisecondes
100M += float, 200M cast, 100M * : 0 millisecondes
100M += double, 200M cast, 100M * : 0 millisecondes
100M += float, 100M cast, 100M var temp, 100 * : 0 millisecondes
100M += float, 100M cast, 100M var temp, 100 * : 0 millisecondes
100M += float+cast& : 0 millisecondes
100M += double+cast& : 0 millisecondes
1M malloc(100), 1M free : 105 millisecondes
1M calloc(100,0), 1M free : 56 millisecondes
1M new char[100], 1M delete : 128 millisecondes
1K malloc(100000), 1M free : 0 millisecondes
1K new char[100000], 1M delete : 0 millisecondes
1M malloc(100), 1M free, 1M creation var interne : 98 millisecondes
100M 10 indirections : 0 millisecondes
100M 2*5 indirections : 0 millisecondes
100M += et 100M sqrt et 100M cast double: 1374 millisecondes
100M += et 100M sin et 100M cast double: 0 millisecondes
100M += et 100M cos et 100M cast double: 0 millisecondes
100M += et 100M tan et 100M cast double: 0 millisecondes
godrik@skynet-ubuntu:~$ g++ -mtune=nocona /tmp/toto.cpp -o /tmp/toto
godrik@skynet-ubuntu:~$ /tmp/toto
100M += : 292 millisecondes
100M += ; 100M appels de fonction inline: 469 millisecondes
100M += ; 100M appels de fonction: 471 millisecondes
100M *= : 502 millisecondes
100M += et 100M + : 312 millisecondes
100M += et 100M * : 338 millisecondes
100M += float : 869 millisecondes
100M += double : 871 millisecondes
100M += float+cast : 869 millisecondes
100M += double+cast : 869 millisecondes
100M += float, 200M cast, 100M * : 881 millisecondes
100M += double, 200M cast, 100M * : 871 millisecondes
100M += float, 100M cast, 100M var temp, 100 * : 1553 millisecondes
100M += float, 100M cast, 100M var temp, 100 * : 1568 millisecondes
100M += float+cast& : 3144 millisecondes
100M += double+cast& : 2246 millisecondes
1M malloc(100), 1M free : 101 millisecondes
1M calloc(100,0), 1M free : 55 millisecondes
1M new char[100], 1M delete : 122 millisecondes
1K malloc(100000), 1M free : 0 millisecondes
1K new char[100000], 1M delete : 0 millisecondes
1M malloc(100), 1M free, 1M creation var interne : 107 millisecondes
100M 10 indirections : 1345 millisecondes
100M 2*5 indirections : 1448 millisecondes
100M += et 100M sqrt et 100M cast double: 3173 millisecondes
100M += et 100M sin et 100M cast double: 10920 millisecondes
100M += et 100M cos et 100M cast double: 10915 millisecondes
100M += et 100M tan et 100M cast double: 16926 millisecondes

godrik@skynet-ubuntu:~$ g++ -mtune=nocona -O2 /tmp/toto.cpp -o /tmp/toto
godrik@skynet-ubuntu:~$ /tmp/toto
100M += : 0 millisecondes
100M += ; 100M appels de fonction inline: 0 millisecondes
100M += ; 100M appels de fonction: 0 millisecondes
100M *= : 0 millisecondes
100M += et 100M + : 0 millisecondes
100M += et 100M * : 0 millisecondes
100M += float : 0 millisecondes
100M += double : 0 millisecondes
100M += float+cast : 0 millisecondes
100M += double+cast : 0 millisecondes
100M += float, 200M cast, 100M * : 0 millisecondes
100M += double, 200M cast, 100M * : 0 millisecondes
100M += float, 100M cast, 100M var temp, 100 * : 0 millisecondes
100M += float, 100M cast, 100M var temp, 100 * : 0 millisecondes
100M += float+cast& : 0 millisecondes
100M += double+cast& : 0 millisecondes
1M malloc(100), 1M free : 106 millisecondes
1M calloc(100,0), 1M free : 57 millisecondes
1M new char[100], 1M delete : 119 millisecondes
1K malloc(100000), 1M free : 0 millisecondes
1K new char[100000], 1M delete : 0 millisecondes
1M malloc(100), 1M free, 1M creation var interne : 98 millisecondes
100M 10 indirections : 0 millisecondes
100M 2*5 indirections : 0 millisecondes
100M += et 100M sqrt et 100M cast double: 1376 millisecondes
100M += et 100M sin et 100M cast double: 0 millisecondes
100M += et 100M cos et 100M cast double: 0 millisecondes
100M += et 100M tan et 100M cast double: 0 millisecondes
godrik@skynet-ubuntu:~$ g++ -mtune=nocona -S -O2 /tmp/toto.cpp -o /tmp/toto.o2.s
godrik@skynet-ubuntu:~$ g++ -mtune=nocona -S -O1 /tmp/toto.cpp -o /tmp/toto.o1.s
godrik@skynet-ubuntu:~$ diff /tmp/toto.o{1,2}.s
154,155d153
< pushq %r13
< .LCFI3:
157c155
< .LCFI4:
---

.LCFI3:

159c157
< .LCFI5:
---

.LCFI4:

161,163c159
< .LCFI6:
< subq $8, %rsp
< .LCFI7:
---

.LCFI5:

168c164
< movl $0, %eax
---

xorl %eax, %eax

174c170
< movl $0, %eax
---

xorl %eax, %eax

180c176
< movl $0, %eax
---

xorl %eax, %eax

186c182
< movl $0, %eax
---

xorl %eax, %eax

192c188
< movl $0, %eax
---

xorl %eax, %eax

198c194
< movl $0, %eax
---

xorl %eax, %eax

204c200
< movl $0, %eax
---

xorl %eax, %eax

210c206
< movl $0, %eax
---

xorl %eax, %eax

216c212
< movl $0, %eax
---

xorl %eax, %eax

222c218
< movl $0, %eax
---

xorl %eax, %eax

228c224
< movl $0, %eax
---

xorl %eax, %eax

234c230
< movl $0, %eax
---

xorl %eax, %eax

240c236
< movl $0, %eax
---

xorl %eax, %eax

246c242
< movl $0, %eax
---

xorl %eax, %eax

252c248
< movl $0, %eax
---

xorl %eax, %eax

258c254
< movl $0, %eax
---

xorl %eax, %eax

261c257
< movl $0, %ebx
---

xorl %ebx, %ebx

273c269
< movl $0, %eax
---

xorl %eax, %eax

276c272
< movl $0, %ebx
---

xorl %ebx, %ebx

278c274
< movl $0, %esi
---

xorl %esi, %esi

289c285
< movl $0, %eax
---

xorl %eax, %eax

292c288
< movl $0, %ebx
---

xorl %ebx, %ebx

307c303
< movl $0, %eax
---

xorl %eax, %eax

310c306
< movl $0, %ebx
---

xorl %ebx, %ebx

322c318
< movl $0, %eax
---

xorl %eax, %eax

325c321
< movw $0, %bx
---

xorw %bx, %bx

340c336
< movl $0, %eax
---

xorl %eax, %eax

343c339
< movw $0, %bx
---

xorw %bx, %bx

355c351
< movl $0, %eax
---

xorl %eax, %eax

360d355
< movq %rax, %r13
362,363c357,362
< movl $0, %ebp
< movl $0, %eax
---

xorl %ebp, %ebp
xorl %eax, %eax
jmp .L26
.L53:
movq %rax, %rbx
movl %ebp, %eax

372,376c371
< je .L27
< movq %rax, %rbx
< movl %ebp, %eax
< jmp .L26
< .L27:
---

jne .L53

381c376
< movl $0, %eax
---

xorl %eax, %eax

387c382
< movl $0, %eax
---

xorl %eax, %eax

389c384
< testq %r13, %r13
---

testq %r12, %r12

400,401c395,399
< movl $0, %ebx
< movl $0, %eax
---

xorl %ebx, %ebx
xorl %ebx, %ebx
xorl %eax, %eax
jmp .L32
.L54:
movl %ebx, %eax

415,419c413
< je .L34
< movl %ebx, %eax
< jmp .L32
< .L34:
< .p2align 4,,5
---

jne .L54

423c417
< movl $0, %eax
---

xorl %eax, %eax

429c423
< movl $0, %eax
---

xorl %eax, %eax

435c429
< movl $0, %eax
---

xorl %eax, %eax

441c435
< movl $0, %eax
---

xorl %eax, %eax

443,444c437
< movl $0, %eax
< addq $8, %rsp
---

xorl %eax, %eax

448d440
< popq %r13
547,554d538
< .byte 0x4
< .long .LCFI6-.LCFI5
< .byte 0xe
< .uleb128 0x28
< .byte 0x4
< .long .LCFI7-.LCFI6
< .byte 0xe
< .uleb128 0x30
556,557d539
< .uleb128 0x5
< .byte 0x86
559c541
< .byte 0x8c
---

.byte 0x86

561c543
< .byte 0x8d
---

.byte 0x8c

godrik
godrik
Niveau 30
14 janvier 2007 à 13:07:34

mea culpa. Quand on ne met pas de´option d´optimisation, c´est du -O0 et pas du -O1.
a partir de -O1, le compilo dégage la plus part du code.
On le voit d´ailleurs dans l´assembleur, ceci est le code de la premiere boucle. Aucun calcul n´est fait, parcontre le compilo ne pourrait pas les supprimer si on affichait le résultat.
.loc 1 83 0
call _Z12ReInitChronov
.loc 1 86 0
call _Z9GetChronov
movq %rax, %rsi
movl $.LC0, %edi
xorl %eax, %eax
call printf

Par contre, j´ai plus de mal a analyser les appels a sqrt et a sin
en -O1, il fait les appels a sqrt mais pas a sin
alors qu´en -O0 il fait les deux. Je ne comprends pas bien pourquoi en -O1 il n´arrive pas a supprimer les appels a sqrt...

Fvirtman
Fvirtman
Niveau 10
14 janvier 2007 à 13:33:21

Intéressant :)

Pour les tests a 0 millisecondes, pour voir si ils ont été purement supprimés, il faut augmenter les itérations.
Avec un int (signed), on peut monter jusqu´a 2 milliards d´itérations. Si la, ça fait toujours 0 ms, c´est qu´il y a soucis.

C´est ce que j´avais quand je ne mettais pas de :
tmp+= _letest

car le compilo detectait que le resultat de _letest n´allait nulle part, donc le virait carrément. Avec le +=, il est obligé d´accumuler pour mettre la variable tmp a jour.
Peut etre que carrément, d´autres compilos plus malins detectent que je ne me sers pas de tmp par la suite, donc zappent quand meme les tests.
J´ai un moyen infaillible pour l´obliger a calculer malgré tout : un bete printf("%d",tmp);
Au moins, la, il est obligé de faire les calculs :)

Sinon, Dnob, tu parles des instructions sinus, cosinus, tangeante, qui seraient directement une instruction machine (sur les CISC du coup non ?)
Si c´est le cas, il doit y avoir moyen d´avoir de tres bons résultats pour les tests trigos, si je peux avoir ça, je suis intéressé.

A defaut, je pense que je programmerai des fonctions trigo a moi, qui auront en interne une table statique (comme dans nos livres de maths au lycée !) , comme ça, un résultat arrondi (un peu moins juste mais suffisant pour pas mal de cas) en temps rapide.

LGV
LGV
Niveau 28
14 janvier 2007 à 14:47:05

je rajoute qq elements :

specs Intel IA32 (ou autres..) avec SSEx ; ca donne tous les details, au niveau des instructions meme. Impossible de dire "une / est X fois plus lent qu´une *" ; ca depend de bcp de choses : vectorisation ? types a traiter ? type des operandes ? leur place dans le cache 1st level ? etc.

connaitre son compilo et l´implemention de choses cruciales comme les tables de virtualite

jeter un oeila "C++ Performance Draft" pour des idees sur des concepts plus generiques

faire des tests et regarder le code ASM *optimise* (avec un BON compilo, comme VC2005 ou ICC ; oubliez gcc)

connaitre qq astuces comme par ex remplacer des virtual calls par des templates specilizations, histoire de virer le virtual overhead de dereferecement non trivial des donnees membres

LGV
LGV
Niveau 28
14 janvier 2007 à 14:54:30

"Peut etre que carrément, d´autres compilos plus malins detectent que je ne me sers pas de tmp par la suite, donc zappent quand meme les tests."

clairement, oui..

"J´ai un moyen infaillible pour l´obliger a calculer malgré tout : un bete printf("%d",tmp)"

a faire en dehors des timers, vu que ca coute un max de temps, ce genre de traitement de chaine. A noter que la encore, un compilo a qui on fait faire 2 milliards de fois une operation qui produit un resultat "predictable" (pas forcement similaire, mais qu´il peut predire), va grandement simplifier le probleme

"Sinon, Dnob, tu parles des instructions sinus, cosinus, tangeante, qui seraient directement une instruction machine (sur les CISC du coup non ?)
Si c´est le cas, il doit y avoir moyen d´avoir de tres bons résultats pour les tests trigos, si je peux avoir ça, je suis intéressé."

toutes les fonctions trigo sont effectivement cablees en dur, avec des mnemoniques associees. Ca ne coute plus "rien" ajd.

"A defaut, je pense que je programmerai des fonctions trigo a moi, qui auront en interne une table statique (comme dans nos livres de maths au lycée !) , comme ça, un résultat arrondi (un peu moins juste mais suffisant pour pas mal de cas) en temps rapide."

ca marchait bien a l´epoque des 3/486 et P1, ou les calculs trigo etaient couteux. Ajd c´est souvent contre-performant d´utiliser son propre mecanisme : le cout des dereferencement (souvent vers une table static, sympa pour le cache..) et d´interpolation a l´arrache sont bien plus eleves qu´utiliser les mnemoniques du CPU.

dnob700
dnob700
Niveau 10
14 janvier 2007 à 16:15:21

oui, dans la version du code que j´ai reposté, j´utilise le résultat des boucles pour l´obliger à les calculer, sinon effectivement, il zappe les boucles.

Par contre, même si le résultat d´une boucle est complétement prévisible, je ne crois pas qu´un compilo va faire le calcul à la compilation pour optimiser le tout, c´est a priori une optimisation trop complexe qu´un compilo ne sait pas faire, on touche là à la limite de l´analyse statique.

Fvirtman
Fvirtman
Niveau 10
15 janvier 2007 à 14:17:55

dnob700 >

J´ai essayé de lancer le programme avec visual 2005, les fonctions trigo restent toujours relativement lentes.
Faut il une config spéciale du projet pour utiliser les fonctions en hardware ?
Comment configurer le projet ?

Tu arrives, toi, a faire utiliser les fonctions trigo en interne ?

godrik
godrik
Niveau 30
15 janvier 2007 à 18:24:54

j´ai beau activer toute les options d´optimisation, je continu de voir un ´call sin´ dans le code assembleur.

LGV
LGV
Niveau 28
15 janvier 2007 à 20:03:56

options du compilo

optimization
optim > max speed
intrinsic > yes
favor fast code

code generation
floating model > fast
instruction set > SOIT mettre sur "not set", soit faire mumuse avec le SSEx mais la faut aussi tripoter le linker pour faire apparaitre directement le code SSE dans l´asm

teste a l´instant sous VC++ 2005 Express

Sous forums
  • Aide à l'achat Mac
  • Création de sites web
  • Création de Jeux
  • Linux
  • Programmation
  • Internet
  • Steam Deck
  • Macintosh
  • Hardware
La vidéo du moment