Page suivantePage pr�c�denteTable des mati�res
Je ne veux en aucun cas jouer les emp�cheurs-de-tourner-en-rond,
mais voici quelques conseils issus d'une exp�rience gagn�e � la dure.
Les avantages de l'assembleur
L'assembleur peut vous permettre de r�aliser des op�rations tr�s bas niveau:
- vous pouvez acc�der aux registres et aux ports d'entr�es/sorties
sp�cifiques � votre machine;
- vous pouvez parfaitement contr�ler le comportemant du code dans
des sections critiques o� pourraient sinon advenir un blocage du processeur
ou des p�riph�riques;
- vous pouvez sortir des conventions de production de code
de votre compilateur habituel;
ce qui peut vous permettre d'effectuer certaines optimisations
(par exemple contourner les r�gles d'allocation m�moire,
g�rer manuellement le cours de l'�x�cution, etc.);
- acc�der � des modes de programmation non courants de votre processeur
(par exemple du code 16 bits pour l'amor�age ou l'interfa�age avec le BIOS,
sur les p�c�s Intel);
- vous pouvez construire des interfaces entre des fragments de codes
utilisant des conventions incompatibles (c'est-�-dire produit par
des compilateurs diff�rents ou s�par�s par une interface bas-niveau);
- vous pouvez g�n�rer un code assez rapide pour les boucles importantes
pour pallier aux d�fauts d'un compilateur qui ne sait les optimiser
(mais bon, il existe des compilateurs optimisateurs librement
disponibles!);
- vous pouvez g�n�rer du code optimis� "� la main" qui
est plus parfaitement r�gl� pour votre configuration mat�rielle pr�cise,
m�me s'il ne l'est pour aucune autre configuration;
- vous pouvez �crire du code pour le compilateur optimisateur
de votre nouveau langage.
(c'est l� une activit� � laquelle peu se livrent, et encore, rarement.)
Les inconv�nients de l'assembleur
L'assembleur est un langage tr�s bas niveau
(le langage du plus bas niveau qui soit au dessus du codage � la main
de motifs d'instructions en binaire). En cons�quence:
- l'�criture de code en est longue et ennuyeuse;
- les bogues apparaissent ais�ment;
- les bogues sont difficiles � rep�rer et supprimer;
- il est difficile de comprendre et de modifier du code
(la maintenance est tr�s compliqu�e);
- le r�sultat est extr�mement peu portable vers une autre architecture,
existante ou future;
- votre code ne sera optimis� que une certaine impl�mentation d'une
m�me architecture: ainsi, parmi les plates-formes compatibles Intel,
chaque r�alisation d'un processeur et de ses variantes
(largeur du bus, vitesse et taille relatives des CPU/caches/RAM/Bus/disques,
pr�sence ou non d'un coprocesseur arithm�tique, et d'extensions MMX ou autres)
implique des techniques d'optimisations parfois radicalement diff�rentes.
Ainsi diff�rent grandement les processeurs d�j� existant et leurs variations:
Intel 386, 486, Pentium, PPro, Pentium II; Cyrix 5x86, 6x86; AMD K5, K6.
Et ce n'est s�rement pas termin�: de nouveaux mod�les apparaissent
continuellement, et cette liste m�me sera rapidement d�pass�e,
sans parler du code ``optimis�'' qui aura �t� �crit pour l'un
quelconque des processeurs ci-dessus.
- le code peut �galement ne pas �tre portable entre diff�rents
syst�mes d'exploitation sur la m�me architecture,
par manque d'outils adapt�s (GAS semble fonctionner sur toutes
les plates-formes; NASM semble fonctionner ou �tre facilement adaptable
sur toutes les plates-formes compatibles Intel);
- un temps incroyable de programmation sera perdu sur de menus d�tails,
plut�t que d'�tre efficacement utilis� pour la conception et le
choix des algorithmes utilis�s, alors que ces derniers sont connus
pour �tre la source de la majeure partie des gains en vitesse d'un programme.
Par exemple, un grand temps peut �tre pass� � grapiller quelques cycles en
�crivant des routines rapides de manipulation de cha�nes ou de listes,
alors qu'un remplacement de la structure de donn�es � un haut niveau,
par des arbres �quilibr�s et/ou des tables de hachage permettraient
imm�diatement un grand gain en vitesse, et une parall�lisation ais�e,
de fa�on portable permettant un entretien facile.
- une petite modification dans la conception algorithmique d'un programme
an�antit la validit� du code assembleur si patiemment �labor�,
r�duisant les d�veloppeurs au dilemne de sacrifier le fruit de leur labeur,
ou de s'encha�ner � une conception algorithmique obsol�te.
- pour des programmes qui fait des choses non point trop �loign�es
de ce que font les benchmarks standards,
les compilateurs/optimiseurs commerciaux produisent du code
plus rapide que le code assembleur �crit � la main
(c'est moins vrai sur les architectures x86 que sur les architectures RISC,
et sans doute moins vrai encore pour les compilateurs librement disponible.
Toujours est-il que pour du code C typique, GCC est plus qu'honorable).
- Quoi qu'il en soit, ains le dit le saige John Levine,
mod�rateur de comp.compilers, "les compilateurs rendent ais�e
l'utilisation de structures de donn�es complexes;
ils ne s'arr�tent pas, morts d'ennui, � mi-chemin du travail,
et produisent du code de qualit� tout � fait satisfaisante".
Ils permettent �galement de propager correctement les transformations
du code � travers l'ensemble du programme, aussi h�naurme soit-il,
et peuvent optimiser le code par-del� les fronti�res entre proc�dures
ou entre modules.
Affirmation
En pesant le pour et le contre, on peut conclure
que si l'assembleur est parfois n�cessaire,
et peut m�me �tre utile dans certains cas o� il ne l'est pas,
il vaut mieux:
- minimiser l'utilisation de code �crit en assembleur;
- encapsuler ce code dans des interfaces bien d�finies;
- engendrer automatiquement le code assembleur
� partir de motifs �crits dans un langage plus de haut niveau que l'assembleur
(par exemple, des macros contenant de l'assembleur en-ligne, avec GCC);
- utiliser des outils automatiques pour transformer ces programmes
en code assembleur;
- faire en sorte que le code soit optimis�, si possible;
- utiliser toutes les techniques pr�c�dentes � la fois,
c'est-�-dire �crire ou �tendre la passe d'optimisation d'un compilateur.
M�me dans les cas o� l'assembleur est n�cessaire
(par exemple lors de d�veloppement d'un syst�me d'exploitation),
ce n'est qu'� petite dose, et sans infirmer les principes ci-dessus.
Consultez � ce sujet les sources du noyau de Linux:
vous verrez qu'il s'y trouve juste le peu qu'il faut d'assembleur,
ce qui permet d'avoir un syst�me d'exploitation rapide, fiable,
portable et d'entretien facile.
M�me un jeu tr�s c�l�bre comme DOOM a �t� en sa plus grande partie �crit en C,
avec une toute petite routine d'affichage en assembleur pour acc�l�rer un peu.
M�thode g�n�rale pour obtenir du code efficace
Comme le dit Charles Fiterman dans comp.compilers � propos
de la diff�rence entre code �crit par l'homme ou la machine,
``L'homme devrait toujours gagner, et voici pourquoi:
- Premi�rement, l'homme �crit tout dans un langage de haut nivrau.
- Deuxi�mement, il mesure les temps d'�x�cution (profiling)
pour d�terminer les endroits o� le programme passe la majeure partie du temps.
- Troisi�mement, il demande au compilateur d'engendrer le code assembleur
produit pour ces petites sections de code.
- Enfin, il effectue � la main modifications et r�glages,
� la recherche des petites am�liorations possibles par rapport au
code engendr� par la machine.
L'homme gagne parce qu'il peut utiliser la machine.''Langages avec des compilateurs optimisateurs
Des langages comme ObjectiveCAML, SML, CommonLISP, Scheme,
ADA, Pascal, C, C++, parmi tant d'autres,
ont tous des compilateurs optimiseurs librement disponibles,
qui optimiseront le gros de vos programmes,
et produiront souvent du code meilleur que de l'assembleur fait-main,
m�me pour des boucles serr�es,
tout en vous permettant de vous concentrer sur des d�tails haut niveau,
et sans vous interdire de gagner par la m�thode pr�c�dente
quelques pourcents de performance suppl�mentaire,
une fois la phase de conception g�n�rale termin�e.
Bien s�r, il existe �galement des compilateurs optimiseurs commerciaux
pour la plupart de ces langages.
Certains langages ont des compilateurs qui produisent du code C
qui peut ensuite �tre optimis� par un compilateur C.
C'est le cas des langages LISP, Scheme, Perl, ainsi que de nombreux autres.
La vitesse des programmes obtenus est toute � fait satisfaisante.
Proc�dure g�n�rale � suivre pour acc�lerer votre code
Pour acc�l�rer votre code, vous ne devriez traiter que
les portions d'un programme qu'un outil de mesure de temps d'�x�cution
(profiler) aura identifi� comme �tant un goulot d'�tranglement
pour la performance de votre programme.
Ainsi, si vous identifiez une partie du code comme �tant trop lente,
vous devriez
- d'abord essayer d'utiliser un meilleur algorithme;
- essayer de la compiler au lieu de l'interpr�ter;
- essayer d'activer les bonnes options d'optimisation
de votre compilateur;
- donner au compilateur des indices d'optimisation
(d�clarations de typage en LISP; utilisation des extensions GNU avec GCC;
la plupart des compilos fourmillent d'options);
- enfin de compte seulement, se mettre � l'assembleur si n�cessaire.
Enfin, avant d'en venir � cette derni�re option,
vous devriez inspecter le code g�n�r�
pour v�rifier que le probl�me vient effectivement
d'une mauvaise g�n�ration de code,
car il se peut fort bien que ce ne soit pas le cas:
le code produit par le compilateur pourrait �tre meilleur
que celui que vous auriez �crit, en particulier sur les architectures
modernes � pipelines multiples!
Il se peut que les portions les plus lentes de votre programme
le soit pour des raisons intrins�ques.
Les plus gros probl�mes sur les architectures modernes � processeur rapide
sont dues aux d�lais introduits par les acc�s m�moires, manqu�s des caches
et TLB, fautes de page;
l'optimisation des registres devient vaine,
et il vaut mieux repenser les structures de donn�es et l'encha�nement
des routines pour obtenir une meilleur localit� des acc�s m�moire.
Il est possible qu'une approche compl�tement diff�rente du probl�me
soit alors utile.
Inspection du code produit par le compilateur
Il existe de nombreuses raisons pour vouloir regarder le code assembleur
produit par le compilateur. Voici ce que vous pourrez faire avec ce code:
- v�rifier si le code produit peut ou non �tre am�liorer avec
du code assembleur �crit � la main
(ou par un r�glage diff�rent des options du compilateur);
- quand c'est le cas, commencer � partir de code automatiquement engendr�
et le modifier plut�t que de repartir de z�ro;
- plus g�n�ralement, utilisez le code produit comme
des scions � greffer, ce qui � tout le moins vous laisse permet
d'avoir gratuitement tout le code d'interfa�age avec le monde ext�rieur.
- rep�rer des bogues �ventuels dus au compilateur lui-m�me
(esp�rons-le tr�s rare, quitte � se restreindre � des versions
``stables'' du compilo).
La mani�re standard d'obtenir le code assembleur g�n�r� est d'appeller
le compilateur avec l'option -S
.
Cela fonctionne avec la plupart des compilateur Unix y compris
le compilateur GNU C (GCC); mais � vous de voir dans votre cas.
Pour ce qui est de GCC, il produira un code un peu plus compr�hensible
avec l'option -fverbose-asm
. Bien sur, si vous souhaitez obtenir
du code assembleur optimis�, n'oubliez pas d'ajouter les options et indices
d'optimisation appropri�es!
Page suivantePage pr�c�denteTable des mati�resHosting by: Hurra Communications GmbH
Generated: 2007-01-26 18:01:15