presque unanime2, qui ne sera pas remise en question à moins d’une
révolution technologique imprévue. Actuellement, des processeurs
avec des centaines voire milliers de coeurs sont ainsi annoncés en
cours de développement [4]. Or, programmer une telle puissance de
calcul est loin d’être simple et l’opposition de Knuth à la direction
prise par les constructeurs est recevable au moins dans ce sens. Pour
approcher les limites théoriques des performances des processeurs
multi-coeurs un modèle de programmation différent s’impose, tout au
moins au niveau assembleur. Dans l’idéal, plusieurs fils d’exécution
devraient pouvoir avancer sur les différents coeurs du système avec
une distribution de la charge uniforme et sans demander excessivement
de synchronisations. On passe de la forme de parallélisme au niveau
des instructions à celle au niveau des tâches, une forme qui ne peut
pas être «déduite» automatiquement par le processeur mais qui, au
contraire, demande que le code soit explicitement parallèle, c’est-à-dire
découpé en «tâches», threads ou processus. Ce découpage n’est pas
une pratique nouvelle : une utilisation explicite de la concurrence
est parfois pertinente dans la construction d’interfaces graphiques
ou logiciels interactifs ; mais, il s’agit d’un besoin de modularité du
programme, d’expressivité, plutôt qu’un souhait de parallélisation afin
d’améliorer les performances. Toutefois, quelque soit l’objectif, les
développeurs qui pratiquent la programmation concurrente s’exposent
aux risques d’un modèle intrinsèquement complexe où le partage de
données mutables, c’est-à-dire non persistantes, et les synchronisations
explicites sont monnaie courante. Cette forme de contrôle explicite
reste donc une technique de bas niveau essentiellement impérative, qui
contraste avec le style fonctionnel et qu’il serait souhaitable de cacher
derrière un style de programmation de plus haut niveau.
Les techniques de programmation parallèle le plus couramment
utilisées ne sont pas de haut niveau, que le modèle de parallélisme soit
à squelettes algorithmiques (skeleton programming), à flot de données
(dataflow), ou data-parallèle imbriqué (nested data parallel), et que
le paradigme de programmation soit au départ impératif, fonctionnel,
logique ou autre. Dans le cadre impératif, le système OpenMP [19]
2. Il existe sur ce choix l’opinion divergente de Donald Knuth [16], qui aurait insisté dans la
direction monoprocesseur pour les difficultés évidentes de la programmation de telles machines.
4