Quand j’étais un peu plus jeune, on faisait des Coding Party ! C’était un rassemblement de personnes qui étaient programmeurs, graphistes ou musiciens. Les Coding Party se faisaient plutôt le weekend du vendredi soir au dimanche matin et s’organisaient soit chez un pote, ou dans une salle des fêtes si des centaines de personnes venaient des 4 coins de la France. Chacun amenait son ordinateur (Atari / Amiga) et son duvet … même si on ne dormais que très peu :p. Il y avait des concours de design / programmation / music et les fameuses « démos » qui consistait à exploiter la machine au mieux pour relever des challenges comme afficher le plus possible de faces « mappé » en 3D !
C’était vraiment fun et passionnant. On rencontraient d’autres personnes, on découvrait les créations des autres sur écran géant et surtout on codaient comme des acharnés !
J’avais ma place en tant que programmeur et mon principal challenge n’étais pas seulement de programmer des effets 2D ou 3D en temps réel, mais surtout d’optimiser le code pour le temps machine. Une optimisation de l’algorithme à faire, puis du code en lui-même ou chaque instruction en assembleur avait son propre temps d’exécution. Par exemple une addition de registre à registre prenait 4 cycles (unité de temps sur Atari) mais une multiplication en prenait 72 cycles !!
Si vous faite un moteur 3D, plus le code sera optimisé, plus vous pourrez afficher des points/faces/faces « mappés ». A l’époque il n’existait pas de carte graphique 3D, tout les calculs pour le rendu étaient fait par le processeur.
Si l’on comparait le rendu d’un code fait normalement a celui du code optimisé, il pouvait il avoir un rapport de 10, 100, 1000 voir 10000 fois plus rapide !
Prenons un exemple simple qui va consister à faire une fonction qui doit afficher un point à l’écran aux coordonnées (X,Y).
Sur Atari, la résolution était de 320 * 200 pixels en 16 couleurs affichage en même temps, et malheureusement 1 pixel ne correspondait pas à un octet, il y avait un système de plan de bits …
enfin bref, une ligne de pixel correspondait à 160 octets et pour simplifier l’explication on va considérer que 1 pixel égal 1 octet.
Donc pour trouver le bon octet en mémoire pour écrire notre pixel il fallait faire :
position du Pixel en mémoire = Y*160+X
Voici le code assembleur :
move.w Y,D0 // 4 cycles
muls.w #160,D0 // 72 cycles
add.w X,D0 // 4 cycles
D0 contient la position du pixel et le temps d’exécution est de 80 cycles.
Si vous faite un moteur 3D avec un rendu en pixels, il va vous falloir que vous affichez beaucoup de points à l’écran dans un laps de temps très court, donc optimiser cette fonction pour exécuter le calcul avec le moins de cycle possible.
Vous allez me dire « bin y*160+x ça s’optimise pas c’est juste une multiplication et une addition ! »
Bin si en faite, car
y*160 = y*(128 +32)
= y*(2^7 + 2^5)
= y*(2^5(2^2 + 1))
et la vous répliquez (si vous suivez :p) : « Mouai et alors c’est encore plus compliqué et ya beaucoup plus d’opérations oO »
oui, yen a plus … mais les puissances de 2 sont plus rapide car il existe une instruction en assembleur qui permet de décaler un registre de N bits vers la gauche ou la droite, et cela reviens à multiplier par 2^N ou diviser par 2^N. l’instruction de décalage de bits le temps d’exécution était de 6+2*N cycles.
Voici le code assembleur correspondant :
move.w Y,D0 // 4 cycles
asl.w #5,D0 // 6+2*n = 16 cycles
move.w D0,D1 // 4 cycles
add.w D1,D1 // 4 cycles
add.w D1,D1 // 4 cycles
add.w D1,D0 // 4 cycles
add.w X,D0 // 4 cycles
Notez que add.w D1,D1 permet de mutiplier D1 par 2, plus rapide qu’un décalage de bits 6+2n cycles ou d’une multiplication par 2 avec muls de 72 cycles.
Donc au lieu de faire 2^2 avec asl.w #2,D1 qui prendrait 10 cycles on fait 2 fois l’instruction add.w D1,D1 ce qui nous fait gagné 2 cycles :p
D0 contient la position du pixel et le temps d’exécution est de 40 cycles on à divisé de moitié le temps d’exécution pour un simple calcul, du coup vous affichez 2 fois plus de points à l’écran !
C’était juste un petit exemple, mais on imagine bien que même sur un simple bout de code il est possible de le faire de pleins de façons différentes.
C’est très important l’optimisation et c’est un défi permanent et de plus ça développe l’esprit à la réflexion. Maintenant je vous laisse imaginer l’impact de l’optimisation sur un code qui doit s’exécuter des millions de fois.
Developpeur iPhone freelance
#1 by nicolas on 27 novembre 2009
Je suis bien d’accord, aujourd’hui un cycle on ne sait plus ce que c’est.
C’était le bon temps tout ça.
Un dev amiga……haaaaaaaa!!