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 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:36]
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_compute_bb.png?​500 |}} 
 + 
 +Pour 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  
  
  
developpement/activites/qualification/30ans1code.txt · Dernière modification: 2019/12/17 15:34 par equemene