Pénalité de performance de 20% pour une conception de logiciel agréable

17

J'écris une petite bibliothèque pour des calculs matriciels clairsemés comme un moyen de m'apprendre à faire le meilleur usage de la programmation orientée objet. J'ai travaillé très dur pour avoir un joli modèle objet, où les parties (matrices clairsemées et les graphiques qui décrivent leur structure de connectivité) sont très peu couplées. À mon avis, le code est beaucoup plus extensible et maintenable pour lui.

Cependant, c'est aussi un peu plus lent que si j'avais utilisé une approche contondante. Afin de tester les compromis d'avoir ce modèle d'objet, j'ai écrit un nouveau type de matrice clairsemée qui a rompu l'encapsulation du graphique sous-jacent pour voir combien plus rapide cela fonctionnerait.

Au début, ça avait l'air plutôt sombre; le code dont j'étais fier était autrefois 60% plus lent qu'une version sans aucune conception logicielle élégante. Mais, j'ai pu faire quelques optimisations de bas niveau - en alignant une fonction et en changeant un peu une boucle - sans changer du tout l'API. Avec ces changements, c'est maintenant seulement 20% plus lent que la concurrence.

Ce qui m'amène à ma question: quelle perte de performances dois-je accepter si cela signifie que j'ai un joli modèle d'objet?

Daniel Shapero
la source
Quelle opération à matrice clairsemée mesuriez-vous?
Bill Barth
Multiplication matrice-vecteur. Les matrices variaient en taille de n=1024,...,16384 . Je leur ai fait le graphique des Laplaciens pour les graphes aléatoires d'Erdos-Renyi avec un degré moyen d=log2n . De plus, le chiffre de 20% empire sur certaines machines, alors maintenant je suis plus enclin à jeter le tout. Soupir profond
Daniel Shapero
3
Quel langage de programmation utilisez-vous? Généralement, quelque chose comme C ++ vous permettra de vous en sortir avec des conceptions élégantes (ish) à un coût faible (ou inexistant). Dans d'autres langages sans méta-programmation (Java, Fortran, etc.) un coût de 20% semble raisonnable.
LKlevin
Pouvez-vous nous montrer votre code? Quelle langue avez-vous utilisée? Quels compilateurs et drapeaux de compilation? Avez-vous trouvé précisément d'où vient le succès de la performance? Comment vous êtes-vous assuré d'avoir trouvé la bonne raison? Quel profileur avez-vous utilisé et comment l'avez-vous utilisé? Êtes-vous certain que le joli modèle d'objet n'est pas implémenté de manière inefficace? 20% est suffisamment petit pour que vous ayez besoin de collecter beaucoup de données et d'avoir une analyse détaillée avant de dire que c'est certainement dû à la conception, plutôt qu'à une implémentation inférieure ou à d'autres problèmes de codage.
Kirill
Petite note: tout le monde semble faire l'éloge du bon design par rapport à la performance pure (avec des raisons très valables, bien sûr). Mais alors, pourquoi tant de code du monde réel est-il vraiment, vraiment impossible à maintenir? Tous les slobs de code se sentent-ils coupables et donc silencieux?
AlexE

Réponses:

9

Très peu de développeurs de logiciels scientifiques comprennent les bons principes de conception, je m'excuse donc si cette réponse est un peu longue. Du point de vue de l'ingénierie logicielle, l'objectif du développeur de logiciels scientifiques est de concevoir une solution répondant à un ensemble de contraintes souvent conflictuelles .

Voici quelques exemples typiques de ces contraintes, qui pourraient être appliqués à la conception de votre bibliothèque matricielle clairsemée:

  • Terminé en un mois
  • Fonctionne correctement sur votre ordinateur portable et plusieurs postes de travail
  • Fonctionne efficacement

Les scientifiques accordent progressivement plus d'attention à certaines autres exigences courantes de l'ingénierie logicielle:

  • Documentation (guide de l'utilisateur, tutoriel, commentaire de code)
  • Maintenabilité (contrôle de version, test, conception modulaire)
  • Réutilisation (conception modulaire, "flexibilité")

Vous devrez peut-être plus ou moins l'une de ces exigences. Si vous essayez de gagner un prix Gordon Bell pour la performance, même des fractions de pour cent sont pertinentes, et peu de juges évalueront la qualité de votre code (tant que vous pourrez les convaincre que c'est vrai). Si vous essayez de justifier l'exécution de ce code sur une ressource partagée telle qu'un cluster ou un supercalculateur, vous devez souvent défendre des affirmations sur les performances de votre code, mais celles-ci sont rarement très strictes. Si vous essayez de publier un article dans un journal décrivant les gains de performance de votre approche, vous devez légitimement être plus rapide que vos concurrents, et 20% de performances sont un compromis que je ferais avec plaisir pour une meilleure maintenabilité et réutilisation.

