Developpez.com - Rubrique HPC

Le Club des Développeurs et IT Pro

Parallélisme en mémoire partagée avec Julia

Le parallélisme imbriqué est pris en compte dès le début, mais le code ne sera pas inclus dans Julia 1.0

Le 2018-06-11 15:39:41, par dourouc05, Responsable Qt & Livres
Julia est un langage de programmation prévu pour le calcul scientifique tout d’abord, même s’il se généralise de plus en plus, notamment pour les interfaces graphiques (InteractBase.jl, par exemple). Il cherche à obtenir le meilleur des deux mondes : celui des langages pour le calcul intensif (C, C++, Fortran…), où la performance est le critère le plus important, ainsi que celui des langages dynamiques (Python, LISP…), bien plus pratiques pour le développement.
Dès 2015, les premières expériences pour apporter le parallélisme à mémoire partagée ont donné naissance à la construction @threads : il devient alors très simple de lancer toutes les itérations d’une boucle donnée en parallèle. Cette manière de procéder correspond à ce qui est le plus souvent fait dans le calcul intensif (elle correspond à OpenMP, par exemple). Son implémentation force à repenser certaines parties de l’implémentation de Julia, afin de s’assurer que toutes les parties du code fonctionnent de manière sécurisée en parallèle : le ramasse-miettes, la génération du code, etc.
Cependant, cette construction est très limitée : elle ne s’adresse qu’aux cas où le même code est exécuté sur des parties de données différentes (parallélisme de données). Ce paradigme correspond très bien au fonctionnement des processeurs graphiques, mais pas à la totalité des applications, qui ont besoin d’un modèle de fils d’exécution plus précis. Par exemple, il n’était pas possible de lancer le code de calcul dans un fil d’exécution séparé de l’interface graphique — cette dernière devait être figée pendant l’exécution des calculs. Bien que limitée, elle s’est montrée très efficace en pratique : Celeste.jl est un moteur d’inférence à base d’images astrophysiques qui a pu être exécuté sur un superordinateur, en développant une puissance de calcul de plus d’un téraflops.
L’approche en cours de développement sera similaire à celle de Cilk (un dérivé de C développé au MIT), avec trois types principaux de construction : spawn pour lancer un fil d’exécution, sync pour en attendre les résultats et parfor pour paralléliser simplement une boucle. Ce paradigme est à la fois très puissant (toutes les fonctionnalités sont disponibles pour implémenter toute logique parallèle) et très simple (ce qui garantit une certaine productivité pour écrire le code et diminue le risque d’erreurs).
Néanmoins, cette manière d’écrire des programmes parallèles pose très vite des questions d’implémentation très pratiques : que faire en cas de parallélisme imbriqué (ou composé) ? Que se passe-t-il lorsqu’un code parallèle appelle une bibliothèque qui exploite elle-même le parallélisme ? En général, ces bibliothèques sont très bien écrites et profitent énormément des capacités parallèles (comme BLAS pour les opérations d’algèbre linéaire), mais la majorité des implémentations actuelles (OpenMP, Cilk…) ne permettent de paralléliser que la boucle extérieure, tandis que toutes les boucles intérieures sont exécutées en série (ce qui inclut les bibliothèques extérieures, de manière générale).
Julia envisage de fonctionner de manière différente, avec un ordonnancement en profondeur. La majorité des systèmes actuels utilisent le “vol” de tâches  : quand un fil d’exécution a terminé toutes ses tâches, il prend le travail d’autres fils qui n’ont pas encore fini. Le problème est qu’il faut donc stocker une liste de toutes les tâches pour chacun des fils d’exécution, ce qui peut représenter une grande quantité de mémoire. Au contraire, l’ordonnancement en profondeur a d’excellentes garanties théoriques (pas besoin de stocker de grandes piles de tâches à exécuter pour chaque fil d’exécution) et, en pratique, a toutes les propriétés requises pour exploiter au mieux les caches des processeurs. Les fils d’exécution ne décident pas eux-mêmes des tâches à exécuter, puisqu’un contrôleur central s’en charge. Cependant, il n’en existe, pour le moment, aucune implémentation utilisable en production, seulement quelques codes de recherche.
Le code pour ce faire en Julia (partr) est en cours de développement depuis plus d’un an et utilise la notion de coroutine pour l’implémentation des tâches. Certaines fonctionnalités sont d’ores et déjà implémentées.

Source : .

Et vous ?

Qu'en pensez-vous ?

Voir aussi

Du neuf sur Julia 0.7 ~~: après la réécriture du moteur d'optimisation, les fonctionnalités du langage seront prêtes pour la 1.0
Science des données : Julia, R ou Python ? ~~Un petit aperçu des avantages et inconvénients du langage Julia
Les fonctionnalités de Julia 1.0 seront arrêtées le 15 décembre, la version finale devrait arriver en février
  Discussion forum
3 commentaires
  • Matthieu76
    Membre éclairé
    Ça a l'air prometteur le Julia, affaire à suivre. Personnellement, j'aime pas trop développer dans des langages un peu moins connu que les autres mais si ce langage ce démocratise un peu plus pourquoi pas, après faudra voir les performances.
  • dourouc05
    Responsable Qt & Livres
    Niveau perf, il joue dans la cour des grands : https://julialang.org/benchmarks/. Sinon, le langage a déjà à peu près six ans (première version publique) et atteint la 1.0 "bientôt", à voir à quel point il sera utilisé. Il a quand même une boîte commerciale derrière lui (https://juliacomputing.com/), donc il ne devrait pas disparaître du jour au lendemain.
  • Matthieu76
    Membre éclairé
    Merci beaucoup pour tes précisions
    Je pense que ce langage est vraiment puissance et en très bonne voie au vu des grosses boîtes qui utilisent julia :

    • Tous les GAFAM (Google, Apple, Facebook, Amazon et Microsoft)
    • La NASA
    • Intel
    • IMB
    • et j'en passe ...