Le langage C ++ fournit une programmation générique et une métaprogrammation via des modèles. Ces techniques ont trouvé leur chemin dans de nombreux progiciels de calcul scientifique à grande échelle (par exemple, MPQC , LAMMPS , CGAL , Trilinos ). Mais qu'est-ce qu'ils ont réellement contribué au calcul scientifique en valeur qui va au-delà des langages non génériques et non méta comme C ou Fortran en termes de temps de développement global et d'utilisation pour une efficacité égale ou adéquate?
Compte tenu d'une tâche de calcul scientifique, la générique et la méta-programmation via des modèles C ++ ont-elles démontré une amélioration de la productivité, de l'expressivité ou de l'utilisabilité mesurée par des repères bien compris (lignes de code, effort personnel, etc.)? De même, quels risques sont associés à l'utilisation de modèles C ++ pour la générique et la méta-programmation?
la source
Réponses:
Je pense que dans l'ensemble, la métaprogrammation de modèle s'est avérée inutilisable dans la pratique - elle se compile trop lentement et les messages d'erreur que nous obtenons sont tout simplement impossibles à déchiffrer. La barrière à l'entrée pour les nouveaux arrivants est également tout simplement trop élevée lors de l'utilisation de la métaprogrammation.
Bien sûr, la programmation générique est un problème entièrement différent, comme en témoignent Trilinos, deal.II (ma propre bibliothèque), DUNE et de nombreuses autres bibliothèques - exprimer le même concept fonctionnant sur différents types de données est en quelque sorte une évidence, et la communauté l'a largement accepté tant qu'il reste dans des limites qui évitent les problèmes de métaprogrammation. Je pense que la programmation générique est un succès évident.
Bien sûr, aucun de ces sujets n'est directement lié à la POO. La POO, encore une fois, est, je dirais, universellement acceptée par la communauté informatique scientifique. Encore moins que la programmation générique, ce n'est pas un sujet de débat: chaque bibliothèque réussie écrite au cours des 15 dernières années (qu'elle soit écrite en C ++, C ou Fortran) utilise des techniques de POO.
la source
Permettez-moi de donner un exemple basé sur l'expérience. La plupart des bibliothèques que j'utilise quotidiennement utilisent la POO d'une manière ou d'une autre. La POO est capable de masquer la complexité requise pour de nombreux domaines, ce n'est pas un mécanisme qui contribue vraiment aux performances. Ce qui peut arriver, c'est qu'une bibliothèque est capable d'utiliser des optimisations spécifiques basées sur la hiérarchie des objets, mais pour l'essentiel, il s'agit de cacher la complexité à l'utilisateur. Recherchez les modèles de conception, ce sont les mécanismes souvent utilisés pour accomplir cette complexité.
Prenons l'exemple de PETSc. PETSc utilise un modèle inspecteur / exécuteur de POO dans lequel l'un de ses algorithmes examine les routines disponibles dans un objet donné et choisit celui à exécuter pour accomplir la routine. Cela permet à un utilisateur de séparer les préoccupations, par exemple l'action de la matrice peut inclure n'importe quel type de routine bloquée ou optimisée et être efficacement utilisée par de nombreux solveurs itératifs. En donnant à l'utilisateur la possibilité de spécifier ses propres types de données et évaluations, il obtient quelques routines importantes accélérées et dispose également de toutes les fonctionnalités de la bibliothèque.
Un autre exemple que je vais vous donner est FEniCS et deal.II. Ces deux bibliothèques utilisent la POO pour généraliser sur un grand nombre de méthodes par éléments finis. Dans les deux cas, le type d'élément, l'ordre des éléments, la représentation en quadrature, etc. sont interchangeables. Bien que ces deux bibliothèques soient "plus lentes" que certains codes FEM structurés à des fins spéciales, elles sont capables de résoudre une grande variété de problèmes avec une grande partie de la complexité de FEM inconnue de l'utilisateur.
Mon dernier exemple est Elemental. Elemental est une nouvelle bibliothèque d'algèbre linéaire dense qui a pris la difficulté de gérer les communicateurs MPI et l'emplacement des données dans une construction de langage très simple. Le résultat est que si vous avez un code série FLAME, en changeant les types de données, vous pouvez également avoir un code parallèle via Elemental. Encore plus intéressant, vous pouvez jouer avec la distribution des données en définissant une distribution égale à une autre.
La POO doit être considérée comme un moyen de gérer la complexité, et non comme un paradigme pour concurrencer l'assemblage roulé à la main. Le fait de le faire mal entraînera également beaucoup de frais généraux, il faut donc continuer à synchroniser et à mettre à jour les mécanismes avec lesquels il l'utilise.
la source
Ce que les fonctionnalités de langage comme
OOP
pour le calcul scientifique permettent d'obtenir des instructions de code plus compactes, ce qui aide à mieux comprendre et utiliser le code. Par exemple, lesFFT
routines doivent transporter un grand nombre d'arguments pour chaque appel de fonction, ce qui rend le code lourd.En utilisant
module
ouclass
instructions , seuls les éléments nécessaires au moment de l'appel peuvent être transmis, car les autres arguments se rapportent à la configuration du problème (c'est-à-dire la taille des tableaux et les coefficients).D'après mon expérience, j'avais
SUBROUTINE
appels avec 55 arguments (entrée et sortie) et je l'ai réduit à 5 pour améliorer le code.C'est de la valeur.
la source
Je suis un ardent défenseur de la programmation générique et de la méta-programmation pour le calcul scientifique. Je suis en train de développer une bibliothèque de logiciels libres C ++ pour les méthodes Galerkin basée sur ces techniques appelée Feel ++ (http://www.feelpp.org) qui prend de plus en plus d'ampleur. Il est vrai qu'il existe encore des difficultés telles que des temps de compilation lents et que la courbe d'apprentissage pourrait être abrupte si l'on veut comprendre ce qui se passe derrière la scène. Ceci est cependant extrêmement intéressant et époustouflant. Si cela se fait au niveau de la bibliothèque et en cachant la complexité derrière un langage spécifique au domaine, vous obtenez un outil extrêmement puissant. Nous avons à notre disposition une très large gamme de méthodes à utiliser et à comparer. Pour l'enseignement du calcul scientifique, c'est génial, pour la recherche et les nouvelles méthodes numériques aussi, pour les applications à grande échelle, bien on y travaille mais jusqu'ici tout va bien, on peut déjà faire de belles choses. Nous avons des ingénieurs, des physiciens et des mathématiciens qui l'utilisent: la plupart d'entre eux utilisent simplement le langage pour la formulation variationnelle et ils en sont satisfaits. En regardant certaines des formulations que nos collègues physiciens manipulent, je ne voudrais pas les voir faites "à la main" sans un langage de haut niveau pour décrire la formulation variationnelle. Personnellement, je considère que ces "techniques" ou "paradigmes" sont maintenant nécessaires pour s'attaquer à la complexité du code de calcul scientifique en devant multiplier la taille du code par un énorme facteur. Il y a probablement un besoin d'améliorer le support de la méta-programmation en C ++ mais elle est déjà en bon état surtout depuis C ++ 11.
la source
Vous trouverez peut-être l'article http://arxiv.org/abs/1104.1729 correspondant à votre question. Il discute des modèles d'expression (une application particulière de la méta-programmation de modèle utilisée dans le code scientifique) du point de vue des performances.
la source
Les modèles sont très efficaces pour supprimer les vérifications de type / domaine au moment de l'exécution. Ceux-ci peuvent être pris en charge au moment de la compilation. Cela peut en théorie augmenter les performances par rapport au même type d'implémentation en C ou en Fortran où la vérification de type ne peut être effectuée qu'au moment de l'exécution - les vérifications sont implémentées dans le code source. Cependant, vous pouvez obtenir les mêmes résultats en C en utilisant des options de précompilateur, mais celles-ci doivent être faites à la main contrairement aux modèles.
Cependant, les modèles peuvent également générer des frais généraux importants. Ils peuvent souvent créer une surcharge de code qui peut avoir un impact sur l'utilisation du cache d'instructions. De plus, les approches génériques peuvent souvent entraver le compilateur lors de l'optimisation - ce n'est pas toujours simple pour l'analyse de code lors de l'utilisation d'approches génériques. C'est toujours un problème d'automatisation - y compris l'optimisation du compilateur - très souvent, le code de sortie n'est pas compatible avec le cache.
Les avantages de la vérification de type / domaine, bien que certainement plus sûrs, sont le seul réel avantage que je puisse voir en termes de performances et ceux-ci sont généralement imperceptibles. Mais comme je l'ai dit, l'effet global peut être négatif selon ce que vous faites. C'est pourquoi il est souvent préférable d'optimiser manuellement votre code là où vous avez des goulots d'étranglement importants.
la source