• Aucun résultat trouvé

3.2.1 Principes et modèle de programmation

Le SIMD ou Single Instruction Multiple Data est une technique qui permet d’ex- ploiter le parallélisme de donnée efficacement en amortissant le hardware de contrôle indépendant des données sur plusieurs unités de calcul (processing elements).

Plusieurs données sont regroupées et traitées de façon synchronisée (lock-step) en parallèle par une seule instruction.

Cette simplification hardware restreint ces éléments de traitement à avoir un flux de contrôle uniforme.

Un branchement où chaque élément de traitement branche vers une instruction différente provoque une divergence communément appelée Branch divergence dans le hardware SIMD. Ceci est généralement traité par une sérialisation de l’exécution ce qui résulte en une utilisation inefficace du hardware SIMD.

Une architecture SIMD consiste donc en un ensemble d’unités de calcul coor- données par une unique unité de contrôle assurant un flux commun d’instructions. Chaque unité de calcul opère sur les données qui lui sont attribuées.

Ce type de parallélisme est dit parallélisme de données car la même instruction est exécutée sur des données différentes.

Nous pouvons voir sur la figure 3.5, que l’addition de deux tableaux de données A et B est effectuée à l’aide d’une unité SIMD de largeur 4. Elle exécute ainsi l’ins- truction d’addition simultanément sur quatre valeurs différentes des vecteur A et B, ensuite elle stocke le résultat dans le vecteur C.

FIGURE3.5 – Addition vectorielle de deux vecteurs A + B en SIMD

Le bénéfice d’une telle architecture n’est plus à démontrer, notamment dans les applications graphiques où les calculs sur les données sont massivement parallèles. Elles sont aussi bien adaptées pour des implémentations d’algorithmes de traitement de signal où les formules mathématiques sont souvent exprimées sous forme de vec- teurs et de matrices.

3.2.2 Mise en œuvre (intrinsics)

Les instructions SIMD sont notamment composées des jeux d’instructions sui- vants :

— Sur processeur x86 : MMX, 3DNow !, SSE, SSE2, SSE3, SSSE3, SSE4, SSE4.1, SSE4.2, AVX, AVX2 et AVX512.

— Sur processeur PowerPC : AltiVec.

— Sur processeur ARM : VFP, VFPv2, VFPv3lite, VFPv3, NEON, VFPv4. — Sur processeur SPARC : VIS et VIS2.

— Sur processeur MIPS : MDMX et MIPS-3D.

Pour cette thèse, nous nous focaliseront sur le jeux d’instruction x86 d’Intel et plus précisément l’AVX2, du fait qu’il est le plus avancé (largeur 256bits) et le plus complet à l’heure où nous rédigeons ce manuscrit.

l’AVX ou Advanced Vector Extensions est une extension du jeux d’instructions x86 pour les microprocesseurs Intel et AMD, elle a été proposée par Intel en mars 2008 et supportée en premier par Intel dans le processeur Sandy Bridge en 2011 (figure 3.6).

l’AVX permet d’exécuter 8 opérations flottantes en même temps à l’aide de re- gistres de 256bits.

Nous avons comparé les performances obtenues (figure 3.7) avec différentes gé- nérations d’instructions SIMD sur un programme FFT. Ce programme utilise la bi-

FIGURE3.6 – Évolution des unités SIMD chez Intel

FIGURE3.7 – Performances FFT obtenues sur CPU Intel Haswell en fonction du jeux d’ins-

tructions SIMD utilisé

bliothèque commerciale IPP d’Intel qui permet d’exécuter une panoplie d’algorithmes de traitement de signal dont la FFT.

Une remarque importante soulignée par la comparaison des performances est que l’augmentation de la largueur des unités SIMD a pour résultat un gain impor- tant des performances obtenues, par rapport aux autres améliorations d’architecture possibles (notamment l’évolution entre le SSE4.2 (128bits) et l’AVX (256bits)).

L’exploitation des unités SIMD se fait essentiellement par l’intermédiaire de trois méthodes :

— soit par compilation : c’est le compilateur qui se charge de vectoriser, néan- moins il n’existe pas encore de compilateur « magique » qui permette une vec-

torisation efficace des programmes.

— soit à l’aide d’intrinsics2: c’est un ensemble de fonctions en langage C qui re-

présentent une correspondance 1 à 1 avec les instructions SIMD du processeur. L’utilisation des intrinsics permet d’écrire du code vectoriel depuis un langage de haut niveau (langage C par exemple). On doit noter aussi que dès qu’on uti- lise les intrinsics, le compilateur n’optimise plus ces portions de code. Le pro- blème majeur de cette méthode est la non portabilité des performances, car si nous avons un code optimisé pour du SSE4.2 (largueur 128bits) et que nous voulons bénéficier des unités AVX, qui sont deux fois plus larges (256bits), nous devons réécrire le programme.

— soit par bibliothèque c’est-à-dire que l’application utilise des bibliothèques optimisées pour utiliser du SIMD comme le cas de la bibliothèque IPP.

La méthode efficace pour tirer profit de ces unités SIMD est l’utilisation des in-

trinsics C. Nous allons étudier dans cette thèse au chapitre 4 comment nous pouvons

tirer partie de ces unités dans un cas d’étude concret, à savoir celui du traitement Radar.

3.2.3 Permutations de valeurs

On a vu en section 2.1.4 que des opérations rapides de permutation de données sont d’un intérêt critique pour l’efficacité de cette partie du calcul de la FFT. Nous dé- taillons donc les capacités de l’architecture SIMD Intel Core sur cet aspect, qui seront utilisées en section 4.1.

Les processeur Intel Core de troisième et quatrième génération sont dotés d’unités SIMD AVX, ces dernières utilisent un jeux de registres de 256bits chacun. Ces registres sont au nombre de 16 et sont nommés YMM (YMM0-YMM15).

Les instructions de permutation sont fournies par le jeux d’instruction. Comme cité précédemment, nous les utilisons à travers des intrinsics C. Pour effecteur la per- mutation de la figure 3.8 nous devons utiliser l’instruction assembleur em vpermilps à l’aide de l’intrinsic suivante :

1 __m256 _mm256_permute_ps ( __m256 a , int imm8 ) ; // vpermilps

L’entier imm8 sert de valeur de contrôle pour l’instruction, dans notre cas il contient la valeur 114 qui correspond à 01110010 en binaire.

Chaque instruction de permutation a une latence et un débit différent, il faut donc bien prendre en compte cet aspect pour l’adaptation de notre application.

Nous allons ici être confronté à un problème spécifique particulier : la largeur des instructions vectorielles SIMD du processeur considéré sera de 16, alors que, sans doute pour des raisons historiques de legacy, les permutations définies ne seront que sur des vecteurs de taille 8 (moitié moins). Il nous faudra donc combiner des opéra- tions de cette taille, en optimisant leur durée, pour recomposer notre permutation de taille 16 désirée.

Nous mettrons en lumière en chapitre 4.1 une utilisation optimisée des instruc- tions de permutation afin de produire une FFT hautement performante.

FIGURE3.8 – Exemple de permutation SIMD en AVX

3.3

Modèle SIMT pour GPU