Annonces Google
Serveur IRC
Serveur : irc.portlane.se
Canal : #AmigaNG
Activité du Site

Pages vues depuis 25/07/2007 : 25 262 720

  • Nb. de membres 187
  • Nb. d'articles 1 270
  • Nb. de forums 19
  • Nb. de sujets 20
  • Nb. de critiques 24

Top 10  Statistiques

Index du forum »»  Création-Développement »» GCC: Pourquoi l'option -O3 est un faux ami (optimisation)

GCC: Pourquoi l'option -O3 est un faux ami (optimisation)#1843

5Contributeur(s)
thellierAmiDARKsinisrusElwoodcorto
3 Modérateur(s)
K-LElwoodcorto
thellier thelliericon_post
Hello

Depuis quelque temps j'ai mis une série de test (benchmarks) pour mesurer la vitesse de mon Microbe3D
Le résultat le plus essentiel étant celui que j'appelle "TPF50" qui est le "temps par frame calculé sur 50 frame"
Par exemple je notais le 15 mars sur une PartyGirl immobile que j'obtenais un TPF50 de 63 ou 64 millisecondes
(donc 1000/64 = 15.6 frames par secondes)
Je programme, je rajoute qques trucs légérs, je rajoute le support arexx sous os4, je teste ça marche

Et paf je regarde mon TP50 : 67 !!! arghh
Aussi le binaire a beaucoup grossi : 482 KO à 566 KO

Mais d'où ça vient ?
De l'option d'optimisation -O3 de gcc :-(

En effet avec O3 on inline les fonctions
"inliner" c'est GCC qui au lieu d'appeler une fonction (un sous programme) met directement les instructions de la fonction à cet endroit
Normalement ça accélére le programme puisqu'il n' y plus de saut dans un sous programme ailleurs mais juste des instructions à ce même endroit

par exemple

/*=================================================================*/
/* Normalize: normalize a vector */
inline void Normalize(Vertex3D *c)
{
register float size;

size = (float)sqrt(c->x * c->x + c->y * c->y + c->z * c->z);
if(size==0) return;
c->x /= size;
c->y /= size;
c->z /= size;
}
/*=================================================================*/
void NormalizeVertices(Vertex3D *V,ULONG nbrepoints)
{
register ULONG n;

for(n=0;n!=nbrepoints;n++)
Normalize(&V[n]);

}
/*=================================================================*/

La fonction Normalize() n'est alors plus appelé dans NormalizeVertices (ce qui prend un certain temps) mais les instructions de Normalize() y sont directement inclues
Normalize() devient donc une macro

Bref normalement -O3 qui inline ce serait bien...

Mais là avec mon wrapper arexx il y avait un gros problème :
c'étais un wrapper qui appelait chaque fonction de l'api Microbe3D (45 fonctions en tout) depuis une fonction arexx
Donc chaque (grosse) fonction de l'api Microbe3D était dupliquée dans la fonction arexx
===> augmentation conséquente de taille du binaire
===> binaire plus gros ==> utilise mal le cache cpu

Conclusion: -O3 c'est pas bien il vaut mieux rajouter "inline" devant les vrais fonctions à inliner (comme celle servant de fonction mathématiques dans des boucles de calculs) et ne plus laisser faire GCC en prenant plutôt -O2
Les bon programmeurs le savent certainement déjà , moi aussi je le savais aussi un peu :-P mais je n'avais jamais réalisé que les progs ayant des wrappers (cad pleins de fonctions vides servant juste à appeler une autre fonction) pouvait etre autant impacté

avec -O2 le binaire revient à 347 KO et refais 64 millisencondes par frame avec le support arexx

Alain













Message édité par : thellier / 07-04-2014 14:48
AmiDARK AmiDARKicon_post
Merci Alain pour ces informations.
J'utilisais O3 sans faire attention car, dans les exemples MiniGL, l'option -O3 est mise en place par défaut et, décrite comme indispensable pour MiniGL ...
Je comprends donc mieux pourquoi ma library donne des .exe énormes :p
Je vais donc supprimer cette option ;)
Merci à toâ :)
sinisrus sinisrusicon_post
ouf tu ma fais peur... :-)
--
Coin coin... amitheme.amiga-ng.org
Sam460 1,15Ghz - OS4.1FE - Radeon Saphir HD7750 R7 250E - 2Go de ram
Elwood Elwoodicon_post
Belle explication. Je ne connaissais pas ce "inline". ça mériterait de mettre ça en anglais et le poster sur os4coding.net
--
Philippe Ferrucci
Avec une Sam460 et AmigaOS 4.1, je suis eco-responsable. Cool !
thellier thelliericon_post
>ça mériterait de mettre ça en anglais et le poster sur os4coding.net
Sans moi : mon anglais est trop afffreux

