Journal Un Python qui rivalise avec du C++

15
27
août
2017

Rencontre avec un code de calcul scientifique open-source - écrit en Python - qui tente de rivaliser avec du C++ sur des supercalculateurs, spectralDNS!

Quelques liens:

La publication initiale : https://arxiv.org/pdf/1602.03638v1.pdf
Une seconde publication : https://arxiv.org/pdf/1607.00850.pdf
Une publication plus récente : https://arxiv.org/pdf/1701.03787v1.pdf
Le dépôt GitHub : https://github.com/spectralDNS/spectralDNS

Première réaction?

Je ne sais pas quelle est votre première réaction. Moi j'y croyais pas trop. Puis j'ai potassé les articles, j'ai fait quelques tests avec le code, j'ai contacté l'auteur principal, et ça semble être du solide!

Présentation

C'est un code de calcul pseudo-spectral pour les équations de Navier-Stokes. Il est donc fortement orienté vers la recherche fondamentale en mécanique des fluides / magnéto-hydrodynamique (donc les plasmas).

Le code de calcul dépend de plusieurs modules python pour gérer les communications entre processeurs et les transformées de Fourier (mpiFFT4py et mpi4py-fft), les structures de données spécifiques aux bases spectrales choisies (shenfun) et les accès disque (h5py).

Et c'est relativement bien documenté : il y a des cas tests et des cas de démonstration.

Perspectives