Pour en revenir à votre question, un «bon design», avec suffisamment de temps de développement, ne doit jamais sacrifier les performances. Si l'objectif est de rendre le code qui s'exécute aussi vite que possible, alors le code doit être conçu autour de ces contraintes. Vous pouvez utiliser des techniques telles que la génération de code, l'assemblage en ligne ou profiter de bibliothèques hautement optimisées pour vous aider à résoudre votre problème.

Mais que faire si vous n'avez pas assez de temps de développement? Qu'est-ce qui est assez bon? Eh bien, cela dépend, et personne ne pourra vous donner une bonne réponse à cette question sans plus de contexte.

FWIW: Si vous êtes vraiment intéressé à écrire des noyaux à matrice clairsemée hautes performances, vous devriez comparer avec une installation PETSc optimisée et travailler avec leur équipe si vous les battez, ils seraient heureux d'incorporer des noyaux accordés à la bibliothèque.

Aron Ahmadia
la source
Je suis curieux de connaître les générateurs de code - je pense qu'ils pourraient être utiles pour moi, mais je crains qu'ils soient difficiles à maintenir. Je sais que les programmeurs Java les utilisent beaucoup mais ils sont souvent adaptés pour générer du code pour des applications spécifiques. Connaissez-vous des codes scientifiques qui les utilisent?
Daniel Shapero
ATLAS, FFTW, Spiral, OSKI, Ignition, stencil_codegen, pour n'en nommer que plusieurs. Ce n'est pas annoncé publiquement, mais je ne serais pas surpris si plusieurs des noyaux importants dans MKL et ESSL sont générés de cette façon. L'écriture de code de génération de noyau maintenable serait une question de suivi intéressante. J'ai de l'expérience dans ce domaine, mais je ne me considérerais pas comme une autorité.
Aron Ahmadia
12

C'est une question sur quoi vous passez votre temps. Pour la plupart d'entre nous, nous passons 3/4 du temps à programmer et 1/4 du temps à attendre les résultats. (Vos chiffres peuvent varier, mais je pense que le nombre n'est pas complètement sans mérite.) Donc, si vous avez un design qui vous permet de programmer deux fois plus vite (3/4 d'une unité de temps au lieu de 1,5 unité de temps), alors vous peut prendre un coup de 300% dans les performances (de 1/4 à 1 unité de temps) et vous êtes toujours en tête en termes de temps réel consacré à la résolution du problème.

D'un autre côté, si vous effectuez des calculs lourds, vos calculs peuvent sembler différents et vous voudrez peut-être passer plus de temps à optimiser votre code.

Pour moi, 20% semble être un assez bon compromis si vous finissez par être plus productif.

Wolfgang Bangerth
la source
Bonne réponse, j'ajouterais également l'importance là où la performance compte. Un code scientifique donné ne fait pas uniquement la multiplication matricielle; si 20% de votre temps d'exécution est en multiplication matricielle, une baisse de performances de 20% ne fait que 4% de différence dans l'ensemble, et je serais ravi de prendre cela en échange d'une bibliothèque plus facile à utiliser.
Aurelius
1
Et une meilleure bibliothèque écrite signifie moins de bogues, de sorte que vous perdez moins de temps à attendre des résultats incorrects.
Davidmh
4

À mon humble avis, une pénalité pouvant aller jusqu'à 50% (quelle qu'en soit la raison) n'est pas si mauvaise.

En fait, j'ai vu une différence de performances de 0 à 30% uniquement en fonction du type de compilateur. C'est pour la routine MatMult clairsemée de PETSc sur des matrices résultant de discrétisations FE d'ordre faible.

stali
la source
1

La conception du logiciel ne s'améliorera pas automatiquement au fil du temps. La performance sera. Vous récupérerez les 20% avec votre prochain CPU. En outre, une bonne conception logicielle facilitera l'extension ou l'amélioration de la bibliothèque à l'avenir.

MirekE
la source
Je ne pense pas que cela réponde à la question.
nicoguaro
0

Un principe général consiste à opter d'abord pour une bonne conception, puis à optimiser les performances uniquement si nécessaire . Les cas d'utilisation où un gain de performances de 20% est vraiment nécessaire sont susceptibles d'être plutôt rares, s'ils surviennent.

jolvi
la source