<strong>Algorithmes</strong> <strong>de</strong> <strong>la</strong> <strong>morphologie</strong> <strong>mathématique</strong> <strong>pour</strong> les architectures orientées fluxJaromír BRAMBORCe skeleton algorithmique est important car il nous permet, par <strong>la</strong> suite, <strong>de</strong> définir facilement l’algorithmecomplet <strong>pour</strong> les quatre opérations en les distinguant par un seul paramètre.6.3.4 Algorithme complet <strong>pour</strong> les transpositions et les rotations par SIMDUne fois expliqué ce qui se passe à l’intérieur d’un macro bloc, nous allons détailler le processus <strong>pour</strong>les transpositions et les rotations <strong>de</strong>s arrays. Pour ce<strong>la</strong>, nous allons revenir à l’algorithme 6.2, présentéprécé<strong>de</strong>mment sur <strong>la</strong> page 132, qui décrivait le skeleton algorithmique <strong>pour</strong> les transpositions/rotationspar macro blocs en travail<strong>la</strong>nt élément par élément. Il va nous servir comme modèle <strong>pour</strong> <strong>la</strong> constructiond’un nouvel algorithme.Ce nouvel algorithme, que nous présentons ici comme l’algorithme 6.6, va utiliser <strong>pour</strong> son travaill’approche SIMD. Ainsi, l’accès aux données sera effectué en utilisant les types <strong>de</strong>s vecteurs paquetés.Ce qui signifie que cet algorithme va percevoir l’array d’entrée comme un array dont les éléments sontdu type <strong>de</strong>s vecteurs paquetés PVec. Par <strong>la</strong> suite, il découpera cet array en macro blocs et il effectueral’opération choisie localement à l’intérieur <strong>de</strong> chacun <strong>de</strong>s macro blocs en utilisant, bien sûr, les algorithmesSIMD décrits précé<strong>de</strong>mment. Puis il effectuera <strong>la</strong> même opération globalement avec les macroblocs en utilisant l’algorithme <strong>de</strong> base issue <strong>de</strong> <strong>la</strong> définition <strong>de</strong> cette opération.Algorithme 6.6 : trRot2DMBSIMD, algorithme complet <strong>de</strong> <strong>la</strong> transposition et rotation d’un array2D utilisant l’approche macro bloc et les fonctionnalités SIMD1 trRot2DMBSIMD :: [Char] → [Char] → I → Ar ( I , I ) α → Ar ( I , I ) α2 trRot2DMBSIMD how axe mbsize ar =3 (mkAr2DFromAr2DPVec axe)4 ◦ arrayFromMxNBlocs5 ◦ fg6 ◦ ( listArray ( (1,1) , (m,n)) )7 ◦ (map ( listArray ( (1,1) , (1, mbsize ) ) ) )8 ◦ (map fl )9 ◦ (map elems)10 ◦ elems11 ◦ (arrayToMxNBlocs m n )12 ◦ (mkAr2DPVec axe mbsize )13 $ ar14 where15 (p,q) = dimsAr2D ar ; (m,n) = ( (div p mbsize ) , (div q mbsize ) )16 fg = trRot2D how17 fl = trRot2DNxPVecNbf howLes paramètres <strong>de</strong> cet algorithme sont les suivants : how désigne le type d’opération à effectuer etpeut avoir les valeurs ”T D” <strong>pour</strong> <strong>la</strong> transposition par diagonale, ”TA” <strong>pour</strong> <strong>la</strong> transposition par l’antidiagonale,”R + ” <strong>pour</strong> <strong>la</strong> rotation <strong>de</strong> + π 2 et ”R − ” <strong>pour</strong> <strong>la</strong> rotation <strong>de</strong> − π 2. Le paramètre axe désigne lesens <strong>de</strong> vectorisation et peut avoir les valeurs ”Fst” <strong>pour</strong> le premier axe et ”Snd” <strong>pour</strong> le <strong>de</strong>uxième. Leparamètre mbsize désigne <strong>la</strong> taille <strong>de</strong>s macro blocs et ar désigne l’array d’entrée.Expliquons alors, pas à pas, <strong>la</strong> construction exacte <strong>de</strong> cet algorithme. La lecture commence sur <strong>la</strong>ligne 13 et on va progresser vers les lignes précé<strong>de</strong>ntes. La première étape est constituée du passaged’un array ar (ligne 13) avec les éléments du type α à un array avec les éléments paquetés PVec I α.Pour effectuer ce<strong>la</strong>, nous allons utiliser <strong>la</strong> fonction mkAr2DPVec (ligne 12) avec <strong>la</strong> bonne clé, soit ”Fst”,soit ”Snd”. Le choix du sens <strong>de</strong> <strong>la</strong> vectorisation est prédéfini par l’axe <strong>de</strong> stockage <strong>de</strong>s données dans <strong>la</strong>mémoire. Ensuite, en utilisant <strong>la</strong> fonction elems, nous extrayons tous les éléments <strong>de</strong> cet array vectoriséet nous les p<strong>la</strong>çons dans un stream (ligne 10). Pour pouvoir appliquer les fonctions macro blocs SIMDcomme décrites précé<strong>de</strong>mment, nous <strong>de</strong>vons passer, <strong>pour</strong> chacun <strong>de</strong>s macro blocs, à son expression en140
Jaromír BRAMBOR6.4. NOTES SUR L’IMPLÉMENTATION, RÉSULTATS EXPÉRIMENTAUXtant que stream. C’est effectué par le mapping (map elems) sur <strong>la</strong> ligne 9. Nous obtenons ainsi un stream<strong>de</strong>s streams, formellement décrit comme :[ [ PVec I α] ]Sur <strong>la</strong> ligne 8, nous appliquons <strong>la</strong> fonction locale par l’expression (map fl) à chacun <strong>de</strong>s macro blocsexprimés en stream. Ensuite, sur <strong>la</strong> ligne 7, nous passons à l’expression <strong>de</strong>s macro blocs en tant quearray 2D et nous reconstituons à nouveau un array dont les éléments sont les macro blocs sur <strong>la</strong> ligne 6.L’opération globale, fg, est appliquée sur cet array reconstitué (sur <strong>la</strong> ligne 5) achevant ainsi notre opération.Ce qui reste à faire c’est <strong>de</strong> passer à partir d’un array <strong>de</strong>s macro blocs à un array dont les élémentssont les vecteurs paquetés (sur <strong>la</strong> ligne 4) <strong>pour</strong>, à <strong>la</strong> fin, appliquer une opération inverse à <strong>la</strong> vectorisationqui donne comme résultat un array du même type que celui d’entrée <strong>de</strong> <strong>la</strong> fonction, du type Ar (I, I) α.Ainsi, nous avons obtenu l’opération souhaitée en utilisant l’approche macro bloc et en employantles opérations SIMD sur les macro blocs.6.4 Notes sur l’implémentation, résultats expérimentauxIl y a, en effet, autant <strong>de</strong> façons d’implémenter les algorithmes décrits dans ce chapitre qu’il y ad’architectures, <strong>de</strong> programmeurs <strong>pour</strong> l’écriture et <strong>de</strong> compi<strong>la</strong>teurs <strong>pour</strong> <strong>la</strong> compi<strong>la</strong>tion du co<strong>de</strong>.Les implémentations sur les architectures parallèles peuvent être facilement déduites <strong>de</strong> nos <strong>de</strong>scriptionsformelles <strong>de</strong>s algorithmes présentés dans ce chapitre. Le parallélisme le plus simple, utilisabledans ces cas, est celui <strong>de</strong> <strong>la</strong> replication fonctionnelle représentée par le skeleton algorithmique farm,cf. 4.4.2.1, page 67. Pour l’employer, nous nous intéressons à toutes les parties <strong>de</strong> notre algorithme quiutilisent <strong>la</strong> fonction map <strong>de</strong> l’application d’une fonction sur tous les éléments d’un stream. Toutes cesparties peuvent être récrites en utilisant le skeleton algorithmique farm à <strong>la</strong> p<strong>la</strong>ce <strong>de</strong> <strong>la</strong> fonction map.Ainsi, nous changeons complètement <strong>la</strong> manière <strong>de</strong> travailler d’une telle partie <strong>de</strong> notre algorithme etnous passons <strong>de</strong> l’exécution en séquence, exprimée par map, à l’exécution en parallèle, exprimée parfarm. Le choix exact dépend <strong>de</strong> nos exigences et <strong>de</strong> nos possibilités matérielles lors <strong>de</strong> l’implémentation.De plus, ces algorithmes entrent dans <strong>la</strong> logique du paradigme Divi<strong>de</strong> and Conquer, présenté parle skeleton algorithmique dc, cf. 4.4.2.2, page 67. La division d’un problème global à <strong>de</strong>s problèmesplus petits et locaux est propre aux algorithmes <strong>de</strong> ce chapitre travail<strong>la</strong>nt sur les macro blocs. Il seraitégalement envisageable d’exprimer ces algorithmes en termes du Divi<strong>de</strong> and conquer et en utilisant leskeleton algorithmique dc car <strong>la</strong> manière <strong>de</strong> travailler <strong>de</strong> ce skeleton est i<strong>de</strong>ntique à ce que nous faisonspar le découpage d’un array sur les macro blocs, l’application <strong>de</strong> <strong>la</strong> fonction locale et son recol<strong>la</strong>geeffectué à <strong>la</strong> fin.Concernant l’implémentation SIMD, <strong>la</strong> première chose que nous <strong>de</strong>vrions souligner est <strong>la</strong> <strong>de</strong>man<strong>de</strong>d’alignement <strong>de</strong>s données <strong>de</strong> l’image dans <strong>la</strong> mémoire aux bornes qui sont les multiples <strong>de</strong> <strong>la</strong> taille Ndu registre multimédia. Si l’image a <strong>de</strong>s dimensions qui sont <strong>de</strong>s multiples <strong>de</strong> N et si, <strong>de</strong> plus, ellesest alignée aux blocs <strong>de</strong> mémoire par N, notre implémentation se révèle simple. Dans le cas contraire,nous <strong>de</strong>vrions faire face aux effets particuliers du travail avec les données non-alignées. L’accès auxdonnées non-alignées est possible sur les architectures multimédia via les instructions spécialisées <strong>pour</strong>un accès non-aligné mais le coût d’un tel accès est, en général, supérieur à un accès alignée. C’est duau fait que <strong>pour</strong> <strong>la</strong> lecture d’une donnée non-alignée vers un registre, l’architecture utilise <strong>de</strong>ux lecturesconsécutives <strong>de</strong>s zones alignées couvrant les données voulues suivies par leur extraction vers le registre.Ces instructions peuvent avoir un coût re<strong>la</strong>tivement faible, mesuré dans les cycles d’horloge, commec’est le cas <strong>pour</strong> les instructions Intel SSE3. La figure 6.7 illustre un exemple <strong>de</strong> <strong>la</strong> transposition d’uneimage alignée mais dont les dimensions ne sont pas un multiple <strong>de</strong> <strong>la</strong> taille du registre multimédia.Nous présentons également <strong>de</strong>ux exemples du co<strong>de</strong> en <strong>la</strong>ngage C implémentant <strong>la</strong> transposition d’unmacro bloc par <strong>la</strong> diagonale.Le premier, présenté sur <strong>la</strong> fig. 6.6, est un co<strong>de</strong> qui provient du MorphoMedia, un outil logiciel quenous avons développé dans le cadre <strong>de</strong> cette thèse. Il s’agit d’un co<strong>de</strong> programmé comme les directivesdu préprocesseur (cf. #<strong>de</strong>fine) qui utilise les fonctions commençant par mrph_asm_ qui nous141