Structures de données pour le code de volume fini: tableaux vs classes
11
Je dois écrire un code de volume fini pour la magnétohydrodynamique (MHD). J'ai déjà écrit du code numérique mais pas à cette échelle. Je voulais juste demander qui serait un bon choix, en utilisant une structure de données (approche orientée objet) avec des classes ou en utilisant simplement plusieurs tableaux pour différentes propriétés, en termes de vitesse, d'évolutivité, etc. Je prévois d'écrire le code en python, et utiliser fortran pour les pièces à forte intensité numérique.
Un exemple de classe en python serait
classCell:def __init__(self, x, y, z, U):
Les tableaux peuvent être simplement définis comme
Réponse simple: en python moderne, chaque type de données est une classe, donc formellement il n'y a pas de différence entre les deux solutions que vous proposez. (N'oubliez pas d'utiliser des classes de nouveau style: les classes classiques sont obsolètes! Voir http://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes )
Maintenant, la question devrait être: comment organiser une structure de données efficace en python? Il ne fait aucun doute que l'idée même d'organiser les cellules en un tableau d' class Cellinstances est bien trop inefficace. Vous vous retrouverez avec un désordre de pointeurs et de données non contigus organisés comme une liste chaînée compliquée. Vous avez bien sûr la possibilité d'insérer facilement de nouvelles cellules dans votre liste: mais avez-vous besoin de cette fonctionnalité? Au contraire, vous aurez un stockage de données non contigu, et vous devrez accéder à chaque cellule par différents niveaux d'indirection.
Si vous organisez vos données sous forme de numpy.ndarraydonnées, alors les données sont contiguës à la mémoire, et l'accès à différentes cellules se fait simplement en parcourant votre bloc de mémoire: peu encombrant (pas de mémoire gaspillée pour les pointeurs) et rapide .
Comme l'a souligné Ethan, les concepts d'OO doivent être utilisés, mais à un niveau supérieur, une fois qu'une structure de données efficace de bas niveau a été mise en œuvre, généralement via numpy.ndarrayle s.
La programmation OO signifie la liaison des données aux méthodes qui opèrent sur les données elles-mêmes à un niveau d'abstraction plus élevé. (Un exemple: j'ai implémenté un code FEM dans lequel la matrice de rigidité a été définie comme une classe avec une méthode de factorisation cholesky super-nodale clairsemée. La première implémentation était in-core: lorsqu'une implémentation out-of-core était nécessaire, cette a été obtenu via l'héritage et des ajustements minimes au stockage des données soulignées. Près de 100% du code cholesky super-nodal a été réutilisé.)
Un dernier commentaire, mais crucial: une procédure numérique efficace est le résultat d'une cartographie intelligente d'un algorithme et d'une structure de données à votre architecture informatique cible. Si vous commencez avec la mauvaise structure de données, il n'y a aucun moyen de récupérer l'efficacité, sans une réécriture complète.
@EthanCoon Merci pour votre commentaire à l'autre réponse, qui m'a amené à écrire le mien.
Stefano M
10
J'y réfléchissais il y a quelques jours (également en Python). Personnellement, je ne pense pas que la programmation orientée objet soit toujours un bon choix pour la programmation numérique. Vous pouvez vous laisser distraire par la conception des classes plutôt que par la simple résolution des équations. Je préfère rester avec des fonctions simples, et avec numpy vous pouvez avoir vos équations vectorisées, donc le nombre de lignes dont vous avez besoin est très peu. Numpy est assez rapide car les calculs réels sont effectués avec un backend C (ou FORTRAN?).
Ce que je vous recommanderais de faire,
Écrivez un script Python qui résout la version la plus simple possible de votre problème en utilisant une approche fonctionnelle avec numpy. Par exemple, ayez tout en unités arbitraires et essayez 1D (ou 2D) uniquement. C'est très bien à ce stade si le code est en désordre. L'important est que vous avanciez dans votre projet.
Une fois que vous avez quelque chose qui fonctionne. Identifiez où le code est verbeux et réfracteur. À ce stade, vous pouvez jouer avec différentes idées sur la façon de simplifier votre code. Peut-être introduisez-vous des fonctions où vous remarquez que vous vous répétez. Vous pouvez comparer avec la version originale afin de savoir que vous n'introduisez pas de bogues.
Décidez si l'approche orientée objet réduira davantage la complexité du code.
Le message principal est de ne pas commencer à écrire des classes avant d'avoir résolu le problème de la manière la plus simple possible. Ce n'est qu'en acquérant l'expérience de la résolution d'un problème que vous saurez définir votre interface orientée objet. Si vous le faites à l'avance, il est probable que cela vous gêne.
Je suis fortement en désaccord avec l'affirmation selon laquelle l'OO n'est pas un bon ajustement pour la programmation numérique, mais où il est un bon ajustement est à un niveau beaucoup plus élevé. OO est très utile pour des choses comme les modèles physiques, les maillages, les solveurs, etc., mais est presque toujours inapproprié au niveau des cellules.
Ethan Coon
Dans le post, je voulais mettre en garde contre les pièges potentiels d'une «objectivation prématurée» du code numérique, en particulier lorsque l'on commence. Je ne suis pas opposé à l'utilisation d'objets, voir mon troisième point: si les objets peuvent réduire la complexité, ils sont une bonne idée. Je conviens que les exemples que vous citez sont de bonnes utilisations, mais pour y parvenir, il faut de l'expérience.
J'y réfléchissais il y a quelques jours (également en Python). Personnellement, je ne pense pas que la programmation orientée objet soit toujours un bon choix pour la programmation numérique. Vous pouvez vous laisser distraire par la conception des classes plutôt que par la simple résolution des équations. Je préfère rester avec des fonctions simples, et avec numpy vous pouvez avoir vos équations vectorisées, donc le nombre de lignes dont vous avez besoin est très peu. Numpy est assez rapide car les calculs réels sont effectués avec un backend C (ou FORTRAN?).
Ce que je vous recommanderais de faire,
Le message principal est de ne pas commencer à écrire des classes avant d'avoir résolu le problème de la manière la plus simple possible. Ce n'est qu'en acquérant l'expérience de la résolution d'un problème que vous saurez définir votre interface orientée objet. Si vous le faites à l'avance, il est probable que cela vous gêne.
la source