Conservatoire national des arts et métiers
Architectures des systèmes informatiques
CHAPITRE 12
Parallélisation des programmes
Année 2002-2003

12.0 PRÉSENTATION

Ce chapitre n'est pas relatif aux architectures. Il est matière à lecture dans le cours d'architectures des systèmes informatiques. Il fait un premier lien avec la partie relative au traitement du signal dans le cours d'architectures parallèles. Il n'a pas de questionnaires, toutefois, pour le lecteur qui en ressent le besoin, des suggestions d'exercices sont faites çà et là.

Nous avons vu que les machines parallèles et les modèles associés sont très variés. Ceci demeure relativement abstrait tant qu'on ne passe pas à l'acte. Au delà de leur conception et de leur choix, l'acte est de programmer ces machines. Le présent chapitre a pour objet de faire saisir le processus qui, à partir d'un problème simple mène à des expressions parallèles. Une fois quelques schémas établis, on présentera les deux styles de programmation induits par les deux catégories, mémoire commune et communication par messages. Le lecteur est invité à considérer ce chapitre comme une illustration de l'usage que l'on peut faire de machines parallèles. Il ne traite pas des langages spécialisés que l'on apprend quand on est face à une machine particulière et à son environnement de programmation. Il ne traite pas non plus des méthodes de programmation existantes.

Ce chapitre contient :
12.1 une introduction;
12.2 la définition des étapes;
12.3 un exemple simple traité par étapes;
12.4 une conclusion.

12.1 INTRODUCTION

Les architectures et les processeurs spécialisés sont choses intéressantes, le processus de parallélisation du travail à faire est tout aussi essentiel.

Cette parallélisation inclut :

L'objectif est d'obtenir la meilleure performance à architecture, à outils et à effort de programmation donnés. Il faut pour cela répartir les tâches de façon équilibrée entre les processeurs et réduire les communications entre les processeurs. Les étapes de création pourraient être idéalement être prises en charge par des outils logiciels, mais ce n'est encore qu'un espoir. Il n'y a pas aujourd'hui, sauf dans des cas particuliers comme les travaux de type vectoriel, d'outils convenables. Même s'il suit un cheminement assez bien établi, le programmeur devra prendre la plupart des décisions.

La liste ci-dessus ne peut être suivie de façon rigoureuse dans de nombreux cas. Elle fait donc l'objet de modifications, de regroupements différents selon les auteurs. La terminologie non plus n'est pas fixée. Dans la suite, ce que nous nommons orchestration est parfois nommé agglomération.

Le lecteur est vivement invité à considérer les paragraphes suivants comme des possibles et non comme l'expression de méthodologies ou de méthodes affirmées. Le but de ce chapitre est à la fois d'illustrer des processus réalistes et de donner une claire idée de la complexité du domaine. En particulier, ne disposant pas d'une machine complètement spécifiée, le modèle de mémoire dont la nécessité était affirmée pour obtenir des programmes efficaces.

12.2 LES ÉTAPES

Dans ce qui suit :

Une tâche est une partie du travail total à réaliser. C'est la plus petite unité de travail mise en parallèle avec d'autres. Elle est exécutée sur un processeur unique. La parallélisation est faite entre les tâches. La définition des tâches est libre. Dans un programme séquentiel, les tâches sont apparentes sous la forme de procédures ou de modules; dans le domaine du temps réel, une tâche est le programme de gestion d'une interruption. Ces trois notions sont très différentes les unes des autres.

La taille des tâches détermine la granularité. Le grain fin (fine grain) qualifie des tâches petites, le grain grossier (coarse grain), des tâches dont les tailles sont relativement grandes. Cette qualification est arbitraire.

Un processus est une entité abstraite, celle qui mène les tâches à leur fin. En anglo-saxon, il est toujours nommé «process» dans le domaine séquentiel, et le plus souvent «thread» en matière simultanée. Le «thread» mènent au bout une tâche. Ceci le distingue du «process» qui mène au bout la totalité du travail à effectuer. Un programme parallélisé est composé de processus multiples. Chacun réalise un sous ensemble des tâches et doit pour cela coopérer avec les autres. Les tâches sont réparties entre les processus par une décision d'affectation. Tout au bout, les processus mènent les tâches à leur fin en les exécutant sur un processeur physique de la machine.

Dans la figure ci-dessus, le programme parallèle est composé de quatre tâches liées entre elles. La machine réelle, composée de quatre processeurs (le hasard est grand) n'a que quatre liens. Il devra y avoir des communications indirectes entre P0 et P3.

