Compiler avec GCC sur Sam440 :Comment optimiser?
-
Hello
J’essaye de recompiler mon Wazp3D.library sur ma Sam440
A part le -O2 qui améliore un peu Sinon c’est toujours aussi lent…
Y a t’il une option gcc magique à ne pas oublier sur PPC un peu comme le -m68881 pour le 68040 ???
Ou alors est ce vraiment le gcc du SDK qui donne du code lent ?!?
Alain
Est-ce que tu utilises le dernier SDK disponible ?
Le PPC n’est pas un 68k, si tu as écrits ton code en essayant d’être « malin » pour le 68k, il se peut qu’en fait soit contre-productif pour PPC.
Quand tu parles de « lent » comment tu le vérifies ? Par exemple maintenant que ta bibliothèque est PPC il faut que ton programme le soit aussi pour profiter de la pleine vitesse, sinon regardes si tes vecteurs 68k ne font pas des choses non optimisées ?
Après une 440 n’est pas une foudre de guerre non plus, toutefois ta lib PPC devrait être plus rapide que la version 68k (mais ce n’est pas magique non plus hein .
Je sais qu’à un moment donné il y avait des problèmes d’alignement sur Sam, cela a été réglé depuis, mais je ne sais pas s’il faut faire quelque chose de particulier.
Le mieux serait de tenter de poser la question sur le forum d’Hyperion dans la rubrique Dev.
>Est-ce que tu utilises le dernier SDK disponible ?
Non tu as raison je vais le récupérer
>Le PPC n’est pas un 68k, si tu as écrits ton code en essayant d’être « malin » pour le 68k
Je suis d’accord malheureusement comme je connais pas l’asm ppc alors je sais pas être aussi malin pour le ppc
>comment tu le vérifies ?
Je teste Aminet/Cow3D sur WinUAE les 2 en 68k
et sur la Sam cow3d/wazp les 2 en ppc
Je prend les options les plus rapides de Cow3D (touche ‘e’ ‘b’ ‘o’ ) et j’obtiens 9FPS sur la Sam contre 16FPS dans WinUAE (( toujours en rendu soft bien entendu
Bon il est vrai que la vache fait 5813 triangles mais même si on teste sur un truc + basique comme le diskmag « The Vague »
en faisant afficher les FPS on voit bien que ça se traine même en désactivant tout les effets de Wazp3D ( cad « Texture:No Coloring » )
On a presque l’impression qui y a pas de fpu ou que le bus ram<-->vram est naze
Bref y a qques chose qui m’échappe….
Si je fais tracer Wazp3D avec le « compositing » de la graphics.library comme renderer alors j’arrive à 56 FPS
Donc c vraiment un problème de « tracage » des pixels
Alain
Note: En rendu hardware (« hard overlay ») j’arrive pour Cow3D sur WinUAE à 63 FPS avec ma nouvelle version Wazp3D v52
Sur Sam440 en rendu hardware avec le vrai WaRp3D je suis à 32 FPS mais là c’est causé par Cow3D pour ppc (buggé sur WaRp3D) qui utilise pas W3d_DrawElements mais W3d_DrawTriangle… Donc là c pas representatif, ça devrait aller 2-3 fois plus vite en trouvant le moyen d’utiliser W3d_DrawElements…
Je crois me souvenir qu’il y a effectivement une option ou une lib qui permet d’accélérer certaines fonctions spécifiques au PPC440.
Mais bon, il n’y a pas de miracle les meilleurs optimisations c’est toujours dans le code
Tiens, ça y est je crois que j’ai retrouvé la lib :
http://sourceforge.net/projects/ppcperflib/
Et un peu de doc ici :
http://www.trash.net/~luethi/fpga/projects/dhrystone/dhrystone.html
Sinon tu peux utilsier aussi le -O3 et un petit strip sur le binaire, ca ne fait pas de mal
SixK
Ok je vais voir ça
J’ai essayé le O3 mais c’est pas une si bonne idée
– C’est lent à compiler
– Comme ça fait de l’inlining alors le binaire devient plus gros ce qui est pas une bonne idée sur une machine avec peu de cache
– Comme ça fait de l’inlining alors on perd le bénéfice des fonctions rapides (celles avec juste 4-5 variables dans les registres)
Au surtout au final ça va pas plus vite…
Quand au strip sur le binaire (gcc -s) ça marche pas car c’est une library (cad les symboles doivent être connus…)
Alain
thellier a écrit :
Ok je vais voir ça
J’ai essayé le O3 mais c’est pas une si bonne idée
– C’est lent à compiler
Ben oui l’optimisation ça prend plus de temps à la compilation que de pas optimiser (un peu comme quand on écrit le code quoi
thellier a écrit :
– Comme ça fait de l’inlining alors le binaire devient plus gros ce qui est pas une bonne idée sur une machine avec peu de cache
– Comme ça fait de l’inlining alors on perd le bénéfice des fonctions rapides (celles avec juste 4-5 variables dans les registres)
Si ta religion t’interdit de faire de l’inline alors il y a un flag GCC permettant de ne désactiver que ça c’est un -f-no-inline quelque chose relit juste le PDF dans SDK:Documentation/Compiler Tools/gcc.pdf (chemin ressorti de mémoire, mais tu vois l’idée)
thellier a écrit :
Quand au strip sur le binaire (gcc -s) ça marche pas car c’est une library (cad les symboles doivent être connus…)
Euh, j’ai toujours fait des strip sur mes bibliothèques et ça a marché nickel, en revanche c’est en utilisant la commande strip *après* l’édition de lien dans GCC… Ca permet d’avoir à la fois (et en une seule compilation) une version avec les symboles de débogage et une version de production issu de la même compilation donc aucune chance d’avoir des choses qui ont bougées entre temps.
Bon, j’avais passé une heure ce matin à répondre et je vois avec horreur que mon post n’a pas été pris.
Je résume donc :
– gcc propose « -mtune=440fp » qui améliore le scheduling des instructions (pairing entre autres, je suppose), et « -mcpu=440fp » pour utiliser les instructions spécifiques au 440 (comme ppcperflib mais le problème c’est que pour les cas généraux, l’accélération ne semble pas visible).
– il y a aussi l’option « -Os » qui peut peut-être préserver un peu le cache. Le cache … sujet ô combien sensible, surtout sur Sam sans cache L2.
– l’optimisation vient avant tout du code .. si tu as écrit correctement (je suppose, sauf problème de design), c’est bon, et le 440 est sans doute tout simplement un peu « juste ». De toute façon, optimiser soit même au niveau instructions, c’est hyper casse-gueule (amélioration qui provoque des régressions sur un autre coeur).
Sur le MicroAOne, je viens d’installer Wazp3D et avec l’exemple Cow, j’ai en gros 10 fps, contre 40 en Warp3D. Note qu’au début, il m’indique 0 fps alors que la vache tourne !
Sinon, j’ai lancé mon profiler. Avec Warp3D, j’ai en gros 40% dans le timer.device alors qu’avec Wazp3D, j’ai :
Percent | Program
7 | SYS:Kickstart/newlib.library.kmod
68 | LIBS:Warp3D.library
5 | Cow3D-Amiga-ppc
1 | SYS:Kickstart/ATIRadeon.chip
5 | SYS:Kickstart/kernel
7 | SYS:Kickstart/timer.device.kmod
2 | SYS:Kickstart/rtg.library
0 | LIBS:Picasso96/emulation.library
count = 0331, percent = 68, name = LIBS:Warp3D.library
Offset = 0x0000762c, Count = 0028, Function = Ztest_zless_update
Offset = 0x00054124, Count = 0003, Function =
Offset = 0x00044ac4, Count = 0034, Function = SOFT3D_ClearZBuffer
Offset = 0x00008400, Count = 0129, Function = PixelsOut16
Offset = 0x0004bf88, Count = 0017, Function = GetVertex
Offset = 0x0001d774, Count = 0002, Function = SetDrawStates
Offset = 0x00046894, Count = 0018, Function = Edge_Tex
Offset = 0x00017b28, Count = 0013, Function = PixelsTex32ToBuffer
Offset = 0x00045a38, Count = 0010, Function = DrawPolyPix
Offset = 0x0001eaac, Count = 0001, Function = SetDrawFunctions
Offset = 0x0000763c, Count = 0008, Function = Ztest_zgequal_update
Offset = 0x00020b00, Count = 0022, Function = Fill_Tex
Offset = 0x00046178, Count = 0009, Function = Poly_Persp0_Tex
Offset = 0x0004f40c, Count = 0007, Function = ClipPoly
Offset = 0x00051d7c, Count = 0003, Function = SOFT3D_DrawPrimitive
Offset = 0x000506d0, Count = 0011, Function = DrawPolyP
Offset = 0x00020d98, Count = 0009, Function = SetTexStates
Offset = 0x0001ac44, Count = 0001, Function = SOFT3D_Flush
Offset = 0x00028828, Count = 0001, Function = WAZP3D_Function
Offset = 0x00044da8, Count = 0001, Function = ZbufferCheck
Offset = 0x00053f70, Count = 0001, Function = W3D_DrawTriangle
Offset = 0x00045594, Count = 0001, Function = PrintPix
Offset = 0x0001d6c8, Count = 0002, Function = SOFT3D_SetDrawStates
count = 0026, percent = 05, name = Cow3D-Amiga-ppc
No information found (wrong file type, wrong offset, program path not found, …)
C’est intéressant :
– On passe 68% du temps dans Wazp3D, ce qui semble cohérent
– Dans Wazp3D, on passe plus de 30% (129 samples sur 331) dans PixelsOut16
– Je n’ai pas le détail dans l’appli Cow … dommage, à voir pourquoi
– Hieronymus devrait proposer un résumé un peu plus lisible, par exemple au sein d’un process, trier par pourcentage décroissant.
J’ai rapidement regardé PixelsOut16() dans le source d’Aminet et il y a moyen de la réécrire de manière beaucoup plus optimisée pour les machines sans L2.
En gros, il vaut sans doute mieux faire les shifts au vol que d’utiliser des tables précalculées couteuses en accès mémoire.
Toujours dans un soucis de réduction des accès mémoire, il faut aussi lire le maximum d’octets de la source en une seule fois. Genre lire d’un coup 32 bits du tableau « RGB » plutôt que lire les octets un par un.
Et idem pour l’écriture, écrire 32 bit par 32 bit (voir même 64bit d’un coup via un double si possible) au lieu d’octet par octet.
Quitte à préparer les données dans une variable intermédiaire et se débrouiller pour qu’elle se retrouve dans un registre.
Si en plus tu arrives à toujours accéder linéairement à la mémoire, tu vas bien aider le petit cache L1 (et son prefetch, s’il existe).
En résumé, nos PowerPC ont des accès mémoire complètement minables qu’il faut réduire à tout prix. Et quand la machine n’a même pas de cache L2 (PowerUp, Sam…), c’est pire.
henes : Ah, tu m’as devancé !
– Vrai pour les tables et les lectures par octets, en plus je pense que les shifts sont d’autant plus à préférer que le PowerPC a des instructions sur les bits très puissantes.
– Pour le prefetch, il me semble que même le petit 440 l’implémente (suivant config), à voir. Sinon, du prefetch à la main peut être tenté mais bon, avec des pincettes
– Même en -O3, j’ai vu que le code généré donne ce genre de choses :
add r0,r0,r8
add r0,r0,r9
stb r0,1(r11)
thellier : Apparemment, les tables sont précalculées pour un format de pixel particulier … il faudrait peut-être utiliser une fonction PixelsOut16 par format de pixel.
Et puis sinon, au niveau prefetch, il faudrait entrelacer un peu le code, là sur ta lecture « RGB = Frag[0].BufferRGBA; », tu es forcé d’attendre la donnée que tu utilises à la ligne d’après, tu fais ton traitement et après, paf, rebelote avec Frag[1].
Sinon Corto, d’après Hyeronimous, passe à l’Amigâterie :
10% de son temps à boire des bières
60% de son temps à répondre sur AI
20% de son temps à regarder Wazp3D pour voir comment il est fait et tenter d’aider Alain l’émaliorer
10% de son temps à se faire embêter par K-L
Corto : quand tu liras ce message, je serai prêt à courir, je m’en fous
- Vous devez être connecté pour répondre à ce sujet.
› Forums › AmigaOS, MorphOS et AROS › Développement › Compiler avec GCC sur Sam440 :Comment optimiser?