Quelques raccourcis :
Notez que le contenu de cette page est en chantier, en particulier sur le plan du formatage, car je suis débordé. Je retravaillerai le tout dès que possible, promis.
Grâce à l'Université de Sherbrooke (en particulier, grâce à Richard Fontaine du CeFTI) et au Collège Lionel-Groulx (en particulier à Patrick Lebonnois et à mes collègues du département d'informatique), j'ai le privilège de participer en personne à CppCon 2023. Notez que la conférence est de retour en format « pleinement en présence » pour la première fois depuis la pandémie.
Ce qui suit est une sorte de journal de voyage (sans la partie voyage!), avec éléments humains et éléments techniques. Au besoin, référez-vous à ce glossaire : ../../Lexique/lexique-wg21.html
Notez que c'est pour moi une semaine très, très occupée, et que j'ai assurément oublié de mentionner plusieurs rencontres. Si je ne vous ai pas mentionné, ça en dit plus sur ma mémoire défaillante que sur l'intérêt que je vous ai porté.
Pour un peu de bagage supplémentaire sur l'événement, voir :
Pour les journaux de « voyage » d'autres participants, voir :
Début du contenu technique
Je vais mettre le contenu technique dans des blocs les mettant comme celui-ci. Si vous ça ne tombe pas dans vos cordes, passez par-dessus.
Fin du contenu technique
Je suis arrivé à l'hôtel en fin d'après-midi. J'ai fait un voyage sans anicroches, outre le fait que j'ai été intercepté aux douanes américaines qui pensaient que j'avais peut-être besoin d'un visa pour l'événement (ça n'a pas duré très longtemps, et je suis arrivé d'avance à l'aéroport alors c'est un moindre mal; l'équipe à la douane était professionnelle et courtoise et nous avons réussi à résoudre l'imbroglio).
J'ai oublié des vêtements ici l'an passé, et il semble que je ne pourrai pas les récupérer (j'ai gardé contact avec l'hôtel pendant l'année, mais mon contact semble avoir quitté... Triste, j'avais une belle veste dans ce que j'ai oublié).
Il n'y aura que quatre classes pré-conférences cette année : la mienne, et celles de Mateusz Pusz (avec un chouette titre!), Nicolai Josuttis et Walter Brown. Je pense que c'est du contenu très solide dans chaque cas. Certaines n'ont pas démarré (faute d'inscriptions, le même phénomène qu'à Toronto cet été) mais auraient été vraiment bonnes.
Durant l'une des pauses lors de la première journée de classe, j'ai eu droit à un beau compliment de la part de mon ami Walter Brown (venant d'une sommité de cette envergure, c'est très touchant!)
Deuxième journée de classe, donc je suis très occupé, et il y a l'enregistrement pour l'événement en soirée. La classe s'est bien passée selon moi, mais je n'ai pas eu le temps de couvrir le volet « profileur » (ennuis techniques) et celui des options de compilation (à préparer cette semaine). J'ai quelques erreurs typographiques à corriger dans le matériel de cours, mais sur plus de 1000 pages c'était probablement inévitable.
Je suis passé en coup de vente à la réception : il fallait que je m'enregistre, mais je présente demain et je ne suis pas prêt (j'ai beaucoup de matériel, mais à 17 h aujourd'hui, après mon cours, j'avais... zéro diapos de prêtes, et aucun embryon de document.
C'est sympathique de revoir les gens (Jason Turner, Ben Deane, Herb Sutter, Inbal levi, Nina Ranns, etc.), même en coup de vent.
Si ça vous intéresse, tout est ridiculement cher ici. Pris au « marché » de l'hôtel (aucun commerce à distance de marche) : une salade, une mini bière, 30 USD...
Debout vers 4 h 30 du matin comme d'habitude (c'est tard pour moi : 6 h 30 du matin heure de Montréal). Douche, puis préparation de la planification de la semaine. CppCon est un événement très riche en contenu, et il y a sept ou huit plages horaires chaque jour avec plusieurs options concurrentes à chaque fois (sauf le soir et tôt le matin, où les options sont limitées à deux ou trois à la fois). Heureusement que tout est enregistré!
Je me suis rasé (je présente en après-midi et ce matin, je n'étais pas vraiment présentable 🙂). Le climat est très sec au Colorado et avec ma peau, garder la barbe un peu trop longue déssèche mon visage alors j'ai intérêt à garder le visage plus lisse cette semaine.
Je mets quelques heures de travail sur ma présentation d'aujourd'hui. Au moment d'arrêter, j'ai 142 diapos, c'est probablement un peu trop mais je vais le gérer « live ». Je vais me relire à tête reposée tantôt car il y a sûrement des trucs qui manquent de fluidité et quelques fautes typographiques.
Petite jasette avec John Lakos dans l'ascenseur (sa chambre est sur le même étage que la mienne). J'en profite pour lui dire merci pour Quantifying Dinosaur Pee et ses présentations sur l'idée de valeur au fil des années : ces présentations sont pleines d'informations qui me servent dans mes cours.
La salle de bal qui accueille la plénière est grand mais plus humble que celle que nous occupions en 2019. L'événement reprend du tonus, mais nous n'en sommes pas revenus à la fréquentation pré-pandémique (j'ai entendu Karen Krueger, l'ange gardien de l'événement, dire que nous étions autour de 700 individus cette année, ce qui est un peu plus de la moitié de la fréquentation de 2019, mais beaucoup mieux que tout ce que nous avons eu depuis!)
Je blague un peu avec Herb Sutter sur des enjeux d'ordre politique. Le band qui nous accueille chaque année depuis la toute première occurrence de CppCon, en 2014, offre l'ambiance musicale. Jon Kalb prend la parole, accueille les gens présents et donne un peu de contexte sur l'événement et son succès. Il met de l'avant que les gens qui présentent sont aussi des participants de l'événement, et qu'on peut leur parler, qu'ils sont mêlés au groupe et sont aussi ici pour profiter des idées qui circuleront. Jon Kalb explique un peu la logistique de l'événement cette année, remercie les commanditaires (il y en a de nouveaux cette année! On a pour la première fois un commanditaire « platine », Bloomberg, c'est chouette! Ils passent une petite vidéo promotionnelle, mais c'est sympa et c'est court). Les badges qui nous ont été donnés one des codes QR qui donnent nos coordonnées si on l'expose aux gens intéressés (ça peut aider au réseautage et à l'embauche). Le CoC (code de conduite) est présenté et notre Ombudsperson explique les règles.
Enfin, Jon Kalb laisse place à Bjarne Stroustrup qui débute son allocution.
Bjarne Stroustrup explique que sa présentation portera sur ce qu'on entend par Safety, Safe C++, l'impact des Core Guidelines et l'idée de profils supportant des objectifs de sécurité. Définir Safety sera l'un des premiers enjeux (Safety est difficile à traduire; il y a des nuances à ce terme).
Bjarne Stroustrup rappelle la position du gouvernement américain à l'effet de ne pas utiliser « C/C++ », ce langage mythique qui n'existe pas. Il indique qu'on parle d'un sujet de préoccupation, pas de panique, et qu'il faut s'occuper de cet enjeu pour redresser la confiance de ces gens (c'est en grande partie un enjeu politique et pédagogique plus que technique). C/C++ n'existe pas, et il recommande d'écrire du C++ tout simplement ce qui règle la plupart des problèmes techniques. Bjarne Stroustrup aborde ensuite l'enjeu de l'image du langage.
Bjarne Stroustrup rappelle que l'idée d'offrir un langage avec complète Resource-Safety et complet Type-Safety fait partie de C++ depuis le début. Cela requiert des approches de programmation judicieuses, supportées par des bibliothèques, de l'hygiène de programmation, de l'analyse statique. Il détaille certaines des principales préoccupations, et liste celles qui se valident à la compilation de même que celles qui se valident à l'exécution. Il présente les contours de ce qu'on entend par Memory Safety au passage.
Bjarne Stroustrup rappelle que C++ permet la progammation système et ne peut pas se permettre de faire de l'impartition des enjeux plus délicats à d'autres langages. Faut être capables de réaliser les tâches critiques en C++. Toute solution aux enjeux de Safety doivent tenir compte des millions de programmeuses et de programmeurs C++ sur la planète et de l'immensité du code existant. Comme il le dit, Stability is a Feature
Bjarne Stroustrup parle du défi de décrire un usage Type-Safe de C++ (pas de fuites de ressources, pas de bris du système de types). Juste convaincre les programmeuses et les programmeurs d'adopter de meilleures pratiques de programmation est un défi, surtout à grande échelle!
Bjarne Stroustrup liste ensuite plusieurs sous-domaines de Safety (autour de dix familles d'enjeux distincts, incluant des erreurs de « timing » et de prévisibilité pour les systèmes critiques tels que les systèmes en temps réel). Certains recoupent les enjeux de ma présentation de cet après-midi. Dans certains cas, les enjeux ont des objectifs mutuellement exclusifs : il faut faire des choix, il faut avoir des objectifs clairs.
Bjarne Stroustrup rappelle que la sécurité n'est pas la même chose que le Memory Safety, et liste de nombreux enjeux de sécurité autour du logiciel qui n'ont rien à voir avec cette particularité des langages. Les langages ne sont pas en soi Safe, mais leur sain usage peut l'être. Il y a des mécanismes qui permettent de coutourner les règles dans tous les langages, quand bien même ce ne serait que pour communiquer avec le système d'exploitation.
Bjarne Stroustrup fait ensuite un petit historique des idéaux de sécurité de C++ depuis 1979. Le Type-Safety a toujours fait partie de ces idéaux, mais la perfection est l'ennemi du bien parfois. Pour gérer la complexité et offrir une efficacité sans compromis, il faut faire certains choix... Bjarne Stroustrup rappelle qu'en 1980, appeler sqrt() incorrectement en C pouvait faire planter l'ordinateur au complet, et que C++ a toujours été plus robuste que cela. La validation stricte de types de paramètres remonte à 1983, à la compilation comme à l'édition des liens.
Bjarne Stroustrup rapelle l'idéal de représenter les idées à même le code, que C++ permet mieux que n'importe quel autre langage. Il donne quelques bribes historique autour du mot const (c'est amusant). L'idée derrière RAII arrive en 1979, la paire constructeur / destructeur qui solidifie l'approche remonte à 1983, et RAII en tant que terme officiel remonte à 1988.
Bjarne Stroustrup revient sur l'historique de la programmation orientée objet, intégrée entre 1981 et 1984 suivant les travaux des auteurs de Simula (on leur doit entre autres l'idée d'héritage). Les templates, les exceptions, les conteneurs, les algorithmes... les concepts! sont tous venus par la suite et ont raffiné C++ en tant qu'outil de pensée et d'expression sécuritaire. Les range-based for et span aident dans le code contemporain à écrire des interfaces correctes. Il rappelle que l'idée de span était dans les plans de Dennis Ritchie pour C dans les années '80 mais qu'il n'avait pas le contrôle requis sur l'évolution du langage pour l'imposer. Il rappelle aussi que son (très bon) livre de C++ pour débutants n'aborde les pointeurs qu'au chapitre 17, après avoir fait des interfaces graphiques.
Bjarne Stroustrup estime que le code démontrablement Safe est celui sur lequel il est le plus simple de raisonner. Juste « être prudent(e) » ne fonctionne pas à grande échelle. Il poursuit en expliquant la démarche derrière les Core Guidelines qui visent à moderniser le code C++ et à réduire la proportion de code inadéquat dans le monde. Parfois, juste exprimer plus clairement ce qui doit être fait aide l'optimiseur, et le code clair est alors aussi le code rapide. L'approche générale est :
Bjarne Stroustrup offre une liste de « règles philosophiques » de programmation (il va trop vite pour que je puisse prendre des notes) et rapelle que limiter C++ à un sous-ensemble ne fonctionne pas. Ce qui fonctionne est la construction d'abstraction de qualité par-dessus les trucs plus dangereux qui se trouve plus profondément. Il liste des trucs qu'on peut éliminer de notre code (je ne suis pas d'accord avec tout ce qu'il y a là, mais c'est correct). Les mécanismes plus dangereux peuvent être utilisés dans des zones de code clairement identifiées. Il parle des marqueurs dans le code pour clarifier que certains « opt-out » sont choisis de manière volontaire. Les abstractions de plus haut niveau de C++ permettent souvent de remplacer les mécanismes de bas niveau à coût nul. Beaucoup de ce qu'il dit sur la vitesse d'exécution et les choix à faire en ce sens recoupe mon discours en classe durant la fin de semaine 🙂
Bjarne Stroustrup parle de mauvaises habitudes importées d'autres langages par des gens qui ne se méfient pas, et de fuites de ressources (pas juste de mémoire!) qui en découlent. Ça correspond à mon expérience aussi. Éviter les pointeurs bruts qui ne sont pas encapsulés règle beaucoup de problèmes (un pointeur brut est un outil d'observation, faut pas présumer plus). Il présente plusieurs exemples mais rien de novateur pour moi. Il propose une annotation pour les invalidations, ça rejoint une proposition de P2966 (mon document semi-omnibus pour SG14 🙂). Il revient sur l'idée de owner<T*> en tant qu'alias sémantiquement chargé pour T* tout en rappelant que unique_ptr<T> est une abstaction préférable si possible.
Bjarne Stroustrup rappelle qu'on peut mieux écrire notre code C++. Plusieurs ne le font pas, tristement, et les Guidelines ne suffisent probablement pas pour cette raison (il nous faut des garanties). Changer le langage en profondeur ne fonctionnera pas (il y a trop de code en circulation sur la planète) ce qui explique qu'il propose des profils. par exemple un profil de sécurité, un profil de vitesse... Il discute au passage de l'idée de remplacer C++, à la mode ces temps-ci, mais il y a beaucoup de « bof » dans cette approche (je suis d'accord avec lui). Il signale au passage que quelques enthousiastes d'un nouveau langage sont souvent bien meilleurs que les programmeuses moyennes et les programmeurs moyens sur la planète. Il discute des coûts de remplacement de code existant, pour donner une idée... Il cite Gall's Law en disant qu'un système complexe qui fonctionne a inévitablement évolué à partir d'un plus petit système qui fonctionnait
Bjarne Stroustrup explique ce qu'il entend par profile. C'est intéressant mais trop gros pour prendre des notes. L'idée est de définir ce qui est exigé des programmes, et d'en imposer le respect à la compilation. L'analyse de code C++ à grande échelle est trop difficile (bibliothèques à liens dynamiques, problème de l'arrêt, ce genre de truc) mais avec des profils à respecter on peut rendre ça viable. Ça prend une approche concertée qui inclut plusieurs volets.
Bjarne Stroustrup parle un peu de l'intégration de modules compilés avec des profils différents. Il propose ensuite une idée d'une syntaxe basée sur des annotations qui ressemble à ce qu'il a en tête (je vois approcher un conflit avec les contrats). P2687 et P2689 (pas sûr du 2e). Il lance un appel à la communauté pour des contributions à l'idée de profil : desquels avons-nous besoin? Comment les spécifier? Bjarne Stroustrup semble vouloir bouger plus vite que WG21...
Q : tu as mentionné un vector<T> sans push_back() dans certains profils. Est-ce qu'éliminer des fonctions membres ferait partie des profils?
Bjarne Stroustrup : c'est pas ma vision des choses. Je livrerais plutôt une implémentation de vector<T> qui teste les bornes par exemple.
Q : en C++, les string sont mutables par défaut. Pourquoi pas des string immuables?
Bjarne Stroustrup : je n'ai pas vu d'argument conséquent justifiant de changer ce comportement
Q : tu parles souvent d'outils autres que le compilateur. Intégrer des outils tiers demande beaucoup d'argent et d'efforts...
Bjarne Stroustrup : il y a des enjeux avec les Toolchains. En C++, nous avons une pluralité d'outils, ça complique leur intégration. J'espère que les profils vont aider aussi en ce sens. Le compilateur est déjà un analyseur statique (sophistiqué!), mais il y a des tâches plus longues à accomplir qui conviennent mieux à d'autres outils
Q : tu parles d'améliorer le langage par des ajouts. On aura peut-être un jour des états par défaut qui sont plus sécuritaires...
Bjarne Stroustrup : pour préserver l'intégrité du langage, il faut le faire évoluer par des extensions.
Q : on veut parfois exprimer qu'une fonction est Thread-Safe ou qu'elle fait des entrées / sorties. Pourrait-on envisager le faire par Tag Dispatching?
Bjarne Stroustrup : j'y irais plus par profils, surtout pour Thread-Safe, mais je ne voudrais pas qu'on ait 50 profils non plus (ce serait le chaos).
Q : pourrait-on implémenter tout cela par réflexivité statique?
Bjarne Stroustrup : je ne pense pas. C'est un bel outil, mais pas l'application cible
Q : nous avons essayé d'utiliser les concepts au travail et ça nous a semblé complexifier le code. On n'y a pas vu de bénéfices...
Bjarne Stroustrup : je les utilise depuis longtemps avec plaisir et succès. Ce qu'il faut éviter est une surabondance de requires requires; ça finit par avoir l'air de langage d'assemblage. Faut choisir des concepts de faible granularité, p. ex. : Comparable plutôt que SupportePlusPetit...
Pas si mal. Il y avait des idées intéressantes là-dedans.
Je bavarde un peu avec Jason Turner, un copain de longue date maintenant, puis je prends un muffin et je me dirige dans la salle où Inbal Levi présentera ce matin. Je blague un peu avec elle puis je bavarde avec Klaus Iglberger (vraiment quelqu'un de sympathique). Jason, Klaus et moi faisons à peu près la même chose (de la formation à temps plein) alors on rencontre souvent des situations semblables et nous tempéraments se ressemblent beaucoup.
Le sujet proposé par Inbal Levi m'intéresse mais c'est pas un sujet simple. J'ai hâte de voir son angle d'approche...
Inbal Levi se présente et indique que sa présentation amorce de Software Design Track pour cette année. Elle se dit d'avis qu'on devrait clarifier les points de personnalisation de nos bibliothèques.
Inbal Levi commence par définir ce qu'elle entend par « bibliothèque ». Elle utilise la définition de Wikipedia, parle de l'aspect « partagé par plusieurs » (incluant des gens ailleurs sur la planète qu'on ne rencontrera jamais). Les points de personnalisation (elle cite Eric Niebler avec N4381) mais explique que cette définition est un peu trop pointue pour ses besoins, alors elle donne sa propre définition (correcte mais plus large)
Inbal Levi explique que les usagers doivent savoir ce que sont les Customization Points (CP), doivent être capable de les personnaliser, d'éviter de se faire « écraser » par les versions par défaut des mêmes outils (p. ex.: erreurs découlant d'ADL). Elle dit qu'un CP est une entité (au sens large) à la frontière entre l'espace usager et l'espace bibliothèque
Inbal Levi : les CP sont un outil d'intégration, un outil de communication et d'expression des requis, et (j'ai manqué le 3e)
Inbal Levi aborde les CP Methods. Elle parlera d'héritage, de spécialisation de templates, d'ADL, de CPO, de concepts, de Tag Invoke, de fonctions personnalisables et de réflexivité.
Inbal Levi aborde l'héritage. Les méthodes abstraites sont des obligations, les méthodes virtuelles sont des fonctionnalités, les alias de types et les constantes sont de la terminologie, et les attributs sont des données. Les implémentations spécialisées dans de code de classes dérivées sont des spécialisations. Elle discute des aspects qui touchent le code client et le code de la bibliothèque, et discute de caractéristiques (intrusif pour le type dérivé, non-intrusif pour la bibliothèque, coûtes des appels virtuels, difficile d'en arriver à un opt-in accidentel...)
Inbal Levi aborde la spécialisation de templates par étapes. Elle montre que dans une fonction comme Sort(It,It) on peut dépendre de terminologie à l'interne (c'est vrai), et départage les responsabilités du code client et du code de bibliothèque. Elle montre diverses approches (« classique », CRTP, hybride, spécialisation de méthodes seulement, foncteur générique -- son truc ressemble à « l'opérateur diamant » de C++ 14, etc.), puis apporte son analyse
Inbal Levi poursuit avec la personnalisation par ADL de Niebler. Elle place tout d'abord ce qu'est ADL, car c'est pas facile d'accès. C'est une bonne explication. Elle utilise enable_if, mais des concepts auraient fonctionné. Je pense qu'il y a un bogue d'ailleurs avec sa diapo à ce sujet (la 26 ou proche). Elle utilise des Hidden Friends (populaire ces temps-ci).
Inbal Levi poursuit avec les CPO. Son exemple me semble manquer un truc important (le pont entre Log et Log_fn) dans la diapo 35
Inbal Levi a un joli exemple avec les concepts où elle requiert la présence d'un type interne logged_type pour accepter un type.
Inbal Levi en arrive à tag_invoke. C'est un peu envahissant, beaucoup de macros... Cela dit, c'est pas bête
Inbal Levi poursuit avec un truc qui n'est pas (encore) standard, soit les fonctions personnalisables (P1292, P2547). Ça passe par virtual sur une fonction globale. C'est pas mal. On en fait un Hidden Friend et ça donne de jolis résultats.
Inbal Levi finit avec la réflexivité (pas encore standard non plus). C'est syntaxiquement lourd, mais c'est le plus puissant du lot (évidemment)
Inbal Levi fait ensuite un bref résumé de la présentation. Il y a de bons trucs là-dedans; je pense que ça ferait un bon article de blogue (avec des exemples validés). Elle ajoute des aspects importants non mentionnés durant la présentation (p. ex. : modèle d'exécution, gestion des erreurs...). Elle mentionne les impacts de choix de design comme ceux-ci (incluant le ralentissement de P2300, un gros morceau)
J'ai bavardé un peu avec Inbal ensuite, et je vais lui emprunter quelques idées pour mes cours (surtout pour le vocabulaire).
Il y a eu beaucoup de questions et je devais aller me faire photographier (ils prennent des photos des présentatrices et des présentateurs) alors je suis arrivé à la dernière minute pour la (chic) présentation de Jason Turner.
Vidéo : à venir
Je n'ai pas pris de notes parce que je bavardais avec la voisine (c'était dez puzzles et elle se demandait pourquoi la réponse était ce qu'elle était) et je relisais mes diapos en préparation de ma propre présentation, mais Jason Turner a fait un super travail. Ses exemples étaient amusants, parfois pervers (incluant un cas de comportement indéfini dû à une interdépendance entre une globale static et une autre thread_local... ark) et recoupaient en partie des trucs de mon cours de la fin de semaine (j'ai eu des regards complices de certains de mes participants).
Beau travail!
J'ai ensuite cheminé vers mon local et je me suis assuré que la technique fonctionnait : on a installé le micro portatif, fait les habituels tests de son, vérifié que le signal vidéo se rendait aux bons endroits, etc. Je me suis aperçu une quinzaine de minutes avant la présentation que je n'avais pas encore intégré la diapositive de présentation officielle de l'événement (on a tous un titre qui a la même apparence, c'est important vu que nous sommes filmé(e)s) alors j'ai fouillé dans mes archives pour retrouver le lien de l'endroit où ces diapos étaient déposées, puis je l'ai intégrée et j'étais prêt.
Guy Davidson et Ben Deane se sont assis juste devant moi pour m'offrir une présence bienveillante. Ils sont très gentils.
Évidemment, c'est ma présentation alors je ne prends pas de notes... J'ai fait de mon mieux, pris quelques questions pendant la présentation et une à la fin (j'ai fini presque pile dans les temps, et la question m'a amené exactement à l'heure de fin).
J'espère que les gens ont aimé. J'ai eu quelques questions de gens souriants après la présentation, dont une en français d'un duo père-fils de la région de Sherbrooke! J'ai eu quelques suggestions pertinentes pour ce que je présentais (parfait, c'est exactement ce que je voulais!) et peut-être même des contributeurs à l'effort pour lequel de cherchais à intéresser les gens dans la salle.
Brève jasette avec le très gentil Cameron DaCamara au kiosque de Visual Studio. Je lui explique le bogue du profileur rencontré en fin de semaine, et il me demande de lui envoyer les infos et les sources (ce que j'ai fait par la suite). Très agréable invididu.
Je suis arrivé quelques minutes en retard à la présentation de Matthias Kretz, et la salle était pleine alors je suis resté debout de je n'ai pas pu prendre mes habituelles notes pseudo-verbatim.
Même si je n'ai pas pris de notes pendant la présentation, j'ai pris des notes mentales et ça m'a amené plusieurs idées et réflexions enrichissantes :
Ça valait la peine. J'ai bavardé un peu avec Inbal Levi, Nevin Liber, David Olsen, Daisy Hollman et Mark Hoemmen par la suite et on a tous apprécié.
Petit sac de pretzels (j'ai presque rien mangé aujourd'hui), puis c'est le début de la présentation de Jeff Garland.
Jeff Garland explique qu'il n'est pas là pour faire le tour des pièges des Ranges mais bien pour offrir un bref tutoriel. Il commence par parle du End of begin() and end() avec un exemple qui trie un tableau, puis l'affiche... avec std::print()
Jeff Garland suit avec std::find_if() qui retourne un itérateur, et montre que ranges::find_if() retourne aussi un itérateur alors les itérateurs ne sont pas disparus. Ensuite, il fait un truc comme print("{}", v | est_pair); et ça affiche ce qu'on pense (oh, chouette!) mais faut que est_pair soit un filter([](int n){ return n % 2 == 0; })
Jeff Garland explique ensuite qu'il va faire le tour de quelques-uns des algorithmes de ranges:: et de ranges::views:: pour nous donner des bases solides. Un range est un truc sur lequel on peut itérer, un range algorithm est un algo qui accepte un range, un view est un Lazy Range that's Cheap to Copy, et un range adaptor est un truc qui transforme un range en un view. Il explique que techniquement, un range est une pair {begin(), sentinelle} et les deux doivent être comparables. David Olsen a aidé à rendre les range algorithms applicables en partie aux conteneurs standards et aux paires d'itérateurs. Il explique d'ailleurs qu'on peut encore passer des paires d'itérateur pour opérer sur des sous-ranges
Jeff Garland explique que le fait que ranges soit un concept permet plusieurs trucs merveilleux comme automatiser l'affichage des conteneurs à travers print(). Ensuite, il explique que les range algorithms s'exécutent immédiatement (le volet « calcul paresseux » n'est pas leur faute; ça prend des views pour ça). Les valeurs de retour ont changé dans certains cas, et plusieurs algorithmes acceptent des projections en paramètre. Les projections viennent de chez Adobe.
Jeff Garland dit que les range algorithms en général sont comme les std:: algorithms, mais en mieux (surtout pour les valeurs de retour, qui est souvent une paire itérateur + information enrichie, p. ex. : contains retourne un booléen et un itérateur) et sont exprimés en termes de concepts. Il donne un joli example qui fait un find_last + drop et travers une string pour trouver le dernier élément d'un nom de répertoire
Jeff Garland dit que les views sont pour l'essentiel Non-Owning (il y a des exceptions), ont pour la plupart des opérations O(1), composent bien et permettent des itérations infinies. Ça donne un style de programmation déclaratif plus qu'impératif. Il montre que c'est l'itération à travers la séquence sur laquelle s'applique la view qui provoque les calculs. Il explique ensuite que dans un enchaînement de views à travers des | l'ordre est important (ça peut impacter le nombre de calculs à faire). Important : il explique qu'une view comme filter_view fait du Caching alors faut les passer par référence de relais, pas par référence-vers-const
Jeff Garland présente cartesian_product(), un chouette algorithme multidimensionnel, puis chun_by(), autre truc chouette, puis zip() et zip_transform()... Au passage, il explique que ranges tend à ne pas bouger les données (ou presque pas).
Jeff Garland va ensuite vers les Adjuncts. Il parle de span (un non-ownng view), constexpr si requis, facile à copier, et permet de muter les éléments. Les range algorithms fonctionnent directement avec des span. Il parle de ranges::to pour générer des conteneurs (générer des owning ranges) et fait remarquer qu'on peut écrire ranges::to<std::deque>() sans spécifier le type (il est déduit du type des éléments de la view). Il montre ensuite views::join. Son exemple soulève des questions (le join d'un vector<string> avec un séparateur string_view donne un range de char... mais plus tard on voit qu'il y avait un autre join plus bas avec un char en paramètre et que c'était le coupable)...
Jeff Garland explique qu'écrire nos propres views est douloureux. Il remercie Walter Brown d'avoir insisté pour que les usagers puissent écrire leurs propres views. Il suggère de lire la documentation de Boost nommée std:interfaces
Jeff Garland montre un joli exemple qui calcule la somme des carrés de nombres pour ne garder que les cinq premiers et produit [(0,0) (1,1) (2,4) (3,9) (4,16)]. Il parle de ranges::fold_left() comme étant ce que std::accumulate() aurait dû être
Jeff Garland montre ensuite le plan pour C++26. P2214 pour les détails.
Q : pourquoi accumulate() n'est pas dans ranges::views?
Jeff Garland : c'était pas prêt à temps. Utilise ranges::fold_left()
Pablo Halpern : on a un exemple avec un Range Adaptor. Quel est l'adaptateur exactement? (Jeff explique)
Q : le | m'impressionne. J'aimerais représenter mon serveur entier sous cette forme! Est-ce qu'on peut exprimer nos serveurs entiers sous la forme d'un pipeline de ranges?
Jeff Garland : on n'est pas là 🙂
Q : le Caching apparaît-il ailleurs que sur filter_view?
Jeff Garland : c'est controversé...
Q : puis-je utiliser ranges si mon vendeur ne l'offre pas encore?
Jeff Garland : ranges v3 ne demande que C++14
Q : que se passe-t-il si je veux appliquer ranges::sort sur une std::list?
Jeff Garland : ça va être rejeté, le conteneur ne respecte pas les exigences de l'algorithme. Exactement comme std::sort()
Q : comment on débogue un enchaînement de | exactement? Si ça compile mais ça ne donne pas la bonne réponse...
Jeff Garland : excellente question. Tu peux le découper en petits morceaux et voir où ça brise...
Q : pourquoi un T&& et non pas un T& pour passer des views?
Jeff Garland : parce que ça fait toujours la bonne chose
Q : quelles sont les exigences pour qu'un conteneur puisse être utilisé avec un ranges algorithm?
Jeff Garland : regarde les concepts associés à ces algorithmes, tu auras ta réponse (ça dépend de l'algorithme)
Q : que se passe-t-il si on passe une view par const T& accidentellement?
Jeff Garland : ça dépend de l'algorithme, et c'est la raison du contentieux à ce sujet.
Intéressant, mais des exemples pour la plupart relativement académiques alors on a évité le croustillant. Cela dit, on état avertis.
Je me dirige ensuite vers le souper des étudiant(e)s, mais je ne reste pas longtemps car j'ai des rendez-vous de dépannage par voie électronique avec mes propres étudiant(e)s... J'ai surtoiut discuté avec Ollivier Roberge, un étudiant québecois qui (je l'ai appris ce soir) présente ce jeudi. Wow, félicitations Ollivier!
Je voulais aller à la soirée de cinéma de Walter Brown mais je devais offrir un peu de support à mes étudiants du Collège... et j'ai assisté à cette soirée à Toronto en 2022 alors j'ai demandé à Walter Brown de m'excuser (ce qu'il a fait, gracieusement). Et après ces quelques séances de soutien, j'ai salué mon amoureuse Za et mes deux plus jeunes Viktor et Ludo, puis j'ai dormi un peu.
Je me lève tôt, je travaille un peu puis je vais voir mon divertissant ami Ben Deane.
Vidéo : à venir
Ben Deane commence en parlant de l'importance du jeu et du plaisir dans la programmation, et de la fine ligne (parfois) entre les trucs jolis et les trucs qui font peur.
Deduction Guides peuvent être explicit... mais on est limités. On peut seulement utiliser le nom du type lui-même, pas un alias, pas decltype... Mais Ben Deane montre qu'on peut spécialiser des templates ce qui donne des types distincts, et qu'on peut utiliser des tag types pour déléguer vers des types distincts de cette manière
Ben Deane aborde ensuite la question des template parameters, surtout quand il y en a plusieurs avec des valeurs par défaut. Il suggère de les grouper dans un config_type un peu comme on ferait avec un struct. On pourrait même faire des membres des signatures de fonctions pour être capables de raisonner sur les types de retour. Ça a de bons côtés (les paramètres ne sont plus positionnels; on peut les spécialiser si on veut remplacer quelques-uns d'entre eux seulement; ils peuvent avoir des états mais peuvent aussi être des NTTP; se testent bien)
Ben Deane montre qu'on ne peut pas spécialiser une fonction générique dans un struct local, mais que les lambdas elles le peuvent. Il y a pourtant eu une proposition, P1988... C'est vrai que c'est pas amusant.
Ben Deane montre son truc pour les paramètres de fonctions constexpr, à partir d'une macro et d'une lambda. Faut une meilleure solution mais c'est une patch perverse 🙂
Ben Deane montre que le paramètre passé à operator++(int) (le operator suffixe) est un vrai paramètre. On peut s'en servir comme d'un std::exchange() pervers. Le compilateur passe 0 par défaut évidemment. Il montre un truc qui utilise auto...args comme paramètre à operator++ qui retourne decltype(auto) et qui choisit entre la version à 0 et à 1 paramètre avec if constexpr (ça marche just avec 0 et 1 int, c'est très strict). Hum...
Ben Deane poursuit avec un truc qui utilise des concepts et des Fold Expressions. Il montre que les Left et les Right Folds n'ont pas tout à fait le même comportement. Sa lecture est que les Fold Expressions sont opaques pour le compilateur. Il règle le problème en groupant une partie des concepts séparément des autres avec des parenthèses. P2963 risque d'aider.
Ben Deane montre qu'on peut utiliser un Bit-Field de taille zéro, ce qui signifie « avancer à la prochaine frontière d'alignement ». J'ai appris quelque chose 🙂 On peut aussi utiliser un Bit-Field de plus de bits que le substrat (ça donne du Padding, en général; c'est Implementation-Defined)
Ben Deane montre qu'on peut avoir un, trois et six '.' consécutifs, pas deux, quatre ou cinq... sauf dans les annotations! On peut mettre pas mal de trucs étranges (n'importe quel jeton, en fait) entre [[ et ]] incluant rien du tout (et on peut les séparer par des virgules alors [[,,,,,]] est légal, et [[attr(ben tiens ..)]] aussi). Même des mots clés, donc [[for(;;)]] auto x = 0; passe. Côté notation, on ne peut pas utiliser une IIFE directement comme []{ return 0; } pour indicer un tableau car les '[' '[' du début dénotent une annotation (faut mettre des parenthèses autour de l'IIFE)
Ben Deane utilise une lambda pour générer des types uniques à partir de types par défaut : template <class Uniq = decltype([]{})> struct S { /* ... */ }; (pas bête du tout!). Il y a peut-être des enjeux d'ODR ici...
Ben Deane parle de ses difficultés à invoquer std::source_location() pour un paramètre de fonction consteval. C'est intrigant...
Ben Deane invite les gens à jouer 🙂
Du beau travail par Ben Deane comme toujours. C'est un de mes présentateurs préférés (et vraiment une chic personne).
Je marche avec Matt Mongeon (un de mes étudiants de la fin de semaine) et on parle brièvement de Bit-Fields, puis je m'installe pour la présentation de Peter Muldoon. Dans la salle jour de la musique de Florence and the Machine ce qui me fait penser à mon amoureuse Za qui me manque (c'est une fan invétérée de Florence).
Peter Muldoon se présente et dit que sa proposition est controversée.
Peter Muldoon dit que C++ ne définit pas clairement ce qu'est une exception. C'est par l'usage qu'on y voit de quoi il s'agit. Bon point. Il sort un exrait du D&E de Bjarne Stroustrup pour relater l'intention derrière le mécanisme. Certains des idéaux ne sont pas rencontrés. Ce que les exceptions nous donnent selon lui est une meilleure lisiblité, et une impossibilité d'ignorer passivement l'exception. Il montre un exemple avec traitement manuel d'erreur (c'est bruyant) puis un équivalent avec exception. Il met l'accent sur l'irritant d'avoir un programme qui « tombe » quand une exception est levée mais pas attrapée (il ajoute un catch(...) qu'il nomme un « exception swallower »)
Peter Muldoon essaie de définir ce qu'est une exception. Il parle de quelque chose qui est lancé, et pourrait être attrapé. L'allocation de ressources lors de la levée d'exception n'est pas définie par le standard, mais les deux types de stratégies conns sont coûteux (Frame-Based, Table-Based). Un catch n'attrape que quelque chose qui a été levé précédemment dans la séquence d'appel. Il dit que dans son expérience les exceptions sont des hiérarchies profondes (quelle mauvaise idée)
Peter Muldoon parle de la levée d'exception. Si ça arrive pendant un Stack Unwinding (p. ex. : destructeur d'une locale) ça termine le programme. Pour l'attraper il faut un Handler d'un type approprié. Côté hygiène, il parle de lever par valeur, d'attraper par référence, d'utiliser le re-throw si approprié, et de placer les catch pour les classes dérivées avant celles des classes parents. Il parle d'Exception Safety (nothrow, basic, strong).
Peter Muldoon parle du volet philosophique des exceptions : des trucs qui sont rares... La publicité dit « on doit lever une exception quand une fonction ne peut pas compléter son travail », ou lors d'un échec de constructeur, ou d'opérateur, ... Quand on a un truc irrécupéable (corruption de mémoire, mémoire épuisée) c'est probablement pas pertinent (il est trop tard). Les cas d'utilisation initiaux étaient de réagir quand une erreur sérieuse survenait ou quand une fonction n'a pas le contexte suffisant pour réagir à un problème. Selon lui, si on utilise les exceptions pour autre chose, c'est probablement une erreur.
Peter Muldoon cite plusieurs sources qui indiquent que les exceptions devraient être rares et que le traitement d'erreurs devrait êtrre disjoint du code régulier. Il se demande si on peut mesurer des bornes supérieure ou inférieur sur la proportion d'un programme qui devrait faire partie du traitement d'erreur. Comment gère-t-on les erreurs mineures plus fréquentes? Aussi, il signale que si on lève une exception, il peut être difficile de retrouver la source de l'erreur. Il souligne que le modèle initial de Bjarne Stroustrup était très clair.
Peter Muldoon se questionne ensuite sur ce que les gens font en pratique avec les exceptions : remettre une ressource dont on a fait l'acquisition et relancer l'exception (il montre un exemple horrible et le remplace par une approche RAII). Il recommande RAII. Ensuite, il parle de « retry » (des try dans des boucles), et dit que si t'en es rendu là retourner un code d'erreur est probablement plus simple. Il demande si avoir plusieurs try ... catch est une bonne idée... Bof, en effet. Je pense qu'il voit des trucs pas jolis au bureau... Il cite Doug McIlroy qui avait des doutes sur la valeur des exceptions.
Peter Muldoon aborde (sans la nommer) la question de la neutralité face aux exceptions, et du fait que le non-respect de cette règle perd du contexte (et coûte plus cher en termes de ressources). Sa solution pour journaliser les exceptions est d'utiliser une std::string mutable pour le contenu... Bof.
Peter Muldoon recommande de retourner expected si la pile des appels est de faible profondeur, et recommande de réagir en fonction du type (bien), mais montre une implémentation moche avec plusieurs types où on fait chaque fois (syntaxiquement) la même chose. Il implémente une simplification à partir d'un variant des types d'exceptions.
Peter Muldoon aborde la questions des hiérarchies d'exceptions. Sa vision est que le message est ce qui compte souvent (si vous me connaissez, vous savez ce que j'en pense). Il présente des cas où ce qui compte dans une exception est le logging, donc pour lesquels l'exception sert en fait de contrôle de flux d'exécution.
Peter Muldoon aborde la question de l'absence d'une string à la construction d'une exception. Il propose sa classe OmegaException qui correspond à sa vision de ce qui est pertinent (une string, une source_location, une stack_trace et un DATA qui vient du volet générique).
Peter Muldoon il donne ses recommandations, mais encore une fois ça se base sur une vision tunnel...
Bjarne Stroustrup : ça fait peur de constater qu'en trente ans on en soit encore là. Quand j'ai fait le design des exceptions, ça m'a pris plusieurs mois avant de comprendre l'interaction des constructeurs et des destructeurs, et de comprendre ce qui serait RAII. Je ne commenterai pas la classe OmegaException...
Bon, au moins j'aurai entendu ce qu'il avait à raconter.
J'ai bavardé un peu avec Mateusz Pusz pendant la pause. Il se trouve dans une situation où on lui demande d'offrir une formation qui lui rapportera en termes financiers, mais où les conditions sont très défavorables. On discute des pour et des contre... J'espère qu'il parviendra à trouver une solution.
J'ai pris une bouchée (du granola et des fruits, c'était simple mais bon et frais!) puis discuté avec Cameron DaCamara pour le bogue du profileur qui m'embête (on ne trouve pas ce que c'est, mais j'ai très peu d'infos à offrir).
Erez Strauss vient me saluer et m'invite à sa présentation du midi, alors je vais aller le voir. Enfin, Daisy Hollman présente nos présentateurs pour le Keynote du jour.
Bret Brown décrit tout d'abord leurs non-buts, ce qu'ils ne feront pas, puis dit qu'ils veulent discuter de la déclaration de bibliothèques installées sur un système de fichiers pour permettre leur découvrabilité. Ils veulent faire un premier pas vers la mise en place d'un système robuste de gestion des paquetages, offrir une spécification de métadonnées, être polyglotes en supportant de multiples langages et de multiples plateformes. Il résume en disant que le projet devrait être aussi portable que nos sources le sont.
Bret Brown montre des statistiques qui mettent clairement en relief que la gestion des dépendances est ridiculement complexe. La majorité des sources de frustration des programmeuses et des programmeurs C++ en découle.
Bret Brown décrit quelques cas communs de bogues de dépendances (fichiers manquants, lier avec les mauvaises bibliothèques, paquetages manquants, etc.) et exprime que selon lui, le problème est un vocabulaire inadéquat. Il faudrait pouvoir indiquer « cette bibliothèque n'est pas installée » (et l'installer, optionnellement) ou « la bibliothèque X et la bibliothèque Y ne concordent pas ». Selon lui, ces irritants mènent à une stagnation des Build Systems, et au sous-développement de l'écosystème de nos bibliothèques... donc à une pression accrue sur la bibliothèque standard?
Bret Brown prend position. Faut faire quelque chose 🙂 Chez lui (Bloomberg) il y a un réel besoin d'un gestionnaire de paquetage « nouvelle génération ». Il retrace l'historique des efforts en ce sens, puis parle de Momentum, leur « nouveau CMake » qui adopte, mais modernise la syntaxe de cet outil très répandu. Un objectif du projet est d'accepter les paquetages existants tels quels.
Bret Brown dit que les modules de C++ ont besoin de métadonnées sur leurs dépendances. Il met d'abord l'accent sur les monorepos. Il reconnaît la présence d'outils externes (p. ex. : godbolt) et de dépendances préinstallées sur diverses machines.
Bret Brown explique que les gens ont de faibles attentes (plusieurs n'utilisent pas de gestionnaires de dépendances, ou se limitent à des bibliothèques Header Only), et qu'il souhaite changer cela. Il y a des limites aux bibliothèques Header-Only de toute manière. Il parle de SBOM (Software Bill of Materials) et de CPS. Je suis dans un monde que je connais peu avec cette conférence. Un des problèmes de la démarche est que... c'est hors-portée pour le standard! Il dit que ça a été un choc pour lui d'appendre (et de comprendre!) cela. Mais ça tend à changer... Il y a un effort de IS pour le Tooling qui est en cours.
Bret Brown aborde les concepts de la démarche et délègue à Bill Hoffman, qui est l'architecte de CMake. Ce dernier examine différentes acceptions du terme «bibliothèque » et il se trouve que les contours sont très flous. Selon lui, pour le futur, la réponse sera « regarde ce qu'il y a dans ton fichier .cps »
Bill Hoffman dit que les standard (par ODR) suppose implicitement l'existence de dépendances. Il montre la mécanique qu'il propose, et dit qu'il faudra quelques règles de nommage (éviter les espaces; éviter les collisions de noms; viser un nommage conséquent à travers le système, etc.).
Bill Hoffman retrace un peu l'évolution de CMake, passant d'une « soupe de fanions » à un système d'importation et d'exportation, avec gestion transitive des bibliothèques à lier (une belle économie d'écriture). Il explique le fonctionnement contemporain de CMake. C'est un problème difficile mais intéressant que ces gens essaient de résoudre. Il parle de l'évolution de CMake en collaboration avec celle de Qt.
Bill Hoffman présente CPS (Common Package Specification) comme la prochaine étape, car ça recoupe plusieurs autres outils que CMake et ça ouvre de nouvelles avenues. Il dit qu'un de ses objectifs originaux était de rendre les paquetages autodescriptifs, et CPS l'y amène. Il montre un exemple concret et met en relief que la communication entre le producteur de la bibliothèque et son consommateur est claire et fonctionnelle.
Bill Hoffman explique que le plan désormais est d'amasser de la rétroaction de la communauté. Ça vise le Ecosystem IS de WG1 (SG15). Il décrit ensuite ce que ça peut apporter comme avantages pour les programmeuses et les programmeurs : réduire les erreurs d'exécution résultant de choix inappropriées de binaires, éditer des liens seulement quand ils sont utilisés, etc.
Je ne note pas toutes les questions parce que c'est un peu loin de moi, mais c'était intéressant tout de même et ça touche beaucoup de gens. En sortant, j'apprends que j'ai droit à un chandail de type « polo » de l'événement alors j'en ai fait l'acquisition (je ne suis pas très « polo » mais je manque régulièrement de chandails alors pourquoi pas?).
Petite discussion avec le sympathique et dynamique Khalil Estell avec qui j'ai aussi discuté après ma présentation de la veille. Il a des métriques comparatives de consommation d'espace et de temps entre le recours à des exceptions et le recours à des valeurs de retour à l'aide de tl::expected (proche de std::expected) et veut mon avis sur le code derrière les métriques. Je lui suggère deux ou trois pistes, il prend des notes. Je pense qu'il va se joindre à nous pour la rencontre de SG14 demain, alors tant mieux!
Vidéo : à venir
Erez Strauss fait une belle catégorisation des types de files concurrentes possibles (sa diapo 5; je vais la lui emprunter). Il passe un commentaire à l'effet que la capacité doit être une puissance de deux du fait qu'il s'agit d'un tampon circulaire, mais je vais devoir aller bavarder avec lui... Ok, ça vient de son implémentation.
Erez Strauss montre ensuite un cas où l'ordonnanceur d'une file MPMC introduit une attente inappropriée (rare, mais quand ça arrive c'est inacceptable). L'interaction se passe entre try_push() et try_pop(), et fait en sorte que parfois tous les consommateurs sont incapables de lire (un spin lock sur une atomique en lecture qui ralentit le progrès d'une écriture sur cette atomique dans try_push()). La suspension d'un thread entre une écriture et son signalement par une incrémentation d'indice peut avoir un effet catastrophique sur la consommation des données.
Erez Strauss explique ses requis (typiques de systèmes de ce genre : pas d'appels systèmes en période critique, pas de blocage, pas de verrous, etc.)
Erez Strauss présente son design. Il a des entrées atomiques alignées avec une Cache line (diapo 9), chacun contient un indice, un fanion et une valeur. Les entrées sont modifiées par CAS atomiques (un succès complète le push ou le pop). Les indices sont modifiés pendant les CAS. Les entrées sont alignées sur la taille des Cache Lines pour éviter le faux-partage. Il utilise un union pour coupler _data et _seq dans le but de modifier les deux d'un coup par un CAS.
Erez Strauss explique qu'il y a un plafond de 12 bytes pour les données dans sa file, mais que ça suffit pour transporter un T* ou un unique_ptr<T> (mais je pense que son code ne fonctionne pas avec un unique_ptr<T>, je vais lui en parler; il nous montre à la fin qu'il a un unique_ptrT> spécial pour ça). L'état des cellulees est synthétisé par une combinaison du contenu de la cellule et de l'index. Il montre son code de push() (c'est lock-free mais pas wait-free), diapo 24. Fedor Pikus fait remarquer qu'un des writers pourrait tourner indéfiniment s'il n'est pas chanceux.
Beaucoup de questions pendant la présentation. Cest pas mal.
Je voulais parler à Erez Strauss après mais il avait beaucoup de questions et d'autres présentateurs auront besoin du plancher, alors je l'aggriperai plus tard aujourd'hui (ou au pire, plus tard cette semaine). Par contre, j'ai pu bavarder avec Inbal Levi et Guy Davidson et nous sommes d'accord que c'est une approche prometteuse sur le plan de l'implémentation (il y a un peu de travail à faire sur l'interface) alors on va l'encourager un peu.
J'ai traité des dossiers familiaux et pour le travail pendant la pause, puis Daisy Hollman a commencé.
Daisy Hollman dit être hors de sa zone de confort, car elle parlera d'ingénierie logicielle plutôt que de programmation seule. Elle dit aussi que ce qu'on est confortable de répéter dans un programme est habituellement la quantité de code qu'on voit sur une diapo. Elle dit aussi avoir un intérêt envers le code qui survivra longtemps.
Daisy Hollman dit qu'on devrait écrire le code en pensant à la manière dont le lectorat le lira, éventuellement. Elle recommande une présentation de Katherine Rocha à CppCon cette année. Elle parle de réduire la charge cognitive requise pour comprendre et utiliser du code. Elle parle ensuite de perte d'information, ce qui survient quand le lectorat n'a pas accès à quelque chose qui semblait évident pour celles et ceux qui l'ont écrit. Elle dit que copier / coller du code est, dans une certaine mesure, égoïste (ça aide l'autrice ou l'auteur, mais ça complique la vie du lectorat).
Daisy Hollman parle de tâches quotidiennes de programmation (écrire le code, surtout avec support d'intelligence artificielle; sauter à la définition d'une fonction; ajouter des couches d'asbtraction; etc.) et dit que ce qui accroît les coûts de compilation de manière linéaire ne sont pas des enjeux à ses yeux. Ce qui les fait croître de manière non-linéaire, c'est autre chose.
Daisy Hollman distingue Interface Sameness et Implementation Sameness. Interface Sameness permet aux usager de traiter les choses de manière semblable (p. ex. : utiliser des noms semblables), alors que Implementation Sameness permet aux usagers de tirer profit des similitudes (mais ça complique les modifications). De manière générale, ce qui est exposé aux usagers est difficile à modifier. Bien réaliser Interface Sameness réduit le couplage; bien réaliser Implementation Sameness accroît la cohésion.
Daisy Hollman parle de polymorphisme « traditionnel », où la réutilisation principale se trouve dans le code client (on itère à travers une séquence d'indirections vers le parent...), puis de templates où les implémentations de vector<T> et vector<U> sont en général très semblables (on a aussi une similitude d'interface bien sûr). Les fonctions qui utilisent ces types peuvent être perçus comme faisant partie de l'interface non-intrusive des types impliqués. Une fonction qui s'applique à vector<T> mais pas à vector<U> distingue en quelque sorte ces interfaces, mais de manière non-intrusive. Donner des noms différents aux choses différentes est en général sage
Daisy Hollman discute de cas avec similitude d'interface mais des implémentations dissimilaires (deux classes distinctes qui offrent des services semblables pour des entités distinctes). Elle examine ensuite des mixins « sauce C++ », p. ex. : class A : public TrucsCommuns<ElemsDeA> et class B : public TrucsCommuns<ElemsDeB> ce qui permet d'appeler template <class T> void f(TrucsCommuns<T>&). On peut voir TrucsCommuns<T> comme un endroit où des services protected seraient pertinents. Ces mixins introduisent par l'héritage public une similitude d'interface.
Daisy Hollman présente un exemple de classes disparates mais pour lesquelles des comparaisons élément-par-élément sont requises. Elle montre une implémentation par mixin où les gens spécialisent des fonctions qui retournent forward_as_tuple(...), ce qui donne une implémentation de CRTP. Le parent implémente operator==(a,b) en faisant a.elements()==b.elements(), et peut faire quelque chose avec print et std::apply(). Ça donne de chics points de personnalisation. Deducing this est une option mais elle dit que CRTP demeure un bon choix. Elle présente operator<=> comme un mixin primitif de C++20 et dit que l'introduction des mixins « par petits morceaux » ajoute de la charge cognitive
Daisy Hollman aborde la question des références de relais. Elle montre que dans le cas de la multiplication de fonctions membres semblables on peut utiliser deducing this. Elle dit qu'il manque un name forwarding en C++ (elle a raison) et montre l'avantage d'exposer des membres individuels d'une variable membre plutôt que d'exposer la variable membre elle-même.
Daisy Hollman va ensuite du côté du principe DRY, et montre diverses techniques de réduction de la répétition. Elle aborde les politiques (custom deletor, allocateur, adapteurs de conteneurs – avec allocateurs – etc.). Elle fait un argumentaire à l'effet que le custom deleter seul ne suffit pas dans un unique_ptr<T,D> mais je ne suis pas d'accord. Par contre, shared_ptr<T,Deleter,Allocator> est étrange, j'en conviens.
Daisy Hollman dit que les concepts extraient de la similitude d'interface sans notre permission (ça fonctionne par noms de services). Ici encore, l'argumentaire semble un peu incomplet.
Q : et si on avait la syntaxe unifiée de fonctions?
Daisy Hollman : ça et « operator. » sont deux trucs qui donnent un peu de similitude mais ont des défauts.
Q : jusqu'où devrait-on aller?
Daisy Hollman : faut que le code reste lisible
J'ai pas écouté toutes les questions. C'était intéressant, moins vers la fin cependant, mais je ne veux pas manquer Lisa Lippincott. Heureusement que je suis arrivé tôt parce que je suis debout et la salle est pleine à craquer.
Vidéo : à venir
Je n'ai pas pu prendre de notes dans les circonstances, mais Lisa Lippincott a encore une fois donné une prestation profonde et pertinente. Une conférence de Lisa Lippincott c'est souvent comme une lecture du Principia Mathematica de Russell et Whitehead : à cause du niveau de rigueur impliqué, on va dans un niveau de détail rien de moins que déstabilisant. À voir absolument si vous avez un intérêt pour l'informatique théorique, mais appliquée (son quasi code est pratiquement du C++ correct, mais avec des mots et des idées qui sont d'elle et qui reviennent d'une présentation à l'autre.
J'ai eu la chance de jaser avec Lisa Lippincott par la suite (c'est une amie). Je pense qu'elle devrait commencer à faire un lexique (une page recto peut-être) des termes de sa démarche pour les gens dont c'est la première fois... et probablement rassembler ses idées dans un livre. Elle m'a dit que John Lakos la harcèle (gentiment!) pour les mêmes raisons.
La collation de cet après-midi est des petits verres de Shooter contenant soit beurre d'arachides et céleri, soit Nutella et pommes. Je dois avouer que le beurre d'arachides fait beaucoup de bien (c'est des journées très intenses pour le corps et pour le cerveau, et en fin de journée je ressens de la fatigue).
Dian-Lun Lin est un étudiant universitaire qui vient nous parler de son projet de recherche : ce que c'est, le modèle de programmation, les métriques, etc. Son système encapsule les appels de fonctions et leurs dépendances dans un graphe de tâches. Il offre un ordonnanceur pour organiser l'exécution des tâches. Ça ressemble (vu de haut) à un modèle d'exécution fork / join. Sa notation de diapos est du C++ suspect, tristement.
Dian-Lun Lin explique un truc intéressant, c'est à dire que son outil génère du code pour le GPU comme pour le CPU, et ordonnance les dépendances des deux de manière à accroître le parallélisme.
(j'ai manqué quelques minutes; il y avait de la demande pour les diapos de ma présentation d'hier alors je cherchais l'endroit où les déposer)
Dian-Lun Lin explique les différences entre attendre la complétion d'une action de manière synchrone (attente) ou asynchrone (sondage, événement), et montre la place de chacun dans Taro. Son projet repose sur CUDA. Ils ont une primitive de la forme task_a.precede(task_b) pour construire les dépendances dans le code, c'est une bonne idée.
(il y a beaucoup de questions et d'interactions du public, ça doit rendre Dian-Lun Lin heureux!)
Dian-Lun Lin présente son ordonnanceur avec des Worker Threads et deux niveaux de files de tâches (une prioritaire pour les suspendues et d'autres à basse-priorité desquelles les Workers peuvent se voler des unités de travail pour accroître le débit). Il explique utiliser les méthodes notify_one() des std::atomic de C++20.
Dian-Lun Lin présente ses métriques incluant ses points de comparaison (ça inclut Boost::Fiber, Taskflow et TaskflowCoro de même qu'un truc nommé RTLFlow qui est spécialisé dans la simulation de circuits). Ses tests impliquent plusieurs topologies classiques (diviser pour règner, embarrassingly parallel, map-reduce, enchaînement linéaire, etc.). Selon ses métriques, son produit se comporte mieux que la compétition (sauf dans le cas de l'enchaînement linéaire, mais on s'y attend; dans ce cas, il est comparable à Boost::Fiber).
Je n'ai pas noté toutes les questions; ça semblait aller dans des directions cherchant à comparer le projet de Dian-Lun Lin avec des projets commerciaux, et ça ne me semblait pas à propos. Je suis allé prendre un bol de salade que j'ai rapporté à ma chambre, j'ai fait du dépannage pour mes étudiant(e)s, et j'ai passé un peu de temps à distance avec Za, son amie Caro, Viktor et Ludo alors que le groupe s'amusait avec un jeu rempli de défis de coordination et de jeux de mots.
Ensuite, je me suis dirigé à la salle de plénière et j'ai salué Bjarne Stroustrup dont j'ai reconnu la grande courtoisie suivant la présentation de Peter Muldoon plus tôt aujourd'hui. Il m'a souri en reconnaissant qu'il n'aurait servi à rien d'être déplaisant dans les circonstances. Avec moi, Bjarne Stroustrup a toujours été de très agréable compagnie.
Sont présent(e)s ce soir : Herb Sutter, Bjarne Stroustrup, Nina Ranns, Michael Wong, Inbal Levi, Gabriel Dos Reis, Daisy Hollman et Pablo Halpern. La modération est faite par Herb Sutter. On commence évidemment par un tour de présentation.
Herb Sutter : quel est votre mécanisme préféré de C++23 et votre plus grand souhait pour C++26?
Daisy Hollman : mdspan, réflexivité
Inbal Levi : deducing this, fonctions personnalisables
Bjarne Stroustrup : import std pour C++23, pas sûr encore pour C++26 (Herb Sutter dit qu'avec les modules, gcc et msvc ont des super résultats)
Michael Wong : operator[] multidimensionnel, et la combinaison des Hazard Pointers et de RCU
Q : comment suivre le déroulement des travaux du comité?
Herb Sutter : comment y arrivez-vous?
Michael Wong : on fait de notre mieux mais c'est pas facile. Il y a un site pour générer les numéros de propositions et faire un suivi, et il y a un github. Le problème est qu'il est difficile de s'y retrouver si on n'a pas de contexte
Bjarne Stroustrup : c'est à peu près impossible, ce qui est triste; si j'ai une responsabilité, c'est de suivre ce qui se passe. Si on veut suivre un dossier, ça se fait bien, mais comprendre les interactions entre la bibliothèque et le Core Language est un défi.
Nina Ranns : plusieurs membres publient des rapports de voyage après les rencontres. C'est un bon endroit pour suivre ce qui se passe si on n'est pas là. Les minutes des rencontres sont publiées sont forme de propositions
Daisy Hollman : si tu n'as pas une bonne raison de suivre les travaux du comité, tu peux suivre d'autres gens comme les formatrices et les formateurs. J'ai rencontré des gens qui disent tout lire et qui ne viennent pas aux rencontres... Rendu là, venez!
Inbal Levi : le github est très actif. Chez LEWG, on publie un résumé anonymisé de nos rencontres, mais pas les minutes qui sont pour usage interne.
Q : je voulais écrire une bibliothèque de sérialisation générale et j'attends la réflexivité depuis longtemps... Est-ce qu'on peut y croire pour C++26?
Daisy Hollman : les deux meilleures personnes pour répondre à ceci ne sont pas à la conférence. Il faut travailler dessus de manière concertée. Je pense qu'on pourrait découper la grosse proposition sur la table et la faire progresser en parties.
Gabriel Dos Reis : personne ne sait vraiment si une proposition, celle-là ou une autre, passera le seuil de l'approbation par le comité. Restez attentives et attentifs. Si vous avez besoin de quelque chose, faut participer ou aider les gens de votre NB
Bjarne Stroustrup : qu'on soit prêt ou pas en 2026, nous allons livrer à temps. Si c'est prêt et s'il y a consensus, ça sera dedans.
Inbal Levi : il nous faut de l'aide des gens qui écrivent des compilateurs et il nous faut de l'aide des utilisatrices comme des utilisateurs.
Q : j'ai une question de débutant. Je compte participer une première fois en novembre, et je me demande comment ça fonctionne
Nina Ranns : si tu t'es inscrit, je t'enverrai un courriel expliquant la mécanique
Pablo Halpern : quand tu auras accès aux mots de passe, tu auras accès aux Wiki et tu pourras planifier ton temps. On a aussi un système de clavardage privé auquel tu pourras participer. Essaie d'être là quand on discute des propositions qui t'intéressent
Q : quand une proposition vous arrive et ne vous semble pas bonne, ça vous prend du temps même si c'est pas terrible. Qu'en pensez-vous?
Michael Wong : on a une proposition de ce genre en vol en ce moment. Ça te donne une idée du travail des Chairs : on ne peut pas empêcher les gens de s'exprimer, même si on pense que ça ne passera pas. On leur dira probablement proceed at your own risk
Bjarne Stroustrup : les proposeurs sont motivés, on n'aime évidemment pas être négatifs et passer du temps sur un truc qui ne nous semble pas adéquat. Les proposeurs ont tendance à nous relancer parce qu'ils croient à ce qu'ils soutiennent. C'est un problème important
Daisy Hollman : je pense que c'est normal qu'il faille investir du temps même quand un truc ne nous semble pas bon. Le parfait est l'ennemi du bien et si on attend les propositions parfaites on n'ira nulle part. Parfois, on n'a pas d'alternative et il faut avancer
Inbal Levi : je pense qu'il faut que les objections reposent sur des raisons rationnelles clairement exprimées. Je pense que ça peut être exprimé avec respect car les gens qui soumettent des propositions travaillent fort
Bjarne Stroustrup : j'aimerais offrir un conseil. Pour convaincre, une proposition doit expliquer le problème à résoudre, les alternatives, montrer les avantages et les inconvénients, décrire les usagers cibles... Ensuite, je peux me faire une tête sur les aspects techniques
Q : parfois, vous dictez des optimisations (vector<bool>, la cache dans certains views...)
Bjarne Stroustrup : vector<bool> a été fait tôt dans les années '90 et n'est pas représentatif des travaux du comités durant le présent millénaire
Pablo Halpern : le comité essaie de ne pas dicter des optimisations. On essaie toutefois de ne pas les empêcher, alors on va poser des questions comme « ceci peut-il être fait de manière concurrente? » par exemple. Pour le caching dans les ranges, l'enjeu est de permettre une optimisation sans endommager l'interface (il explique l'enjeu de views::filter...). Parfois, c'est même pas une optimisation, c'est simplement un enjeu d'utilisabilité
Gabriel Dos Reis : on définit plus des transformations possibles que des optimisations. Il y a des cas intéressants comme le mouvement, qui a été suivi de Guaranteed Copy Elision, mais c'est mal nommé (il n'y avait pas lieu d'avoir une copie de prime abord!) alors est-ce une optimisation? C'est observable (les constructeurs peuvent avoir des effets de bord). Parfois, ça ouvre la porte à des techniques de programmation. Le mouvement permet de mettre des flux dans des conteneurs; ça ouvre des avenues de programmation, l'optimisation est un effet secondaire
Q : que pensez-vous être le plus élégant mécanisme de C++?
Gabriel Dos Reis : l'interaction entre constructeurs et destructeurs. Ça me manque beaucoup dans d'autres langages
Bjarne Stroustrup : les destructeurs et les multiples constructeurs sont apparus durant la 2e semaine de conception du langage. C'est le roc sur lequel l'édifice repose
Nina Ranns cite un poème dans le texte du standard inséré par Andrew Koenig la veille de la publication de C++98. Le paragraphe qui précède est de Bjarne Stroustrup et est terriblement plate; le Limerick de Andrew Koenig est là pour que ce soit digeste
Pablo Halpern : la partie la moins élégante pour moi est que la syntaxe des templates est très différente du reste. Je comprends pourquoi, mais... Ça s'améliore avec auto et constexpr, heureusement (Bjarne Stroustrup dit que c'était pas un accident)
Daisy Hollman : la partie la plus mélangeante et difficile à comprendre pour moi est le modèle mémoire
Michael Wong : je trouve que le modèle mémoire est très élégant :) Ce que je trouve beau est de voir ce que les gens font de surprenant avec le langage : ce que les gens ont fait avec les templates, les lambdas. etc. Les gens font de la magie et dépassent nos attentes!
Bjarne Stroustrup : les lambdas sont une notation très élégante pour les foncteurs, et les foncteurs sont une des raisons pour les surcharges de fonctions
Q : les coroutines sont une abstraction très puissante, mais je crains pour la capacité de déboguer des bases de code qui reposeraient largement sur cet outil. Pensez-vous à ce genre d'enjeu quand vous acceptez une proposition?
Herb Sutter : on a SG15, un groupe spécifiquement dédié au tooling
Gabriel Dos Reis : le tooling est une préoccupation pour nous, et a parfois mené au refus de propositions. Au-delà des coroutines, l'enjeu de « l'adoptabilité » est important. Je ne sais pas quelle est la proportion de gens qui utilisent C++20 aujourd'hui, en 2023. En même temps, on ne peut pas toujours attendre que les outils soient prêts
Herb Sutter : et l'éditeur de liens?
Gabriel Dos Reis : on respecte encore les limites de l'éditeur de liens du langage C. Je pense que maintenant qu'on a les modules, il est temps d'améliorer l'éditeur de liens
Bjarne Stroustrup : avec les coroutines, oui il y aura des problèmes, mais les coroutines sont mon gagne-pain depuis une décennie. Ça se débogue pas si mal car elles sont généralement petites et qu'elles gardent elles-mêmes la trace de leurs états
Daisy Hollman : si tu travailles sur les derniers outils tout le temps, tu vas avoir plus de petits irritants c'est sûr. Profites-en pour t'amuser! Les outils vont suivre
Herb Sutter : comment est-ce que je débogue une fonction qui est résolue à la compilation? Qu'est-ce que nos outils devraient nous offrir?
Inbal Levi : il y a un enjeu d'analyse statique bien sûr. Il nous faudra peut-être des compilateurs interactifs, un peu comme des interpréteurs
(il reste une trentaine de minutes, mais je quitte parce que je suis fatigué)
Ouf, grosse journée, mais intéressante à bien des égards.
Quelques mots avec Za et Ludo ce matin, puis un peu de gestion de courriels et de soutien aux étudiant(e)s. J'ai eu des nouvelles d'une amie de longue date, Estelle Paventi, qui a vécu une chirurgie et ça m'a rassuré de savoir qu'elle s'en remettait alors j'ai pris la peine de lui écrire quelques mots.
Aujourd'hui, quelques présentations intéressantes au menu, et je vais être occupé en après-midi car SG14 tient une rencontre hybride sur place et je suis appelé à présenter mes travaux.
Je croise Erez Strauss avec quu je discute de la conférence d'hier (bon boulot!) de même qu'un dénommé Minh et un dénommé Sam qui veulent bavarder plus tard aujourd'hui (Sam sera à SG14 tantôt apparemment). Je salue les gens qui préparent le café (des amours!) puis je vais à la premièe conférence.
Vidéo : à venir
Luke Valenty se présente, puis aborde les entiers à notre disposition, les enjeux associés aux débordements (avec des exemples concrets de conséquences), puis il aborde la question de ce qui peut être fait lorsqu'un débordement survient. Il cite plusieurs cas très sérieux d'incident survenus suite à des débordements, même quand on les gère.
Luke Valenty dit qu'on veut probablement que les entiers concrets se comportent comme les entiers idéaux du monde des mathématiques. Les options incluent les laisser croître (mais il y a quand même des limites) entre autres. Il suggère d'injecter des préconditions, idéalement à la compilation, sur les opérations. Il parle de deux bibliothèques soit Boost::safe_numerics (C++14) et github.com/intel/safe-arithmetic (son projet)
Luke Valenty décrit son approche : entreposer les valeurs dans des types décrivant les contraintes (donc exprimant l'ensemble des valeurs acceptables), offrir des mécanismes pour les créer de manière sécurisée, et (il m'en manque un). Il a des types comme safe::u16 ou safe::s32. Ses opérations bit à bit sont des safe::* (p. ex. : si on extrait un bloc de trois bits la plage acceptable sera [0..7]). Il a aussi des littéraux maison. Il a aussi des intervalles, p. ex. : ival_32<1,100> pour un entier 32 bits entre 1 et 100 inclusivement
Luke Valenty dit que les intervalles s'accompagnent de types avec contraintes arbitraires, p. ex. : var<int32_t,ival<1,100>> ou des masques (optimisés pour le bit à bit), ou des ensembles de valeurs possibles, ou des union ensemblistes (il utilise || entre deux intervalles) ou des intersections (avec &&). Les affectations dangereuses (p. ex. : acceptant un entier arbitraire) ne sont pas permises (ça échoue à la compilation).
Luke Valenty montre que ses opérations produisent des nombres avec de nouvelles contraintes. Par exemple, un ival_u32<0,100> multiplié par un ival_32<-1,1> donne un ival_u32<-100,100>. Il supporte min, max et clamp. L'affectation n'est possible que si l'expression à droite respecte les contraintes de l'objet à gauche. Les valeurs qui ne peuvent pas être initialisées à zéro doivent être initialisées explicitement
Luke Valenty montre que pour les valeurs dynamiques, il a un match(expr...) qui prend une valeur et fait une sorte de Pattern Matching et exécute les expr... auxquelles la valeur correspond. La valeur de retour est l'union des résultats. Le code généré est identique au code manuel, mais on gagne des garanties statiques.
Luke Valenty rappelle qu'on peut toujours contourner la mécanique, et qu'il y a sûrement des raisonsm mais dit que dans un tel moment il faut que ce sot visible dans le code. Il a un unsafe_cast<T>(safe_expr) pour ça. Pour extraire les valeurs, il a un safe_cast<T>(safe_expr) qui échouera si T ne permet pas de représenter les valeurs possibles de safe_expr. Il a des algorithmes particuliers parce que les techniques classiques comme incrémenter un compteur peuvent être douloureuses (si i est un ival_32<1,100> alors i++ est un ival_32<1,101> ce qui peut être déplaisamt... et imaginez accumulate()!)
Q : as-tu pensé à l'équivalent d'un NaN dans ta bibliothèque?
Luke Valenty : j'y ai pensé mais je suis un peu paresseux (d'une bonne manière). J'ai d'autres stratégies
Q : peux-tu le configurer pour que ce soit utilisable avec des bornes connues à l'exécution?
Luke Valenty : non 🙂
Q : as-tu pensé à une approche utilisant diverses politiques en cas de débordements?
Luke Valenty : non, pas encore
Matthias Kretz : as-tu pensé intégrer cela à la bibliothèque standard?
Luke Valenty : je ne sais pas si j'ai été assez rigoureux pour ça (Walter Brown : nous allons t'aider!)
Q : les aspects historiques de la proposition m'intéressent. En quoi les incidents mentionnés au début seraient-ils compensés par ta démarche?
Luke Valenty : je ne sais pas! Mais le choix d'une valeur par défaut repose sur les erreurs du code client
Q : quel est l'algorithme dans match() pour faire un choix?
Luke Valenty : je les teste simplement dans l'ordre, c'est comme une séquence de if... else
Walter Brown : as-tu implémenté des algos comme std::div avec ta bibliothèque? Ce serait une bonne idée
Luke Valenty : bonne suggestion, merci!
C'était bien ça! Je bavarde un peu avec Jody Hagins, toujours aussi sympathique, à propos du partage des connaissances.
Je fais un peu de travail pour le Collège pendant la pause. On manque cruellement de prises de courant cette semaine et les gens ont tendance à trébucher sur mon fil alors j'essaie de prévenir plutôt que de guérir.,.
Timur Doumler ne sera pas ici (je crois comprendre qu'il aura un premier enfant incessamment) alors c'est Pablo Halpern qui portera le flambeau de cet important dossier.
Pablo Halpern commence en traçant des liens entre les enjeux de la guilde des acteurs et ceux qui nous intéressent : pour avoir de bons programmes, il faut avoir de bons contrats 🙂
Pablo Halpern dit que les contats aident à tester les programmes, mais qu'il faut pouvoir tester nos contrats aussi. Il parlera de noexcept, de l'écriture de contrats, et des tests de contrats. Il dit qu'on fera tout deux fois : une fois en surface, une fois en profondeur.
Pablo Halpern commence par un survol de noexcept, qu'il décrit par this function will not throw. Les destructeurs sont implicitement noexcept. Un appelant n'a pas à se prémunir contre des exceptions si la fonction se dit noexcept. On peut faire de noexcept quelque chose de conditionnel, p.ex. : noexcept(true), noexcept(false), ou encore template <class T> T * allocate() noexcept(sizeof(T) <= THRESHOLD)
Pablo Halpern explique ce qui se passe si on lève une exception dans un contexte noexcept : terminate(). On peut mettre un throw dans une fonction noexcept (ça ne terminera pas le programme si on ne la rencontre pas)
Pablo Halpern poursuit avec l'opérateur noexcept(expr) qui est évalué à la compilation (l'expression elle-même n'est pas évaluée). Il indique que ça sert surtout à des fins d'optimisation (choisir un algo plutôt qu'un autre).
Pablo Halpern revient sur les contrats, qu'il décrit comme une promesse : si tu fais ceci, alors je ferai cela. On exprime le contrat d'une fonction par un ensemble de préconditions et un ensemble de postconditions. Pour vector<T>::pop_back(), la précondition est !empty() et la postcondition est que le dernier élément a été retiré
Pablo Halpern dit qu'un wide contract n'a pas de préconditions. Une fonction comme vector<T>::size() n'a pas de préconditions. Un narrow contract a des préconditions : l'addition entre deux entiers signés a une précondition car un débordement mène à du comportement indéfini
Pablo Halpern enchaîne avec les violations de contrat, qui sont toujours un bogue dans le code (pas dans les données) : quelqu'un n'a pas fait son travail (n'a pas respecté ses préconditions ou ses postconditions). Certaines conditions comme « ce pointeur n'est pas nul » sont faciles à exprimer dans le code (et ne coûtent souvent rien du tout), d'autres (ce conteneur est trié) sont dispendieuses, et d'autres ne sont pas vérifiables (ce nombre est aléatoire). Comnment vérifier ce qui est vérifiable, alors? Il montre une approche classique (des assertions aux endroits opportuns), et montre que ça ne suffit pas (il a une erreur dans ses tests qui est masquée par un autre test)
Pablo Halpern aborde les CCA (contract-checking annotations). On peut trouver des macros ici et là, p. ex. : PRECONDITION(code) dans des bibliothèques, mais on espère avoir un mécanisme de niveau langage sous peu suite aux travaux de SG21. Il note que les CCA peuvent entraîner des bogues et doivent être testées. Elles peuvent faire planter le programme ou masquer un problème. En plus, abuser de noexcept peut interférer avec les tests unitaires
(Timur Doumler présente sa partie par vidéo)
Timur Doumler recommande d'utiliser les contrats et les tests unitaires. Il montre comment tester une fonction avec un narrow contract comme vector<T>::front(). Selon lui, les fonctions avec des narrow contracts devraient valider les préconditions quand c'est trivial de le faire. Il rappelle que les préconditions sont du code et doivent être testées comme telles. Idéalement, il suggère d'écrire les tests d'abord, approche TDD
Timur Doumler aborde la question des tests des préconditions. Il parle d'une macro REQUIRE_ASSERT_FAIL(expr) pour vérifier que certains opérations échouent (sorte de tests négatifs). Les exceptions sont un bon mécanisme pour cela, mais faut avoir son propre ASSERT plutôt que celui de <cassert> évidemment. Il implémente REQUIRE_ASSERT_FAIL(expr) par REQUIRE_THROWS(expr, onFailOp). Évidemment, si on rend vector<T>::front() noexcept il devient impossible de faire ce genre de test soudainement, ce qui explique la Lakos Rule (ne marquez pas une fonction noexcept si elle a un narrow contract) et les Throws: nothing dans la spécification de la bibliothèque standard. Il réfère à P2861, P2831 et P2837
Timur Doumler poursuit avec P2831 en relatant un cas vécu où un collègue tenait mordicus à noexcept pour des raisons de vitesse. Il a cherché une alternative pour fins de tests, et en est arrivé à NOEXCEPT qui correspond à noexcept ou à rien du tout selon les modes de compilation. Ça fonctionne mais c'est pas terrible (plusieurs bibliothèques font cela) et il relate des histoires de guerre... Entre autres, c'est observable alors ça peut influencer le code client! Il a fait des recherches pour des alternatives : setjmp/longjmp (bof, beaucoup de problèmes en C++ avec les destructeurs des locales), avoir des threads enfants (exécuter le code dans ces fils et réagir si ça va mal, et ça laisse fuire des ressources), des coroutines « stackful » (ça laisse fuir des ressources aussi et c'est pas tout à fait trivial; en plus, ça peut mener à des débordements de pile), des signaux (ça ne marche pas vraiment, c'est un callback), et des Death Tests (fork-based, clone-based, spawn-based) qui peuvent fonctionner, soit lancer un processus auxiliaire et constater son décès, mais c'est complexe et c'est lent.
Timur Doumler montre que les contrats envisagés pourraient fonctionner. On utiliserait un contract violation handler qui pourrait lever une exception, mais ça ne réglerait pas le problème des fonctions avec des narrow contracts qui se disent noexcept (ça terminerait le programme quand même)
(Timur Doumler nous quitte)
Pablo Halpern dit qu'on va maintenant aller plus profondément mais rapidement. Il parle d'un cadriciel de programmation défensive avec des assertions sous forme de macros, un mécanisme pour les désactiver, et un mécanisme pour laisser les usagers réagir lors d'un bris de contrat. Il définit PRECONDITION(expr), POSTCONDITION(expr) et INVARIANT(expr) comme étant ASSERT(expr). Le mécanisme pour réagir à une violation de contrat doit être configurable par le code client; il peut faire du logging, faire _asm{ _int 3; };, appeler std::terminate(), etc. La solution la plus simple est, dans ce gestionnaire de violations de contrat, lever une exception rapportant le lieu du problème. Il propose trois macros : TEST_EXPECT(expr), TEST_EXPECT_PASS(expr) et TEST_EXPECT_FAIL(expr)
Pablo Halpern revient sur noexcept. Son but original est de faire en sorte que vector<T> soit important; ça peut réduire la taille des binaires mais c'est pas le but, et si on ne le combine pas avec l'opérateur noexcept ça n'accélère pas l'exécution des programmes. Il montre vector<T,A>:reallocate(size_type)... Son implémentation n'est pas efficace (un try à chaque copie) mais fonctionne.
Pablo Halpern aborde les garanties d'exception safety (basic -- pas de fuites, pas de corruptions, strong -- objet inchangé; Pablo souligne que c'est moins utile qu'il n'y paraît si on ne veut pas récupérer l'objet, noexcept). Il donne des exemples des trois. Ses exemples sont excellents.
Pablo Halpern rappelle que noexcept est pour toujours : c'est observable du code client. C'est utile, parfois essentiel, mais faut vivre avec (idéalement : fonctions triviales, mouvement, et swap).
Pablo Halpern dit avoir proposé [[throws_nothing]] qui n'impacte pas le comportement du programme de manière observable. On se rapproche de la notation de la bibliothèque standard. On verra où ça nous mènera!
Belle présentation mais Pablo Halpern a manqué de tenmps à la fin. C'était très instructif et très clair, je vais la recommander à mes étudiant(e)s et à mes collègues. J'aime beaucoup le style de Pablo dans ses présentations : c'est toujours clair, avec un peu d'humour, et ça reste décontracté mais il est toujours visiblement très préparé et fouille ses sujets en profondeur.
Quelques échanges informels en route vers la plénière (Guy Davidson, Roth Michaels et d'autres que je ne connais pas encore mais qui viennent dire bonjour), la plupart en lien avec la rencontre de SG14 tantôt. Ce matin on a de petits shooters de jus de fruits (très bon) et de petites bouchées de fruits et de granola. Ce sont de bons choix, et je suis content que les bouchées qui nous sont offertes soient « santé » (ça fait du bien au corps). Cameron DaCamara est installé là où je suis habituellement (le monstre! 🙂) alors je me trouve un autre endroit.
Jon Kalb fait le point quotidien, puis Sean Parent présente Laura Savino. Il dit qu'elle est très connue dans le monde du langage Swift et de iOS, et est très élogieux à son égard.
Laura Savino commence en présentant la petite maison dans laquelle elle habite, et parle des travaux qu'il a fallu y faire (la peinture contenait du plomb). Il se trouve qu'elle était liée contractuellement à la peinture en place et qu'il a fallu faire avec
Laura Savino trace un parallèle avec le code des autres, qu'on ne peut pas envisager remplacer à 100% quand on ne l'aime pas. Elle parle du plaisir d'équilibrer une table de café qui oscille un peu en glissant un morceau de carton sous une patte... Elle dit avoir cette espèce d'envie de tout régler, mais que parfois faut se retenir (avoir un bébé, tu vois un sac de plastique dans la rue, tu ne mets pas le bébé par terre pour courir après le sac).
Laura Savino parle de table de fréquences. Il y a des trucs qui sont juste trop répandus pour qu'une seule personne puisse les arranger. Sa question clé est « fine, what should I do next? ». Au lieu de perdre de l'énergie, fais un choix, procède. En début de carrière, une de ses questions clés était « Should I even be here? », et parle du sentiment d'appartenance qu'on a quand on a l'impression de pouvoir aider, corriger des problèmes, communiquer des connaissances.
Laura Savino montre des schémas de groupes d'individus qui parlent entre eux et de manière de se disposer pour accroître le volet accueillant.
Laura Savino demande si la rencontre de code incompréhensible est un signe qu'on n'est pas au bon endroit. Non, évidemment. Nos croyances impactent nos relations, et en impactent les conséquences. Faut comprendre les défis du quotidien comme des défis normaux qui peuvent être surmontés. Elle parle de « find someone who'll meet you where you are », quelqu'un à qui on peut poser des questions qui peuvent sembler bêtes sans en être gêné(e). Faut s'attendre à une période d'adaptation, et si on a un rôle d'expertise il faut trouver le moyen de répondre de manière efficace aux erreurs. Pour se sentir incluse ou inclus, elle parle de ne pas craindre de regarder métaphoriquement « au-dessus des épaules » de quelqu'un pour intégrer les comportements locaux.
Laura Savino parle ensuite de la mi-carrière, où on voit beaucoup le code des autres. Je voudrais changer ce code mais je ne peux pas... On peut frustrer : n'importe qui peut corriger ce bogue! Mais c'est pas toujours réaliste. Elle parle d'un cas où elle a dû corriger un problème sur un site Web, mais ses aptitudes n'étaient pas tout à fait à jour... ça ne fonctionnait toujours pas, mais c'était devenu sa faute! Alors il faut accepter ces choses qu'on décide de ne pas changer. J'ai vu ces patterns et... j'ai décidé de ne pas m'en occuper. J'ai fait des choix, je les assume... et je n'ai pas envie d'en débattre, mon énergie sert à autre chose. Elle trace un parallèle avec les solutions bon, beau et pas cher qu'on trouve parfois à la maison et dont on tire une certaine fierté
Laura Savino dit que c'est pas nécessairement mauvais d'avoir de petites frustrations. C'est d'obséder sur la question d'échapper à ces frustrations qui devient nuisible. C'est intéressant de s'attaquer à ces frustrations si ça aide à la poursuite de nos objectifs. On se sent mieux quand on dirige nos efforts vers la réalisation de nos objectifs; ça nous donne une forme de contrôle.
Laura Savino dit qu'en mi-carrière, on peut aussi avoir l'impression que les collègues ne partagent pas nos préoccupations, ce qui peut nuire encore une fois au sentiment d'appartenance... mais l'idée d'être en équipe est justement d'avoir des intérêts et des forces (et des faiblesses) différentes! Elle aborde la question de l'opposition entre puristes et pragmatistes. Évidemment, découper le monde en extrêmes est un peu contre-productif. Et évidemment, c'est facile de dire que la perfection est l'ennemi du bien, jusqu'à ce qu'on utilise un SGBD qui est trop lent et qui nous rend fous...
Laura Savino parle des risques de burnout. L'épuisement à la fin de la journée. Elle recommande d'utiliser son capital social pour protéger son temps de repos. Faut bien sûr faire attention aux dynamiques de pouvoir, et ne pas se trouver dans la position où on est gestionnaire, nos employé(e)s se tuent au travail et on semble se la couler douce. Elle recommande aux hommes de combattre le sexisme en prenant des pauses ou des congés (de paternité ou autres). Le burnout peut aussi s'accompagner de cynisme, d'une impression que notre travail n'a pas de valeur. Elle parle des Hack Weeks que certaines entreprises ont, où on donne de l'autonomie aux employé(e)s, mais rappelle qu'il faut prendre soin des testeurs.
Laura Savino parle des fois où on compense en réécrivant le code. Elle parle du « ownership of fallout », comme dans les cas où on fait un changement et ça brise un système sur une autre plateforme à laquelle on n'a pas accès. Elle parle de demandes de changements focalisées, qui mettent en valeur la productivité des programmeuses et des programmeurs. Et surtout, prendre soin des gens (no shaming! be kind!). Elle parle du sentiment d'avoir l'impression de pouvoir obtenir des résultats au travail.
Laura Savino parle des aptitutdes de navigation dans le code des gens. Elle suggère des techniques de recherche efficace dans le code source. La recompilation peut prendre du temps et nous sortir de « la zone », alors on peut devenir bonnes et bons à ne pas recompiler (en particulier, en organisation mieux le code... ou en ne le modifiant pas!). Utiliser des points d'arrêts plus avancés. Un bon truc : écrire ses hypothèses, pour gagner un peu en focus. Elle suggère de prendre des notes sur ce qui aidera à redémarrer plus rapidement le lendemain (mes ICI dans le code).
Laura Savino suggère de s'orienter, en particulier en parlant aux gens qui vivent le problème et ont des hypothèses a priori. Ça sauve du temps, ça épargne de l'énergie. Elle recommande de prendre le burnout au sérieux.
Laura Savino aborde la question de ces moments où on est avancés dans notre carrière. On risque de penser « pourquoi cette base de code n'est-elle pas aussi charmante que les autres? ». Elle aborde encore la question de la perfection... ou de systèmes qui fonctionnent et qu'on parvient à livrer. Elle rappelle qu'on a tendance à voir ce qui ne fonctionne pas et à ne pas porter suffisamment attention à ce qui fonctionne bien. Elle recommande de porter attention à ce qui va bien. L'influence qu'on acquiert fait en sorte qu'on peut essayer d'empêcher les gens de faire des changements... Elle recommande de laisser les membres de l'équipe apprendre, prendre des risques.
Laura Savino parle de « inspirational mediocrity » et dit que la capacité pour des gens de se sentir à l'aise de donner une présentation ordinaire (de ne pas avoir à être extraordinaire pour faire sa place) est importante. On veut accueillir une plus grande diversité de gens. Le sentiment d'appartenance demeure un enjeu.
Laura Savino en arrive à sa conclusion en rappelant ses conseils. Un de ceux que j'ai manqués en chemin est « remove what you can, encapsulate the rest ». J'aime bien.
Il y a prise de photo de groupe après la Keynote de Laura Savino, qui a fait du très bon travail alors il n'y a pas de séance de questions publiques. On se regroupe dans l'espace qui sert de lieu de rassemblement pour le café et les collations, et le photographe (sympathique; on le voit dans chaque présentation) fait son travail.
Je vais me chercher une salade, puis je passe en coup de vent voir Walter Brown car SG14 chevauche sa présentation.
Vidéo : à venir
Walter Brown fait des versions réduites en taille de conférences du passé. Je reste pour la première (bien faite, sur l'idée de type et la zoologie des types en C++) puis je quitte pour la rencontre de SG14.
Ma rencontre est dans la salle d'en face...
Vidéo : à venir
J'ai été très occupé lors de cette présentation, partageant mon temps entre présentation, animation (mais l'animateur principal était mon ami Guy Davidson; Inbal Levi nous a aussi aidé) et jouer au scribe (il fallait certains privilèges d'accès que j'ai mais que la majorité n'a pas). Michael Wong était avec nous au début et il a démarré les travaux, mais il a dû quitter (il avait une présentation à donner) pendant à peu près la moitié de la rencontre.
Dans les grands enjeux aujourd'hui :
Il y avait beaucoup de gens (presque 60) en début de rencontre, un peu moins de la moitié à la fin (c'est normal). Nous avons eu des ennuis d'audio la première heure, mais c'était mieux à la fin.
Petite pause (on arrive trop tard pour les collations, zut!). J'aide Lawrence O'Boyle à rencontrer Nevin Liber qui pourra le guider s'il veut contribuer à std::graph et à WG21, puis j'échange avec Braden Ganetsky qui vient de Winnipeg et aimerait s'impliquer dans le comité.
J'arrive un peu en retard à la présentation de Vincent Reverdy.
Vidéo : à venir
Je suis arrivé trop tard pour avoir une place près d'une prise de courant, mais c'était intéressant. Vincent Reverdy a construit une infrastructure de calcul symbolique à la compilation qui donne du code tout à fait charmant. Ça donne le goût de programmer...
Pause pour le souper. Salade et une petite bière. J'ai pris un peu de temps pour bavarder avec Za, Ludo et Viktor. Ensuite, j'ai lu un texte de Daniel Hanson qui publiera un premier livre sous peu, question de l'aider un peu, puis je l'ai rencontré en personne une vingtaine de minutes pour lui donner un coup de pouce.
Les Lightning Talks débutent ensuite...
Vidéo : à venir
Phil Nash est le maître de cérémonie...
Chris Trasher présente un truc sur Who builds your code? pour faire réfléchir sur l'éthique et l'hygiène pour aider les gens à compiler nos sources : désactiver les trucs optionnels, simplifier leur tâche, maximiser les probabilités de succès, etc. Il distingue les User builds des Developer builds car les besoins sont différents (les développeurs veulent les options « extra » comme les tests et tout le tralala)
Max Huddleston parle de Constraining automated trading risk with Linux signals, et met l'accent sur les scénarios qui demandent un shutdown d'urgence. Il parle des principaux signaux en ce sens dont SIGINT et SIGKILL
Vadim Alexandrov parle de Program complexity and thermodynamics. Il essaie de montrer que ce qui rend les programmes difficile à comprendre est l'entropie du système, le chaos. Eh oui... Pouvons nous écrire un « programme idéal »? Oui s'il est minimaliste, p. ex. : int main(){}. Il recommande la programmation par composants qui isole les changements, et trace un parallèle avec la première loi de la thermodynamique et dit qu'il faut utiliser de l'isolant (encapsuler), dépenser de l'énergie (tester), repousser la complexité (faire de petits modules) etc.
Patrick Roberts parle de Conquering substitution failure with __builtin_constant_p. Il va vite et les diapos somt difficiles à lire, ce qui est triste car ça semble amusant (non-portable mais amusant). Il se trouve que l'intrinsèque __builtin_constant_p détermine si une valeur est une constante connue à la compilation ou pas, ce qui permet de savoir si on peut utiliser if constexpr. À revoir quand ça sortira sur YouTube.
Alu Akmutawa parle de Forbidden C++. Il fait un quiz pour savoir ce qui compile et ce qui ne compile pas. Des trucs très laids...
Ed Catmur parle de Higher-Order Template Metaprogramming with C++23. Il montre quelques trucs qui compilent sur au moins un compilateur... C'est pervers. Il a quelques horreurs, dont une fonction de type const void...
Jefferson Carpenter parle de Un-undefining Undefined Behavior. Il essaie de construire des trucs où le compilateur ne peut plus voir qu'on a triché... Ark. Il fait de véritables horreurs (son code réécrit sur lui-même pour effacer le code qui fait semblant qu'on n'est pas dans du comportement indéfini...)
Amir Kirsh parle de Filling the Bucket: Reading Code, C++ code interviews and exams. C'est som Lightning Talk de Toronto, mais il a ajouté un petit bout avec ChatGPT
Brody Holden parle de You Shoud Use AddressSanitizer. Il explique ce qu'est ASan, ce que ça détecte, comment on s'en sert... Point important, ASan est aussi bon que notre Code Coverage, au sens où ça n'attrapera pas des bogues dans des zones où l'exécution ne passera pas.
Alon Wolf parle de Implementing Coroutines using C++17. Il montre son code et dit que c'est horrible, mais que ça compile encore. En effet, c'est épouvantable
Rudyard Merriam pré.sente Introverts: Speak! où (il a eu une grosse journée; j'ai bavardé avec lui et ce retraité a donné deux conférences aujourd'hui) il parle de lui-même, et invite les autres à parler.
Ben Deane présente Lets' write a lambda. Ça part d'un défi de Jason Turner à l'effet de mettre tout ce qu'une lambda peut contenir dans une même lambda. Hé la la... Une horreur absolue https://www.youtube.com/watch?v=EqiLTgQcDPM
Anastasia Kazakova parle de Clang Format is not <...>. Elle explique ce que c'est... et ce que ce n'est pas. Elle rapporte qu'encore aujourd'hui, un peu moinms de 9% des projets sur les gihtub visités utilisent Clang Format... Elle montre de petits bogues et comment les contourner.
Braden Ganetsky parle de Help! My expression template names are too long! Il présente une petite création de sa part. C'est une chouette syntaxe! Ça donne toutefois des noms de types monstrueusement longs... Il montre qu'il peut réduire le bruit en logeant des types intermédiaire dans une lambda générique locale. Les noms trop longs ralentissent la compilation (il est passé de 40 secondes à des grenailles).
Megh Parikh parle de Interfaces in C++. Il montre diverses manières de créer des interfaces en C++, et dit avoir une nouvelle technique en tête, mais je ne suis pas convaincu...
Petite marche vers la chambre. J'ai fait une folie et j'ai pris une crème glacée avant de me coucher. Je pense que c'est la seule chose qui est à un prix semblable à celui connu à la maison, soit 3USD. Le climat est très sec ici, ça a fait du bien.
J'ai reçu un appel de Za et de Ludo alors que j'allais prendre ma douche. Reste juste un dodo... Après la douche, je me suis rasé (moins de barbe, moins de déshydratation) et j'ai fait un peu de trucs administratifs.
Quand je suis arrivé à la présentation de Luke Valenty, c'était déjà débuté et la salle était plutôt pleine alors j'ai suivi le tout sans prendre de notes.
Vidéo : à venir
Même si je n'ai pas pris de notes, c'était très bien. Luke Valenty (avec l'aide de Ben Deane) a construit une bibliothèque qui permet de représenter des registres accessibles par voie de mémoire de manière efficace et simple. L'essentiel est fait à la compilation, et les entrées / sorties sont faites de manìère asycnhrone par senders et receivers (ça roule bien sur des systèmes embarqués et le code est beau).
Bien, ce truc. Bravo Ben Deane en particulier!
Le café est arrivé, enfin! Je remplis ma tasse et je vais à la présentation de Fedor Pikus.
Fedor Pikus explique ce qu'est le comportement indéfini et dit qu'il essaiera de départager les faits des légendes. Entre autres, il dit que les « démons nasaux » sont un peu forts de café, et que les exagérations tendent à rendre les gens blasés... et il ne faudrait pas l'être car les dangers sont bien réels. En particulier, s'il y a une opération indéfinie, le programme entier peut l'être.
Fedor Pikus montre un cas simple où, si le code client d'une fonction est visible au compilateur, ce dernier peut supposer qu'une action incorrecte ne se fera pas (p. ex. : le client valide un paramètre avant de le passer) et éliminer le code inutile dans l'appelé. Dans d'autres cas, bool f(int i) { return i + 1 > i; } peut devenir bool f(int) { return true; } car le débordement sur un entiers signé est indéfini. Il montre que changer int pour unsigned int change tout car dans ce cas, le débordement est défini.
Fedor Pikus rappelle que si votre compilateur ne vous donne pas de surprises aujourd'hui dans un cas de comportement indéfini, il pourrait le faire demain. Il donne des exemples concrets. Par exemple, int i = 1; int main() { puts("Avant"); while(i){} puts("Apres"); } donne Avant (puis on tourne dans le vide) sur certains compilateurs et Avant Apres sur d'autres.
Fedor Pikus se demande pourquoi le standard ne définit pas tout : c'est parfois pour permettre des optimisations, pour supporter une variété de plateformes matérielles, parfois des ommissions dans le texte du standard, et parfois parce que c'est juste impossible de le faire. En particulier, il montre en quoi la supposition que les boucles se terminent toutes permet des optimisations pertinentes. Les compilateurs ont besoin de faire certaines hypothèses qu'ils ne peuvent pas prouver
Fedor Pikus distingue comportement indéfini, comportement non-spécifié (ça va faire l'une des choses suivantes), et comportement dépendant de l'implémentation (ça peut changer selon la plateforme, mais sur une plateforme donnée c'est bien défini). La logique derrière le UB est (a) suppose que ça n'arrivera pas, (b) déduis les contraintes sur les valeurs connues à l'exécution, (c) suppose que ces contraintes sont respectées car sinon, le code serait indéfini or le programme ne contient (évidemment!) pas de comportement indéfini. Il montre des exemples où on déréférence un pointeur nul sans valider, et les conséquences...
Fedor Pikus montre qu'un UB teinte le programme tout entier, car le code à risque impacte ce qui le précède aussi. Ça peut surprendre quand on fait une séance de débogage! Il montre ensuite les limites de ce genre d'optimisation (ce sont de bons exemples)
Fedor Pikus présente le UB comme quelque chose d'utile, mais d'irritant et qu'on devrait éviter. Il montre comment UBSan fonctionne (c'est un outil de validation à l'exécution). Il rappelle qu'un programme rencontrant du UB est un programme qui s'exécute hors-contrat. Faut prendre ça au sérieux. Il recommande d'adopter des wide contracts dans la mesure du possible, et de définir ce qui surviendra lors d'un bris de contrat.
Q : que dire aux gens qui disent qu'on devrait éteindre l'optimiseur et regarder le code machine?
Fedor Pikus explique que certains trucs comme le Dead Code Elimination seront faits que l'optimiseur soit actif ou pas. Lire le code machine tout le temps est contre-productif.
Bonne présentation sur le sujet. J'avais pas réalisé qu'Emery Berger donnerait une mini présentation ensuite alors j'ai un bonus! J'ai bavardé avec Jody Hagins qui aimerait bien que je donne une formation à distance à son équipe cet hiver alors on va essayer de réaliser quelque chose.
Emery Berger d'un outil de profilage en ligne nommé Scalene, basé sur les produits d'OpenAI. Ça consomme du Python, par exemple, et ça donne des accélérations de l'ordre de x90
Emery Berger parle de Coz qui profile du code C, C++ et Rust. Ils ont pris un outil qui profile et optimise du code, et suggère des optimisations. Les profileurs savent où le code est inefficace, et pourquoi il est inefficace. En Python, ça peut t'indiquer que tu passes beaucoup de temps dans l'interpréteur et t'aiguiller vers des bibliothèques natives, ou suggérer des registres vectoriels, ou...
Emery Berger explique que le code original sert d'oracle pour le profileur. Il devient possible de rouler des tests sur le code avant et après l'optimisation et voir que les sorties sont les mêmes si les entrées sont les mêmes.
Emery Berger présente ChatDBG, un débogueur expérimental pour C, C++, Python et Rust qui fait des diagnostics. Le programme plante, ça génère un Core Dump, et la commande à taper est why. Les résultats qu'il nous présentent sont chouettes. Ça charge au conseil (trois sous dans le cas de son exemple). Ça ne garamtit pas les résultats, mais c'est chouette
Emery Berger parle de CWhy, qui explique les messages d'erreurs générés par un compilateur et donne des suggestions de correctifs franchement pas vilaines. Ça marche avec C++ par défaut mais ça supporte d'autres langages aussi. C'est un simple wrapper qui parle à OpenAI, en fait, et ça fonctionne vraiment pas mal.
Emery Berger pense que pour des programmeuses et des programmeurs, ces outils rendent le travail vraiment plus agréable.
Q : j'ai vu CWhy et ça m'a donné le goût de venir ici! Avec ChatDBG, j'aime bien l'idée de naviguer la pile des appels et d'envoyer le code source, mais je suis préoccupé des cas où le bogue se trouverait ailleurs. Pour un petit projet, pourrait-on envoyer tout le code, ou une partie plus significative?
Emery Berger : le modèle commercial est basé sur les jetons (des mots ou des parties de mots). Le bloc par défaut est 4K. Il propose quelques avenues interactives qui pourraient complémenter cela (p. ex. : des séances de débogage guidées)
Q : est-ce que vous n'envoyez que ces jetons ou est-ce que vous créez une base de données en vue du futur?
Emery Berger : il y a un truc nommé Vector Embedding qui fait ce que tu as en tête, mais on ne le fait pas encore.
Q : ça peut changer radicalement la vie des programmeuses et des programmeurs. Comment vois-tu le futur?
Emery Berger : je pense que les outils vont continuer de s'améliorer et qu'on va devoir s'adapter. C'est comme avoir un super-pouvoir
Q : as-tu des cas qui ne fonctionnent pas si bien?
Emery Berger : oui. Parfois, ChatDBG donne des erreurs moins pertinentes, p. ex. : quand la file des appels est corrompueé
Q : que faites-vous quand la réponse est incorrecte?
Emery Berger : bonne question. Poser la même question plusieurs fois peut donner des raisons différentes. Si on a des doutes, on peut simplement réessayer
C'est fou quand même les changements que le monde a vécu juste cette année. Ouf!
Pendant la pause, je grignote (il y a des biscottis et de petits gâteaux, c'est bon) et je travaille à distance avec mes collègues Maxime Barakatt et Philippe Simard sur une proposition d'examen intra pour mes ami(e)s de première session au Collège.
Herb Sutter prend ensuite le plancher.
Herb Sutter poursuit son aventure de conception d'un nouveau langage qui compile vers C++ mais est à ses yeux plus simple et plus sécuritaire, tout en permettant une inteopérabilité pleine et entière avec C++. C'est une version mise à jour de sa présentation à CppNow cet été alors je ne prendrai pas tout en note. Il présente un exemple de main() qu'il dit sans coût, mais c'est faux (il fait un test de bornes sur argv[0] alors que l'indice zéro est garanti valide dans argv... Sa prétention est que le coût vient d'utiliser operator[] sur args – on n'est pas obligés – mais reste que c'est un coût superflu).
Herb Sutter a organisé un moment musical avec le House Band. C'est charmant.
Herb Sutter utilise une syntaxe où les métafonctions applicables aux types débutent par @ (p. ex. : @enum, @value, @interface). Inspiré par Circle, peut-être? Il a un « flag enum » en exemple, une des requêtes de SG14 avec P2966. Il a un concept de ce genre dans son langage. Son approche utilise beaucoup de réflexivité statique, mais ça se comprend
Herb Sutter travaille fort pour montrer que ses idées émergent de la pensée de Bjarne Stroustrup. Il le cite souvent. C'est une mince ligne sur laquelle marcher...
Herb Sutter cite John Carmack à propos des nouveautés (programmation fonctionnelle, Memory Safety, etc.) et recommande de réfléchir aux bénéfices de ce que nous avons.
Herb Sutter fait son comparatif entre Dart (qui voulait remplacer JavaScript) et TypeScript (qui construisait par addition et enrobage), et met en valeur que TypeScript bénéficie de tout le code JavaScript existant... Selon lui, l'idéal est une interopérabilité complète et sans heurts. En TypeScript, tout programme JavaScript compile tel quel. La relation entre C et C++ est semblable (pas totale, mais vraiment pas mal).
Herb Sutter rappelle l'histoire catastrophique du passage de Python 2.7 à Python 3. Python 3 est nettement meilleur, mais la cassure entre les deux a coûté plus de douze ans de migration. Ouf! Il raconte échanger régulièrement avec Guido Van Rossum (maintenant chez Microsoft) et que ce dernier ne cache pas que si c'était à refaire, il ferait littéralement tout autrement. Il raconte d'autres histoires d'horreur (Visual Studio 6 à Visual Studio 10, ça a pris 12 ans; C99 avec _Complex et les LVA, ça a pris 12 ans; le bris de std::string avec COW chez gcc lors de C++11, ça a pris 11 ans...). Il place plusieurs langages (dont Rust et D, et même les langages .NET) dans la famille « Dart » de langages qui cherchent à prendre la place d'un langage important sans offrir de rampe d'interopérabilité transparente (des langages qui le font avec des Wrappers car ça induit des coûts cérébraux et techniques importants).
Herb Sutter relate le problème que nous avons avec les contrats, qui se heurtent au fait que C a une macro nommée assert() ce qui bloque l'évolution de C++ (difficile de trouver un meilleur mot). C'est embêtant, le nommage, et à plusieurs égards, car ça impacte l'évolution. Il rappelle std::byte, yield (on a dû prendre co_yield car il y a déjà std::thread::yield()). Il parle de l'avantage de sa « syntaxe v2 » où il peut réutiliser des mots clés de C++ dans son métacode.
Herb Sutter fait une micro démo à la fin avec une espèce de variant faite à partir d'un union de cpp2. Sa démo se fait dans le débogueur pas à pas de Visual Studio (chouette!). Il dit que ça a fonctionné sans effort parce que le code généré était du C++ et que le pont avec les numéros de lignes dans le .cpp2 était un automatisme. Il fait venir quelqu'un sur la scène et montre que ça fonctionne aussi avec Visual Studio pour MacOS, et ça utilise inspect. Un autre vient et fait la même chose avec XCode (c'est un truc avec des prix de bouffe; il fait clairement des blagues avec les prix déraisonnables à l'hôtel), le tout à travers lldb. Il fait la même chose avec QtCreator. C'est une bonne démo, vraiment, qui montre clairement les bénéfices de l'interopérabilité parfaite avec C++ : on a les outils gratuitement.
Herb Sutter cite John Carmack à nouveau. Il rappelle les approches « à la Dart » et « à la TypeScript » qui sont le thème conceptuel de sa présentation.
On a dépassé le temps alloué. Je ne sais pas si c'est volontaire (je suspecte que ce soit le cas 🙂) mais Herb Sutter laisse rarement du temps pour les questions...
Je suis passé à ma chambre quelques minutes. À mon retour, je suis allé me chercher une salade mais ils étaient à court alors je me suis pris un panini pesto et champignons (nourriture chaude pour une des rares fois cette semaine). C'est bon, mais c'est 10 USD pour un petit sandwich. J'en ai profité pour bavarder avec Herb Sutter dont l'adrénaline commençait à redescendre. Il doit quitter la conférence aujourd'hui pour des raisons personnelles, alors je lui ai souhaité bon voyage.
J'arrive dans la salle où Walter Brown donne ses présentations du midi. Il a déjà commencé.
Vidéo : à venir
Walter Brown fait des versions réduites en taille de conférences du passé.
J'ai manqué la première...
Celle qui est en cours à mon arrivée parle de tableaux et de manières de les indicer, avec des références au passé. Je le vois développer un HeapSort et utiliser le fait que tab[i] est équivalent à i[tab] pour des fins pertinentes (eh bien!). Bien fait, comme d'habitude.
La suivante explique ce que C++ doit à Emmy Noether. On apprend des choses sur David Hilbert en chemin (chaque fois que j'en apprends sur lui, je le trouve plus sympathique). Emmy Noether est une personne remarquable à bien des égards. Walter Brown la présente comme l'égale d'Albert Einstein. Il lui attribue l'introduction des concepts dans le langage
Walter Brown en ajoute une quatrième dans les dix minutes qui restent, à propos d'une de ses propositions récentes, soit P2971 (Implication for C++). Il souhaite ajouter un nouvel opérateur, l'implication logique. Sa notation serait p => q au sens de p implique q. Toutes les expressions d'implication sont true sauf si p&&!q alors c'est équivalent à !(p&&!q) donc !p||q. Il détaille certaines propriétés qu'il pourrait être intéressant d'exploiter dans du code. On peut vouloir l'implémenter par une fonction mais on n'aura pas le court-circuit souhaité. Il donne des exemples comme celui de la spécification du destructeur d'un unique_ptr<T> ou encore celle de optional<T>::has_value(). Walter Brown remarque que ça sert beaucoup dans la spécification des requis. Il vise une précédence basse (nouveau niveau juste sous celui de ||) et la capacité de le surcharger.
Intéressant!
Je me demande s'il y aura des contraintes sur les types, parce que c'est un brin de syntaxe qu'il serait tentant d'exploiter pour autre chose aussi. Je laisse Walter Brown aller mais je lui en glisserai un mot un peu plus tard. Je me déplace vers la salle où Ollivier Roberge présentera; je suis curieux de voir ce qu'il aura à nous raconter.
Ollivier Roberge commence par expliquer que « collège » n'a pas le même sens chez lui (au Québec) qu'aux États-Unis, et qu'il peut expliquer sur demande. Il explique ensuite que quand son père était jeune, passer d'un langage d'assemblage à FORTRAN était une bonne chose. Il émet des souhaits de simplification pour C++ au passage.
Ollivier Roberge dit qu'il nous faut une idée importante pour les années 2020. Il parle de Data-Oriented Design, et dit que ce n'est pas vraiment un enjeu de Cache, mais bien un enjeu de transformation de données et de visualisation d'un programme comme une série de transformations. Il propose un schéma modélisant sa vision. Il met de l'avant que les données à traiter peuvent influencer le comportement d'un programme et les choix des algorithmes.
Ollivier Roberge dit que le DoD tend à donner du code spécifique à la plateforme, impératif, spécifique à un problème ou à un format de données, et optimisé essentiellement de manière manuelle pour optimiser l'accès à la cache. Pour améliorer la situation, il a questionné ChatGPT et n'a rien eu de très pertinent. Il suggère donc de prendre le problème sous un autre angle : code portable, déclaratif, générique, et qui laisse l'organisation des données en fonction de la Cache au compilateur
Ollivier Roberge présente le code fonctionnel comme un enchaînement de fonctions qui mène à un programme. Il montre que F(G(H(D))) est équivalent à F'(D) et met de l'avant que DoD est isomorphe à la programmation fonctionnelle, du moins en partie. Ce qui change est le lieu où nous concentrons nos efforts (sur les données ou sur les fonctions). Il recommande d'éviter les extrêmes : placer toute son attention sur la programmation fonctionnelle ou sur le DoD est contreproductif.
Ollivier Roberge explore ensuite les options de programmation fonctionnelle en C++ (lambdas, algorithmes, ranges, pointeurs de fonctions; métaprogrammation avec des templates, à la Lisp). On peut faire de la programmation fonctionnelle en C++ », et il parle de quelque chose qui serait du compiler-level functional programming. Il suggère de l'améliorer en pigeant quelques idées dans la POO. Son cas d'espèce sera le chargement d'images. Il montre une approche OO traditionnelle (parent Image, dérivées selon les formats à supporter) et dit qu'il l'adaptera à une approche TOD. Il parle des limites et des couts de cette approche.
Ollivier Roberge explique qu'en TOD il n'y aurait pas de classe parent universelle. Il y aurait des fonctions, et un focus sur les données. Il décrit ensuite les transform packages et dit que ce ces choses contiennet de même que ce qu'elles représentent
Ollivier Roberge poursuit aves les impacts du TOD sur le design : ce que ferait le code client, la bibliothèque, et le paquetage contenanmt les objets qui réalisent les transformations. Il se dit prêt à écrire du code à ce stade. Il a des objectifs : fair disparaître des switch pour les automatiser et n'appeler des fonctions que si elles existent (il dit ne pas savoir comment faire, mais il est au courant de std::void_t), et ce sans réflexitivité
Ollivier Roberge montre un premier exemple dont il dit ne pas être fier (liste de types fonctionnelle). Il a une macro TRANSFORM_CALL qui génère des templates qui n'appellent une fonction que si elle existe. Ensuite, disant que les switch son des mappings d'une variable vers un type, Si deuxième exemple le rend plus heureux. Il dit que son approche pourrait être simplifiée de diverses manières. Il aimerait traiter le code comme des données (sa diapo parle aussi de traiter les données comme du code)
Ollivier Roberge conclut en disant que c'est le compilateur qui écrit le code, pas nous; que l'optimisation se fait à tous les niveaux; et qu'il faut trouver les ressemblances parmi les différences, même si elles sont marquées.
Ollivier Roberge se demande s'il a amélioré DoD? Il n'est pas sûr. Le TOD est selon lui compatible avec d'autres paradigmes et que c'est utilisable tout de suite. Il pense que le TOD pourrait être la vogue de 2020.
La salle semble aimer son humour 🙂 Ollivier Roberge a été courageux de donner une première présentation dans un colloque de grand envergure comme ça. Bravo!
Il y a des biscuits pour collation. Je m'endors un peu alors un soupçon de sucre, ça fait du bien.
Je suis curieux de voir ce dont la prochaine présentation parlera...
Vidéo : à venir
Adrian Stanciu dit venir de Roumanie. Il présente brièvement son pedigree et dit que le travail présenté aujourd'hui se base sur ses travaux personnels; ce n'est pas relié à ses engagements professionnels.
Adrian Stanciu présente sommairement le Machine Learning (ML) dans le contexte de ses travaux, soit apprendre à partir de données pour faire des prédictions par la suite. Il explique ensuite que les systèmes embarqués sont habituellement des appareils aux ressources limitées. La combinaison des deux lui semble être une alternative à l'apprentissage sur le Cloud. Cela permet du traitement en temps réel, une opération déconnectée, un meilleur respect de la vie privée... mais les mises à jour sont plus compliquées à faire et il faut se préoccuper d'une variété de plateformes matérielles. C++ lui semble être un bon langage pour ce type de tâche
Adrian Stanciu aborde la question de la classification des images. Il décrit (à haut niveau) un algorithme d'apprentissage supervisé, puis présente sommairement les réseaux neuroniques, avant de poursuivre avec les réseaux de neurones convolutionnels (CNN) qu'il dit efficaces pour classifier des images.
Adrian Stanciu décrit le système embarqué sur lequel il a fait ses tests (un Rapsbery Pi). Il a utilisé OpenCV et un CNN pré-entraîné nommé MobileNet fourni par Google. Son algorithme est en huit étapes : les trois premières sont de l'initialisation alors que les cinq autres se font de manière itérative. L'étape 1 (lecture du modèle) est simple. L'étape 2 crée un interpréteur multithread mais le code est simple. L'étape 3 alloue les tenseurs.
Adrian Stanciu explique ensuite les étapes itératives. L'étape 4 est la lecture d'une image (vraiment, un constructeur). L'étape 5 demande de redimensionner l'image (simple avec OpenCV). L'étape 6 copie l'image sur le tenseur (un memcpy()). L'étape 7 est d'exécuter l'inférence (une fonction) et l'étape 8 est d'extraire les résultats diu tenseur. Le code est simple mais propre.
Adrian Stanciu enchaîne avec une démo « live » pour distinguer une balle de tennis jaune d'une tomate rouge. Simple et joli. Avec la balle de tennis, c'est un succès, mais avec la tomate le logiciel hésite entre un poivron rouge et un vase... Il se trouve qu'il n'y avait pas de tomates dans le modèle utilisé pour l'entraînement 🙂
Adrian Stanciu compare les résultats entre les version C++ et Python. Monothread c'est un peu à l'avantage de C++, mais avec plusieurs threads C++ domine... et prend beaucoup moins de mémoire!
Adrian Stanciu veut ensuite jour à roche-papier-ciseaux avec son programme. Il présente deux Data Sets utilisés pour l'entraînement (qu'il ne fait pas sur son Raspberry Pi parce que même sur son laptop ça prend plusieurs minutes). Il ajoute dans ce cas une caméra et deux bibliothèques soit libcamera et gstreamer. Le code pour capturer le flux de la caméra est propre. L'algorithme est simple : dans une boucle, saisir une image, résoudre,afficher les prédictions. La démo est très chouette!
Adrian Stanciu explique ses plans de déplacer les inférences sur le GPU...
Q : quels étaient les temps pour les inférences?
Adrian Stanciu : montre les données cumulées
Roth Michaels : il y a de nouveaux opérateurs qui arrivent sur Tensorflow. As-tu joué avec (un autre moteur)? Et es-tu satisfait de l'API?
Adrian Stanciu : je ne connais pas ce moteur
Q : les stats que tu as tirées sont intéressantes. Est-ce que la taille obtenue pour le modèle te semble raisonnable pour la tâche à réaliser?
Adrian Stanciu : ça peut clairement être optimisé un peu plus (il donne des techniques envisageables)
Pablo Halpern : est-ce la même méthodologie que pour apprendre à une machine à comprendre les langues parlées?
Adrian Stanciu : oui, pour l'essentiel
Pablo Halpern : quand la caméra tourne en boucle, consomme-t-elle beaucoup de chaleur?
Adrian Stanciu : je ne l'ai pas mesuré, mais je pense que c'est très peu
Q : qu'est-ce qui explique les différences de vitesse entre Python et C++
Adrian Stanciu : Python utilise Tensorflow Lite, mais consomme vraiment plus de mémoire
Q : est-ce que tu entraînes ton modèle juste avec roche, papier et ciseaux?
Adrian Stanciu : oui, juste ça
Q : quel est l'impact de la lumière ambiante sur la classification?
Adrian Stanciu : le décor a un gros impact, je peux te dire ça
C'était pas renversant, mais c'était sympathique et c'était clair. Je reste au même endroit pour la prochaine présentation, et je bavarde avec le toujours sympathique Roth Michaels qui veut s'impliquer dans SG14 et SG19 (bonne nouvelle, il a le bon profil!). Juste à côté, Khalil Estell explique sa théorie sur la taille du code gérant des exceptions à Pablo Halpern.
Andreas Weis est venu bavarder pendant la pause. Très chic type. On devrait collaborer sur des propositions bientôt.
Vidéo : à venir
Michael Wong prend la parole. Il expliquera ce qui, dans le C++ contemporain, aura un impact sur SYCL (partie de Nevin Liber) puis sur SYCL SC (pour Security Critical, ce sera la partie de Verena Beckham). Michael Wong explique brièvement ce qu'est SYCL, et trace un parallèle entre l'évolution de C++ et celle de SYCL. Deux implémentations de SYCL sont en développement, soit DPC++ (basé sur LLVMO et hipSYCL (multiples backends). SYCL est un projet à code ouvert et est supporté par godbolt.
Michael Wong explique que SYCL a désormais des tests de conformité (SYCL-CTS, il y a un github de Khronos pour ça). Il décrit ensuite les modalités de mouvement de données entre les unités de traitement (implicites, explicites). SYCL, comme AMP, utilisent le modèle implicite. SYCL ajoute une version explicite depuis 2020 pour faciliter la migration de code CUDA ou OpenMP. Michael Wong présente SYCL comme un bon point de départ pour écrire ce genre de code.
Michael Wong présente la UXL (une nouvelle fondation qui a à peine une semaine ou deux de vie) : https://uxlfoundation.org/
Michael Wong explique que SYCL facilite l'utilisation de superordinateurs. Ça fonctionne entre autres sur les GPU de NVIDIA
Nevin Liber arrive ensuite pour expliquer en quoi C++ et SYCL ensemble oeuvrent pour améliorer la sécurité logicielle. Il rappelle qu'il ne parle par pour WG21, car personne ne le fait. On vote, on fait du consensus par comité, pas du design par comité
Nevin Liber explique comment il définit Safety : limiter les dégats causés à un système par des bogues. Il préfère la prévention (compile-time) à la détection (run-time). Il définit Security comme la mitigation d'attaques délibérées contre des parties vulnérables d'un système. Les mesures relatives (à quel point est-ce Safe ou Secure?) sont plus faciles à atteindre que des mesures absolues (est-ce Safe? Secure?). Et il y a l'enjeu du Correctness, celui de la vitesse... C'est un jeu d'équilibre
Nevin Liber rappelle qu'on essaie de se débarrasser le plus possible du UB, et rappelle (à juste titre) que dépendre de UB est toujours un bogue. Il rappelle toutefois que l'arithmétique sur des entiers non-signés ou sur des atomiques est bien définie, mais que 90+% du temps c'est probablement un bogue malgré tout. Éliminer les cas de UB n'est pas la même chose qu'éliminer tous les bogues.
Nevin Liber rappelle en partie l'historique de span et mdspan et discute de l'enjeu de la validation des bornes. Est-ce Safe? Non. Peut-être Safer, mais pas Safe car il n'est pas toujours possible de vérifier si un pointeur appartient à un intervalle. Il parle de la naissance de SG23, sur la base d'une multitude d'opinions sur le sujet.
Nevin Liber dit que mdspan résout plusieurs problèmes difficile d'arithmétiques, ce qui réduit les risques de bogues. Il est possible de valider les bornes avec un AccessorPolicy, mais ça ne règle pas tout. span.at() aussi, aide à écrire du code plus solide, mais ne fait pas disparaître tous les bogues. Entre autres, dans les deux cas, ça dépend de l'initialisation (complète ou pas) du substrat. Et lever une exception signale un problème, ça ne le règle pas. Il montre une série de propositions qu'il a soumises au comité sur des sujets connexes et qui ont tous été rejetés. Il parle de P2951, Shadowing is good for safety, puis de P2955...
Nevin Liber parle de propositions pour améliorer le Safety du langage. P2723 propose d'initialiser toutes les variables à zéro (il y a un coût, mais il faut le mesurer... est-il le même sur les GPU?). Ça enlève un UB (safer), mais ça peut créer des bogues de logique (less correct). P2795 introduit l'idée de Erroneous Behavior qui distingue certains comportements incorrects de UB.
Nevin Liber parle ensuite des contrats, ce qui va vraiment nous aider.
Nevin Liber continue avec SYCL. Certaines fonctions (p. ex. : sycl::malloc(0)) ont un comportement semblable à celui de C (avec std::malloc(0)), même si on aurait pu faire autre chose, mais on a déterminé que ce que fait C était la chose à faire dans les circonstances. Avec sycl::complex tous les membres sont initialisés en tout temps, mais on se demande si un mécanisme explicite pour escamoter l'initialisation devrait être offert. Il fait remarquer qu'il y a du UB dans SYCL aussi (il cite Shafik Yaghnmour).
Nevin Liber patle de sycl::buffer (un propriétaire occasionnel de données) et de sycl::accessor (une vue). Il montre des cas problèmes avec ces outils. C'est difficile de bien définir les contours de certains outils...
Nevin Liber dit que les experts de C++ et de SYCL ne sont pas des Safety Experts. On a besoin de plus de principes et de discipline. Ceci explique la création de SYCL SC
Verena Beckham explique ce qu'est SYCL SC en lien avec SYCL. Elle définit un système comme Safety-Critical quand une panne pourrait blesser ou tuer des gens. Il y a des niveaux de Safety en fonction de la gravité des pannes, et cela requiert du Functional Safety : il faut que les fonctions fonctionnent correctement. Il faut que les risques aient été analysés, qu'un mitigation ait été apportée et qu'on puisse démontrer cela.
Verena Beckham explique les processus pour atteindre le Functional Safety du logiciel. Il faut éviter les bogues, respecter les standards, tester le code, assurer une couverture du code, etc. Il faut aussi que les résultats soient livrés à temps et à chaque fois.
Verena Beckham dit que sur le plan du langage, on peut éviter les mécanismes susceptibles de causer des erreurs, et on peut éviter les opérations indéterministes en temps comme la levée d'exceptions.
Verena Beckham dit que sur le plan des API, on voudra intégrer de l'intelligence artificielle, mais cela demande de l'énergie et pour en déployer dans un truc comme une voiture autonome, SYCL devient attrayant. On veut donc des API déterministes en temps et en résultats.
Verena Beckham dit que C++ ajoute sans cesse des mécanismes qui aident à atteindre ces objectifs, et c'est bien, mais il faut aussi de l'analyse statique, des profileurs, des bibliothèques optimisées, des programmeuses et des programmeurs d'expérience. L'écosystème de C++ est extrêmement attrayant pour la communauté SC malgré certains irritants. Il faudra des guidelines (MISRA va aider), des outils certifiés, etc. SYCL utilise les exceptions, mais leur comportement n'est pas déterministe. L'allocation dynamique de mémoire est un autre enjeu... SYCL dépend enfin de la bibliothèque standard.
Verena Beckham parle de l'enjeu de la mémoire allouée dynamiquement. Si on ne peut pas en avoir dans une application, il faut connaître tous nos besoins à la compilation (c'est restrictif!). On accepte donc (a) les allocations à l'initialisation (ce qui permet de faire des Object Pools) et (b) on doit connaître le pire cas de temps d'exécution. Elle montre des exemples. C'est pas simple car les spécifications de SYCL ouvrent la porte à de l'allocation dynamique de mémoire.
Michael Wong : on veut que SYCL soit mainstream, mais il faut que ce soit portable et le matériel change souvent. Il explique comment on peut s'impliquer dans SYCL.
Khalil Estell : je veux mieux comprendre les enjeux sur le non-déterminsme des exceptions. Est-ce seulement l'allocation dynamique de mémoire ou y a-t-il autre chose?
Verena Beckham : elles utilisent RTTI aussi, ce qui ajoute au problème
Michael Wong : le Stack Unwinding est aussi un enjeu. Le standard ne dit pas que les exceptions doivent allouer de la mémoire dynanmiquent
Nevin Liber : Howard Hinnant a montré que ça s'implémente sans allocation dynamique
Pas mal finalement. Une bonne journée. Il reste quinze minutes avant le banquet... J'ai parlé un peu avec quelques chouettes personnes dont Michael Wong et Erez Strauss. Nous sommes tous fatigués; ça paraît que la semaine achève.
Jon Kalb est passé et m'a donné du chocolat. Il y avait des bouchées (délicieuses : shooters de poisson cru et concombres au sésame, dumplings frits, petites brochettes de légumes et de fromage marinés, etc.) et un bar ouvert pour une demi-heure avant l'ouverture de la salle de banquet (j'ai pris un IPA, c'était agréable en fin de journée).
Vidéo : à venir
Les portes du banquet se sont ouvertes et nous nous sommes dispersés dans la salle où des bols de salade nous attendaient (la vinaigrette était offerte à la cuillère par le service). Je me suis assis quelque part et à ma table se trouvaaient aussi Ollivier Roberge, Andre Kostur, Vincent Reverdy, Greg Marr, et un de mes étudiants de la fin de semaine (je pense que son nom est Andrew Pletta mais je ne suis pas 100% sûr car je n'ai pas bien mémorisé les noms; c'est quelqu'un de très agréable cela dit et j'étais bien content de bavarder avec lui).
On a bavardé en mangeant (c'était très bon : saumon, boeuf, légumes, un dessert agréable, des portions raisonnables – j'aime moins quand c'est démesuré – et la modération était à propos car on ne veut pas s'endormir pendant les Lightning Talks qui suivent). Ce fut un moment apprécié. J'ai appris que Andre Kostur va se joindre à la délégation canadienne pour WG21 et j'en suis bien content (c'est un chic type, intelligent et courtois, qui connaît bien les enjeux).
J'ai dû m'excuser après le repas car j'avais promis à Daniel Hanson de prendre un peu de temps pour l'aider (il a des questions techniques pour un livre sur lequel il travaille). Je me dirige dans la salle de plénière. Andre Kostur vient me rejoindre et me présente son épouse Laura Kostur, très sympathique (elle parle très bien français, félicitations!) avec qui je bavarde un peu. En plus de discuter d'animaux, elle me parle de son projet d'un futur « C++ Plus One » pour les gens qui voyagent avec leur partenaire de vie. C'est une bonne idée! J'aime bien quand je peux être accompagné par mon amoureuse, mais en même temps lors de ces événements je suis tellement occupé que je suis un peu « plate »...
Daniel Hanson est venu me rejoindre, et on a examiné certaines de ses interrogations. Les Lightning Talks débutent ensuite. J'ai manqué le début pendant que Daniel Hanson et moi finissions d'examiner ses questionnements.
Vidéo : à venir
Phil Nash est le maître de cérémonie...
Jonathan Müller présente un truc qui était assurément bon, mais je n'ai pas pu entendre ce qu'il faisait.
Shachar Shemesh présente un truc sur les exceptions où il réagit visiblement à la présentation de Peter Muldoon plus tôt cette semaine. Je n'ai vu que la fin.
Paul Tsouchlos parle de Polymorphism: is it really that bad? Il mentionne XSTRRAHL et de SARRP, un logiciel de robotique et d'imagerie médicale (pour animaux?). Il parle de gestion des changements de substrats matériels. Il parle d'une solution basée sur l'héritage et du recours à final pour garder la structure simple.
Laura Kostur parle de Undefined Behavior, but not the one you're thinking of. Son point est les cas où les testeurs ne comprennent pas nos intentions, ou encore quand les autres ne comprennent pas notre code. Elle suggère des pistes pour clarifier les intentions. Belle présentation!
Vasu Agrawai parle de Making friends with CUDA programmers (please constexpr all the things). Il présente CUDA, de son modèle de programmation, et montre une option de CUDA qui relaxe les restrictions de constexpr. La proportion de constexpr dans leurs bibliothèques croît avec le temps...
Glenn Philen parle de A fast, concurrent data loader for time-series data. Ils ont des caméras qui prennent des photos concurrement et qu'il faut charger et assembler par la suite. Il parle de charger les données efficacement et de les charger concurremment comme deux problèmes distincts.
Jergen Forgh parle de Thread safety with synchronized_value. Il réfère à la proposition d'Anthony Williams ici. Il donne des exemples d'utilisation
Sara Boulé parle de C++ and the next generation: how to support women and families in tech. Elle est là avec son bébé dans un sac ventral. Plusieurs femmes quittent le monde de la technologie avant l'âge de 35 ans et c'est une tragédie. Elle donne de multiples raisons pour expliquer cette triste réalité... Elle parle de politiques d'accommodement qui ne fonctionnent pas. Elle met ensuite en valeur des manières de faciliter le retour au travail (trois mois d'absence est une éternité!). Bravo!!!
Valentina Ricupero parle de The power of silence and music. Elle cherche des cadriciels qui mettent l'humain au centre des préoccupations, et parle de sa gestiomn d'équipe sur le plan humain. Les moments de silence et les moments de musique ont aidé.
Roth Michaels parle de Write valid C++ and Python in one file. Il travaille chez Native Instruments. Il propose des macros (les lignes qui débutent par # en Python sont des commentaires!). Oh boy...
Dan Curran parle de... il reviendra (problèmes techniques)
Griswald Brooks parle de spammy: abusing mdspan is within arm's reach. Il fait de la robotique et fait une démo avec un bras qui s'assure qu'il ne manquera pas de bière!
Dan Curran revient et parle de... la manière officielle de placer un rouleau de papier hygiénique, puis de la largeur des écrans, puis des fonctions trop longues... puis d'indentation incorrecte... et finalement, ça parlait de formatage de code
Benjamin Brock parle de Let's Fix Sparse
Linear Algebra with C++. It'll be Fun and Easy!. Il parle de
simplification des boucles imbriquées dans un parcours de matrice en
écrivant une fonction rows(matrice) et une fonction columns(rangée). Il
utilise les adaptateurs de ranges pour ce faire
Neil Henderson qui est australien et parle de The Responsibility of C++. Il fait un tas de blagues amusantes.
Yannic Staudt qui parle de Why would you want to do That? et dit qu'il a fait des trucs qu'il ne faudrait pas faire, soit de la compilation croisée à travers Wine.. Il a construit un outil nommé Intercalaire pour compenser les irritants. Ça s'appelle Tipi
J'ai eu la chance de parler à Sara Boulé et à son amoureux (ils sont adorables) qui ont amené leur cocotte de huit mois ici. Ils ont été bien traités (ouf!) mais j'aimerais qu'on puisse les libérer un peu dans le futur et avoir une forme de service de garde...
J'ai retourné quelques courriels à mon retour à la chambre, mais je suis très fatigué alors ce fut le dodo peu de temps après.
En ce début de dernière journée, je fais les tâches normales pour un tel jour (douche, refaire les bagages – je ne veux pas oublier de vêtements cette fois! – et autres revérifications de l'horaire des vols vers la maison). J'ai téléchargé l'essai de maîtrise (en cours de rédaction) de mon étudiant Jhonny Louis-Alcius dans le but de travailler dessus dans l'avion tantôt si je ne suis pas trop fatigué (on se croise les doigts), travaillé un peu, parlé à mon amoureuse Za, puis je suis allé faire mon Check-Out.
Chose moche : cette année, pour réduire les frais un peu (ce que je comprends), le colloque n'a pas son propre Wi-Fi et on utilise celui de l'hôtel, ce qui a généralement bien fonctionné mais demande d'avoir une chambre ici (aux gens qui résident ailleurs, les organisateurs recommandent de se faire un ami et d'utiliser son identité). Il se trouve que, en faisant mon Check-Out, j'ai automatiquement perdu mon accès Internet (c'est sérieusement moche) et aucun accommodement ne semblait possible (j'aurais aimé le conserver jusqu'à midi, étant donné que je vais quitter vers 13 h environ pour l'aéroport).
Heureusement, en bavardant avec le toujours sympathique Lawrence O'Boyle, j'ai appris qu'il était inscrit à d'autres cours en fin de semaine et résidait par le fait-même encore à l'hôtel pour 48 heures. Il m'a gracieusement offert d'utiliser son identité pour ce matin, ce que j'apprécie beaucoup.
Shachar Shemesh dit qu'il veut nous convaincre que les méthodes virtuelles, c'est pas si lent qu'on ne le craindrait. Il dit ne pas vouloir convaincre les gens de les utiliser, juste les convaincre de ne pas se priver sur la base de la seule vitesse. Il prépare un microbenchmark dans lequel... les méthodes virtuelles sont plus rapides que les méthodes concrètes! Cela dit, son benchmark n'est pas très bon (le compilateur voir probablement à travers).
Shachar Shemesh montre d'autres exemples, et prétend que la vitesse relative dépend du matériel, des options de compilation, etc. alors il questionne la pertinence de prétendre que les fonctions virtuelles sont plus lentes. Il montre rarement son code de test, tristement
Shachar Shemesh finit en questionnant la valeur des benchmarks. Il dit de se méfier de variant... Hum, faudrait que je parle avec lui :)
Shachar Shemesh en arrive à son point principal : est-ce que la différence est importante? Il pense qu'il faut choisir le bon design pour le problème à résoudre (sur ce point, je suis d'accord). Il questionne l'intérêt des benchmarks et recommande de tester en contexte, de profiler (c'est raisonnable)
Q : j'utilise des variant parce que c'est pour moi un enjeu de Correctness...
Shachar Shemesh : le point est de prendre l'outil qui convient!
Q : le vrai coût des fonctions virtuelles est la difficulté de réaliser de l'inlining. Tes tests vérifient-ils cela?
Shachar Shemesh : si tu peux faire du inlining, pourquoi y serais-tu allé avec une fonction virtuelle en premier lieu?
Q : as-tu analysé le code généré?
Shachar Shemesh : pas du tout. Ce n'est pas ce qui m'intéresse
Le point « prends ce qui convient à ton design » me convient, mais ses tests ne sont pas satisfaisants alors la valeur des résultats est... suspecte 🙂 Mais il était enthousiaste et divertissant. Disons qu'avec des tests plus élaborés, les résultats peuvent être... radicalement différents.
Vidéo : à venir
Yannic Bonnenberger parle des structures de données de la bibliothèque standard, en particulier std::vector<T>, std:deque<T> et std::list<T> mais il touche aussi aux adaptateurs. Il parle des avantages et des inconvénients de chacun, et disserte de l'impact (positif à ses yeux) des architectures matérielles contemporaines pour un truc comme std::deque<T>
Yannic Bonnenberger examine ensuite plus en détail std::list<T> et les enjeux associés à la Cache. Il présente un schéma qui tient compte de l'allocateur et montre qu'il est possible de tenir les noeuds dans un espace plus contigü avec un allocateur bien pensé. Cela dit, le surcoût de la paire de pointeurs (prédécesseur, successeur) accroît le coût en espace mémoire et demeure un enjeu.
Yannic Bonnenberger parle de FixedStack<T,N>, sans aucune allocation dynamique de mémoire. Il nomme son substrat Page<T,CAP>. Son code n'est pas exception-safe... Son Page<T,CAP> contient un tableau de Slot<T> qui représente des blocs proportionnels à la taille d'une Cache Line. Son Slot<T> utilise des SlotImpl<T> qui contient un pointeur... Queue<T, size_t page_size> contient une PageList<T,page_size> mais n'est pas exception-safe non plus. Son Queue<T, size_t> est plus près de std::deque<T> que d'autres trucs.
Q : tu utilises un char[N] à titre de tampon. Pourquoi pas un union?
Yannic Bonnenberger : question de confort
Q : comment as-tu réussi un benchmark avec une « bonne » invalidation de cache?
Yannic Bonnenberger : je n'y suis pas vraiment arrivé
L'idée d'une structure qui profite de la taille des Cache Lines n'est pas folle, mais le code présenté était moyen. Je vais peut-être jouer avec un truc analogue (mais avec une interface exception-safe).
Il y a du granola, du yogourt et des fruits en collation. Ça fait un bien fou (je me suis fait un deuxième bol). Plusieurs petites conversations en cours de route; tout le monde semble heureux, mais fatigué..
Vidéo : à venir
Alex Dathskovsky demande si le processeur exécute le programme tel qu'on l'a écrit (la réponse : rarement). Il va donner un résultat équivalent à ce que tu as écrit, en pratique. Il présente un bout de code naïf et montre des optimisations qu'un compilateur (même simpliste) ferait probablement. Il le refait avec plusieurs exemples, et montre plusieurs optimisations (sortir une initialisation d'une boucle; profiter de la distributivité de la multiplication sur l'addition; supprimer le code inutile; etc.)
Alex Dathskovsky montre aussi des optimisations réalisées par les processeurs. incluant la prédiction des branchements, l'exécution des instructions dans le désordre pour mieux profiter du pipeline interne du processeur. Il explique comment les exécutions dans le désordre s'articulent (belle explication d'ailleurs)
Alex Dathskovsky explique le fonctionnement de la cache, qui accélère les lectures mais tend à ralentir les écritures.
Alex Dathskovsky aborde la question de C++ en lien avec tout cela. Il explique l'exigence de respecter les dépendances de données, la règle du as-if, l'impact des effets de bord... Il parle de l'effet du UB, qui brise le raisonnement.
Alex Dathskovsky examine les ordonnancements entre threads. Ça l'amène à aborder la cohérence séquentielle, propriété souhaitable mais très dispendieuse. C++ offre SC-DRF (Sequentially Consistent if Data-Race Free). On peut s'en approcher avec des outils de synchronisation et une bonne compréhension des règles de Happens-Before.
Alex Dathskovsky parle de volatile et de ce que ça ne fait pas. Ensuite, il parle de barrières et de clôtures dans le code en utilisant du code assembleur inline, puis recommande d'utiliser les outils standards. Il aborde thread_local, et mentionne qu'il faut utiliser un tel mécanisme « proprement » (p. ex. : ne passe pas son adresse à une fonction). Il parle de std::atomic, puis montre comment en profiter pour faire un atomic_thread_fence(), puis montre comment se passer du atomic_thread_fence() par la suite. Il explique que sur x86, écrire sur une atomique est un XCHG ce qui est une pleine barrière
Alex Dathskovsky parle de std::atomic<std::shared_ptr<T>> qui collabore bien avec les atomiques. Il parle de std::future<F> et std::promise<T>. Il parle de std::jthread et de std::stop_token. Il parle de std::mutex et de std::lock_guard de même que de std::unique_lock et std::scoped_lock. Il parle de sémaphores, binaires ou non. Il touche à std::latch et std::barrier... C'est un tour d'horizon, donc, grosso modo
C'était pas mal, mais j'aurais aimé que ça parle plus du modèle mémoire que des outils.
À partir de maintenant, j'ai laissé des traces de ce que j'aurais fait si j'avais pu rester, mais les affres du voyage de retour font que je dois quitter vers l'aéroport pour m'assurer de retrouver ma famille ce soir...
Vidéo : à venir
J'aurais voulu aller saluer Walter Brown et profiter de ses excellentes présentations une dernière fois cette semaine, mais j'aurais été « serré » pour mon avion...
Vidéo : à venir
Ce sont deux excellents conférenciers et deux penseurs d'exception dans notre domaine. Je suis triste de les manquer
Vidéo : à venir
David Sankel donne toujours des présentations intelligentes, pertinentes et divertissantes...
Vidéo : à venir
J'attendais ce Keynote avec impatience. J'espère qu'il sera publié très rapidement!
Ce fut une semaine intéressante et pertinente
Je suis arrivé tard à la maison, mais un peu en avance sur le temps prévu. Le taxi à Montréal a coûté une petite fortune et avait une conduite un peu dangereuse (souvent en sens contraire du trafic) malgré mes rappels à l'ordre. Tout de même, je suis de retour sain et sauf, et j'ai plusieurs idées collectées durant la semaine qui vont se retrouver dans mes cours désormais alors ça a clairement valu la peine.