Nous présentons ci-après la suite de ces opérations sur un exemple qui sera détaillé au fur et à mesure du besoin.

Note : Les étapes ci-dessus ne relèvent pas d'une vérité démontrée. Selon les cas, une répartition différente peut-être utilisée. Par exemple selon la machine disponible ou encore selon le problème à traiter.

Le découpage en tâches, suivi par les autres étapes est une opération dont le principe existe ailleurs. Rappelons que dans une architecture superscalaire, le pipeline d'instructions est présentable avec :

Nous manipulons ici un pipeline de processus présentable avec : 12.2.1. La décomposition

En termes de performances, le paramètre essentiel est le nombre de processus, issu lui-même du nombre de tâches susceptibles de simultanéité.

Les évaluations de performances seront faites dans la suite en posant :

On nomme abusivement accélération le rapport du temps séquentiel au temps parallèle : 1/s.

Exemple d'évaluation.

Soit une image carrée NxN à traiter comme suit :

Dans toute la suite, on suppose que chaque opération est faite en un temps unitaire.

Le temps séquentiel est 2N².

On suppose disposer de p processeurs. Comment s'y prendre, hors toute considération de communication ?

1ère solution.

On affecte N²/p points à chaque processeur et on réalise la sommation de façon séquentielle.
Si toutes les opérations sont faites en un même temps, le temps total consommé sera N²/p pour la première partie, N² pour la seconde, soit N²/p + N².
L'accélération est alors 2N²/(N²+N²/p) soit 2p/(p+1).

L'accélération est 2p/(p+1)
Elle ne dépend pas du nombre de points,
elle a pour valeur limite 2 quand p croît indéfiniment.

2ème solution.

Décomposons la deuxième partie en deux phases. Dans la première chaque processeur fait les sommations relatives à ses données, dans la seconde, la sommation finale intervient. Les temps sont alors :

N²/p pour la première partie;
N²/p pour la première phase de la deuxième partie;
p pour la deuxième phase de la deuxième partie, soit  2xN²/p +p.

L'accélération est 2pN²/(2N²+p²).
Elle ne dépend pas du nombre de points,
elle est tend à être proportionnelle à p quand N devient grand devant p.

L'accélération possible ne dépend donc pas seulement du problème à traiter mais aussi de la façon dont on s'y prend.

12.2.2 L'affectation (ou répartition)

L'affectation groupe les tâches en processus.

Dans cette étape, le propos est de répartir équitablement la quantité de travail entre les processus, de limiter au mieux les communications entre les processus et de réduire le temps nécessaire à la gestion de cette répartition. Cette phase n'a pas non plus de règles fixes, c'est le règne des heuristiques plus ou moins bien adaptées. Fort heureusement, l'habitude prise depuis de nombreuses années de structurer les programmes séquentiels peut aider à faire l'affectation.

On distingue

En général, la décomposition et l'affectation sont faites sans référence à la topologie et à la nature du multiprocesseur. Il faut toutefois vérifier ensuite que le système d'exploitation ou la communication n'apportent pas des coûts excessifs induits sur la machine dont on dispose.

12.2.3 L'orchestration

Le processus acquièrent une existence. Ils vont avoir besoin de mécanismes pour nommer les données, pour y accéder, pour faire des échanges entre processus et pour les synchroniser. L'architecture du système, le modèle de programmation et le langage de programmation jouent pour cela des rôles importants. Les choix à faire dépendent peu des deux étapes précédentes. Il se peut qu'à ce stade on doive revoir l'organisation des données. On y décide aussi de la taille des messages s'il y en a et de la synchronisation explicite ou implicite.

Les objectifs principaux de cette étape sont :

12.2.4 Le placement

Il s'agit de placer les processus sur les processeurs. On prend en compte la topologie de communication de la machine. Il se peut que le système d'exploitation gère cette activité. Quand il le fait de façon dynamique, changeant de sa propre initiative la place de certains processus, il faut vérifier que l'on n'a pas des migrations nombreuses, coûteuses en temps. La solution est d'affecter (to pin en anglais, c'est-à-dire épingler) processus à processeur. Si le système d'exploitation ne fait pas le placement, seul ou avec le compilateur, le programmeur devra le faire avec les outils dont il dispose.

CE FICHIER N'A PAS DE QUESTIONNAIRE

Conservatoire national des arts et métiers
Architectures des systèmes informatiques
CHAPITRE 12
Parallélisation des programmes
Année 2002-2003