Article : Parallélisation, distribution : de nouveaux enjeux pour les applications d'entreprise?

le 24/11/2008 par Marc Bojoly
Tags: Software Engineering

Les applications informatiques ont toujours été gourmandes en ressources, les besoins en nouvelles fonctionnalités ou l'accroissement du nombre d'utilisateurs étant une constante des applications réussies. Face à cet état de fait, les constructeurs informatiques ont bâti d'années en années des ordinateurs de plus en plus puissants. Aujourd'hui doit-on attendre l'arrivée de nouveaux ordinateurs pour disposer de meilleurs temps de réponse ? Quelles sont les autres alternatives?

Les progrès constants des ordinateurs est illustrée au niveau des processeurs par la loi de Moore. Celle-ci annonçait en 1975 que le nombre de puces sur un transistor doublerait tous les 18 mois à coût constant. Cela est respecté depuis plus de 30 ans et permet d'offrir des processeurs toujours plus puissants.

Certaines applications d'entreprise ont cependant besoin dès aujourd'hui de capacités de calculs dépassant celles d'un processeur. Les systèmes de gestion de bases de données (SGBD) comme Oracle ou les serveurs d'applications permettent d'utiliser plusieurs processeurs en utilisant le parallélisme.

Depuis quelques années, les applications les plus consommatrices en ressources gagnent même à être distribuées au sein de grilles. En effet, utiliser plusieurs serveurs d'entrées de gammes se révèlent moins cher qu'un serveur haut de gamme. Dans certains domaines comme le pricing des salles de marché, la demande de puissance de calcul est telle qu'elle ne peut être satisfaite par un seul ordinateur. La gestion du parallélisme et de la distribution sont indispensables dans ces applications.

Depuis le milieu de cette décennie, la loi de Moore a changé d'aspect. Depuis 30 ans, celle-ci se traduisait par des fréquences de fonctionnement de plus en plus rapides qui bénéficiaient quasi immédiatement à nos applications. Depuis quelques années les fondeurs proposent des puces de même fréquence mais multi-coeurs. Seules les applications écrites en tenant compte du parallèlisme pourront espérer en tirer parti et ainsi gagner en performance.

La maîtrise du parallélisme et de la distribution sont donc deux sujets importants appelés à se généraliser dans les années à venir. Cette série d'articles abordera les différents concepts de programmation permettant la parallélisation et la distribution. Notons cependant que nous nous limiterons au niveau langage de programmation : les notions de pipelining et de processeurs vectoriels ou superscalaires ne seront pas abordées car elles nécessitent peu d'adaptations au niveau du code.

La parallélisation aujourd'hui

Les ordinateurs savent réaliser plusieurs tâches en parallèle depuis de très nombreuses années. Les premiers systèmes multi-tâches datent des années 1960. Cependant, ces techniques sont restées longtemps confinées aux couches basses des systèmes. La gestion de plusieurs processus au sein des applications se limitaient à quelques applications serveurs comme Oracle. Les threads ou processus légers, qui partagent la même mémoire facilitent l'échange d'informations par le partage de la mémoire entre threads. Les interfaces graphiques font ainsi largement appel à ces mécanismes pour ne pas bloquer l'utilisateur.

Cependant, ces mécanismes restaient relativement bas niveau. Ils nécessitent des librairies spécialisées et le fait d'exécuter réellement deux traitements en parallèle nécessite une gestion fine de la concurrence. Tout accès à une donnée partagée entre deux fils d'exécution ou thread nécessite d'être protégé par un mécanisme de lock. En dehors des interfaces graphiques, seules quelques librairies pour le calcul intensif comme OpenMP prennent en charge cette gestion.

Le web est l'un des exemples où la parallélisation a été rendue plus transparente. Le protocole http étant déconnecté, le développeur est assuré que deux requêtes sont totalement indépendantes. Aucune donnée n'étant partagée entre les requêtes, chacune peut être exécutée dans un fil d'exécution différent. Prenons l'exemple du conteneur de servlet Tomcat : le développeur implémentera une servlet et Tomcat gérera de façon transparente le parallélisme. Les serveurs d'applications .Net ou JEE ont étendu ce concept en proposant des modèles d'exécution permettant au développeur d'ignorer cette gestion du parallélisme. A condition de se conformer au modèle de programmation (respect du cycle de vie des composants, pas de gestion de thread manuelle), le serveur d'application se charge de paralléliser le traitement des différentes requêtes.

De la parallélisation à la distribution

Lors de l'utilisation du protocole déconnecté, il devient également possible de faire traiter chaque requête sur un ordinateur différent. Prenons l'exemple des fermes de serveur web : chaque requête http est aiguillée par un routeur (logiciel tels que les modules de load-balancing ou matériel tel que les Alteon ) sur un serveur différent. Les seules données présentes dans la requête permettent de répondre à cette dernière. La quantité de données échangées entre serveur est donc très faible ce qui rend le modèle performant. Mais est-ce que ce modèle de distribution peut être étendu à d'autres traitements?

Prenons l'exemple des EAI. Ces intergiciels assurent la transformation et le routage de messages entre différentes applications. Là encore les seules données présentes dans un message suffisent à la transformation et au routage du message. Très souvent ces middlewares sont construits autour d'un bus de message, d'un MOM (message oriented middelware). Celui-ci permet de transmettre facilement des messages entre plateformes. Aussi, les EAI permettent fréquemment du load balancing donc de la distribution. Les messages en entrée sont envoyés sur le bus. Ceux-ci seront ensuite consommés par une des machines de la ferme en fonction de sa disponibilité.

Ce dernier exemple permet de mettre en évidence un pré-requis à une parallélisation efficace. Imaginons comme contre-exemple un EAI chargé de traiter un fichier de données monolithique. Celui-ci formera un unique message qui ne pourra être traité que par une seule machine. Dans ce cas la parallélisation pour être efficace nécessite un traitement sur un nombre important de données. Dans le cas des EAI, la solution consiste fréquemment à découper le fichier. Lorsque celui-ci est en fait un ensemble de lignes indépendantes au niveau métier, le composant d'insertion se charge de le transformer en un ensemble de messages qui dès lors pourront être traités de manière indépendante.

Deux exemples de conception pour la parallélisation et la distribution

Dans les deux articles suivants, nous verrons comment appliquer ces concepts de parallélisation et de distribution à des traitements métiers qui apparaissent au premier abord comme monolithique.

Nous verrons un modèle de conception utilisé pour distribuer des calculs sur une grille. Puis nous évoquerons le modèle de conception proposé par la future version 7 de java pour permettre des traitements parallèles. Ces différents modèles sont certes plus faciles à mettre en oeuvre qu'une gestion multi-thread native mais leur compréhension est indispensable pour espérer tirer parti de toute la puissance des serveurs d'entreprise : multi-coeurs, multi-processeurs ou grille.

Références

Multi-tâche : http://fr.wikipedia.org/wiki/Multit%C3%A2che Loi de Moore : http://fr.wikipedia.org/wiki/Loi_de_moore Processus léger : http://fr.wikipedia.org/wiki/Processus_léger http://en.wikipedia.org/wiki/Thread_(computer_science) Article : The Free Lunch Is Over: A Fundamental Turn Toward Concurrency in Software