Depuis prêt de 40 ans, la parallélisation de l’exécution des codes est un must en terme d’algorithme et domaine quasi réservé au calculs scientifiques (ingénierie, recherche..)

Depuis 2 ans les machines bi-core ont fait leur apparition, et se généralisent (on parle déjà d’octo-processor sur les machines de bureau…) et la parallélisation des codes devient incontournable. Pourquoi me direz vous ? hé bien tout simplement pour ne pas friser le ridicule J

Le binaire que l’on produit depuis 20 ans sur Windows bénéficie de l’augmentation de puissance constant des processeurs, mais le mur de la chaleur, fait que la loi de more continue mais en exploitant la voie de la multiplication des coeus, plutôt que par l’augmentation de la fréquence et du nombre de transistors.

Cette première barrière physique (à 6 Ghz, nos processeurs ont une dissipation thermique exorbitante), fait que notre code va devenir de plus en plus « ridicule » : alors que notre super algo consommait 100% de CPU dans les années 2000, il n’en consomme plus que 50% sur un bi-core, 25% sur un quadri, 12,5 sur un Octo… Bref, point de salut sans parallélisation !!!

 

La difficulté de coder en parallèle vient de plusieurs constats :

-          On ne raisonne pas parallèle au moment du design, et il est souvent difficile de paralléliser ensuite sans erreur..

-          Il n’y a pas de sémantique liant les objets de synchro avec les thread…sauf dans la tête du développeur( j’entends par la qu’une simple erreur ou oubli n’est pas détectée par les compilateurs et générera, tôt ou tard,  un bug difficile a identifier

-          A ce jour il existe trop peu de librairies, simplifiant, le développement parallèle, il existe juste les primitives de thread et d’objet de synchro, même en .NET l’abstraction n’est pas suffisante pour généraliser le développement parallèle.

-         

Pour vous aider a immerger dans ces problématiques et ces méthodologies je vous recommande un ensemble de Webimar actuellement diffusé par Intel  ou vous retrouverez un webcast d’introduction par H Sutter très intéressant.

 

Un axe de travail d’abstraction de la parallélisation : et plusieurs voies de recherche

-          Encapsulation dans une sémantique abstraite des patterns Thread/synchro

o   Pattern de gestion des race condition, deadloack, reader/writer locks, c’est le cas d’OpenMP , TPL (), PLinq()  MPI Boost(/ ) MPI ()…

-          Exploitation hardware

o   C’est le cas du GPU, qui est parallèle « by design » et permet de paralléliser des calculs (cas des shader de directX, que l’on peut imaginer rendre disponible via des librairies simple d’emploi…) voir le projet CUDA de NVidia (voir aussi  un article en francais assez didactique) également GPGPU

 

 

Les solutions pour l’avenir (très proche !) on le sent passeront par des librairies apportant un bon niveau d’abstraction vs les thread et objets de synchronisation. Difficile en effet de demander à développeurs d’application d’exploiter les finesse de calcul d’un GPU.

Plusieurs équipes travaillent sur ces sujets (pas que chez Microsoft !) et s’inspire des pattern existant par exemple dans OpenMP (librairie existant depuis le début des année 60 !)et des notions de fork/join ou de variable Future. Herb Sutter a un ensemble de présentation et de billets sur son blog centrés sur ces thématiques (cf. son projet conccur) que je vous recommande chaudement ! (cf. son blog )

 

 

Ce qui arrive de manière très concrète :

Un support parallèle au requêtes LINQ :  c’est une approche quasiment transparente puisqu’il suffira de coder la requête ainsi :

IEnumerable<T> data = ...;

var q = data.Where(x => p(x)).Orderby(x => k(x)).Select(x => f(x));

foreach (var e in q) a(e);

devient :

IEnumerable<T> data = ...;
var q = data.AsParallel().Where(x => p(x)).Orderby(x => k(x)).Select(x => f(x));
foreach (var e in q) a(e);

 

Un support pour paralléliser le code .NET  de Microsoft Research travail (comme vous pouvez l’imaginer) sur ces concepts/problématique ; Ils ont mis au point un librairie (très prochainement en CTP) qui permettra de prendre du recul vs la mise en œuvre de thread dans nos code, ici aussi on retrouve les pattern OpenMP. Par exemple

 

for (int i = 0; i < 100; i++) { 
  a[i] = a[i]*a[i]; 
}

Deviendra :

 

Parallel.For(0, 100, delegate(int i) { 
  a[i] = a[i]*a[i]; 
});

 

 

Ce sujet passionnant est un véritable défis au monde du développement, l’exploitation de la performance d’une machine donnée, d’une grille ou d’un cluster de  calcul dépende de notre capacité à gérer efficacement des architecture multi cœur et/ou distribuée. A l’aube de la généralisation des machines multi-cœur, il est urgent que des librairies d’abstraction du multi tache, ou de nouveaux paradigme ou concept de programmation  fassent leur apparition et soient a la hauteur de nos attentent pour être accessible au plus grand nombre de développeurs.

 

 Il est temps  de se réveiller car l’ère du développement parallèle a déjà débutée J

 

 

Eric