MMX avec Delphi 6 / Kylix
Date de publication :
03/11/2002
Date de mise a jour :
03/11/2002
Par
Eric SIBERT (Site)
Les instructions MMX (MultiMedia eXtended) sont des instructions sensées faciliter les traitements multimédia. Ces instructions sont apparues pour la première fois sur les Pentium MMX et sont présentes depuis sur toutes la gamme des microprocesseurs Intel à l'exception du Pentium Pro. Ces instructions sont aussi disponibles sur les produits concurrents.
En quoi consistent ces instructions ?
Elles permettent de traiter plusieurs calculs sur les nombres entiers simultanément au lieu de un à la fois avec les instructions classiques. Ceci peut être particulièrement intéressant lorsque vous faites du traitement d'image et que vous devez effectuer les mêmes opérations sur l'ensemble des points de l'image.
Comment les exploiter ?
C'est là que commencent les difficultés. Lorsque vous compilez un programme, Delphi prend votre code Pascal et le transforme en instructions pour le microprocesseur (vous pouvez voir le résultat dans la fenêtre CPU). Mais il n'utilise jamais les instructions MMX, d'une part pour des raisons de compatibilité avec la plate-forme i386, d'autre part parce qu'en Pascal, nous ne codons des opérations que de façons séquentielle alors que les instructions MMX effectuent un traitement parallèle.
La seule solution pour exploiter les possibilités MMX est de "court-circuiter" le compilateur et d'indiquer directement les instructions que nous voulons utiliser. En d'autres termes, travailler en ASSEMBLEUR. En assembleur, nous écrivons les instructions microprocesseurs à l'aide de séquences mnémotechniques qui sont directement traduites en binaire. Le Pascal Objet dispose de BASM (Built-in ASseMbler) qui permet d'inclure de l'assembleur dans le code pascal. Sauf que jusqu'à Delphi 5 inclus, BASM ne connaissait pas les mnémotechniques correspondants aux instructions MMX. Il fallait réaliser soi même le codage en binaire. Maintenant Delphi 6 et Kylix prennent en charge les instructions MMX. Il n'y a donc plus qu'à les saisir en assembleur et tout va bien.
Il reste à connaître les instructions utilisables. La première étape obligatoire est de récupérer la liste des instructions chez Intel sous le nom de Instruction Set Refernce Manual. Vous récupérez une petite documentation au format pdf de 6,7 Mo et d'un millier de pages. Pour reconnaître les instructions MMX, prenez plutôt celles qui commencent par un P comme Packed, qui travaillent sur des paquets de données.
Allons du côté de Packed Add:
Vous avez trois instructions différentes PADDB/PADDW/PADDD. Elles permettent d'additionner deux séries, dans l'ordre, soit de 8 bytes (PADDByte), soit de 4 words (PADDWord), soit de 2 doubleword (PADDDoubleword). Nous remarquons au passage que ces instructions utilisent des registres spéciaux, les registres MMX. Ces registres, qui sont au nombre de 8 (de mm0 à mm7) ont une dimension de 64 bits. En fait, ce sont les registres ST pour les opérations sur les nombres à virgule flottante et on ne peut pas utiliser simultanément les opérations MMX et celles sur les nombres à virgule flottante.
Passons à la pratique. J'ai voulu essayer l'addition simultanée de 4 entiers 16 bits. Voici le code :
type
T16bit = array[0..3] of word;
procedure AdditionMMX(A,B : T16bit; var resultat : T16bit); register;
asm
movq mm0,[EAX]
paddw mm0,[EDX]
movq [ECX],mm0
end;
Et voilà, trois instructions pour quatre additions, transfert des données compris. Et ça marche.
Pour compliquer, j'ai voulu programmer la multiplication. Il y a un petit problème avec la dimension des paramètres. Je décide de réaliser la multiplication de bytes pour obtenir des words.
type
T8bit = array[0..3] of byte;
T16bit = array[0..3] of word;
procedure MultiplicationMMX(A,B : T8bit; var resultat : T16bit); register;
asm
pxor mm0,mm0
movd mm1,EAX
PUNPCKLBW mm1,mm0
movd mm2,EDX
PUNPCKLBW mm2,mm0
PMULLW mm1,mm2
movq [ECX],mm1
end;
Nous voyons en particulier l'étape d'extension des données 8 bits en 16 bits.
Le code source de l'ensemble avec les mêmes opérations avec et sans MMX est ici (3 ko). Vous remarquerez un petit détail :
asm
EMMS
end;
Comme signalé plus haut, il y a incompatibilité en les instructions MMX et celles sur virgule flottante. Il faut donc désactiver l'unité MMX avant d'effectuer une opération FP, en l'occurrence l'affichage du temps écoulé. Dans l'autre sens (FP -> MMX), ce n'est pas nécessaire, le compilateur mettant d'office un FWAIT en sorti des opérations sur virgule flottante.
Point de vue performances, le recours aux instructions MMX permet de multiplier la vitesse d'un facteur compris entre 4 et 5 aussi bien pour les additions que pour les multiplications. Donc, les instructions MMX sont efficaces. Reste à les utiliser en conditions réelles :))) Ce qui est fait dans mon nouvel article.
Sinon, sachez que Delphi 6 et Kylix prennent aussi en charge d'autres jeux d'instructions SIMD (single intruction multiple datas = une seule intructions, plusieurs données). Il en va ainsi des instructions SSE et SSE2 (calcul simultané sur plusieurs réels) apparues avec les Pentium III et 4 chez Intel et reprises pour les premières par l'Athlon 4 chez AMD. On retrouve aussi les instructions 3D Now! (à partir du K6-2) et Extended 3D Now! (Athlon) de chez AMD (même principe que SSE) et quelques autres détails. Un article présente l'utilisation de ces instructions.
Pour terminer, sachez que les instructions MMX ont été étendues aux registres SSE avec le jeu d'instruction SSE2. Comme les regsitres correspondants sont deux fois plus grands, vous pouvez traiter deux fois plus de données avec les mêmes instructions.
Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur.
La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.
|