Dans quelle mesure les génériques et la méta-programmation utilisant des modèles C ++ sont-ils utiles en science informatique?


17

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?


Je crains que cette question ne soit trop ouverte aux opinions, mais je veux voir ce que les gens de la communauté disent.
Geoff Oxberry

1
J'ai complètement supprimé le déraillement du commentaire. Si vous souhaitez qu'il soit republié pour discuter ou méta, je suis heureux de le faire. Voir ma méta ici .
Aron Ahmadia

3
Consultez également la question connexe ici sur les conseils pour savoir quand utiliser et quand éviter les modèles d'expression .
Aron Ahmadia

Je ne pense pas qu'il soit correct de dire que LAMMPS utilise des modèles ou des métaprogrammations. LAMMPS est un code orienté objet qui ressemble beaucoup à Fortran la plupart du temps. Je ne pense pas que MPQC ait beaucoup de modèles non plus, mais il est fortement orienté objet et polymorphe.
Jeff

1
OpenFOAM fait un usage des modèles et d'autres fonctionnalités de C ++.
Dohn Joe

Réponses:


14

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.


4
tmp peut être difficile pour les utilisateurs novices, mais il est souvent très bien fait à l'intérieur de la bibliothèque. C'est l'une de ces techniques qui peuvent vraiment réduire la quantité de code, mais vous devez vraiment savoir ce que vous faites. Si vous ne me croyez pas, allez lire la source d'Eigen ou Elemental. Son beau code qui sans modèles serait à peu près impossible.
aterrel

5
Bien sûr, c'est une technique qui a de la valeur. Mais il est difficile à maintenir, et il est souvent difficile à utiliser s'il est exposé à l'interface externe. Cela dit, je pense que l'une des raisons pour lesquelles TMP n'a pas été tout à fait le succès auquel les gens s'attendaient au départ est que les compilateurs viennent de devenir très bons. TMP vit du fait que beaucoup de choses sont connues au moment de la compilation et peuvent ensuite être propagées sous forme de constantes dans le code réel. Mais les compilateurs sont devenus assez bons pour l'inlining, le clonage de fonctions, etc., et donc une partie significative des avantages peut aujourd'hui être obtenue en utilisant une programmation "normale".
Wolfgang Bangerth

15

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.


3

Ce que les fonctionnalités de langage comme OOPpour le calcul scientifique permettent d'obtenir des instructions de code plus compactes, ce qui aide à mieux comprendre et utiliser le code. Par exemple, les FFTroutines doivent transporter un grand nombre d'arguments pour chaque appel de fonction, ce qui rend le code lourd.

En utilisant moduleouclass 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.


3

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.


2

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.


Ce papier me rend fou. Comparez le Fortran ordinaire le plus rapide que vous avez au MKL et il perdra également. L'assemblage réglé à la main n'est pas une chose à laquelle on aspire, c'est ce que vous faites lorsque chaque nanoseconde compte et peut être réutilisé par un très grand nombre de personnes.
aterrel

@aterrel: C'est précisément le contraste que je me demande. Sachant que vous devrez faire de l'optimisation manuelle comme toute dernière étape de développement, quelle langue choisiriez-vous comme base à utiliser avant la dernière étape? Avons-nous des données fiables pour suggérer la langue à choisir?
Deathbreath

9
@Deathbreath: Je répéterai également une réponse que j'ai faite sur plusieurs autres threads - que dans l'ensemble, régler le dernier bit de vitesse hors de votre code est quelque chose que vous faites très rarement. Mais vous programmez tout le temps des algorithmes de haut niveau. Choisissez donc la langue qui vous permet de faire les gros trucs rapidement. Il y a toujours un moyen d'inclure des choses de bas niveau d'une manière ou d'une autre, mais ce ne devrait pas être la chose qui détermine votre choix de langage de programmation.
Wolfgang Bangerth

0

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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.