lasher a écrit 2730 commentaires

  • [^] # Re: A chaque clou son marteau

    Posté par  . En réponse au journal La multiplicité des gestionnaires de paquets. Évalué à 2.

    Je ne me souviens plus du nom, mais après googling, je crois que j'utilisais dh-make-perl (je peux me tromper). Lorsque ça ne marchait pas, c'était généralement que la compilation au niveau de Makefile.PL se passait mal (donc le paquetage était mal formé de toute manière).

    Y'a un topic sur PerlMonks à ce sujet.

  • [^] # Re: A chaque clou son marteau

    Posté par  . En réponse au journal La multiplicité des gestionnaires de paquets. Évalué à 3.

    C'est intéressant, tu sous-entend au début (mais ta conclusion dit l'inverse) qu'aucun système ne peut prétendre tout résoudre à la fois. Partant de là on peut se demander comment faire efficacement cohabiter les trois outils : celui du sysadmin et de la distribution, celui du développeur et celui de l'utilisateur "bureau". Sans oublier le mainteneur de logiciels à qui on demande des paquets pour tous les systèmes possibles…

    Alors j'arrive après la bataille, mais par exemple pour Perl, il existe des outils dans Debian qui permettent d'utiliser cpan/CPAM.pm (l'outil de gestion de paquetages de Perl), de les télécharger, lancer les scripts kivonbien, puis de convertir le tout sous forme de paquet .deb en modifiant les chemins pour les bibliothèques, etc. Les fois où je m'en étais servi, cet outil faisait le boulot comme je voulais, et du coup j'avais un workflow relativement fluide.

    Qu'est-ce qui empêcherait les gens de faire de même avec les gem/pip/etc. ? (je suis sûr qu'il y a de bonnes raisons, je ne sais juste pas lesquelles).

  • [^] # Re: Solution à base de types variants en ADA

    Posté par  . En réponse à la dépêche Sortie de GHC 8.0.2 et une petite histoire de typage statique. Évalué à 3. Dernière modification le 02 février 2017 à 17:59.

    Les cas pathologiques pour la complexité exponentielle, on les rencontres dans du « vrai » code ?

    Ce ne sont pas des cas pathologiques, c'est bien le problème. La boucle en elle-même est peut-être « simplement » 2D ou 3D. Mais tout un tas d'applications scientifiques qui simulent des phénomènes naturels (différents aspects météo, dynamique moléculaire, etc., dont je ne maîtrise absolument pas la théorie derrière) utilisent des dizaines de variables, tableaux, etc., pour représenter divers paramètres et aspects du modèle. La complexité ne vient pas uniquement du nid de boucle, mais aussi de l'explosion du nombre de variables dans les systèmes d'(in)équations linéaires qui en résultent. Beaucoup de ces applications utilisent des tableaux à une, deux, ou trois dimensions, ce qui fait exploser le nombre d'états (car le problème des dépendances inter-itérations est qu'il faut maintenir un vecteur d'itération par tableau, plus ou moins, pour tracer les dépendances qui doivent être résolues, et celles qui peuvent être potentiellement « dynamiques » et malgré tout « calculables » par le compilateur pour déterminer si la forme de l'espace d'itération ET du réseau de dépendances constituent toujours un polyèdre convexe).

    Enfin, pour paraphraser Feautrier lors d'une keynote sur le sujet, « le modèle polyédrique n'est que polyédrique ». Beaucoup de codes de la vie réelle font appel à des tableaux d'indirection (algèbre linéaire creux, méthodes par éléments finis, et en général pas mal d'algorithmes fonctionnant à partir de représentations par graphes). Le résultat est que dans le cas général le modèle polyédrique ne peut rien car il est impossible de savoir si on a bien un polyèdre convexe pour les dépendances de données1.

    Cependant j'ai vu des gens montrer au cas par cas comment dépasser le problème de la convexité, au moins partiellement. Du coup peut-être que dans vingt ans on aura une théorie et des outils pour aller au-delà des limites actuelles du modèle. :)

    EDIT: j'oubliais aussi un cas important : si on commence à avoir l'analyse polyédrique activable (genre Polly dans LLVM, qui est dans la branche principale je crois), il faut accepter que l'analyse va sans doute s'appliquer à TOUTES les boucles du programme. Ça risque de sérieusement rallonger le temps de compilation (du coup il faudra passer par des méthodes de ségrégation de certaines fonctions pour qu'elles soient isolées dans des fichiers spécifiques avec des options de compilation spécifiques). C'est déjà plus ou moins le cas dans pas mal de codes scientifiques optimisés, mais ça rajoute des contraintes sur le programmeur.


    1. En pratique je connais des gens capables de faire tout un tas de trucs très cool malgré tout. Par exemple, si tu sais que malgré une indirection de type a[b[i]] par construction les valeurs de b sont monotones (croissantes ou décroissantes) tu peux quand même utiliser l'analyse polyédrique pour permettre la parallélisation. Mais du coup ça demande d'avoir un utilisateur qui le dit au compilateur. 

  • [^] # Re: Solution à base de types variants en ADA

    Posté par  . En réponse à la dépêche Sortie de GHC 8.0.2 et une petite histoire de typage statique. Évalué à 3.

    Si je prends un exemple pour illustrer la chose. Dans la vidéo de la conférence sur JML (dont le lien était erroné, le voici), l'orateur expose sur un cas particulier une méthode d'analyse statique dite analyse polyédrique (vers la 40ème minute). Il conclue l'étude de cette exemple avec une diapo qui contient ce passage :

    Juste un mot là-dessus : premièrement je n'ai pas encore vu la vidéo1.

    L'analyse polyédrique a été proposée pour l'optimisation et la parallélisation en compilation depuis la fin des années 80 (voir ici par exemple pour un résumé du modèle). Lorsque j'ai décrit la technique à un pote bien plus avancé en maths que moi (faire une analyse de formes convexes dans un domaine discret), il a tout de suite pigé la difficulté (dans le domaine continu, c'est « trivial », mais dans le domaine discret, pas du tout), et a proposé de suite la première solution utilisée dans ce cas : utiliser un solveur de programmation linéaire entière (pas sûr de la traduction de integer linear programming solver). Et c'est ce qu'a fait Feautrier à l'époque (il a écrit PIP rien que pour ça).

    Mais utiliser un solveur ILP mène à de sérieuses contraintes, entre autres que le temps de résolution des (in)équations augmente exponentiellement avec la complexité du nid de boucle à paralléliser/optimiser. De nos jours il y a enfin quelques compilateurs/transpilers qui sont relativement efficaces pour correctement compiler tout ça dans un temps raisonnable, et qui ne passent pas nécessairement par un solveur ILP (et donc le temps d'exploration des espaces d'itération est bien moins grand), mais même dans GCC qui a (avait?) une branche pour les optimisations suivant le modèle polyédrique, ce ne serait jamais activé par défaut.

    Bref. Pour passer d'un modèle mathématique correct, et qui fonctionne sur des programmes/boucles jouet, à un compilateur qui peut compiler du « vrai » code (principalement scientifique), il a fallu attendre environ 20 ans (et sacrifier pas mal de thésards à l'autel du modèle polyédrique). Et malgré tout, ce n'est toujours pas intégré dans les compilateurs « mainstream » (tout au plus est-ce une option qu'il faut activer volontairement), car les résultats mathématiques ne se réduisent pas nécessairement en possibilité d'implémentation efficace.


    1. Je suis en train de la télécharger, mais apparemment depuis les US ça prend 300 ans.  

  • [^] # Re: Solution à base de types variants en ADA

    Posté par  . En réponse à la dépêche Sortie de GHC 8.0.2 et une petite histoire de typage statique. Évalué à 3.

    Je réponds alors : le type checking (tache qui incombe au compilateur) c'est de l'analyse statique; et dans l'exemple donné il y a clairement un problème de typage qui peut être détecté statiquement, c'est-à-dire à la compilation. Puis j'illustre mon propos sur un exemple pour montrer en quoi cela peut être utile : réduire l'overhead à l'exécution. Comme la chose est vérifiée une

    Deux choses:

    1. La vérification de types peut se faire tout bêtement de façon sûre, mais à l'exécution. Voir par exemple Java (si on excepte les types primitifs): on a une garantie de ne pas se retrouver dans un état indéfini lorsqu'on passe par les classes et objets du langage, mais la plupart du temps ce sera détecté à l'exécution. Et pourtant, on peut parfaitement utiliser du lambda calcul pour définir le système de types de Java (voir par exemple le bouquin de Benjamin Pierce, « Types and Programming Languages »).
    2. Il ne faut pas oublier que les spécifications des langages mais aussi les techniques d'analyse (sémantique, entre autres) évoluent avec le temps. ADA existe depuis un bout de temps (plus de 30 ans); C aussi. Mais on doit aussi faire face à ce qui n'est pas (et ne sera peut-être jamais) déprécié dans le langage, et qui du coup doit « passer » à la compilation, parce qu'à l'époque, on ne savait pas faire de détection efficace (parce que bon, si ton compilateur prend 3 heures pour te vérifier les types, personne ne l'utilisera sauf application ultra-critique et dont le code bougera peu). Idem avec C: n'importe quel compilateur moderne (Clang, GCC, ICC, XL/C, etc.) sait faire une analyse statique poussée du langage, malgré toutes les ambiguïtés qu'il embarque. Ces analyses vont bien plus loin que la norme, mais comme il y a des obligations de compatibilité ascendante, le compilateur ne peut émettre que des warnings. Ceci étant dit, si tu demandes à des développeurs expérimentés ce qu'il en est, ils te diront qu'il faut utiliser -Werror pour du code nouveau. Si ton code a un comportement particulier qui peut générer des avertissements du compilateur, mieux vaut le montrer explicitement sur la ligne de compilation avec des options de type -Wno-…. Si ton code est lié à des bibliothèques qui désormais génèrent des avertissements (qui n'étaient pas générés il y a 10 ans), alors évidemment il faut faire des exceptions.

    Bref, ne pas oublier « l'existant », qui explique beaucoup de fois pourquoi un compilateur de « vieux » langage dit des choses qu'il faut « écouter » mais ne les force pas.

  • [^] # Re: Magazine papier ou magazine informatique papier ?

    Posté par  . En réponse au sondage Quel est votre magazine papier préféré ?. Évalué à 3.

    Tu as évidemment raison pour la règle grammaticale, mais le côté « rude » c'est peut-être vrai en anglais britannique, mais pas tellement en anglais américain (ça fait surtout pas très doué niveau grammaire quoi). Par contre, étant donné la façon dont les gens écrivent leurs blogs et leurs commentaires en anglais sur le net, je ne m'étonne pas de ne pas voir « English » avec une majuscule dans des forums.

    Perso j'ai été bien plus choqué par son « Somes says » ! :-)

  • [^] # Re: L'annonce

    Posté par  . En réponse au journal Grumpy : un nouveau concurrent à pythran. Évalué à 4.

    les sessions en parallèle

    Concurrentes, pas parallèle ;)

    Alors, j'avais bien précisé « parallèle » parce que si ce n'est « que » concurrent, ben du coup ça veut dire que deux processus ou threads peuvent se partager un cœur ou thread matériel et du coup tu n'exploites toujours pas ta machine (voire, au contraire, tu la rend plus lente, car il y a du coup des changements de contexte, des évictions de lignes de cache, etc.). :-)

    Ce qui m'intéresse c'est qu'une application exploite la machine au mieux, donc la concurrence c'est bien si tu surcharges la machine de threads (c'est pas forcément une mauvaise idée s'il y a beaucoup d'entrées-sorties), mais si y'a des cœurs dispo, on obtient une machine sous-utilisée.

    [à propos de node.js] Tu peu éventuellement lancer plusieurs threads pour en avoir autant que de CPU mais pas plus.

    Donc on a bien un comportement parallèle ! VICTORY !
    … Ahem.

    L'idée c'est que tu ne peux pas faire plus de 4/8/16 choses en parallèles sur une machine selon la CPU. L'idée derrière ça c'est de faire de l'asynchrone plutôt que du vrai parallélisme. Il y a moins de deadlock et on passe moins de temps à faire des changements de contexte.

    c'est quelque chose de « classique » en HPC : on module le parallélisme en fonction des ressources matérielles disponibles. Ça inclut le nombre d'unités de calcul (threads matériels, cœurs, etc.), mais aussi la bande-passante pour accéder à la mémoire vive, voire la bande-passante pour accéder à la mémoire de masse si le programme produit ou consomme beaucoup de données.

    Bon après dans le cas spécifique du calcul intensif/parallèle, on a aussi des connexions réseau ultra-rapide et spécialisées qui ne nécessitent pas l'utilisation de TCP/IP, ce qui fait que la transmission de données est généralement pas spécialement plus lente qu'accéder à la RAM (voire moins, ça dépend de ce que t'es prêt à payer).

    Pour l'histoire de deadlocks je suis un peu circonspect. C'est un fait que plus tu augmentes la concurrence d'un programme plus les problèmes de race condition/data race, ainsi que les problèmes d'accès aux verrous apparaissent vite. Mais réduire le nombre de processus ou threads ne fait que limiter le potentiel pour un deadlock, et ne supprime absolument pas le problème en lui-même : si t'as un deadlock, c'est que y'a un bug quelque part ! :-)

    Bon et sinon, viser l'asynchronie, je suis à fond pour… même pour les threads. Plutôt qu'avoir des gros threads qui tournent et doivent explicitement acquérir 12000 verrous pour modifier l'état du système, je préfère des petits threads qui ne peuvent tourner que si toutes leurs dépendances (notamment en termes de données, mais aussi de ressources) sont satisfaites. Par contre en échange, le thread fait une (« petite ») chose, la fait bien, et ne peut plus être interrompu n'importe comment (donc il faut faire attention à comment on les utilise, sous peine de verrouiller toute la machine).

  • [^] # Re: L'annonce

    Posté par  . En réponse au journal Grumpy : un nouveau concurrent à pythran. Évalué à 2.

    Je ne connais pas du tout le système du coup je ne peux pas commenter. Mais ça m'étonnerait que le serveur web sur lequel reddit repose soit mono-process ou mono-thread. Donc peut-être que le backend est mono-* mais entre les possibles caches de données, les sessions en parallèle, etc., je pense qu'il est raisonnable de penser que y'a quand même du parallélisme quelque part. :-)

  • [^] # Re: L'annonce

    Posté par  . En réponse au journal Grumpy : un nouveau concurrent à pythran. Évalué à 2.

    Ben l'appel CreateProcess sous Windows permet l'héritage/la filiation entre processus non ?

    Ensuite, c'était un peu le propos de mon post : en supposant que l'API de fork est bien respectée (ie, duplication de l'espace mémoire d'un processus, et création d'une hiérarchie de processus entre le père qui récupère le pid du fils, et le fils, qui récupère 0 comme valeur — ou -1 s'il y a erreur), alors porter Python sous Windows devrait être plus facile dans un premier temps car les appels POSIX sont supportés.

    Ensuite, évidemment, il serait mieux de pouvoir utiliser les appels natifs, mais c'est une autre histoire…

  • [^] # Re: L'annonce

    Posté par  . En réponse au journal Grumpy : un nouveau concurrent à pythran. Évalué à 2.

    Oui les méthodes pour ré-implémenter les appels POSIX ou les émuler existent mais la question est est-ce qu'un langage comme python devrait se baser là dessus ?

    Je ne vois pas où est le problème. Tout dépend de tes attentes en termes d'overhead. Si tu considères que l'overhead des solutions existantes pour reproduire la fonctionnalité de fork est trop grand, alors non, bien entendu, il ne faut pas. Mais si tu considères que c'est un coût acceptable, alors oui, complètement. C'est comme l'optimisation de code : d'abord tu écris un code qui fonctionne (en pensant un minimum en amont à des solutions optimisables sans tout récrire) et ensuite tu optimises.

    Pour finir sur ce sujet : l'utilisation de fork doit être vue plus comme une façon de permettre une premier port de l'interpréteur sous Windows, pas comme une façon d'avoir le truc le plus efficace. Par exemple, si tu voulais porter Python sous un OS comme VMS, tu serais bien embêté, car il n'y a pas de fork non plus, et l'appel système de création de processus ressemble plus à ce que l'ont trouve sous Windows NT / Win32 API que sous UNIX/Linux (ce qui n'est pas très étonnant, quand on considère qu'une partie des gens qui ont codé le noyau original de NT, et donc spécifié son API ont aussi bossé sur VMS).

    Oui, ça aussi ça peut être vu comme un troll ! Il existe plein de domaines ou tu peux lancer des tâches indépendantes mais tu as besoin d'en lancer plein, dans ce cas un script bien fait pour lancer un job PBS et c'est parfaitement adapté !

    Ben la formulation est peut-être trollifère, mais les stats, elles, sont là. Les sysadmin de plein de centres de calcul ont tout bêtement regardé la charge de leurs clusters, et réalisé que si les programmes en eux-mêmes peuvent être gourmands en mémoire, ils ne sont en grande majorité pas parallélisés du tout. On ne parle pas de lancer 4 programmes en parallèle via un script (et même là, tu n'utilises qu'un quart de ta machine au mieux pour des nœuds de calcul récents).

    Je ne dis donc pas qu'il n'y a pas des domaines où lancer plusieurs programmes n'est pas logique, juste que c'est ultra-rare en moyenne sur les clusters/supercalculateurs.

    Je te parle d'utiliser un programme mono-processus, mono-thread, et rien d'autre. Il y a peut-être des cas de programmes parallélisés avec MPI mais qui ne font que des communications nœud à nœud et ne cherchent pas à paralléliser dans le nœud (je ne vois pas pourquoi, mais admettons). Ça ne changerait rien au fait que ces processus ne tirent absolument pas partie du parallélisme disponible au niveau du nœud lui-même. Et comme la plupart des jobs soumis dans des calculateurs demandent généralement d'avoir un accès exclusif au nœud de calcul…

  • [^] # Re: logique pour Google

    Posté par  . En réponse au journal Grumpy : un nouveau concurrent à pythran. Évalué à 4.

    Grumpy ne va pas deux fois plus vite que CPython. Sur un benchmark probablement pourri (vu le nom "fib", on peut supposer que c'est un calcul de la suite de Fibonacci),

    Oui, c'est un benchmark classique pour évaluer l'overhead de création de threads/processus pour une application parallèle. Le code « classique » est le suivant :

    /* J'utilise OpenMP pour paralléliser parce que je suis paresseux */
    long fib (long n) {
        long n1 = 0, n2 = 1;
        if (n < 2) return n;
    #   pragma omp task shared(n1) firstprivate(n)
        n1 = fib(n-1);
    #   pragma omp task shared(n2) firstprivate(n)
        n2 = fib(n-2);    
    #   pragma omp taskwait
        return n1+n2;
    }

    À noter que la performance parallèle de ce code est abominable, et qu'une bonne implémentation séquentielle et impérative ira 100 fois plus vite (littéralement).

    Mais ce code permet d'évaluer la robustesse du runtime/système quand on crée des tâches de façon exponentielle, car il n'y a pratiquement pas de calcul à effectuer. C'est un benchmark classique dans le domaine de l'évaluation de création de tâches. Cependant, je connais aussi pas mal de gens qui n'aiment pas ce benchmark, car il n'est pas forcément représentatif de vrais workloads utilisés pour des applications parallèles, et fait l'impasse sur certaines optimisations qui existent dans les environnement d'exécution qui proposent un système de création de threads/tâches et qui tirent parti de tout un tas d'aspects architecturaux.

    Mais là n'était pas mon propos. Je n'ai pas analysé la pertinence de ce benchmark dans mon post précédent. Juste que, lorsqu'on publie un graphique pareil, généralement ce n'est pas anodin, et qu'on estime que ça va permettre d'avoir des performances pas obtenues par ailleurs.

    Grumpy est deux fois plus lent en simple thread que CPython, et ne parvient à devenir plus rapide qu'en utilisant plus de cœurs…

    C'est relativement classique dans l'implémentation de runtimes pour favoriser les threads : l'avantage ne commence à se voir que lorsqu'on les exécute sur de grands nombres de processeurs/threads matériels.

    (note : ne pas confondre CPython - l'implémentation principale de Python, écrite en C - et Cython - un compilateur statique de Python vers C)

    Oups ! Oui tu as complètement raison, j'ai lu vite et mon cerveau a (mal) interpolé.

  • [^] # Re: L'annonce

    Posté par  . En réponse au journal Grumpy : un nouveau concurrent à pythran. Évalué à 5.

    Bof … ça sent plus le troll qu'autre chose. Les solutions qui sont de passer par cygwin, l'api posix de windows me semblent tout sauf simple. […]

    Relis mieux le lien que j'ai posté : on parle de l'implémentation de Cygwin parce qu'il s'agit d'une des implémentations notables qui reproduit une API POSIX, et en particulier fork. Mais le post explique qu'une partie de la lenteur du fork de Cygwin vient du fait qu'ils utilisaient certains appels systèmes purement pour des raisons de compatibilité avec des OS datant du siècle dernier.

    Ensuite, il existait SFU (Services For UNIX) mais qui, à ma connaissance étaient plutôt mal vus par ses utilisateurs (souvent issus du monde Linux/UNIX) car pas forcément performants ou stables (mais qui fournissait une API POSIX: Windows NT implémente une partie de l'API POSIX depuis un moment, et SFU était une bibliothèque écrite par MS qui essayait de compléter ce qui manquait). La solution de MS a été d'introduire SUA, un ensemble d'outils en ligne de commande que MS a directement porté depuis leur source UNIX, et qui utilise l'API standard de Windows (notamment : on peut utiliser Perl, les outils de ligne de commande classique GNU, etc., en ligne de commande).

    Donc non, il ne s'agit pas d'un troll. Il existe bel et bien des méthodes pour ré-implémenter les appels POSIX manquants, mais comme il s'agit d'un OS différent, alors il y a un coût à cela—en particulier, la « vieille » méthode qu'utilisait Cygwin pendant longtemps pour effectuer un fork impliquait d'allouer de nouvelles pages mémoires pour effectuer des copies explicites du processus parent, ce qui avait pour conséquence de ne pas profiter du COW (dont parle barmic dans sa réponse à mon commentaire).

    [processus vs. threads] Par exemple chez nous on envisage d'avoir des services qui tournent sur des PC dédiés et que l'on appelle dans python sur d'autres PC grâce à ZeroRPC. Cela n'est pas si compliqué à faire lorsque l'on s'est mis dans les contraintes du multi-process, c'est bien plus difficile si l'on part du multi-thread (enfin je pense, on ne l'a pas encore fait …).

    En règle générale, lorsqu'on conçoit un logiciel pour être multithreadé, il faut s'imposer des contraintes dès le départ, notamment sur les API qu'on développe. Dès le début on essaie d'expliquer aux nouveaux étudiants en programmation que les variables globales sont à éviter, mais c'est généralement pour des raisons liées au génie logiciel. Dans le cas de programmes multithreadés, c'est aussi une contrainte liée aux risques de conflits d'accès concurrent aux variables, qui peut engendrer des plantages (meilleur cas), comportements imprévisibles (cas déjà beaucoup plus gênant), ou même se comporter « normalement » et sembler calculer tout correctement, sauf que l'accès concurrent (non protégé) mène ensuite à un calcul faux qui n'est pas détecté tout de suite (pire cas : rien ne permet de savoir que quelque chose ne va pas car les jeux de tests ne sont pas assez poussés pour le détecter).

    Donc oui, utiliser un système multi-processus est plus « facile » à implémenter car tu bénéficies de l'isolation de l'espace mémoire entre les processus. En termes de performance, tout dépend vraiment de comment tu utilises ta machine. Quand on sait que ~70% des programmes lancés sur les nœuds de calcul de supercalculateurs sont mono-processus, mono-thread (et que donc ils n'utilisent pas 90% de la machine en termes de puissance de calcul), avoir une vraie conception multi-processus est déjà mieux que la moyenne, et de loin. :-)

    s'il faut dupliquer les flux de données important pour émuler la mémoire partagé, cela perd vraiment de l'intérêt. Mais généralement quand tu en es là, tu peux tout à fait partir sur un module cython et relacher le GIL, cela me semble bien moins compliqué que de passer toute sa base de code de python vers Go.

    Ben pas forcément : dans leur cas, ils n'utilisent plus de modules écrits en C et qui utilisent l'interface Python adéquate, car ils ne peuvent pas gérer les ressources utilisées, mais en retour, ils génèrent du code Go directement en gardant le source Python, ce qui permet aux programmeurs de maintenir un programme avec un langage de haut niveau malgré tout plus simple à utiliser que Go directement. Tout dépend de l'objectif du projet donc. :-) Et surtout, s'ils ont déjà tout un tas de bibliothèques déjà écrites pour Go et qui satisfont leurs besoins, alors l'intérêt des modules C devient « mécaniquement » moins grand.

  • [^] # Re: L'annonce

    Posté par  . En réponse au journal Grumpy : un nouveau concurrent à pythran. Évalué à 2.

    Complètement d'accord pour dire que COW (et d'autres techniques de recyclage de pages mémoire aussi) permet de réduire une partie du problème. Après tout dépend de la nature de l'application. Si tes processus sont censés partager des données, du point de vue du modèle d'exécution, à moins de passer par des segments de mémoire partagée ou équivalent, tu vas devoir passer par des IPC de type passage de message, socket, ou pipe. À ce moment-là, COW permettra de réduire l'impact de la duplication des données et de l'allocation mémoire (il y a même de bonnes chances pour qu'au moins la partie purement « lecture seule » soit correctement unique à tous les processus dupliqués).

    Cependant, par exemple dans des processus parallèles (je pense notamment à des trucs genre calcul utilisant MPI), il y a souvent des échanges de données (par exemple dans des algos itératifs qui se basent sur des représentations à base de graphes, il faut échanger les « cellules fantôme » (ghost cells) ), et en fonction du nombre, ça peut mener à de grosses sur-consommation mémoire si on passe par des processus plutôt que des threads (j'ai des exemples de collègues qui à l'époque avaient réussi à réduire l'empreinte mémoire de plusieurs giga-octets en utilisant une implémentation de MPI maison basée sur les threads plutôt que les processus).

    Ensuite, je suis complètement d'accord pour dire que les exemples que je peux donner sont relativement marginaux, car ils s'inscrivent dans le cadre d'applications hautement parallèles avec un grand besoin en performance.

  • [^] # Re: L'annonce

    Posté par  . En réponse au journal Grumpy : un nouveau concurrent à pythran. Évalué à 3.

    Quelques remarques :

    1. L'article explique que leur traduction Python → Go n'utilise pas de GIL. Ça signifie qu'ils peuvent utiliser de vrais threads et pas de processus. D'un point de vue performance, c'est quelque chose d'extrêmement important, mais en fait je pense que c'est encore plus important d'un point de vue empreinte mémoire : lorsque tu crées de nouveaux processus, tu dupliques tout l'espace mémoire associé (y compris un interpréteur, par exemple…); quand tu crées des threads, l'empreinte mémoire est bien moindre, ce qui a plusieurs implications en termes de nombre de tâches concurrentes que tu peux exécuter à la fois, mais aussi lorsque le système effectue des changements de contexte, les caches sont moins mis à contribution (moins de cache thrashing) ce qui permet d'obtenir une meilleure performance.
    2. Ils disent eux-même que la capacité à utiliser des threads est directement le résultat d'une décision de conception : interdiction d'utiliser les modules écrits en C et exécutés depuis Python. Ils se coupent donc d'une partie de l'écosystème Python pour pouvoir obtenir de bonnes performances depuis Python « pur » (mais bon, en échange, ils peuvent importer les bibliothèques Go, donc ça s'équilibre).

    Sinon, concernant ton explication que Windows n'a pas d'appel à fork : c'est vrai, il n'y a pas de fork POSIX (quoique, c'est plus tout à fait vrai depuis un petit moment, vu qu'il existe une implémentation d'une partie de l'API POSIX en Windows « natif » pour Win10 depuis quelques mois déjà). Mais tu penses bien qu'ils ont un moyen de dupliquer l'espace mémoire d'un processus s'il le faut. :-) C'est juste que l'API est plus complexe. Voir ici par exemple.

  • [^] # Re: logique pour Google

    Posté par  . En réponse au journal Grumpy : un nouveau concurrent à pythran. Évalué à 3.

    Je comprends ton point de vue, mais lorsqu'on met en avant des graphes qui montrent que Grumpy va deux fois plus vite que Cython, alors il me semble assez clair que l'idée est aussi de générer du code qui va vite.

    Tout ce que je dis, c'est que la lisibilité est rarement compatible avec la performance — c'est pas impossible, mais le temps passé à générer du code lisible, c'est autant de temps pas passé à générer du code performant.

  • [^] # Re: logique pour Google

    Posté par  . En réponse au journal Grumpy : un nouveau concurrent à pythran. Évalué à 1.

    Quand tu génères du JavaScript, derrière il y a plusieurs implémentations de l'interpréteur […] Du coup, le principe est plutôt de laisser le runtime faire l'optimisation.

    Oui, c'est pour ça que je demandais. :-)
    Dans le cas de CoffeeScript → JavaScript, puisque de toute manière la machine virtuelle et son éventuel moteur JIT vont faire le boulot d'optimisation, celui qui écrit le compilateur peut se permettre de se focaliser sur une génération « propre » de code.

    Je ne suis pas certain que ce soit vrai pour la génération de code Go.

    On a un peu la même philosophie quand on génère du bytecode Java: le bytecode standard est pas du tout optimal, en fait il est plutôt éloigné de ce que les machines virtuelles font vraiement

    J'étais surpris par ça, du coup j'ai fait un peu de recherche. Il semblerait que tu aies raison, mais principalement parce que l'optimiseur JIT aurait trop de mal à optimiser quoi que ce soit si le code avait déjà de grosses optimisations faites à la compilation (parce que sinon, comme la machine à pile implémentée par la JVM est complètement spécifiée, y'aurait aucune raison de ne pas faire des transformations optimisantes statiquement sinon).

  • [^] # Re: logique pour Google

    Posté par  . En réponse au journal Grumpy : un nouveau concurrent à pythran. Évalué à 4.

    Est-ce que CoffeeScript a une ambition de performance ? (Quelque part, puisqu'on parle d'un langage qui génère du JS, qui tourne le plus souvent sur un navigateur, je suppose que non, ou en tout cas qu'on estime que le code généré a une performance acceptable sans être nécessairement proche d'optimale). De ce que j'en avais vu, CoffeeScript est « à peine » (en exagérant un peu j'avoue) plus haut niveau que JavaScript, ce qui aide aussi je pense.

    Si ton but est de générer du code lisible, alors oui tu vas faire un effort pour la génération de code. Mais dans 90% des cas (et je suis généreux, il faudrait plutôt parler de 99%), tu cherches à générer du code-tout-court, voire à générer du code-qui-va-vite. Autant générer du code qui reprend le nom des variables du programme original n'est pas trop compliqué (au pire, tu t'en sers comme d'un préfixe et tu rajoutes des indices si tu dois générer des formes intermédiaires), autant générer du code qui doit créer de nouvelles variables qui ne sont pas utiles dans le langage de plus haut niveau va généralement impliquer l'utilisation d'une variable « anonyme » avec un bête compteur (parce que tout bêtement ton compilateur n'en sait généralement pas assez au niveau de la sémantique du programme pour donner un nom qui fait sens dans un contexte donné).

    Et enfin, même à la main, lorsqu'on commence à réellement optimiser le code généré (je ne suis pas sûr que ce soit l'objectif de ce projet, mais ça pourrait arriver à terme), alors il est quasiment impossible d'obtenir du code lisible. Ou plus exactement : il est lisible pour qui comprend les optimisations appliquées — et encore.

    PS: oui je chipote et je trolle, mais il est « à peine » vendredi ici. :-)

  • [^] # Re: logique pour Google

    Posté par  . En réponse au journal Grumpy : un nouveau concurrent à pythran. Évalué à 4.

    Hum, tu t'attendais à quoi ? N'importe quel compilateur va forcément générer du code difficile à lire au final, et c'est normal. :-)

    Oui, la génération de code automatisée rend les programmes imbitables, mais j'ai envie de dire, c'est comme ceux qui se plaignent de XML en disant que c'est pas lisible quand c'est généré par une machine. Ben justement, si, c'est lisible, et ça reste plus lisible que de l'assembleur ou du langage machine. Malgré le côté obscur du code (Go ou XML) généré, ça reste un langage dont on peut comprendre la syntaxe, qui permet de faire des choses de haut niveau, etc. Même principe. Par contre, la seule raison de mater le code est si tu veux optimiser quelque chose ou que le générateur de code a mal fait son boulot (le code est pas correct par exemple).

    Le côté simple/facile à lire de Go c'est pour un humain qui génère du code lui-même. Si tu veux la version simple à lire de ce programme, tu prends la version Python. :-)

  • [^] # Re: Temps d'exécution sans optimisation ?

    Posté par  . En réponse au journal Pythran chatouille Cython. Évalué à 5.

    Tu pars du principe que le programmeur est meilleur que la machine pour optimiser et donc qu'il est plus efficace de partir d'un langage bas niveau qui donne toute la latitude pour piloter le calcul.

    Ça dépend de quel type d'optimisation on discute (voir plus bas). Dans le cas normal je suis d'accord avec toi, le compilateur est souvent meilleur que toi. Lorsqu'on parle de gens qui cherchent à optimiser une boucle après avoir observé que c'est celle-ci prend beaucoup de temps à s'exécuter, alors c'est un cas différent : tu as déjà compilé avec -O3, possiblement en promettant à ton compilo que les pointeurs ne pointent pas sur des zones qui se recouvrent1

    Les langages fonctionnelles sont très efficaces pour cela. Les notions de fonctions pures, de typage fort (avec ou sans inférence), d'évaluation paresseuse, les map (qui sont une forme de SIMD)

    (c'est moi qui graisse) Si le concept est similaire (une seule instruction appliquée à un jeu de données vs. une seule fonction appliquée à une liste d'éléments), les implications en termes de génération de code n'ont strictement rien à voir.

    Quand il s'agit de vectorisation, les compilateurs (y compris Intel) sont quand même pas complètement au point. Ils font souvent de la « vectorisation partielle », dans le sens où ils utilisent correctement les registres SSE/AVX (avec le bon type d'instructions du coup), mais où ils ne savent pas s'ils ont le droit de correctement charger les données 128 ou 256 bits à la fois, et donc utilisent ces registres principalement pour charger des données 64 bits dans des registres qui font le double ou le quadruple en capacité. Depuis peu, GCC fait de l'auto-vectorisation partielle (qui me semble légèrement moins au point que celle d'Intel), mais dans tous les cas, à moins d'avoir des garanties en béton sur les pointeurs, sur le code, etc., la vectorisation complète (càd : qui utilise pleinement les registres vectoriels des machines x86/x64) est rarement achevée. C'est pour ça qu'on continue d'utiliser les intrinsics à la main dans beaucoup de codes à partir du moment où on se dit que ça va pas assez vite. Après, il existe des outils pour déterminer si ça vaut le coup de se prendre la tête à vectoriser, en regardant le rapport entre le nombre d'instructions arithmétiques et le nombre de mouvements mémoire : un code peut être vectorisable sans pour autant faire gagner en performance, car le processeur passe son temps à attendre que la mémoire lui fournisse les prochains éléments à traiter.

    D'ailleurs, c'est tellement reconnu que le dernier standard en date pour OpenMP (qui est le langage de programmation parallèle le plus populaire dans la communauté du calcul intensif) fournit une clause (le mot-clef « simd ») pour dire au compilateur que le code est vectorisable (donc en gros le programmeur prend la responsabilité d'avoir vérifié que l'agencement des données permet effectivement de vectoriser le code, mais au moins il n'a plus à utiliser les intrinsics — enfin, on espère).


    1. En C/C++, ça s'exprime avec restrict dans la signature des fonctions, ou au niveau du compilateur tu peux le spécifier « par fichier » avec un flag de type -fno-alias chez Intel ou -fstrict-aliasing chez GCC je crois — et il semblerait qu'au moins avec gcc ce soit activé à partir de -O2.  

  • [^] # Re: Pourquoi faire simple ...

    Posté par  . En réponse au journal Échanger des courriels avec Pôle-Emploi, ça peut être compliqué. Évalué à 2.

    On est bien d'accord, mais ça donne quand même une certaine idée. Par contre, si la distribution des salaires suit en proportion celle des divers employés (externes, internes, etc.) au niveau national, on obtient :

    • En France le salaire médian est de ~1700€/mois, contre un salaire moyen de ~2400€/mois.
    • En extrapolant, ça voudrait dire (en supposant un salaire moyen annuel de ~45k€/an) que le salaire moyen annuel à Pôle Emploi est de ~3750€/mois, et le salaire médian de ~2600€/mois.
  • [^] # Re: Le code de la route n'est rien d'autre qu'un ensemble de protocoles pour réseaux routiers

    Posté par  . En réponse au journal Et vous, vous voulez qu'elle fasse quoi votre voiture autonome ?. Évalué à 3.

    C'est la réflexion que je me faisais en voyant les progrès effectués dans le domaine

    Oui, mais il faut bien voir que même le saligot moyen de région parisienne ou ailleurs sait souvent mieux conduire que l’étasunien moyen. En Europe on a un système relativement complexe de signes pour le code de la route, alors qu'aux US mis à part les symboles vraiment super courants, presque tout est écrit en anglais (et du coup l'universalité du code de la route en prend pour son grade). On peut ajouter à cela que ce qu'on apprend en France/Europe sur comment se comporter sur autoroute (du genre : aller sur la file la plus à droite sauf si tu doubles, etc.) est complètement ignoré en moyenne aux USA, que l'utilisation du clignotant est souvent considéré comme facultative, etc. (je sais que souvent en France on se plaint des mecs qui utilisent pas le clignotant, mais en comparaison avec les USA, c'est franchement rare).

    Je ne parle même pas de la notion de priorité à droite (bon, pour les défendre, aux US généralement tout est explicitement signalé, donc pas besoin de dire qu'une route est prioritaire, ou d'user de la priorité à droite : absolument tous les croisements sont équipés de panneaux « STOP » ou « céder le passage » si besoin).

  • [^] # Re: Qu'elle n'envoie pas mes données de déplacement partout

    Posté par  . En réponse au journal Et vous, vous voulez qu'elle fasse quoi votre voiture autonome ?. Évalué à 3.

    Con ? non, interagir avec les personnes que tu ne connaît pas c'est bien aussi. :)

    Tu te rends compte que cet argument est exactement le même que celui qui était utilisé dans les années 90 ou début 2000 à propos des gens qui causaient sur IRC ou autres systèmes de discussion, et à qui on disait « c'est bien, tu parles à quelqu'un qui vit en Australie, mais tu ne connais même pas ton voisin de palier ! » ? :-)

    Ben non, mon voisin de pallier, tout ce que je sais, c'est que c'est une voisine, qui recevait un monsieur qui fumait dans son entrée, et qui empestait tout le pallier d'odeur de tabac froid (je suis ancien fumeur et j'ai aucun problème à ce que les gens fument, mais un minimum de vivre ensemble et fumer plus près d'une fenêtre c'est pas la panacée)1.

    C'est aussi l'argument sorti de nos jours à propos des gens qui communiquent pas entre eux. Ben je sais pas toi, mais moi le matin, je suis rarement bien réveillé et de bonne humeur (je me réveille doucement dans le train—enfin, quand j'étais encore en région parisienne), et j'ai pas spécialement envie de discuter avec mon/mes voisins. Et avant les portables, on avait les baladeurs qui nous permettaient justement de nous isoler un peu du monde et de continuer de voyager pendant nos 1h30 de transports journaliers moyens sans stresser trop (parce que les transports en commun en heure de pointe, c'est pas du tout relaxant, ou même neutre).


    1. A contrario, je connaissais des voisins d'autres paliers et on s'entendait bien. Comme quoi… 

  • [^] # Re: Ne plus avoir de voiture

    Posté par  . En réponse au journal Et vous, vous voulez qu'elle fasse quoi votre voiture autonome ?. Évalué à 2.

    Je sais que tu blagues, mais pour faire mon littéral : c'pas pareil ! On parle de deux points arbitraires !

    Voilà, j'ai fini.

  • [^] # Re: Ne plus avoir de voiture

    Posté par  . En réponse au journal Et vous, vous voulez qu'elle fasse quoi votre voiture autonome ?. Évalué à 5.

    Je vais même aller plus loin : la poste, justement pour des histoires d'efficacité/productivité/pas embaucher de fonctionnaires/etc. embauche des externes pour livrer tout un tas de trucs, leur donne des objectifs journaliers de nombre de colis/lettres à livrer, tout en étendant la surface de livraison. Et c'est pareil pour les mecs de type FedEx/UPS/etc. Au final, c'est justement la réduction de personnel, liée à l'augmentation des objectifs en termes de productivité qui génèrent ce genre de comportements.

  • [^] # Re: Pourquoi faire simple ...

    Posté par  . En réponse au journal Échanger des courriels avec Pôle-Emploi, ça peut être compliqué. Évalué à 2.

    Tu peux être sûr que dans l'administration il y a des pics et des creux dans l'activité informatique. Tu ne vas pas recruter une armée de développeurs pour que une bonne partie se touche la nouille quand il y a moins de projets. Tu ne vas pas non plus recruter des gens dont la compétence est nécessaire sur un projet donné mais pas sur les autres.

    Mais d'un autre côté, si tu permets aux développeurs (pas forcément ingénieurs !) de se former pendant les creux, quand il s'agira de développer un nouveau projet, et si on peut planifier suffisamment à l'avance, alors tes développeurs pourraient avoir suffisamment d'expérience (en dév en général, et d'heures de formation/expérimentation) pour passer à l'exécution du projet. De plus, c'est pas comme si les SSII ne vendaient jamais leurs « ingénieurs » (je mets des guillemets car il n'est pas rare de voir quelqu'un de vendu en tant que tel mais qui n'a pas le titre à proprement parler) en tant « qu'experts » (ce qui, en langue de bois SSII-ienne veut parfois dire « il s'est auto-formé il y a 15 jours »).