Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
Prochaine révision Les deux révisions suivantes
developpement:activites:qualification:30ans1code [2019/11/27 12:20]
equemene [Parallélisation avec OpenCL]
developpement:activites:qualification:30ans1code [2019/11/27 17:58]
equemene [Parallélisation avec OpenCL]
Ligne 288: Ligne 288:
 Plutôt que de coder en C ou en C++, beaucoup trop difficile à maintenir, nous choisissons l'​option Python. En effet, [[https://​documen.tician.de/​pyopencl/​|PyOpenCL]] existe depuis plus de 10 ans et permet de simplifier dramatiquement l'​exploitation de OpenCL. De plus, il existe également le pendant CUDA avec [[https://​documen.tician.de/​pycuda/​|PyCUDA]]. Profitons en pour remercier Andreas Kloeckner pour ces superbes outils ! Plutôt que de coder en C ou en C++, beaucoup trop difficile à maintenir, nous choisissons l'​option Python. En effet, [[https://​documen.tician.de/​pyopencl/​|PyOpenCL]] existe depuis plus de 10 ans et permet de simplifier dramatiquement l'​exploitation de OpenCL. De plus, il existe également le pendant CUDA avec [[https://​documen.tician.de/​pycuda/​|PyCUDA]]. Profitons en pour remercier Andreas Kloeckner pour ces superbes outils !
  
-Sachant que, pour exploiter au mieux nos machines, il faut paralléliser au maximum, regardons comme distribuer nos tâches en OpenCL. La première, c'est le code sans la moindre parallélisation,​ ce sera **Original**. La seconde, ce sera d'​appliquer la même méthode qu'en OpenMP : ce sera **EachCircle** où chaque tâche aura à traiter un paramètre d'​impact,​ donc parallélisme équivalent à la moitié de la taille de l'​image. Le troisième, ce sera d'​exploiter du //​raytracing//​ brutal, où, pour chaque pixel, la trajectoire est recherchée : ce sera la méthode **EachPixel**. Les deux dernières méthodes seront des méthodes hybrides : la première calculera toutes les trajectoires en parallèle, puis la seconde estimera en parallèle pour tous les secteurs de chaque cercle associé et chaque paramètre d'​impact la valeur de chaque pixel ; ce sera **TrajectoCircle**. La dernière exploitera les trajectoires calculées dans une première phase dans une seconde en associant directement un trajectoire à un pixel donné. ​+Sachant que, pour exploiter au mieux nos machines, il faut paralléliser au maximum, regardons comme distribuer nos tâches en OpenCL. La première, c'est le code sans la moindre parallélisation,​ ce sera **Original**. La seconde, ce sera d'​appliquer la même méthode qu'en OpenMP : ce sera **EachCircle** où chaque tâche aura à traiter un paramètre d'​impact,​ donc parallélisme équivalent à la moitié de la taille de l'​image. Le troisième, ce sera d'​exploiter du //​raytracing//​ brutal, où, pour chaque pixel, la trajectoire est recherchée : ce sera la méthode **EachPixel**. Les deux dernières méthodes seront des méthodes hybrides : la première calculera toutes les trajectoires en parallèle, puis la seconde estimera en parallèle pour tous les secteurs de chaque cercle associé et chaque paramètre d'​impact la valeur de chaque pixel ; ce sera **TrajectoCircle**. La dernière exploitera les trajectoires calculées dans une première phase dans une seconde en associant directement un trajectoire à un pixel donné.
  
-Ainsi, nous pouvons résumer, pour une image de taille NxN, les parallélisations que nous allons appliquer ​pour chaque méthode :+Ainsi, nous pouvons résumer, pour une image de taille NxN, le nombre de tâches exécutables en parallèles ​pour chaque méthode, le "​régime de parallélisme"​ en somme :
   * **Original** : 1   * **Original** : 1
   * **EachCircle** : N/2   * **EachCircle** : N/2
Ligne 297: Ligne 297:
   * **TrajectoPixel** : N/2 puis NxN   * **TrajectoPixel** : N/2 puis NxN
  
-Chacune des méthodes (à l'​exception de **Original**) sera donc étudiée et comparée aux autres pour des images allant de 64x64 à 16384x16384. Dix lancements ​successives ​pour chaque méthode permettront ensuite de disposer d'une statistique pertinente.+Chacune des méthodes (à l'​exception de **Original**) sera donc étudiée et comparée aux autres pour des images allant de 64x64 à 16384x16384. Dix lancements ​successifs ​pour chaque méthode permettront ensuite de disposer d'une statistique pertinente. ​ 
 + 
 +Petit détail pour la métrologie : dans le cas du programme originel, le temps de calcul était estimé à partir de plusieurs //timers// : l'un en secondes indexé sur l'​horloge temps réel (''​time(NULL)''​),​ l'un en microsecondes sur la même horloge (''​getttimeofday()''​),​ le dernier exploitant ''​cputime()''​. Avec OpenCL, le principe est d'​exploiter un "​périphérique",​ même si ce dernier est en fait le processeur. Les pesaces mémoire exploités doivent être échangés entre l'​hôte et le périphérique,​ et cela prend du temps ! Ainsi, il faut séparer deux durées : celle du calcul proprement dit (ce sera **Compute**),​ et celle du "temps écoulé",​ ajoutant le temps de calcul au temps de transfert de la mémoire du périphérique à l'​hôte (ce sera le **Elapsed**).  
 + 
 +=== Premier lancement en OpenCL === 
 + 
 +Illustrons cela sur le processeur ''​TOP 1''​ de notre exécution séquentielle,​ sans parallélisation : sur le ThreadRipper 1950X. ​ Et comparons donc les temps de calcul ou écoulé pour les 7 méthodes pour une grosse image 16384x16384 : **Serial** sans parallélisation,​ **OpenMP** et les 5 méthodes exploitant OpenCL. 
 + 
 +{{ :​developpement:​activites:​qualification:​tr1950x_7methods_elapsed.png?​500 |}} 
 + 
 +Sur cette illustration,​ //less is better//. Nous constatons que la méthode **OpenCL EachPixel** est fortement inefficace : le calcul élémentaire de la trajectoire sur chaque pixel est bien rédhibitoire. De plus, la méthode **OpenCL Original** est moins efficace qu'​avec le programme séquentiel **Serial**. Les méthodes hybrides **OpenCL TrajectoPixel** et **OpenCL TrajectoCircle** sont plutôt proches. Les méthodes **OpenMP** et **OpenCL EachCircle**,​ comparables en approche de programmation,​ semblent tourner à l'​avantage de cette dernière.  
 + 
 +De manière à en avoir le coeur net, calculons la performance,​ le //​PixHertz//​ de chaque méthode en divisant le nombre de pixels de l'​image par les deux durées **Compute** et **Elapsed**. 
 + 
 +{{ :​developpement:​activites:​qualification:​tr1950x_7methods_pixhertz.png?​500 |}} 
 + 
 +Nous confirmons que la méthode **OpenCL EachPixel** est bien la plus mauvaise, que **OpenCL Original** est un peu moins bon que **Serial**. Sur la comparaison entre **OpenMP** et **OpenCL EachCircle**,​ nous remarquons que OpenCL l'​emporte de presque un facteur 2, mais uniquement en calcul. En temps écoulé, **EachCircle** reste comparable à **OpenMP**... En effet, le temps de transfert des plusieurs GB qu'​occupent les deux images de plus d'1/4 de milliard de pixels prend autour d'une seconde, à peine supérieur au temps de calcul : une belle illustration que, en OpenCL, le temps de transfert entre hôte et périphérique "​compte"​ pour la performance du calcul. Nous sommes toutefois rassurés que notre effort de portage OpenCL nous permette, en calcul, d'​améliorer nos performances. 
 + 
 +=== Les performances sur tous les processeurs en OpenCL === 
 + 
 +Focalisons nous sur la capacité de calcul, donc le "​Compute Time" pour les simulations **Mono** ou **BB**. 
 + 
 +{{ :​developpement:​activites:​qualification:​cpu_compute_mono.png?​500 |}} 
 + 
 +Inutile de préciser que, pour les processeurs antérieurs à 2008, leurs performances sont imperceptibles. 
 + 
 +En Mono, nous retrouvons le facteur 2 de performances entre OpenCL et OpenMP pour le ThreadRipper. Mais pour les processeurs Intel récents, c'est encore meilleur ! Les derniers Skylake d'​Intel (W-2145 et Gold 5122) présentent des performances entre 4 et 5 fois meilleures qu'en OpenMP ! Etrangement,​ le Silver 4114, pourtant Skylake, ne gagne "​que"​ 70% mais le numéro 1, le système disposant de 28 coeurs à base de E5-2680v4, double ses performances. Tous les processeurs Intel gagnent un OpenCL, même l'​antique système à base de E5440 ne fonctionnant qu'​avec l'​implémentation OpenCL d'​AMD. 
 + 
 +En BB, le constat est plus nuancé. Pour le Threadripper,​ les performances OpenCL et OpenMP sont équivalentes et rétrograde de la seconde à la cinquième place. Les processeurs Intel s'en sortent plutôt mieux au point que le dernier Skylake W-2145 à 8 coeurs détrône le système à E5-2680v4 à 28 coeurs ! Pour les processeurs anciens X5550 et E5440, l'​OpenMP fait bien mieux. 
 + 
 +Regardons ces performances maintenant en intégrant les temps de transferts 
 + 
 +{{ :​developpement:​activites:​qualification:​cpu_elapsed_mono.png?​500 |}} 
 + 
 +En Mono, le Threadripper se retrouve au même niveau en OpenCL qu'en OpenMP. Seul le dernier Skylake Intel W-2145 gagne un facteur 2.5x entre OpenCL et OpenMP. Les autres gagnent timidement de 80% à quelques dizaines de %. Le Silver déçoit en étant moins performant en OpenCL qu'en OpenMP. 
 + 
 +{{ :​developpement:​activites:​qualification:​cpu_elapsed_bb.png?​500 |}} 
 + 
 +En BB, nous réalisons quasiment les mêmes constats : Threadripper de second à cinquième, meilleur en OpenMP que OpenCL ; les Skylake bien meilleurs d'un facteur presque 3 en OpenCL ; le Silver et les deux Broadwell avec quelques % de mieux. Le système E5-2680v4  
 + 
 +Quelles conclusions tirer de ces comparaisons ? 
 + 
 +Tout d'​abord qu'​Intel a très bien travaillé son OpenCL pour ses propres processeurs... Sans les Skylake, essentiellement le Gold et le W-2145, les gains seraient substantiels pour la partie **Compute** mais fondent dès que les temps de transfert sont intégrés. Puis que le Threadripper "​résiste",​ mais pas pour tous les usages : un test trop sommaire peut donc rapidement induire en erreur quant à la performance d'un processeur. Ensuite que les processeurs anciens, dès lors que l'​implémentation Intel est exploitable (donc après la génération Nehalem), l'​OpenCL reste une bonne option. Enfin que, avec OpenCL, notre ratio de performances de calcul frise les 100 millions en BB et 35 millions en Mono. En intégrant les transferts, ces ratios tombent à 81 millions en BB et 17 millions en Mono : 8 ordres de grandeurs séparent des processeurs séparés de 30 ans. 
 + 
 +=== Intégration des accélérateurs en OpenCL === 
 + 
  
  
developpement/activites/qualification/30ans1code.txt · Dernière modification: 2019/12/17 15:34 par equemene