En fait il faut bien voir les limites du système de l'inlining :
1) Si ça insére ( les instruction d' ) une fonction petite dans toutes les grosses fonctions qui s'en servent = c'est bien
2) Si ça insére ( les instruction d' ) une fonction grosse dans toutes les petites fonctions qui s'en servent = c'est pas bien

Par exemple si on a une petite fonction mathématique comme mon Normalize (qui donnera peut être 20 instructions ASM) alors autant l'insérer aux rares endroits où on s'en sert = là l'inlining est efficace

Par contre si chaque fonction qui utilise ma grosse fonction DrawObject() (qui elle doit faire des milliers d'instructions) commence à insérer tout ça alors là l'obésité du code menace = là l'inlining fait n'importe quoi

En plus certaines fonctions servent rarement (par exemple mon AddObject() qui sert qu'au moment du chargement de fichiers 3D) ==> est il utile de les rendre objectivement plus rapides mais aussi plus grosses ?

Bref si on y réfléchis les fonctions que l'on veut vraiment inliner sont:

1) Celles qui servent qu'à un endroit où on aurait d'ailleurs dû écrire le code mais qu'on a mis dans une fonction séparée pour faire plus propre

2) Celles qui servent souvent et/ou dans des boucles et sont petites (comme une fonction mathématique)
Normalement on en ferait des macros mais parfois c'est plus pratique à écrire sous forme de fonction
Par exemple la fonction Normalize aurait été chiante à écrire en macro à cause de la variable locale size

Pour ces fonctions il faut donc ajouter "inline"
comme ça
inline void Normalize(Vertex3D *c)

Alain








AmiDARK AmiDARKicon_post
Oui Alain,

l'AmiDARK Engine étant un système basé sur des "fonctions" ... cela peut rapidement provoquer un grossissement des .EXE et des fonctions à rallonge.
(sachant qu'il y a des dépendances de fonctions)

Je vais testouiller sans le -03...
Sais-tu si le -O2 ou -O1 est intéressant ?

@+
thellier thelliericon_post
Je me suis rabattu sur le -O2 qui a pas l'air mal pour mon cas puisque je retrouve les mêmes performances et avec un .exe plus petit
Mais j'ai quand même mis "inline" devant mes qques fonctions stratégiques

Après faut voir si certaines des options qu'activais aussi -O3 ne mériteraient pas d'être aussi remise manuellement (je veut dire en dehors de l'inlining que lui on peut remettre avec "inline" devant les fonctions stratégiques)

Voir ce site
http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
Mais j'y comprends pas grand choses...

Alain
AmiDARK AmiDARKicon_post
Thellier,

Comment procèdes-tu pour le inline de certaines fonctions.

D'ailleurs, existe t-il une façon (via OS4 ou GCC) de mettre une fonction précise en cache ?

@+
thellier thelliericon_post
Ben tu mets "inline" devant la description de la fonction: je viens de l ecrire tu lis ou tu dors :-p
pour le cache je sais pas et je doute que cela soit possible...

Ce qui serait bien serait un outil qui donnerait la taille et l adresse des fonctions dans un binaire : comme ca on pourrait essayer de regrouper les fonctions strategiques au meme endroit en esperant qu elle soient toutes dans le cache.

Alain
AmiDARK AmiDARKicon_post
Oué .... Environ 4h par nuit :p
Donc la journée .... J'ai du mal :( MDR

Ok. Je vais testouiller voire si ça améliore les performances.
Petites Annonces

0 annonce(s) publiée(s)

Consulter

AmigaOS 4.1

Laissez-vous tenter par
AmigaOS 4.1
AmiTheme

AmiTheme