Le fait qu'un code écrit en Python soit aussi performant qu'un code écrit en C++, c'est la norme ou c'est l'apanage des mauvais codeurs C++ / des très bons codeurs Python? Avez-vous beaucoup d'exemples similaires?

  • # Précision

    Posté par  . Évalué à 5.

    Le journal ne le précise pas très bien, mais le code est bien adapté aux environnements massivement parallèles. Faut bien voir les perspectives sous cet aspect.

  • # Pas si choquant que ça

    Posté par  (site web personnel) . Évalué à 10.

    En effet, il y a un mot-clef important : numpy, qui est une bibliothèque de calcul scientifique pour Python, mais qui sous le capot utilise du C.

    Du coup, quand on utilise numpy au mieux de ses capacités, le code Python ne sert que de ciment à des appels de code C ; tout le boulot est fait par du C optimisé.

    • [^] # Re: Pas si choquant que ça

      Posté par  . Évalué à -9.

      L'important est la personne qui va coder. Apprendre le C est probablement plus ardu que le python. Puis, si on réfléchis comme ça, l'interpréteur python n'est-il pas codé en C? Au final, C fait tout le boulot de toute manière, n'est-ce pas?

    • [^] # Re: Pas si choquant que ça

      Posté par  (site web personnel) . Évalué à 10.

      le code Python ne sert que de ciment à des appels de code C

      C'est d'ailleurs le cas pour la plus part des bibliothèques Python. En caricaturant un peu on pourrait dire que Python n'est qu'une sur-couche du C :-)

      kentoc'h mervel eget bezan saotred

      • [^] # Re: Pas si choquant que ça

        Posté par  . Évalué à 2.

        Faux: la plupart des bibliothèques sont écrites en python, qui génèrent du bytecode qui est ensuite exécuté par une machine virtuelle.

        Pour des raisons de perf, il est possible (quoi que j'ai un doute) que certaines libs standard soient des "appels de code C" (le terme à mon avis est mal choisi), mais ce n'est pas le cas de la plupart des bibliothèques que l'on trouve partout.

        numpy diffère de la plupart des bibliothèqies python par le fait que cette bibliothèque ne génère pas de bytecode, mais appelle directement du code exécutable, compilé par un compilateur C avec une interface adéquate (un peu comme JNI pp
        our Java
        ). On bypasse la couche bytecode + Virtual machine pour exécuter du code natif à la plate-forme directement par le processeur (je schématise/raccourcis beaucoup, mais c'est le principe de base).

        En caricaturant un peu on pourrait dire que Python n'est qu'une sur-couche du C :-)
        Bof … Peut-être en considérant que le bytecode est une surcouche du C, mais dans ce cas, quid de jython ?

        • [^] # Re: Pas si choquant que ça

          Posté par  (site web personnel) . Évalué à 10.

          mais ce n'est pas le cas de la plupart des bibliothèques que l'on trouve partout.

          Pour ce que ça vaut, sur 80 modules Python que j’ai installé moi-même, j’en compte 35 qui comportent une partie compilée en bibliothèque ELF.

          Ce n’est peut-être pas « la plupart », mais ce n’est pas rare non plus.

          • [^] # Re: Pas si choquant que ça

            Posté par  . Évalué à 1.

            Hum, c'est peut-être les 35 modules de base utilisés par un tas de module plus haut niveau (je dis ça mais je sais rien non plus).

      • [^] # Re: Pas si choquant que ça

        Posté par  . Évalué à 10.

        C'est le cas pour la plupart des langages haut niveau bien pensés, et c'est d'ailleurs exactement ce qu'ils sont censés faire. Tu codes dans un langage de haut niveau pour gérer les entrées-sorties, la gestion des erreurs, la portabilité, l'évolutivité du logiciel, etc. Et les quelques parties gourmandes en temps de calcul, tu enchaines les appels de fonctions optimisées prises dans les bibliothèques du langage, et souvent codées en C (ou en assembleur, ou en n'importe quoi du moment que c'est efficace) par des gens qui savent le faire.

        Au final, sur une application scientifique par exemple, il est très rare d'avoir besoin de coder soi-même une partie au cœur de l'algorithme (d'ailleurs, c'est souvent inenvisageable, parce qu'on ne peut pas vraiment être à la fois une pointure dans un domaine scientifique et en programmation bas niveau). Tu vas mettre en place ton modèle, stocker tes objets, analyser les sorties, etc, et tu vas leur appliquer des opérations de calcul "standard" : appel à des générateurs de nombres aléatoires qui tirent dans des distributions spécifiques, optimisation de fonctions multivariées, inversion de matrices, parcours d'arbres, etc etc. Évidemment, tout dépend du problème et de la compétence téchnique autour de soi, mais dans certains domaines, l'analyse de données scientifiques revient souvent à scripter un «pipeline» qui enchaine des opérations successives ou parallèles de traitement de données. Ça n'est pas le même métier que de mettre au point les algorithmes eux-mêmes…

  • # Numpy FTW

    Posté par  . Évalué à 10.

    J'ai survolé le code source ; sous le capot ça fait des appels à numpy, qui est codé en C. Donc ton python ne sert qu'à coller ensemble du code en C, donc oui c'est rapide, forcément.

    Le fait qu'un code écrit en Python soit aussi performant qu'un code écrit en C++, c'est la norme

    Pas du tout. Python est intrinsèquement plus lent que C, ne serait-ce parce qu'il n'existe pas de compilateur pour. Certains interpréteurs sont plus ou moins performants, mais aucun ne bat généralement du code natif.

    • [^] # Re: Numpy FTW

      Posté par  . Évalué à 6.

      Pour gagner encore plus tu peux utiliser pythran. Il converti le code python en c++ (gérant au passage openmp), et ainsi avec quelques petites retouches (bien séparer la partie algorithme utilisant numpy du reste) tu as la même chose en plus performant. C'est assez bluffant(même si c'est pas encore parfait)

  • # ni l'un ni l'autre, c'est du C

    Posté par  . Évalué à 10. Dernière modification le 27 août 2017 à 23:39.

    La force de python c'est de très bien s'interfacer à des bibliothèques de calculs en C.
    Et du coup, c'est du bonheur à utiliser.

    • [^] # Re: ni l'un ni l'autre, c'est du C

      Posté par  . Évalué à 7.

      Oui, mais mon impression, c'est que dans le domaine du calcul parallèle haute-performances, en particulier pour la mécanique des fluides, on bidouille surtout du fortran / C / C++, et on utilise peu de python / langages de haut-niveau.

      Je dirais que l’efficacité des langages de haut niveau sur des plateformes massivement parallèles n'est pas encore évidente pour tout le monde, moi le premier. C'est pour ça que j'ai fait un journal.

  • # Cython inside

    Posté par  (site web personnel) . Évalué à 10.

    lu dans le README

    The efficiency of the pure NumPy/mpi4py solver has been enhanced using Cython for certain routines.

    Donc triche :-) Ce n'est plus du Python mais un langage hybride…

  • # Python pour scripter, C/C++ sous la capot.

    Posté par  (site web personnel) . Évalué à 10. Dernière modification le 28 août 2017 à 11:40.

    Je travaille en environnement où le calcul distribué haute performance est la norme.
    Et oui c'est courant de voir du Python sur super-calculateur.

    Simplement parce que python est facile à prendre en main, la barrière d'entrée est basse, et n'importe quel scientifique arrive à pondre quelque chose qui tombe en marche en python…

    C'est souvent fait avec les pieds, c'est souvent illisible et pas portable. Ils sont souvent des cancre du software engineering…. Mais ils s'en fichent, ils veulent simplement leur résultat, pas redévelopper le monde.

    Le fait qu'un code écrit en Python soit aussi performant qu'un code écrit en C++, c'est la norme ou c'est l'apanage des mauvais codeurs C++ / des très bons codeurs Python? Avez-vous beaucoup d'exemples similaires?

    Comme dit plus haut, la force de python en environnent scientifique / HPC vient du fait que TOUTES ses librairies critiques sont codés en C/C++, donc avec les performances de C/C++.

    Et accessoirement, que c'est relativement trivial d'interfacer python avec un module C.

    Les performances d'un code python purement python sont généralement entre horribles, et complétement affigeantes . Mais en pratique ce n'est souvent pas un problème, car 80/90% des sections critiques du code scientifique sont en C/C++ dans des routines numpy / scipy / pandas / BLAS / FFTW / HDF5 ou dans une section C/C++ d'un simulateur maison.

    Bref :

    • Python pour le scripting c'est bien mangez en.
    • Si vous voulez faire un soft scientifique HPC, codez le en C, C++ ou Rust et donnez lui une interface python.
    • [^] # essayer Julia ?

      Posté par  (site web personnel) . Évalué à 5.

      Effectivement, la capacité d'interfaçage est aujourd'hui une clef importante.

      Pour ma part, j'ai complètement craqué pour Julia, qui me permet de résoudre le problème des deux langages (auparavant j'alternais entre C/C++ et scilab). J'ai beaucoup gagné en vitesse d'écriture par rapport au C/C++ avec une perte de vitesse d'exécution très raisonnable.
      C'est un petit peu dommage que tout le monde n'ait que Python a la bouche, c'est un peu le handicap pour le développement de Julia.

      • [^] # Re: essayer Julia ?

        Posté par  . Évalué à 1.

        Je compte bien tester! Je suis en attente de ce module : https://summerofcode.withgoogle.com/projects/#5245954998403072

      • [^] # Re: essayer Julia ?

        Posté par  . Évalué à 10.

        C'est un petit peu dommage que tout le monde n'ait que Python a la bouche, c'est un peu le handicap pour le développement de Julia.

        Le problème, c'est que tu peux passer ta vie à apprendre de nouveaux langages « plus optimisés pour ceci » ou « plus rapides pour cela ». Depuis 8 ans, j'ai appris 14 langages différents, en approfondissant peut-être deux d'entre eux. À un moment donné, tu choisis un langage, même si c'est pas le plus classe pour ton usage, et tu t'y tiens, autrement, ça ne finit jamais.

        Python a l'avantage d'être facile à lire et de permettre de coder aussi bien de l'appli desktop, des jeux, des AI, du calcul, du web,… L'apprendre est un investissement bien placé. Après, le truc aussi c'est que beaucoup de dev utilisent Python comme du pseudocode schématique, sans tirer parti des spécificités syntaxiques et structurelles qu'il offre. Par exemple, le module itertools accélère de façon dramatique les tours de boucle sur des itérables. La plupart des scientifiques qui ont été formés sur Matlab et qui apprennent Python à la volée ne savent même pas qu'il existe. Soient ils vont utiliser les opérations matricielles comme Matlab (ce qui n'est possible qu'avec des variables de dtype=float), soient ils vont coder des boucles FOR.

        Et le problème, c'est que comme Python a l'air simple, peu de gens prennent le temps d'apprendre ses finesses et de tirer parti de ses raccourcis.

        Voir aussi : https://www.ibm.com/developerworks/community/blogs/jfp/entry/Python_Meets_Julia_Micro_Performance?lang=en

        • [^] # Re: essayer Julia ?

          Posté par  . Évalué à 10.

          La plupart des scientifiques […] ne savent même pas qu'il existe

          Ce genre de trucs, c'est quand même assez récurrent, et à mon avis c'est quand même en grande partie attribuable à des défauts des langages de programmation. On vit dans un monde où il y a des dizaines de langages populaires, et des centaines si on ajoute des trucs comme Julia. Tous les ans, des dizaines de nouveaux langages apparaissent. Dès qu'on fait un peu de programmation, il faut être polyglotte, et si la programmation n'est pas le cœur de métier, alors on peut s'attendre à ce que la règle générale soit de ne pas maitriser les spécificités du langage.

          Or, ces langages ont l'air d'être conçus par et pour des gens qui vont en connaitre tous les détails, tout ce qui est mal documenté, tout ce qui n'est pas intuitif, et que c'est de la faute du programmeur s'il ne connait pas ces "finesses". Je trouve que c'est une excuse qui fait injustement reporter la faute sur les utilisateurs et pas sur les concepteurs des langages. Un moment donné, est-ce qu'il n'est pas naturel de s'attendre à ce que la meilleure manière de faire une boucle FOR, c'est de faire une boucle FOR?

          La fragmentation, c'est aussi un problème dans ce genre de cas. On a parlé de Julia, par exemple, qui arrive dans un contexte où il y a déja de nombreux langages "scientifiques" et de nombreuses possibilités ; dans une équipe de recherche de 10 personnes, on trouve parfois 10 langages différents : C, C++, Fortran, Ada, OCalm, R, Python, Perl, MatLab, plus les pseudo-langage des logiciels spécialisés (SAS, Mathematica… ), les langages de script, etc. Encore une fois, tout ça vient en plus de la formation scientifique, les gens utilisent ces outils pour arriver à leurs fins, mais la programmation n'est pas leur métier. Et là, paf, «Pourquoi tu ne fais pas du Julia?», «Pourquoi ne pas regarder du côté de Ruby?», «L'avenir, c'est le Go.», etc. Alors oui, tout cela part d'une bonne intention, mais il faut bien comprendre qu'on ne remplace pas un langage par un autre, tout ça se juxtapose. Quand on incite à utiliser Julia pour les nouveaux projets, on peut éventuellement gagner un peu en productivité, mais quid de la maintenance du code une fois que le post-doc ou le doctorant sera parti? Quid du temps de formation, et du manque de support local? Évidemment, ça n'est pas une raison pour ne jamais évoluer, et c'est vrai que des trucs comme Ada, Fortran, ou même C tendent à disparaitre peu à peu, mais ça n'est pas une raison pour refaire pour la 1000e fois le coup du "apprenez ce truc nouveau, ça vous fera gagner du temps". Au final, plus personne ne maitrise réellement chaque langage, ça diminue la qualité du code, et ça n'apporte pas grand chose.

          • [^] # Re: essayer Julia ?

            Posté par  . Évalué à 6.

            Un moment donné, est-ce qu'il n'est pas naturel de s'attendre à ce que la meilleure manière de faire une boucle FOR, c'est de faire une boucle FOR?

            Non, quand tu as fait des maths, la manière la plus naturelle d'éviter une boucle FOR, c'est de vectoriser ton calcul. Sinon, tu fais du C pur.

            Avec un langage interprété comme Python, quand tu sais comment c'est fait sous le capot, tu utilises le moins possible ton code comme un langage et le plus possible comme une interface avec des modules C ou Fortran optimisés qui vont effectivement se taper les calculs.

            Dès que tu vises du code qui ne fait pas « juste marcher » mais marche vite, tu es bien obligé de rentrer dans les détails bas niveau, même si la programmation n'est pas ton métier. Utiliser des entiers 8 bits à la place de flottants 64 bits quand ça n'est pas nécessaire, arrêter de stocker 3 copies de la même matrice dans 3 variables différentes que tu ne réutiliseras plus, mettre en cache des fonctions, utiliser des compilateurs JIT, feeder tes itérations à un sous-module C au lieu de les recoder, etc.

            Évidemment, ça n'est pas une raison pour ne jamais évoluer, et c'est vrai que des trucs comme Ada, Fortran, ou même C tendent à disparaitre peu à peu, mais ça n'est pas une raison pour refaire pour la 1000e fois le coup du "apprenez ce truc nouveau, ça vous fera gagner du temps". Au final, plus personne ne maitrise réellement chaque langage, ça diminue la qualité du code, et ça n'apporte pas grand chose.

            C'est exactement ce que je dis.

            • [^] # Re: essayer Julia ?

              Posté par  . Évalué à 8.

              Non, quand tu as fait des maths, la manière la plus naturelle d'éviter une boucle FOR, c'est de vectoriser ton calcul. Sinon, tu fais du C pur.

              Le lien entre les maths et la programmation est ténu, en plus d'être souvent dangereux. L'idée d'adopter une pensée mathématique quand on code ne me semble pas une bonne idée du tout.

              En plus, je ne suis même pas certain que ça soit vrai. Assez souvent, le formalisme mathématique utilise l'équivalent de boucles FOR (sommes et produits) ; le recours à l'algèbre linéaire est loin d'être systématique, et me semble inexistant dans certains domaines (suites, systèmes dynamiques?). D'autre part, les notations d'algèbre linéaire sont souvent compactes (typiquement, les successions de produits de matrices inversées et transposées), mais sont très inefficaces en terme de calcul. Bref, pas concaincu du tout qu'il soit naturel de vectoriser, surtout quand on code dans un langage qu'on connait mal. Ça me semble être un peu un argument a posteriori, la logique de la vectorisation est très puissante quand le langage est organisé autour de ça, mais il n'y a pas de raison a priori qu'elle paraisse plus naturelle qu'une autre.

              tu es bien obligé de rentrer dans les détails bas niveau

              Pas forcément, tu peux déja optimiser énormément en restant à haut-niveau, et les compilateurs sont aussi censés t'aider à ne pas micro-optimiser le code. Il arrive d'ailleurs souvent en C++ par exemple qu'une optimisation "logique" (par exemple, retourner un résultat par référence plutôt que par valeur) ralentisse le programme, parce que le compilateur l'avait déja fait, et de manière plus efficace qu'à la main. J'ai récemment essayé de plonger un peu dans la micro-optimisation d'une fonction critique en C++, et à mon niveau de compréhension, tout ça s'est avéré relever de la magie noire ; tout fonctionne sans optimisation, mais dès qu'on est en O2 ou O3, l'effet des changements (par exemple jouer avec le nombre et l'ordre des tests conditionnels) est totalement imprévisible, ce qui me donne à penser que plus on fait des trucs sioux et plus on gène le compilo plutôt qu'autre chose.

              • [^] # Re: essayer Julia ?

                Posté par  . Évalué à 3.

                Le lien entre les maths et la programmation est ténu, en plus d'être souvent dangereux. L'idée d'adopter une pensée mathématique quand on code ne me semble pas une bonne idée du tout.

                Tu veux dire que les RBTree c'est plus lent qu'un mathématicien ne l'imaginerai (à cause du fait que ce soit une chiée de pointeurs avec donc des accès mémoires probablement très fragmentés qui pourrissent le cache)? Quelle surprise :p

                Pas forcément, tu peux déja optimiser énormément en restant à haut-niveau

                Qu'appelles-tu haut et bas niveau, en optimisation?

                Par exemple, optimiser ton architecture pour exploiter au maximum la taille des lignes de cache, c'est du haut, ou du bas niveau?

                par exemple, retourner un résultat par référence plutôt que par valeur

                Retourner une référence sur une structure plus petite plus petite que la taille d'un pointeur n'est pas une optimisation… donc ce n'est pas une optimisation "logique".
                En plus, cette optimisation la, elle dépend de la version du langage et de l'âge du compilo: si c'est du C++98, tu n'auras pas la move semantic et donc en moyenne (dans les cas ou, bien sûr, l'objet n'est pas construit par ta fonction) tu auras de meilleures perf qu'en passant par valeur, à cause du fait que tu auras des appels inutiles au constructeur et destructeur. Je dis bien, en moyenne, hein.
                Du coup, c'est plutôt faire la passation par valeur qui est une optimisation par rapport à l'historique.
                Ceci étant dit, j'ai rarement vu des retours de référence, sauf pour la surcharge d'opérateurs. En général, j'ai plutôt vu des retours de pointeurs (pas forcément mieux, je ne fais que constater) ce qui a le mérite d'être plus explicite, je dirais (et d'éviter une copie silencieuse potentiellement mal placée).

                tout ça s'est avéré relever de la magie noire ; tout fonctionne sans optimisation, mais dès qu'on est en O2 ou O3

                Si ton «optimisation» se base sur du cas indéfini, alors oui, tu risques d'être vite fait dans la merde quand le compilo se mets à interpréter différemment les choses.

                par exemple jouer avec le nombre et l'ordre des tests conditionnels

                Ça, ça sent le mélange d'opérateurs post/pré-incrémentation (ou décrémentation, pour ce que ça vaut)…

                Je suis curieux, as-tu la possibilité de nous montrer un exemple?

                • [^] # Re: essayer Julia ?

                  Posté par  . Évalué à 2.

                  Par exemple, optimiser ton architecture pour exploiter au maximum la taille des lignes de cache, c'est du haut, ou du bas niveau?

                  Pour moi, c'est du très bas niveau. Classiquement, dans mon domaine de recherche (biologie/bio-info), tu n'as aucune idée de la machine sur laquelle ton code va tourner (ça va de ton portable à un gros calculateur, en passant par des clusters pas homogènes). Bref, très difficile d'écrire du code spécifique pour une machine.

                  ce qui a le mérite d'être plus explicite, je dirais

                  Bof, des pointeurs à poil en C++ moderne…

                  Je suis curieux, as-tu la possibilité de nous montrer un exemple?

                  Pas évident sans refiler tout un tas de code imbittable. De mémoire, ça ressemblait à des tentatives d'éviter des multiplications par zéro:

                  double result = fun1();
                  
                  const bool is_a_zero = (a==0.);
                  const bool is_b_zero = (b==0.); // + the same for is_c_zero etc. 
                  
                  if (!is_a_zero) {
                    for (unsigned int i = 0; i < BIGSTUFF; i++)
                       result += a*fun2(i);
                  }
                  
                  if (!is_b_zero) {
                    for (unsigned int i = 0; i < BIGSTUFF; i++)
                      result += b*fun3(i);
                  }
                  

                  C'est simplifié mais c'est l'idée. Les variables a et b sont lues dans un fichier de paramètres (donc inconnues du compilo). Je ne me rappelle plus exactement des résultats, mais en fonction des valeurs du couples is_a_zero et is_b_zero, on se retrouvait à préférer les versions avec test ou sans test sans vraiment de logique. Ça me faisait penser à un compilo qui prévoit un certain nombre de combinaisons de branches, mais pas toutes (sur quelle base? Aucune idée). Du coup, quand on passe par une combinaison de branchements prévue, ça va vite, mais quand la combinaison n'est pas prévue, il faut se taper une série de tests conditionnels, et c'est lent ; ça irait plus vite de faire les multiplications par zéro.

                  J'en ai conclu que le résultat de telles optimisations était au mieux inégal, et au pire imprévisible.

                  • [^] # Re: essayer Julia ?

                    Posté par  . Évalué à 2.

                    Bref, très difficile d'écrire du code spécifique pour une machine.

                    En effet.
                    Ceci dit, ce niveau d'optimisation (optimiser pour exploiter le fait qu'une ligne de cache à une taille définie) à plusieurs paliers aussi: par exemple dans une classe mettre les membres les moins utilisés à la fin, ou tout simplement faire gaffe à l'alignement des données en fonction de la taille du type (tiens d'ailleurs… je me demande comment ça marche ce genre de problématiques dans les langages sans typage statique?).
                    Ces cas restent des cas d'optimisation qui sont relativement simples à mettre en œuvre et ne dépendent pas (trop) de la machine cible. Ça n'implique d'ailleurs pas non plus de repenser toute l'archi.

                    Pour le coup, on peut même simplement se dire qu'un bloc de données qui sont rarement utilisées, plutôt que de les mettre dans la même classe que des trucs utilisés en permanence, stocker une référence (dans le sens français du terme, pas C++: ça peut être un id, un itérateur, un pointeur, peu importe) qui permets d'accéder à ces données peu usitées permets d'augmenter la densité des données utiles (si l'objet est utilisé dans un tableau, bien entendu).

                    Bon, certes, c'est pas «optimiser au maximum», juste optimiser un poil :)

                    ce qui a le mérite d'être plus explicite, je dirais
                    

                    Bof, des pointeurs à poil en C++ moderne…

                    Bah… à moins de bricoler un pointeur qui ne peut être libéré (ce qui à tendance à être mon choix, pour le coup), y'a moyennement le choix. Sinon, faut utiliser shared_ptr, et la on passe de (sur une machine classique) 8 octets à 24 (pointeur + compteur + deleter quand on veut utiliser ça pour des structures C, 16 si on prend juste le delete par défaut de l'objet stocké) du coup ça peut piquer pour les perfs.

                    Pas évident sans refiler tout un tas de code imbittable.

                    Tant pis alors. Parce qu'effectivement la je ne vois pas comment ça peut tomber dans un comportement non défini.

                    • [^] # Re: essayer Julia ?

                      Posté par  . Évalué à 2.

                      y'a moyennement le choix

                      Le choix, ça pourrait être de coder avec des retours par valeur et de laisser le compilo gérer, ce qu'il fait plutôt bien quand le code est clair. En tout cas, c'est ce que j'ai tendance à faire à mon niveau.

                      Mais bon, j'avoue que je surestime souvent les capacités du compilo à faire des trucs intelligents, notamment pour la gestion de la mémoire. Par exemple, quand on a une fonction qui alloue de la mémoire, fait un traitement, et désalloue la mémoire, appeller la fonction n fois dans une boucle for réalloue et désalloue n fois la mémoire, ce qui me semble assez abérrant. Moi ça me file des boutons en C++11 de refiler des pointeurs vers de la mémoire libre en paramètre des fonctions ou de passer des gros objets par références non-constantes, j'ai l'impression que c'est du mélange crado de paradigmes. Étrangement, ce genre de code est beaucoup plus performant dans certains langages de haut niveau qui vectorisent les appels de fonction.

                      je ne vois pas comment ça peut tomber dans un comportement non défini.

                      Je me suis peut-être mal exprimé, mais je n'ai jamais eu de problème avec le comportement du code, seulement avec le temps d'exécution (donc je ne parlais pas du tout de comportement non-défini). Mon problème, c'est que le temps d'exécution du code compilé avec un niveau d'optimisation agressif par le compilo n'était pas compréhensible (tout du moins par moi), avec des temps d'éxécution qui variaient substantiellement et visiblement de manière chaotique en fonction de l'ordre et du nombre de tests conditionnels.

                      • [^] # Re: essayer Julia ?

                        Posté par  . Évalué à 2.

                        . Par exemple, quand on a une fonction qui alloue de la mémoire, fait un traitement, et désalloue la mémoire, appeller la fonction n fois dans une boucle for réalloue et désalloue n fois la mémoire, ce qui me semble assez abérrant.

                        Fonction potentiellement mal codee. Ou boucle for mal foutue, au choix.
                        Perso, vite fait, je me dis autant allouer la memoire dans une variable statique de la fonction, et avoir un moyen de faire un appel pour liberer si necessaire.
                        Ou alors filer un buffer, pour eviter que la fonction n'alloues elle meme.
                        Mais, oui, ca necessite de savoir qu'un appel systeme c'est lent et de prendre ca en compte quand on code.

                        Moi ça me file des boutons en C++11 de refiler des pointeurs vers de la mémoire libre en paramètre des fonctions ou de passer des gros objets par références non-constantes, j'ai l'impression que c'est du mélange crado de paradigmes.

                        Pourquoi? Le cpp est prevu pour interegir avec le systeme, donc pour les effets de bord (meme si, certes, moins y'en a mieux c'est). Ce n'est pas un langage fonctionnel…
                        Et justement pour moi la force de ce langage c'est qu'il ne m'enferme pas dans une facon de penser: je n'ai pas a toujours faire des classes pour que dalle (java), mais je peux si je veux (c). Je peux faire du fonctionnel (avec const) mais je peux aussi facilement interagir avec le systeme. J'ai meme de la prog generique que je crois puissante.

                        Le fait de pouvoir passer des buffers, ca permets justement aux gens de reduire le nombre d'allocations et donc de syscalls.

                        Étrangement, ce genre de code est beaucoup plus performant dans certains langages de haut niveau qui vectorisent les appels de fonction.

                        Puis-je etre curieux et avoir un exemple? Je ne serais pas surpris qu'ils soient plus simples a gerer, mais plus rapides? Ca m'intrigue.

                        • [^] # Re: essayer Julia ?

                          Posté par  (site web personnel) . Évalué à 3.

                          Perso, vite fait, je me dis autant allouer la memoire dans une variable statique de la fonction, et avoir un moyen de faire un appel pour liberer si necessaire.

                          Les variables statiques, à l'ère du multi-threading hyper courant, c'est une mauvaise idée, puisque ta fonction ne sera pas ré-entrante. Personnellement je transformerai cette fonction en une classe avec une méthode (au moins) ; l'allocation du buffer irai dans le constructeur (RAII et compagnie, et donc la désallocation dans le destructeur évidemment), et le traitement principal dans ladite méthode. Si la méthode n'est pas protégée pas un mutex (pour être un poil plus rapide), l'objet ne devrait pas être partagé par différents threads (malheureusement C++ ne permet pas de vérifier ce genre de mauvais usage à la compilation), mais au moins chaque thread peut créer/utiliser sa propre instance sans souci.

                          • [^] # Re: essayer Julia ?

                            Posté par  . Évalué à 1.

                            D'où le «vite fait»: c'est plus rapide de faire ce genre de bidouille que recréer une classe ;)

                            • [^] # Re: essayer Julia ?

                              Posté par  (site web personnel) . Évalué à 5.

                              J'imagine que c'est de l'humour, mais vu l'incubateur d'excellence qu'est LinuxFr, je vais quand même répondre. :)

                              À part des cas très spécifiques, par exemple toutes ces conditions sont vérifiées:

                              • on n'a pas de thread donc pas possible que ça introduise un bug.
                              • on a vérifié que l'optimisation règle effectivement un problème en production très critique.
                              • on doit livrer très rapidement une version qui corrige ledit problème mais sans casser l'API, et derrière on fera une version avec une nouvelle API correcte (celle que je proposait par exemple) (on peut même garder la vieille API en "deprecated").

                              soit on garde la vielle version (lente mais correcte), soit on fait une version rapide et correcte (ce qui en l'occurrence n'était pas bien long, les lignes en plus n'étant quelques déclarations). Mais conseiller en premier une bidouille infâme ne me semble pas une bonne chose ; le C++ est déjà assez piégeux comme ça.

              • [^] # Re: essayer Julia ?

                Posté par  . Évalué à 5. Dernière modification le 08 septembre 2017 à 17:05.

                Le lien entre les maths et la programmation est ténu, en plus d'être souvent dangereux. L'idée d'adopter une pensée mathématique quand on code ne me semble pas une bonne idée du tout.

                J'imagine, comme GuieA_7, que c'est de l'humour, mais vu l'incubateur d'excellence qu'est LinuxFr, je vais quand même répondre. :)

                En mathématique, on a tout de même l'habitude d'apporter des preuves de ce que l'on affirme et non de lancer des affirmations en l'air. Tentons de réfuter le propos.

                Déjà il me semble bien que Gödel, Church, Turing et Von Neumann étaient avant tout des mathématiciens et logiciens. J'ai là, sous les yeux, l'article de Turing où il expose son concept de machine et celui-ci est intitulé Théorie des nombres calculables, suivie d'une application au problème de la décision. Il traite ce fameux problème à la section 8 et montre son caractère insoluble : c'est le fameux problème de l'arrêt. Le problème en question fut posé par Hilbert et renvoie au deuxième des 23 qu'il posa au deuxième congrès international des mathématiciens, tenu à Paris en août 1900.

                Ceci étant dit, on s'étonnera moins du fait que le laboratoire Preuves, Programmes, Systèmes (PPS) de l'Institut de Recherche en Informatique Fondamentale, associée à l'équipe de logique de l'Institut Mathématique de Jussieu, propose un master intitulé Logique Mathématique et Fondements de l'Informatique.

                On s'étonnera moins, également, d'un résultat notoirement connu chez les théoriciens sous le nom de correspondance preuve-programme ou corresponcance de Curry-Howard : un programme est la preuve d'un théorème et l'énoncé de ce dernier est le type du programme. Dans cette lignée de pensée, on trouve le système F (ou lambda-calcul polymorphe) de Jean-Yves Girard qui est la base des langages (et de leur système de type) comme Haskell ou OCaml. Le système F date tout de même de 1972 et fut mis au point, entre autre, pour résoudre la conjecture de Takeuti qui généralise un résultat obtenu par Gentzen dans les années 30 afin de résoudre le fameux deuxième problème de Hilbert.

                Illustration rapide avec le calcul de la longueur d'une liste chaînée :

                let rec length = function
                  | [] -> 0
                  | _ :: tl -> 1 + length tl
                
                let length_tr l =
                  let rec loop acc = function
                    | [] -> acc
                    | _ :: tl -> loop (acc + 1) tl
                  in loop 0 l

                Déjà, on peut faire de la récursivité sans boucle for ni boucle while. La première version a un gros défaut : on risque le débordement de pile, la deuxième utilise un espace constant sur la pile (c'est l'équivalent d'une boucle for ou while). Mais les deux miment un principe de raisonnement standard en mathématique : le raisonnement par récurrence. Si une propriété est vraie de 0 (P 0), puis qu'elle passe au successeur (si Pn alors P(n+1)) alors elle est vraie pour tout entier (pour tout n, Pn). En réalité seule la deuxième utilise ce principe, la première utilise l'hypothèse de récurrence sous la forme : si pour tout m ≤ n, Pm alors P(n+1). Autrement dit, il faut garder sur la pile toutes les preuves depuis 0 pour passer à l'étape suivante : on risque le débordement de pile sur une machine. ;-)

                Je pourrais continuer comme cela pendant longtemps mais, pour des langages comme le C, on pourra se reporter à l'excellent tutoriel Introduction à la preuve de programmes C avec Frama-C et son greffon WP sur le site zeste de savoir. Frama-C développé en partenariat par le CEA list et l'Inria.

                Frama-C est une plateforme d’analyse de codes sources. Elle met en œuvre des techniques d’interprétation abstraite, de vérification déductive, de slicing et d’analyse dynamique dont la caractéristique commune est de reposer sur des méthodes formelles qui assurent que leurs résultats sont rigoureusement corrects. Dans une dynamique open-source, cette plateforme permet non seulement le développement d’approches variées par une communauté d’utilisateurs divers, mais aussi de combiner ces approches pour atteindre des objectifs de validation ambitieux. Ces analyses sont particulièrement adaptées à des programmes dans lesquels la sûreté de fonctionnement, ou la sécurité face aux actions malveillantes, est essentielle.

                Pour conclure rapidement, sur les mathématiciens qui ne comprennent pas le problèmes de cache (ça, c'est pour freem). Voyons voir le calcul matriciel. Un matrice carré simple comme

                1 2 3
                4 5 6
                7 8 9
                

                est représentée en mémoire ligne par ligne 1 2 3 4 5 6 7 8 9 pour le C, ou colonne par colonne par 1 4 7 2 5 8 3 6 9 en Fortran. Résultat dans un langage comme le C si on parcourt une matrice ligne par ligne ça va plus vite et on a moins de cache miss sur de grosses matrices. Pour faire le produit, on peut par exemple transposer d'abord la seconde matrice avant de faire la boucle for qui calcule le produit pour avoir à parcourir les deux matrices ligne par ligne.

                On peut aussi découper les matrices très grandes récursivement en matrice plus petite selon le procédé de la courbe de Lebesgue

                courbe lebesgue

                courbe Z

                comme cela on linéarise la représentation en mémoire de notre matrice en suivant la courbe et les petites matrices rentre bien sur une ligne de cache. Ensuite on fait du Map-Reduce pour opérer sur la grande matrice à partir des petites, ce qui en plus à l'avantage de bien se paralléliser.

                On peut aussi utiliser, comme alternative, la courbe de Hilbert :

                Pour les bases de données multi-dimensionnelles, la courbe de Hilbert a été proposée à la place de la courbe de Lebesgue parce qu'elle a un comportement préservant mieux la localité.

                courbe de Moore

                C'est joli et utile les fractales ! :-)

                Alors toujours convaincu que : « Le lien entre les maths et la programmation est ténu, en plus d'être souvent dangereux. L'idée d'adopter une pensée mathématique quand on code ne me semble pas une bonne idée du tout » ?

                Ou je peux conclure comme un récent commentaire d'arnaudus :

                En face de certains bistros, il y a des universités, et dans les universités, il y a des gens qui travaillent sérieusement sur de telles questions ; il existe par exemple des discipline scientifiques qui s'appellent Informatique et Mathématique et qui permettent d'aller un peu plus loin que les platitudes habituelles.

                Désolé pour la conclusion, mais c'était de bonne guerre. ;-)

                Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

                • [^] # Re: essayer Julia ?

                  Posté par  . Évalué à 3.

                  Tu détournes habilement le sujet, mais je pense que tu as tort sur le fond. Les mathématiques fournissent évidemment des raisonnements et des résultats qui peuvent être utiles en informatique, et même éventuellement, parfois, dans la pratique quotidienne de la programmation (typiquement, en algorithmique).

                  Mais je ne sais pas si tu as fait semblant de mal comprendre là où je voulais en venir, ou si je ne m'étais pas exprimé clairement. La question qu'on discutait, c'était de dire que la vectorisation était une manière intuitive en mathématique d'aborder un problème, et que les gens qui considéraient une boucle FOR plus intuitive qu'un calcul vectorisé avaient, en gros, un problème de formation. Or, c'est à mon avis faux. Très souvent, la pensée mathématique est catastrophique en programmation. En calcul numérique, l'utilisation de la définition mathématique est souvent une très mauvaise idée : pour calculer une intégrale, une dérivée, ou même simplement une variance, "penser mathématique" ne mène qu'à des algos inefficaces.

                  Bref, le fait que certaines applications des mathématiques soient utiles en algorithmique n'invalide absolument pas le fait que quand on code dans la plupart des langages (qui sont destinés à produire des logiciels et pas des démonstrations mathématiques), on doit avant tout penser aux aspects informatiques des problèmes (efficacité de l'algorithme en temps et en mémoire, gestion des arrondis, évolutivité, modularité et clarté du code). Dans ce cadre, les maths sont un outil, et pas un état d'esprit.

                  • [^] # Re: essayer Julia ?

                    Posté par  . Évalué à 5.

                    Tu détournes habilement le sujet, mais je pense que tu as tort sur le fond.

                    Je ne pense pas détourner le sujet, et je pense fondamentalement avoir raison sur le fond. ;-)

                    quand on code dans la plupart des langages (qui sont destinés à produire des logiciels et pas des démonstrations mathématiques), on doit avant tout penser aux aspects informatiques des problèmes (efficacité de l'algorithme en temps et en mémoire, gestion des arrondis, évolutivité, modularité et clarté du code). Dans ce cadre, les maths sont un outil, et pas un état d'esprit.

                    Et les concepts que tu mets en branle, dans ton esprit, quand tu penses aux aspects informatiques des problèmes, ils relèvent de quelle science à ton avis ? ;-) Je t'ai donné l'exemple d'une équipe membre de l'Institut de Recherche en Informatique Fondamentale qui s'associe avec une autre équipe de l'Institut Mathématique de Jussieu pour dispenser une formation intituler Logique Mathématique et Fondements de l'Informatique, et tu ne vois toujours pas le rapport ?

                    Tu me fais penser à M. Jourdain : il faisait de la prose sans le savoir mais, quand on lui a expliqué ce qu'était la prose, il a au moins reconnu qu'il en faisait. Toi c'est un peu différent, tu fais des mathématiques sans le savoir (sans doute par ce que tu ignores ce que sont les mathématiques et que tu n'en reconnais pas toujours quand tu en vois), je t'expliques qu'en réalité tu en fais quand tu programmes, mais tu restes dans le déni et prétends que tu n'en fais pas.

                    Je vais le dire autrement avec le théorème de Pythagore. Voilà un théorème qui dit : donne moi un triangle, je te construirais trois carrés dont la surface de l'un et la somme de la surface des autres. Autrement dit c'est une fonction qui prend en entrée un triangle et retourne un triplet de carré. Alors assurément, comme tout théorème, il a plus d'une démonstration mais elles font toutes la même chose. Cela étant, dans toutes ces démonstrations, il y en a qui sont plus efficaces que d'autres pour produire la sortie. C'est pareil pour toutes les fonctions que tu codes : ce sont des preuves de théorèmes mais certaines sont plus efficaces que d'autres. Que tu l'ignores ou que tu ne le vois pas, c'est une chose; que ce soit faux, s'en est une autre. ;-)

                    Pour revenir au débat d'origine avec aurelienpierre :

                    Mais je ne sais pas si tu as fait semblant de mal comprendre là où je voulais en venir, ou si je ne m'étais pas exprimé clairement. La question qu'on discutait, c'était de dire que la vectorisation était une manière intuitive en mathématique d'aborder un problème, et que les gens qui considéraient une boucle FOR plus intuitive qu'un calcul vectorisé avaient, en gros, un problème de formation.

                    Je ne sais pas trop ce qu'il faut entendre dans votre discussion par le terme vectorisation. S'agit-il des instructions SIMD des CPU ou de manipuler des structures de données abstraites représentant le concept mathématique de vecteur que l'on trouve en algèbre linéaire ?

                    Pour ce qui est des idiomes des langages, en python on utilisera volontiers des itérateurs plutôt que des boucles FOR (en C++ aussi, il me semble qu'il y a des itérateurs dans la STL). Le produit scalaire entre deux vecteurs se définira ainsi :

                    import operator
                    def dotprod(vec1, vec2):
                      return sum(map(operator.mul, vec1, vec2))

                    et non avec une boucle FOR. Il me semble que c'était déjà, là, une des choses que voulait faire remarquer aurelienpierre. Dans un langage comme le C, assurément on fera la même chose avec une boucle FOR mais parce c'est là l'idiome du langage pour faire ce genre de calcul.

                    Revenons au calcul du produit matriciel et à la quette d'optimisation. En C, la traduction naïve de la chose donnerait :

                    for (i = 0; i < N; ++i)
                        for (j = 0; j < N; ++j)
                          for (k = 0; k < N; ++k)
                            res[i][j] += mul1[i][k] * mul2[k][j];

                    Ici comme on parcourt la deuxième matrice colonne par colonne, sur de grosses matrices on a du cache miss. En la transposant d'abord on a :

                    double tmp[N][N];
                      for (i = 0; i < N; ++i)
                        for (j = 0; j < N; ++j)
                          tmp[i][j] = mul2[j][i];
                      for (i = 0; i < N; ++i)
                        for (j = 0; j < N; ++j)
                          for (k = 0; k < N; ++k)
                            res[i][j] += mul1[i][k] * tmp[j][k];

                    Les exemples de code sont issus de Memory part 5: What programmers can do, une série d'articles sur LWN par Ulrich Drepper au sujet du fonctionnement de la mémoire et des caches. Rien que là, dans ses benchmarks, il a un gain de 76.6%.

                    Néanmoins, il faut allouer une matrice temporaire : c'est lourd et on a pas toujours l'envie ni la place de faire. Il propose alors mieux :

                    #define SM (CLS / sizeof (double))
                    
                      for (i = 0; i < N; i += SM)
                          for (j = 0; j < N; j += SM)
                              for (k = 0; k < N; k += SM)
                                  for (i2 = 0, rres = &res[i][j],
                                       rmul1 = &mul1[i][k]; i2 < SM;
                                       ++i2, rres += N, rmul1 += N)
                                      for (k2 = 0, rmul2 = &mul2[k][j];
                                           k2 < SM; ++k2, rmul2 += N)
                                          for (j2 = 0; j2 < SM; ++j2)
                                              rres[j2] += rmul1[k2] * rmul2[j2];

                    et il compile le code avec gcc -DCLS=$(getconf LEVEL1_DCACHE_LINESIZE) pour optimiser le code pour la machine sur lequel il est compilé : CLS représente la taille d'une ligne de cache de niveau 1 sur la machine. Et là ce qu'il fait, avec des boucles FOR parce que tel est l'idome du C, c'est suivre la courbe en Z de Lebesgue (cf. mon premier commentaire) en adaptant la taille des zigzag à celui de la ligne de cache.

                    Il évite ainsi d'allouer une matrice temporaire pour calculer la transposer et il gagne 6.1% de plus qu'avec le code précédent. Mais au fond ce qu'il vient d'écrire ce n'est que la traduction dans le langage formel qu'est le C d'une pensée qui est mathématique de part en part.

                    Il conclue, enfin, en disant que l'on peut aller encore plus loin en vectorisant (instruction SIMD) le code et gagner encore 7.3%. À l'arrivée, il a un code qui va 10% plus vite que la boucle FOR naïve.

                    Ceci étant, les compilateurs appliquent déjà des optimisations de ce genre (pas forcément sur ces problèmes, mais sur d'autres) mais pour ce faire leurs auteurs, eux, connaissent l'outillage conceptuel mathématique nécessaire et il vaut mieux les laisser faire que d'essayer de le faire soi-même (ce que tu as reconnu ;-).

                    Encore un autre exemple, si tu n'est toujours pas convaincu. Voici une liste chaînée :

                    : -> : -> : -> : -> []
                    |    |    |    |
                    1    2    3    4
                    

                    elle a sa petite sœur, la liste doublement chaînée :

                    ] <- : <- : <- FOCUS -> : -> []
                          |    |      |      |
                          1    2      3      4
                    

                    en programmation fonctionnelle on appelle cela le zipper sur une liste. Et bien le zipper (ou liste doublement chaînée) et le type dérivé du type des listes chaînées. Explication ici : The algebra (and calculus!) of algebraic data types, on tu verras du développement en série entières et du calcul différentiel sur des types. ;-)

                    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

                    • [^] # Re: essayer Julia ?

                      Posté par  (site web personnel) . Évalué à 3. Dernière modification le 10 septembre 2017 à 13:38.

                      Il évite ainsi d'allouer une matrice temporaire pour calculer la transposer et il gagne 6.1% de plus qu'avec le code précédent. Mais au fond ce qu'il vient d'écrire ce n'est que la traduction dans le langage formel qu'est le C d'une pensée qui est mathématique de part en part.

                      Je vais me faire l'avocat du diable mais allons y…

                      Sur ça je suis juste simplement pas d'accord, et ton exemple l'illustre parfaitement la différence entre mathématiques et informatique.

                      L'implémentation d'une multiplication de matrice en C est effectivement juste une bête traduction d'une logique mathématique en un programme informatique.

                      L'optimisation de l'implémentation pour satisfaire des contraintes bien physiques, non fonctionnelles comme: la taille de cache, la vitesse d'execution, la lisibilité du code, la portabilité….. n'a elle rien de mathématique, ni même de penser mathématique, encore moins de formel…
                      Elle est la pour adapter un "algorithme théorique fonctionnel " aux contraintes d'un monde bien réel et aux limitations de son hardware, de temps de calcul, d'espace mémoire de nos machines de tous les jours…. Et c'est ça, ça n'a rien d'une formalisation mathématiques, Et c'est ça une grande part de l'informatique.

                      Pour prendre un cas similaire, je dirai qu'il y a la même relation entre Mathématique et Informatique qu'entre Physique et Ingénieuri.

                      Titre de l'image

                      L'un se base sur les connaissances de l'autre, mais est un domaine à part entière. Souvent car il se doit de répondre à un besoin, répondre à un problème, et non être uniquement un art en lui même…. Et se faisant, il devient un nouvel art en lui même.

                      De mon expérience, un bon ingénieur a toujours des bases solides en physiques. Un bon physicien est rarement un bon ingénieur, car il lui manque souvent les considérations pratiques.

                      Il en va généralement exactement de même pour les informaticiens et les mathématiciens.

                      Réduire l'informatique aux Maths et à la preuve formelle uniquement est une stupidité. Mais ignorer l'origine mathématique de l'informatique est également une stupidité.

                      • [^] # Re: essayer Julia ?

                        Posté par  . Évalué à 3.

                        Je vais me faire l'avocat du diable mais allons y…

                        Objection rejetée ! :-P

                        Non que je sois en désaccord avec ce que tu dis, mais tu as mal interprété mes propos (peut être bien par ma faute, je me suis sans doute mal exprimé). Je n'ai jamais dit cela :

                        Réduire l'informatique aux Maths et à la preuve formelle uniquement est une stupidité.

                        autrement elles ne seraient pas traitée comme deux sciences distinctes, mais la première serait simplement une branche de la seconde. Néanmoins quand je regarde l'image de ton message, la première impression qui me vient à l'esprit est celle-ci : elle a été faite par un ingénieur, autrement dit une personne qui se fait une fausse idée de ce qu'est la science mais qui veut tout de même exprimer son avis dessus.

                        Il n'en reste pas moins que les mathématiques et la preuve formelle fournissent les outils conceptuels, par exemple, pour les systèmes de typage langage de programmation. Je reprends mon exemple de Pythagore : si en entrée tui lui donnes un carré, il va te répondre qu'elle n'a pas le bon type, lui il veut un triangle rectangle ! Par contre, tu as un autre théorème qui te dis que si tu coupes un carré selon sa diagonale, tu obtiens deux triangles rectangles. Et boum, en composant les deux théorèmes, tu résous le problème de la duplication du carré : à partir d'un carré donné, construire un carré de surface double. La démarche est strictement similaire, dans l'organisation du discours, à ce que l'on fait en programmation en découpant le code en fonctions que l'on combine ensemble. D'un problème compliqué, on le découpe en problème plus simple, et on obtient la solution par composition : divide and conquer. On obtient alors ce parallèle entre informatique et mathématique :

                        Informatique Mathématiques
                        Type Formule
                        Programme Preuve
                        Primitive système Axiome
                        Fonction de A vers B Preuve de « A implique B »
                        Paire de A et B Preuve de « A et B »
                        Type somme sur A et B Preuve de « A ou B »
                        Interpréteur Théorème de correction
                        Décompilateur Théorème de complétude

                        J'ai repris le tableau de la dépêche de Perthmâd sur Coq 8.5, tu pourras t'y reporter pour de plus amples développements.

                        Je régissais au départ à cette proposition d'arnaudus :

                        Le lien entre les maths et la programmation est ténu, en plus d'être souvent dangereux. L'idée d'adopter une pensée mathématique quand on code ne me semble pas une bonne idée du tout.

                        Les liens sont tout sauf ténus, soutenir le contraire est une ineptie. Mais reprenons un exigence d'arnaudus :

                        (efficacité de l'algorithme en temps et en mémoire, gestion des arrondis, évolutivité, modularité et clarté du code)

                        La pensée mathématique ne serait-elle pas totalement modulaire, par exemple ? Le travail des algébristes, par exemple, qui classent leurs structures en monoïdes, groupes, groupes abéliens, anneaux, corps, espaces vectoriels… Et en algèbre linéaire, pour reprendre le calcul sur matrices, les théories parlent d'espaces vectoriels sur un corps quelconques (le corps des réels n'étant qu'un corps particuliers), les théorèmes et preuves sont faites sur un corps des scalaires quelconques : la voilà la programmation générique et la modularité ! On voit la route s'ouvrir vers le polymorphisme paramétrique, i.e. les types paramétrés, les templates du C++, les generics du Java et j'en passe (voir le besoin exprimé par l'échange entre Gabbro et Albert_ plus bas dans le fil de discussion).

                        Illustration avec le concept le plus simple : le monoïde. C'est une structure munie d'une opération interne et d'un élément neutre pour celle-ci (comme les entiers avec l'addition).

                        module type Monoid = sig
                          type t
                          val e : t
                          val op : t -> t -> t
                        end

                        À partir de là, on peut facilement, sur un monoïde donné, répéter l'application de l'opérateur interne sur une suite d'élément, comme lorsque l'on calcule la somme 1 + 2 + 3 + 4.

                        let sum (type a) (module M : Monoid with type t = a) =
                          List.fold_left M.op M.e

                        Maintenant, outre les entiers munis de l'addition avec 0 pour élément neutre, on peut remarquer que les string muni de l'opération de concaténation forme un monoïde avec pour élément neutre la chaîne vide "".

                        module String_mon = struct
                          type t = string
                          let e = ""
                          let op = ( ^ )
                        end

                        On peut faire pareil avec les int et l'addition, les int et la multiplication, ou bien encore les listes et l'opération de concaténation.

                        module Int_plus_mon = struct
                          type t = int
                          let e = 0
                          let op = ( + )
                        end
                        
                        module Int_mul_mon = struct
                          type t = int
                          let e = 1
                          let op = ( * )
                        end
                        
                        module List_mon (T : sig type t end) : Monoid with type t = T.t list = struct
                          type t = T.t list
                          let e = []
                          let op = ( @ )
                        end

                        Voyons voir à l'usage :

                        sum (module Int_plus_mon) [1; 2; 3; 4];;
                        - : int = 10
                        
                        sum (module Int_mul_mon) [1; 2; 3; 4];;
                        - : int = 24
                        
                        sum (module String_mon) ["Hello"; " "; "World!"];;
                        - : string = "Hello World!"
                        
                        sum (module List_mon(struct type t = int end)) [[1; 2]; [3; 4]];;
                        - : int list = [1; 2; 3; 4]

                        Et là je définis le produit scalaire comme en Python dans mon commentaire précédent, mais avec la garantie du typage statique (le type checker vérifie que ma preuve n'a pas de vice de forme) :

                        let dotprod v1 v2 = sum (module Int_plus_mon) (List.map2 ( * ) v1 v2);;
                        val dotprod : int list -> int list -> int = <fun>
                        
                        dotprod [1; 2; 3] [3; 4; 5];;
                        - : int = 26

                        On peut aller plus loin, là c'était un simple échauffement. :-) L'exemple vient d'une bibliothèque dont l'annonce de publication a été faite hier sur le forum OCaml. Prenons un algorithme qui a cet forme :

                        algorithm a b ::=
                                 x := f a;
                                 y := f b;
                                 return (x + y);
                        

                        f est une fonction définie ailleurs dans le code. On pourrait aller plus loin puis le paramétrer par la fonction f et la fonction appliquée sur x et y avant d'être retournée.

                         algorithm ((_ + _), (f _)) a b ::=
                                 x := f a;
                                 y := f b;
                                 return (x + y);
                        

                        Ici le return et le point-virgule ; ont usuellement une sémantique bien définie par le langage : ce couple forme ce que l'on appelle une monade (là je sens les haskelleux venir en masse). On peut donc paramétrer l'algorithme par une monade et prendre de la liberté vis à vis d'une sémantique contrainte par le langage hôte :

                        algorithm ((return _), (_ := _ ; _)) ((_ + _), (f _)) a b ::=
                                 x := f a;
                                 y := f b;
                                 return (x + y);
                        

                        le paramètre (_ := _ ; _), qui contrôle la sémantique du ;, est usuellement appelé bind. Ce qui donne la signature de module suivante :

                        module type Monad = sig
                          type 'a t
                          val return : 'a -> 'a t
                          val bind : 'a t -> ('a -> 'b t) -> 'b t
                        end

                        et notre algorithme devient un module paramétré par une monade et un autre module qui contient les interprétations de + et f.

                        module Algorithm (M : Monad) (R : ... ) = struct
                           open R
                           open M
                        
                           let run a b =
                             f a >>= fun x ->
                             f b >>= fun y ->
                             return (x + y)
                        end

                        ici >>= est un alias courant pour bind quand on joue avec les monades, et run sert comme son nom l'indique à exécuter le calcul. Il existe un paquet de monades intéressantes (en plus de celle avec le sens usuel de ; et return dans les langages impératifs), la documentation de la bibliothèque en question en donne quelques exemples (bibliothèque à la structure on ne peut plus modulaire). Et tout cela sert bien évidemment à produire des logiciels, en l'occurence le projet BAP (Binary Analysis Platform) :

                        The Binary Analysis Platform is a reverse engineering and program analysis platform that targets binaries, i.e., compiled programs without the source code. BAP supports multiple architectures (more than 30), though the first tier architectures are x86, x86-64, and ARM. BAP operates by disassembling and lifting the binary code into the RISC-like BAP Instruction Language (BIL). Thus the analysis, implemented in BAP, is architecture independent in a sense that it will work equally well for all the supported architectures. The platform comes with a set of tools, libraries, and plugins. The main purpose of BAP is to provide a toolkit for automated program analysis. BAP is written in OCaml and it is the preferred language to write analysis, we have bindings to C, Python and Rust.

                        Quand je regarde l'architecture de cette bibliothèque, la dernière pensée qui me vient à l'esprit est bien celle-ci : « l'idée d'adopter une pensée mathématique quand on code ne me semble pas une bonne idée du tout », mais au contraire je me dis : l'idée d'adopter une pensée mathématique quand on code me semble une excellente idée ! :-)

                        On veut un truc qui marche rapidement : on va au plus simple; on veut plus de sécurité : on adapte la monade; on veut travailler sur l'optimisation : on change le module de l'algorithme… Vous ne voyez toujours pas l'utilité ? Alors effectivement, toutes ces contraintes auxquels il faut s'adapter proviennent du monde extérieur et donc sont en quelques sortes extra-mathématiques, mais croire que la méthodologie mathématique est inadaptée, voire impropre, au besoin de l'ingénieur informaticien c'est ignorer ce que sont les mathématiques.

                        Et pour terminer sur ces histoires d'optimisation de code (et donc de compléxité algorithmique), je citerai la présentation du module Logique et théorie du calcul du MDFI :

                        La théorie de la calculabilité s'intéresse essentiellement à la question suivante : au moyen d'un ordinateur, quelles fonctions peut-on calculer et quels problèmes peut-on résoudre ? Son développement est concomitant de l'apparition des principaux modèles de calcul (fonctions récursives, machines de Turing, lambda-calcul,…) et est très étroitement lié à la logique mathématique : théorème d'incomplétude de Gödel (qui sera abordé dans ce cours), lambda-calcul typé (cours Preuves et types)…

                        La complexité cherche quant à elle à mesurer le degré de difficulté d'un problème, typiquement en termes de temps de calcul et d'espace utilisé. Il s'agit donc de questions plus fines, qui font l'objet de nombreuses recherches actuelles, notamment en rapport avec la logique.

                        L'objectif de ce cours est de présenter les outils et résultats fondamentaux pour aborder ces questions.

                        Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

                        • [^] # Re: essayer Julia ?

                          Posté par  (site web personnel) . Évalué à 0.

                          Je n'ai nullement l'intention de perdre mon temps avec un logicien qui n'a nullement envie de discuter, et re-déballe en boucle ses propres examples non corrélés.

                          Mais allons y… c'est dimanche.

                          autrement elles ne seraient pas traitée comme deux sciences distinctes, mais la première serait simplement une branche de la seconde.

                          Non c'est ton interprétation biaisé. L'informatique n'est en rien une branche des mathématiques, sauf dans l'esprit tordu des logiciens qui ne peuvent la concevoir autrement.

                          C'est un domaine à part entière qui utilise également les mathématiques. Tout comme la physique d'ailleurs, Je te conseil d'aller voir un physicien et de lui dire qu'il ne pratique qu'une branche des maths, juste pour rigoler un peu.

                          Néanmoins quand je regarde l'image de ton message, la première impression qui me vient à l'esprit est celle-ci : elle a été faite par un ingénieur, autrement dit une personne qui se fait une fausse idée de ce qu'est la science mais qui veut tout de même exprimer son avis dessus.

                          Ah manque d'arguments donc attaque personnelle.

                          Mais pour information, J'ai passé 7 ans de ma vie à travailler pour deux des plus grandes expériences scientifiques de cette planète. J'ai aussi fait un doctorat. Donc en toute modestie, l'ingénieur ( et rechercheur ) que je suis en connaît probablement plus sur la "science" que toi même, désolé pour ton ego.

                          Il n'en reste pas moins que les mathématiques et la preuve formelle fournissent les outils conceptuels, par exemple, pour les systèmes de typage langage de programmation. Je reprends mon exemple de Pythagore : si en entrée tui lui donnes un carré, il va te répondre qu'elle n'a pas le bon type, lui il veut un triangle rectangle

                          Donc l'informatique tout entière peut-être ramenée à un système de typage et un triangle rectangle. Intéressant comme la logique d'un logicien peut parfois être biaisé quand ça l'arrange.

                          J'ai repris le tableau de la dépêche de Perthmâd sur Coq 8.5, tu pourras t'y reporter pour de plus amples développements.

                          Tu aimes te parler à toi même non ?

                          Je connais Coq merci.
                          Tout comme je connais l'inutilité de la plupart des logiciels de preuves formelles qui ne font même pas capable de gérer 2000 lignes de C dés qu'on ajoute du threading et des I/O.

                          Ton pavé ne change strictement rien à ce que je disais.

                          Alors effectivement, toutes ces contraintes auxquels il faut s'adapter proviennent du monde extérieur et donc sont en quelques sortes extra-mathématiques, mais croire que la méthodologie mathématique est inadaptée, voire impropre, au besoin de l'ingénieur informaticien c'est ignorer ce que sont les mathématiques.

                          il faut s'adapter proviennent du monde extérieur et donc sont en quelques sortes extra-mathématiques, mais croire que la méthodologie mathématique est inadaptée

                          alléluia

                          Donc un paver pour admettre que l'informatique a besoin des Mathématiques, mais l'informatique n'est pas les Mathématiques…

                          Mais on s'en arrêtera là je pense.

                          Et pour terminer sur ces histoires d'optimisation de code (et donc de compléxité algorithmique), je citerai la présentation du module Logique et théorie du calcul du MDFI :

                          Ça fait 20 ans que La logique formelle, le lambda calculs, la programmation par preuve, et la théorie du calcul est enseigné à l'Université. Rien de nouveau ni d’évangéliste là dedans.

                          • [^] # Re: essayer Julia ?

                            Posté par  . Évalué à 3. Dernière modification le 10 septembre 2017 à 23:46.

                            Je crois qu'il y a un problème de compréhension entre nous.

                            Non c'est ton interprétation biaisé. L'informatique n'est en rien une branche des mathématiques, sauf dans l'esprit tordu des logiciens qui ne peuvent la concevoir autrement.

                            C'est exactement ce que je venais d'écrire et je suis d'accord avec toi, m'étais-je mal exprimé ? Ma phrase que tu cites était :

                            autrement elles ne seraient pas traitée comme deux sciences distinctes, mais la première serait simplement une branche de la seconde.

                            Que l'on pourrait reformuler ainsi : si l'informatique était une branche des mathématiques alors elles ne seraient pas traitées comme deux sciences distinctes, or elles sont traitées comme deux sciences distinctes (à bon droit), donc l'informatique n'est en rien une branche des mathématiques.

                            Je ne vois pas comment je peux exprimer plus clairement le fond de ma pensée. À quel moment ai-j écrit (ou peut-on conclure de mes commentaires) que l'informatique est une branche des mathématiques ?

                            Ah manque d'arguments donc attaque personnelle.

                            Ce n'était nullement une attaque personnelle. La photo est une caricature grossière : n'importe quelle personne, même quelqu'un n'ayant jamais étudié la physique, comprend que l'équilibre de gauche est totalement instable. C'est en cela qu'il me fait plus penser à la solution proposée par freem à laquelle GuieA_7 reprochée (je le cite) :

                            À part des cas très spécifiques, par exemple toutes ces conditions sont vérifiées:

                            • on n'a pas de thread donc pas possible que ça introduise un bug.
                            • on a vérifié que l'optimisation règle effectivement un problème en production très critique.
                            • on doit livrer très rapidement une version qui corrige ledit problème mais sans casser l'API, et derrière on fera une version avec une nouvelle API correcte (celle que je proposait par exemple) (on peut même garder la vieille API en "deprecated").

                            soit on garde la vielle version (lente mais correcte), soit on fait une version rapide et correcte (ce qui en l'occurrence n'était pas bien long, les lignes en plus n'étant quelques déclarations). Mais conseiller en premier une bidouille infâme ne me semble pas une bonne chose ; le C++ est déjà assez piégeux comme ça.

                            réponse (d'un ingénieur ou d'un scientifique, peu m'importe je ne suis ni l'un ni l'autre, je ne suis dans aucun camp et n'est pas de problème d'égo) qui relève clairement du côté droit de ton image.

                            Donc l'informatique tout entière peut-être ramenée à un système de typage et un triangle rectangle. Intéressant comme la logique d'un logicien peut parfois être biaisé quand ça l'arrange.

                            Je n'ai jamais soutenu une telle chose.

                            Ton pavé ne change strictement rien à ce que je disais.

                            Tel n'était pas son but. Il avait pour finalité d'apporter une objection à ce propos : « l'idée d'adopter une pensée mathématique quand on code1 ne me semble pas une bonne idée du tout » et de montrer qu'une pensée structurée mathématiquement2 pouvait traiter les problématiques attendues par arnaudus, à savoir : « efficacité de l'algorithme en temps et en mémoire, gestion des arrondis, évolutivité, modularité et clarté du code ».

                            re-déballe en boucle ses propres examples non corrélés.

                            Qu'entends-tu pas exemples non corrélés ? Les lignes automatiques du métro parisien (la ligne 14 date de la fin des années 90) est-ce un exemple corrélé et qui te conviendrait ?

                            L'inventeur de l'atelier B a donné une conférence sur le sujet au Collège de France. Il se présente ainsi :

                            Il y a deux sortes de chercheurs : les prolifiques et les monomaniaques. Je fais partie de la seconde catégorie, car j'ai toujours pratiqué le même genre d’investigations, à savoir la spécification et la construction vérifiée de systèmes informatisés.

                            Au sujet du développement de la ligne 14, il y dit :

                            la RATP décide de supprimer les tests unitaires et d'intégration

                            Octobre 98 : lancement de la ligne 14

                            Depuis lors pas de problèmes avec le logiciel développé

                            avec pour méthode de développement :

                            86.000 lignes en ADA ont été produites automatiquement

                            27.800 preuves ont été faites

                            92% ont été prouvés automatiquement par l'Atelier B

                            Coût des preuves interactives : 7 hommes-mois

                            Les preuves interactives sont moins chères que les tests

                            J'ai du mal à croire qu'un tel système n'est pas à gérer du threading et des I/O.

                            Du côté de Coq, j'ai du mal à voir CompertCert (un compilateur C certifié) comme un échec des approches formelles. Xavier Leroy a même reçu le prix Milner, entre autre pour cela, et j'avais écrit un journal à l'occasion.


                            1. le « quand on code » a son importance, l'informatique ne se limite pas à l'écriture de code. 

                            2. mais à dire vrai, ou plutôt le fond de ma pensée, tel est le cas de tout logiciel, y compris les codes d'Ulrich Drepper, même si tu penses le contraire (là dessus je n'ai pas bien compris ta position). 

                            Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

                        • [^] # Re: essayer Julia ?

                          Posté par  (site web personnel) . Évalué à 2.

                          Et boum, en composant les deux théorèmes, tu résous le problème de la duplication du carré : à partir d'un carré donné, construire un carré de surface double.

                          Et boum, à force de composer des éléments parfaitement valides mathématiquement, tu as un programme qui accomplit sa tâche en plus longtemps que l'âge actuel de l'univers. Mais attention, ça sera le bon résultat hein, et c'est en temps fini, alors pourquoi tu râles ?

                          • [^] # Re: essayer Julia ?

                            Posté par  . Évalué à 3. Dernière modification le 11 septembre 2017 à 00:13.

                            L'exemple avait pour but d'illustrer l'analogie et la correspondance fonctionnelle entre un théorème et un programme, ainsi que le parallèle entre la recherche de preuve et la résolution algorithmique d'un problème. On ne peut nullement en conclure :

                            • que toute fonction ainsi obtenue est efficace (complexité tant en temps qu'en espace) ;
                            • que toute fonction ainsi obtenue est inefficace.

                            Je n'ai jamais soutenu la première (ce que tu laisses sous-entendre), tu sembles fortement insister pour soutenir la seconde. Les deux propositions n'étant pas antinomiques, il reste une troisième possibilité…

                            Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

                      • [^] # Re: essayer Julia ?

                        Posté par  . Évalué à 2. Dernière modification le 10 septembre 2017 à 18:36.

                        Petit ajout, pour reprendre ton image :

                        security

                        L'image de gauche c'est freem rappeler à l'ordre par GuieA_7, l'image de droite c'est ce que je prônes; mais bizarrement j'inverserais les légendes. :-P

                        Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

    • [^] # Re: Python pour scripter, C/C++ sous la capot.

      Posté par  . Évalué à 2.

      Votre réponse est formidable, mais j'aimerais voir des exemples / des liens hypertexte / du code / des chiffres! Par exemple, les scripts python en question arrivent a utiliser efficacement combien de processeurs sur du parallélisme MPI?

      Le truc, c'est que en mécanique des fluides numérique, moi je trouve encore des codes en Fortran77. Alors un code python performant, c'est le rêve!

      • [^] # Re: Python pour scripter, C/C++ sous la capot.

        Posté par  . Évalué à -1.

        Alors un code python performant, c'est le rêve!

        Non non, c'est du C.

        "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

      • [^] # Re: Python pour scripter, C/C++ sous la capot.

        Posté par  (site web personnel) . Évalué à 10. Dernière modification le 28 août 2017 à 22:36.

        Votre réponse est formidable, mais j'aimerais voir des exemples / des liens hypertexte / du code / des chiffres! Par exemple, les scripts python en question arrivent a utiliser efficacement combien de processeurs sur du parallélisme MPI?

        Neuron simulator : https://www.neuron.yale.edu/neuron/
        Fer de Lance de la neurosciences pour la simulation au niveau cellulaire. Utilisé et respecté par les neuroscientistes du monde entier. Codé en C/C++, interfacé en python pour la configuration de la simulation. Scale du petit PC personnel au plus gros super-calculateur des USA.

        STEPS : http://steps.sourceforge.net/STEPS/default.php
        Simulateur sub-cellulaire ( reaction, diffusion, calcul de champs magnétique ). Codé en C++ comme un module python. Scale d'une simple machine à plusieurs milliers de noeuds.

        ROOT : https://root.cern.ch/
        Framework phare du CERN dans le domaine de la physique des particules. Créé en hard-core C++ avec son propre interpréteur C++ embarqué. Mais dispose quand même d'une interface en python largement utilisée par les physiciens.

        Nest : http://www.nest-simulator.org/
        Simulateur de réseau neuronaux points à points. Codé en C++, interfacé en python. Scale sur le super-calculateur BlueGeneQ machines du Juelich center ( http://www.fz-juelich.de/portal/DE/Home/home_node.html ), un des plus gros au monde.

        Tensorflow : https://github.com/tensorflow/tensorflow
        Machine learning framework. Codé en C++, interfacé en python… supporte GPGPU et calcul distribué.

        Qu'on soit claire, je suis dev C++, je n'ai clairement pas le profil du pythonneux fan boy… Et il y a des tas de choses que je déteste avec python, et probablement une liste trop longue pour la mettre ici.

        Mais c'est un fait, comme langage d’interfaçage, de configuration, de scripting quick & dirty, python s'est largement imposé dans le monde scientifique, et il y a des raisons à ça.

      • [^] # Re: Python pour scripter, C/C++ sous la capot.

        Posté par  . Évalué à 6.

        Trouver des codes en Fortran 77 ce n'est pas surprenant, ils peuvent être sur le web depuis les années 90. Ce qui serait inquiétant c'est qu'on enseigne le Fortran 77 au lieu du Fortran actuel et qu'on écrive, aujourd'hui, un nouveau code en Fortran 77.

        • [^] # Re: Python pour scripter, C/C++ sous la capot.

          Posté par  . Évalué à 6.

          Mon collègue, doctorant en science, utilise un programme en Fortran 77. Il l'étend en Fortran 77. Et comme il a appris pour ça ce langage, et qu'il n'en connait pas d'autre, il fait ses pré- et post-traitement en Fortran 77.
          Un autre collègue fait du Fortran 90, mais sur un vieux code sans module, avec des contraintes stupides, comme une fonction par fichier.

          On peut faire du boulot correct en Fortran récent (même si l'absence de programmation générique me fait suer), je ne dis pas le contraire, mais certains scientifiques que je côtoie sont restés à « le Fortran 77 est plus rapide que les autres, donc je code en Fortran 77 ».
          Personnellement, faire du C++ 2011 est une manière de m'assurer de ne pas avoir à gérer la compatibilité avec leur code (seulement les entrées-sorties, qui sont déjà incroyablement foireuses).

          • [^] # Re: Python pour scripter, C/C++ sous la capot.

            Posté par  . Évalué à 2.

            Fortran 2003 a la programmation générique et fortran 90/95 en est pas loin avec les modules.

            • [^] # Re: Python pour scripter, C/C++ sous la capot.

              Posté par  . Évalué à 2.

              As-tu un document un peu lisible là-dessus ? Car tout ce que j'ai vu, c'est des interfaces à écrire à la main, ou des select type.
              Mettons que je veuille créer une structure de donnée (comme ce qu'on trouve dans la bibliothèque standard du C++) qui soit utilisable avec n'importe quel type, y compris des types créés par l’utilisateur, ou des entiers ou flottants avec des kind arbitraires, vers quoi devrai-je me tourner ?

              Je sais que flibs fait des trucs comme ça, mais je n'ai pas trouvé le point clé en fouillant le code.

              • [^] # Re: Python pour scripter, C/C++ sous la capot.

                Posté par  . Évalué à 5. Dernière modification le 31 août 2017 à 06:26.

                Ce que tu veux (si je comprend bien) date de fortran 90. Par contre cela te force à faire le méthode à la main la ou c++, il me semble, permet des trucs plus automatique.

                En gros cela se résume à faire un module, un type, les méthodes associées suivant tes type en entrée, définir l'interface nommé ou tu mets juste le nom des méthodes.

                3.3.3 Generic procedures

                Modules allow arguments of derived type and hence generic procedures with derived types:

                MODULE genswap
                IMPLICIT NONE

                TYPE point
                REAL :: x, y
                END TYPE point

                INTERFACE swap
                MODULE PROCEDURE swapreal, swapint, swaplog, swappoint
                END INTERFACE

                CONTAINS

                SUBROUTINE swappoint (a,b)
                IMPLICIT NONE
                TYPE (point), INTENT(INOUT) :: a, b
                TYPE (point) :: temp
                temp = a
                a = b
                b = temp
                END SUBROUTINE swappoint

                SUBROUTINE swapreal (a, b)
                IMPLICIT NONE
                REAL, INTENT(INOUT) :: a,b
                REAL :: temp
                temp=a
                a=b
                b=temp
                END SUBROUTINE swapreal

                !similar subroutines for swapint and swaplog


                END MODULE genswap

                • [^] # Re: Python pour scripter, C/C++ sous la capot.

                  Posté par  . Évalué à 1.

                  Par contre cela te force à faire le méthode à la main la ou c++, il me semble, permet des trucs plus automatique.

                  C'est là mon problème. Je ne peux donc pas créer un conteneur qui puisse contenir n'importe quoi, puisque si un utilisateur veut utiliser mon conteneur pour un type qu'il a lui-même créé, ça ne va pas marcher.

                  Si je crée un type case avec deux entiers i, j, je vais devoir réécrire swapcase, et ce bien que le code derrière soit le même d'un point de vue algorithmique. Je voudrai un truc comme

                  SUBROUTINE swap (a,b)
                  IMPLICIT NONE
                  OSEF, INTENT(INOUT) :: a, b
                  SAME_TYPE_THAN(a) :: temp
                  temp = a
                  a = b
                  b = temp
                  END SUBROUTINE swap
                  

                  Qui marcherait pour tous les types (entier, flottant, point, case…). En c++, il y a les templates, en python, le duck typing, en julia (dont on parlait plus haut), je crois bien que c'est possible par défaut aussi.
                  Ça fait partie des rares points qui me font éviter le Fortran aujourd'hui.

                  • [^] # Re: Python pour scripter, C/C++ sous la capot.

                    Posté par  . Évalué à 3.

                    C'est là mon problème. Je ne peux donc pas créer un conteneur qui puisse contenir n'importe quoi, puisque si un utilisateur veut utiliser mon conteneur pour un type qu'il a lui-même créé, ça ne va pas marcher.

                    Je vais probablement dire une grosse connerie car ca fait longtemps que j'ai pas fait ce genre de truc mais bon tu peux etendre un module donc normalement tu import ton container (qui est dans un module) et tu rajoutes les nouvelles methodes pour ton nouveau type et tu rajoutes un interface.

                    Regarde aussi les normes 2003 et 2008 car il y a eu pas mal de changement de fait dont, en particulier, la programmation objet. Cela m'etonnerait bien que ce genre de cas ne soit pas gerable d'une facon ou d'une autre maintenant.

          • [^] # Re: Python pour scripter, C/C++ sous la capot.

            Posté par  . Évalué à 6.

            Mon collègue, doctorant en science, utilise un programme en Fortran 77. Il l'étend en Fortran 77. Et comme il a appris pour ça ce langage, et qu'il n'en connait pas d'autre, il fait ses pré- et post-traitement en Fortran 77.

            Si mon doctorant faisait ça, je lui enlèverais les droits de commit sur notre projet tant qu'il n'aurait pas appris le Fortran et compris pourquoi c'est stupide de développer aujourd'hui en Fortran 77. De toutes façons, s'il me laissait un code en Fortran 77 en fin de thèse, le code irait directement à la poubelle parce que non lisible, non maintenable, donc sans valeur au-delà de la thèse. Pourquoi pas sur cartes perforées tant qu'il y est ?

            • [^] # Re: Python pour scripter, C/C++ sous la capot.

              Posté par  . Évalué à 10.

              Pourquoi pas sur cartes perforées tant qu'il y est ?

              Parce qu'on est en août, le budget perforatrice est épuisé depuis janvier.

              « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

            • [^] # Re: Python pour scripter, C/C++ sous la capot.

              Posté par  . Évalué à 6.

              Au cas où il y aurait le moindre doute : ce sont ses encadrants qui l'ont poussé sur un logiciel en Fortran 77 et qui le font l'étendre. Quant au post/pré traitement, je ne serais pas surpris qu'il fasse ça sur conseil de ses encadrants.

              La seule chose que l'on peut lui reprocher, c'est de ne pas avoir refusé.

              De toutes façons, s'il me laissait un code en Fortran 77 en fin de thèse, le code irait directement à la poubelle parce que non lisible, non maintenable, donc sans valeur au-delà de la thèse.

              Comme si mes codes allaient être utilisés après ma thèse. Mes encadrants ne les ont jamais lus (jamais, ni pour vérification, ni pour comprendre le fonctionnement). Si j'oublie de leur envoyer, ils vont être tout simplement supprimé quand je partirai…

              En vrai, je profite de l'anonymat relatif d'internet pour pester un peu, car il y a pas mal de choses aberrantes qui se font dans mon labo.

              • [^] # Re: Python pour scripter, C/C++ sous la capot.

                Posté par  . Évalué à 0.

                Oui et ? Le thésard peut et doit leur dire merde. En même temps si il ne comprend pas que faire du fortran 77 c'est débile et qu'il est utilisé par des vieux chercheurs comme techniciens pas cher il mérite sa torture.
                Sans rire dis lui de dire stop à cette hérésie, c'est pas vraiment d'avenir et cela ne sera pas très bien vu dans les commissions de recrutement.

                • [^] # Re: Python pour scripter, C/C++ sous la capot.

                  Posté par  . Évalué à 10.

                  Tu souhaites vraiment qu'on parle des rapports de pouvoir entre les doctorants et permanents dans les labos ? On a déjà tenté de me prendre pour un con en parlant informatique avec des permanents, je m'en suis sorti parce que je savais ce que je disais, mais face à un non-informaticien, j'ose à peine imaginer le teneur de l'échange. Probablement « fais comme je fais, pas autrement ».
                  Pour peu que le doctorant ne soit pas à l'aise, soit étranger ou n'ait pas envie de trop se mettre en porte à faux avec ses encadrants, je peux comprendre cette attitude, même si ce n'est pas la mienne.

                  • [^] # Re: Python pour scripter, C/C++ sous la capot.

                    Posté par  . Évalué à 5.

                    Je connais TRES bien le probleme et bon la these c'est aussi un moment ou tu dois devenir independant dans ta recherche et si tu n'es pas capable de comprendre que ce que tu fais n'a absolument aucun interet pour le reste de ta carriere c'est tant pis pour toi.

                    Aujour'd hui faire du fortran 77 c'est du grand n'importe quoi, cela te bloque et ne t'apporte absolument AUCUNE expertise en dehors de montrer que tu n'as pas la capacite de devenir un chercheur independant avec tes idees a toi en ayant la capacite de les amener au bout.

                    • [^] # Re: Python pour scripter, C/C++ sous la capot.

                      Posté par  . Évalué à 5.

                      Tout à fait, surtout que le Fortran est un merveilleux langage de programmation pour faire du calcul scientifique, justement parce qu'il évolue et se bonifie avec chaque nouveau standard.

                    • [^] # Re: Python pour scripter, C/C++ sous la capot.

                      Posté par  . Évalué à 3.

                      Tu as bien entendu conscience que du Fortran 77 ça se trouve encore dans des codes relativement modernes dans l'industrie hein ? :-)

                      Pendant ma thèse (entre 2006 et 2010) j'ai bossé sur des codes en Fortran. TOUS étaient écrits au mieux en Fortran 90. Sur quatre codes industriels, deux étaient écrits en F77. Et il s'agissait d'ISV, donc leurs clients faisaient aussi du code qui se servaient du leur. Certains réclamaient de se conformer à la norme IEEE 754 strictement, même si les nouvelles archis/les nouveaux compilos sont capables d'aller jusqu'à 80 bits de précision (parce que ça passe pas les tests unitaires du client sinon).

                      Autre exemple con : dans les cours d'info, lorsqu'on enseigne le C aux étudiants, beaucoup, beaucoup de profs continuent d'enseigner C89. Alors que depuis on a eu 2 normes qui sont sorties. Donc ils continuent de forcer les élèves à déclarer toutes leurs variables en haut d'un bloc alors que ça fait 20 ans ou presque que la norme permet de déclarer des variables n'importe où dans un bloc de code.

                      Je suis à fond pour utiliser F2008 (car en plus y'a Co-Array Fortran et que c'est un sous-langage rigolo :-)), mais ton affirmation selon laquelle un thésard peut dire non à son directeur de thèse n'est que partiellement vraie. Je dis aux élèves de Master/thèse qu'il y a forcément un moment pendant la thèse où il faut apprendre à dire non. Cependant, je dis aussi que généralement, la première année on se contente de fermer sa gueule et d'appliquer les méthodes. On peut (et on doit !) les questionner, mais au final, à de très rares exceptions près, le directeur de thèse en 1ère année reste le patron. Perso F77 m'emmerde, donc j'ai fourni mes codes optimisés aux boites avec qui on bossait en leur disant que je savais pas me satisfaire des contraintes désormais artificielles de F77 et que du coup j'avais codé le tout en F90 (ce qui est globalement vrai). Leur réaction a été soit « t'as accéléré mon code de 30%, et mon compilateur sait mélanger les deux, t'inquiète on gère », soit « pas de problème on réécrira le code en F77 ».

                      • [^] # Re: Python pour scripter, C/C++ sous la capot.

                        Posté par  . Évalué à 3. Dernière modification le 13 septembre 2017 à 09:56.

                        Tu as bien entendu conscience que du Fortran 77 ça se trouve encore dans des codes relativement modernes dans l'industrie hein ? :-)

                        Oh oui.

                        On parle de these donc pas de code industriel et bon a moins que ton programme soit un seul fichier de 10 millions de lignes de code, tu peux associer de bout de 90 et de 77 et tu le mentionnes bien a la fin.

                        Je suis assez d'accord avec toi dans l'ensemble et tu donnes la methode a applique. Perso je n'ai JAMAIS vu un seul directeur de these refuse un code qui fonctionnait meme si cela voulait dire qu'il y avait un melange de 77 et 90. Jamais. Apres c'est aussi au thesard de faire en sorte que la chaine de compilation ne casse pas. Du coup, tu fais comme la plupart des thesards, tu dis rien et tu change la facon de faire par des trucs plus modernes et tu as les merci de ton dirlo une fois qu'il a fini de fumer et qu'il reflechi. Tu as la deuxieme solution qui est de se plaindre de devoir faire du 77 en sachant que cela sert a rien au contraire cela n'est pas bon signe pour la capacite d'independance de la personne et surtout il n'a pas a se plaindre. C'est un choix de sa part.

                        En ce qui concerne le C, un etudiant que je connais me disais que en math applis, ils enseignaient jusqu'a present le fortran mais que l'annee derniere ils avaient change pour passer au C et "oh surprise" les etudiants galerent avec les pointeurs! Encore des personnes qui ne savent pas ce que veux dire Fortran.

      • [^] # Re: Python pour scripter, C/C++ sous la capot.

        Posté par  . Évalué à 2. Dernière modification le 30 août 2017 à 22:28.

        Il y a beaucoup de modules de scipy qui reposent sur des routines en Fortran. Citons par exemples les algo de régression non linéaire de la librairie scipy.optimize, les algo d'intégration numérique d'EDO/EDP de scipy.integrate, etc.

        Numpy repose aussi sur LINPACK, mais je n'ai jamais compris si c'est sur son implémentation C ou Fortran.

        • [^] # Re: Python pour scripter, C/C++ sous la capot.

          Posté par  (site web personnel) . Évalué à 4.

          Numpy repose aussi sur LINPACK, mais je n'ai jamais compris si c'est sur son implémentation C ou Fortran.

          LAPACK et non LINPACK, LINKPACK est l'outil de benchmarking, LAPACK est une library de résolution pour système linéaires.

          LAPACK dans sa version originelle est en Fortran, et c'est actuellement la seul réel dépendance généralement toujours en fortran.

          BLAS est de nos jours remplacé par OpenBLAS ( C ), BLIS (C++) ou MKL ( C++ )

    • [^] # Re: Python pour scripter, C/C++ sous la capot.

      Posté par  . Évalué à 4.

      Euh les plus gros hpc européens ont la grande majorité de leur utilisation faite par des code écris en fortran… Ce qui est normal pour du calcul numérique.

      • [^] # Re: Python pour scripter, C/C++ sous la capot.

        Posté par  . Évalué à 1.

        C'est le point de vue que j'avais. Mais le code que je présente dans le journal entend bousculer cet avis…

        Voir un code écrit en python aussi efficace qu'un code fortran / C / C++, ce n'est pas surprenant. Ce qui l'est pour moi, c'est bien l’extension de ce fait aux environnements hautement parallèles.

        Soit c'est du foin, soit la majorité des codes qui tournent sur les gros calculateurs européens pourraient être simplifiés.

        • [^] # Re: Python pour scripter, C/C++ sous la capot.

          Posté par  . Évalué à 3.

          Je ne dis pas que l'idee est nul et vu l'evolution du niveau des etudiants de science en programmation il n'y a de tout de maniere pas trop le choix et il va falloir continuer a fournir des front-end simplifie pour faire du calculs numerique. Python est une des options, matlab se positionne pas mal sur le creneau aussi mais aussi des trucs plus specialise comme Ansys (gros monstre hybride) ou abaqus.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.