À propos de cppcon 2015

Quelques raccourcis :

Grâce à l'Université de Sherbrooke (en particulier, grâce à Jean Goulet et à Claude Cardinal du CeFTI) et au Collège Lionel-Groulx (en particulier à Lucia Lepage), j'ai le privilège de participer à cppcon 2015.

Gros merci à Gabriel Aubut-Lussier pour avoir épluché le tout et dépisté de nombreuses erreurs de frappe.

Ce qui suit est une sorte de journal de voyage, avec éléments humains et éléments techniques. Notez que le colloque s'est, en cours de route, enrichi d'un nouveau membre nommé Schrödinger : https://www.facebook.com/media/set/?set=a.411120545751971.1073741830.178628992334462&type=3&uploaded=2 (mais je ne sais pas de quoi il est spécialiste)

Glossaire

Quelques termes que vous verrez ci-dessous :

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

Jour -1 19 septembre 2015

Coûts du séjour pour aujourd'hui :

Je ne compte pas ici les 200 USD de monnaie, qui devraient me durer toute la semaine, car je les utilise principalement pour le transport (autobus, navette) et pour la lessive

La veille du départ, mon épouse Za et moi avions prévu aller passer un peu de temps das le Vieux-Montréal. Les parents de mon épouse (Danielle et Jocelyn, que je salue) avaient pris les plus jeunes de nos enfants en charge pour nous donner un peu de temps (et permettre à Za de m'amener à l'aéroport aux aurores). Malheureusement, la vie étant ce qu'elle est, un de nos adorables enfants (Vayda) est allée faire du trampoline et s'est blessée, à la nuque et au petit doigt (de la main droite; heureusement, elle est gauchère). La nuque, finalement, c'est musculaire donc rien de grave; le doigt, par contre, c'est une fracture du condyle et c'est compliqué, donc on s'en est tirés avec un plâtre. Conséquence : le moment d'amoureux est devenu une visite à Ste-Justine, et la nuit pré-voyage a fondu comme peau-de-chagrin (en gros : trente minutes).

À l'aéroport de Montréal, je me suis pris 200 USD pour faire la semaine (je voyage en autobus et je fais un aller et un retour en navette, alors...)... et ça m'a coûté près de 300 CAD. Taux de change de merde.

Après notre non-nuit, j'ai cogné des clous à plusieurs reprises aujourd'hui. Dans les aéroports, dans les avions, sur la route, etc.

J'ai passé le voyage Montréal-Vancouver à chercher à dormir, mais malheureusement j'étais mal installé (siège du centre, donc nulle-part pour s'accoter). Pour des raisons qui remontent à l'époque où ma plus vieillie (Marguerite) était bébé, mon coccyx n'aime pas que je reste assis, alors ce fut déplaisant. J'ai par contre constaté en fin de parcours que ma voisine était une sommelière vedette, Élyse Lambert, à qui je souhaite bonne chance dans ses concours prochains et dans sa vie en général.

À Vancouver, il y a (beaucoup!) plus de gens avec traits asiatiques que de gens avec traits caucasiens, ce qui est amusant. L'aéroport est trilingue (anglais, français, dialecte chinois). Le passage à cet aéroport est différent de l'an dernier pour moi (le jour et la nuit, littéralement!), car l'an dernier je suis passé par Vancouver au milieu de la nuit et l'endroit était désert. Aujourd'hui, l'endroit était plein, vibrant... et asiatique :)

Le trajet entre Vancouver et Seattle fut bref (moins d'une heure), mais je me suis assoupi à quelques reprises. Mon voisin dormait aussi (je pense). Pour ce type de trajet, les avions sont très petits (une soixantaine de places). J'aurais voulu profiter du paysage mais j'était trop fatigué..

À 17h30, j'avais prévu un souper avec d'autres participants à l'événement au Tap House Grill de Bellevue. J'ai annulé (trop tard, trop mort). J'espère qu'ils comprendront. Je suis plutôt allé prendre possession des lieux, faire une petite épicerie, m'assurer (maladroitement : ma 1er chambre sentait la cigarette, mais j'ai réussi à la faire changer sans difficulté; la nouvelle n'a pas de vaisselle ou d'outils pour cuisiner, mais je m'en suis occupé) de pouvoir fonctionner cette semaine (p. ex. : je n'ai pas de quoi boucher le lavabo de la cuisine pour faire ma vaisselle, mais je viens de le constater), etc. J'ai aussi pris des nouvelles de ma famille que j'adore et qui me manque, et j'ai bavardé (virtuellement) avec mon ancien étudiant Alex Boulanger qui est présent à Seattle pour l'événement lui aussi. Je me suis fait quelque chose de simple (pâtes, champignons, oignon, un peu de saucisses, sauce commerciale) ce qui me fera des restes pour demain.

Jour 0 20 septembre 2015

Coûts du séjour pour aujourd'hui :

Le plan de match pour aujourd'hui est :

Je vais aussi aller chercher quelques trucs manquants : du savon à lessive (petite quantité; la dame à l'accueil m'a recommandé de faire ça, alors je vais lui faire confiance), un chiffon rugueux pour nettoyer les plats (évidemment, dans un hôtel deux étoiles, les instruments de cuisson fournis sont de deux dans lesquels faut gratter pour nettoyer), ce genre de truc. La dame à l'accueil, très gentille, m'a expliqué que l'hôtel ne fournit plus de bouchons pour les lavabos (semble que ce soit une question de salubrité) et m'a suggéré de boucher le lavabo avec une guénille quand je fais la vaisselle; ils vont me remplacer les guénilles au fur et à mesure. Eh ben.

Je ne suis pas encore adapté au changement de fuseau horaire; j'ai l'impression que ma journée est à moitié faite et, ici, les gens se lèvent à peine.

Plus tôt ce matin, en organisant les finances de son épicerie (elle étudie à l'extérieur et dans notre entente, elle fait l'épicerie et je lui transfère les fonds correspondants – vive Internet!), j'expliquais à ma fille Calypso Trudeau-Roy le plan de match financier et alimentaire de la semaine :

Bref échange avec Sumant Tambe par Twitter en matinée. Sumant est un programmeur fonctionnel très intéressant et présentera un truc sur l'Internet of Things cette semaine, sujet qui croise directement celui de mon doctorat, alors on va bavarder un peu à la réception ce soir.

La journée a surtout été passée à préparer du matériel et faire des tests (j'ai pas fini; ça va être serré pour mercredi).


Une fois sur place pour l'inscription officielle, plusieurs visages connus, certains qui me reconnaissent et d'autres non. Petit bonjour à Jon Kalb, le très gentil organisateur de l'événement, saisie du matériel promotionnel et du badge (pas d'erreur sur mon nom cette année), bonjour à Louis Dionne et à Marshall Clow avec qui j'ai eu le privilège de travailler en mai dernier. J'attends mes ex-étudiantds Alex Boulanger et Félix-Antoine Ouellet avec qui j'ai promis d'aller prendre une bière dans le coin avant la réception de ce soir.

Bière fort agréable d'ailleurs. Je voulais les amener au Tap House, où le choix de bières est grand, mais ma mémoire était incorrecte et je les ai plutôt amenés dans un bar sportif (bruyant par moment, car il y avait un match des Seahawks, équipe locale de football), mais qui faisait sa propre bière (de très bonne qualité; la mienne, à la citrouille, était très digne) et des plats à base de bière (j'ai pris une pizza dont la croûte, à base de bière justement, était délicieuse). Bavarder avec ces deux amis fut fort agréable.

Par la suite, retour à l'accueil. Je croise, alors que je fais la file pour le goûter qui nous est offert., John McFarlane avec qui je travaille dans SG14 et avec qui j'échange des courriels depuis quelques semaines, mais que je ne n'avais jamais rencontré en personne. Très agréable rencontre. Alors que je parle avec lui, Gor Nishanov (avec qui j'ai eu le plaisir de travailler en mai dernier) est passé nous saluer, et nous avons échangé avec enthousiasme sur son projet de coroutines, les forces particulières de son approche, et des questions que John se posait sur la gestion des états des fonctions dans une situation de continuation.

Des gens se joignaient à nous pour la conversation, assez enthousiaste. Nous avions droit à une consommation gratuite (un scotch très correct dans mon cas) et avons poursuivi la discussion un certain temps, quand deux chics types de l'équipe de Visual Studio, James McNellis et Yuriy Solodkyy, se sont joints à nous. Je connaissais James, pour avoir parlé (et pris quelques bières) avec lui l'an dernier et pour avoir gardé contact informellement depuis, et je ne connaissais par Yuriy mais c'est quelqu'un de très sympathique. James travaille encore sur le CRT (Common Runtime) de Visual Studio, et Yuriy travaille à faire compiler Clang et MSVC de manière à ce que les binaires résultants puissent fonctionner ensemble.

Nous avons bavardé un peu de trucs de la vie. James travaille maintenant à distance, et s'est déplacé près de l'endroit où il a grandi, se disant plus ou moins fait pour la vie de banlieue; on a blagué sur le « faux James » que Microsoft tient au bureau, une sorte de mannequin à tête d'écran que ses collègues décorent de chemises colorées quand il appelle. Enfin, je suis reparti vers l'hôtel, autobus oblige.

Dehors, il pleuvait un crachin des plus constants, mais c'était tout de même correct. Arrivé à la chambre d'hôtel, j'ai retourné quelques courriels, écrit un (court) mot d'amour à ma belle, et je suis tombé d'épuisement.

Jour 1 21 septembre 2015

Coûts du séjour pour aujourd'hui :

Je me suis levé vers 4h du matin, combinaison de décalage horaire, d'envie de parler à mon épouse et aux plus jeunes, et de travail à faire.

Malheureusement, Skype a des ennuis ce matin. Je suis parvenu à écrire à mon épouse, mais nos logiciels respectifs nous disaient mutuellement inaccessibles et refusaient que l'on s'appelle. J'ai fini par redémarrer Skype pour constater qu'on ne pouvait plus se connecter par la suite. Grrrr... J'ai redémarré mon ordinateur tout entier, mais rien n'y fait; j'ai pu valider par la suite que Skype a vraiment des ennuis, et qu'il me faudra « faire avec » ce matin, le temps qu'ils corrigent la situation.

Je suis arrivé tôt ce matin, vers 7h15. Dans l'autobus, une personne d'origine Est-européenne, à l'oeil, lit avec intérêt un livre s'intitulant « Cracking the Coding Interview », alors je suppose qu'il se préparait pour une entrevue ce matin.

Alors que j'écris ceci, un gars vient s'asseoir juste à côté; il se trouve que c'est Jason Turner, qui anime http://cppcast.com/ (espèce de « show de radio » archi technique pour programmeurs). Il est surpris qu'on le reconnaisse (moi et un autre gars non loin), et nous offre des tee-shirts. Eh ben, inattendu!

On sent que « la vibe » est différente ce matin, avec le début des conférences, et le Keynote de Bjarne Stroustrup pour ouvrir les hostilités. La musique rock joue dans la grande salle où se tiendra le Keynote tantôt, mais je travaille quelques étages plus haut pour le moment. Et toujours pas moyen de se connecter à Skype... Ah, c'est officiel : http://www.express.co.uk/life-style/science-technology/606780/Skype-DOWN-Microsoft-Messenger-Not-Working-Europe-Australia-USA (quel sens du timing!)

Une paire de dames, probablement des gens des ressources humaines d'une entreprise d'informatique si je me fie à leur discours, fait passer une entrevue à la table juste derrière moi. Ce qui me fait penser : bien que l'audience soit surtout masculine, il y a plus de femmes cette année que l'an dernier, et c'est une excellente nouvelle. Je constate aussi que, pour le nommage symbolique des salles de conférence cette année, Jon Kalb a pris soin de donner à chaque salles le nom d'une scientifique plutôt que celui d'un scientifique, une initiative pertinente selon moi. Corriger des années (des siècles!) d'inéquité est un processus long, mais nécessaire.

Avant de descendre, je vais saluer Sumant Tambe dont j'irai voir la présentation plus tard ce matin, question de prendre contact étant donné la proximité de son sujet et de ma thèse. Sympathique bonhomme; il m'a reconnu, ce qui signifie qu'il avait jeté un coup d'oeil sur la liste des participants de la conférence (disponible en ligne, du moins pour les gens qui sont inscrits) pour voir de quoi j'avais l'air. On se serre la main et on échange quelques mots pour se dire qu'on prendra le temps de se parler un peu plus tard : je dois aller au Keynote et lui doit fignoler sa prestation.


Dans la grande salle, on trouve du café et des fruits. Je croise la toujours sympathique Kate Gregory et le très pertinent Jonathan Caves. Kate me raconte le cauchemar de son trajet par avion (elle a eu un service épouvantable au départ), mais semble d'excellente humeur.

Le band joue du Led Zeppelin. C'est pas mal du tout. Il reste 20 minutes avant le début du Keynote et la salle se remplit assez rapidement. Je me trouve un endroit au sol sur le bord du mur, comme c'est mon habitude dans ces circonstances : je ne peux prendre de notes sans une source de courant, la pile de mon ordinateur portatif étant misérable.

Pour voir la présentation : http://vid.plus/1OEu9C51K2A

Keynote – Bjarne Stroustrup : Writing Good C++ 14

Jon Kalb prend le plancher, évidemment, et sonde la foule pour savoir combien de gens n'étaient pas présents l'an dernier... Beaucoup de mains se lèvent, ce qui est sympathique. Il mentionne aussi SG14 (mon groupe de travail), et indique qu'une présentation sommaire de nos travaux sera faite demain matin, 8h15. Évidemment, je vais y aller. Il mentionne un jeu nommé « Cards against Compilers » pour aider les gens à faire connaissance (mon épouse Za verra un lien avec un jeu qu'elle aime bien)

Début du contenu technique

Bjarne Stroustrup prend place. Il parlera de la GSL

Il pose la question du « bon » code dans le C++ moderne. Nombreuses et nombreux sont celles et ceux qui veulent écrire du « bon » code, mais rares sont les ressources qui expliquent ce que cela signifie.

Nous avons un bon langage maintenant (depuis C++ 11, mieux avec C++ 14, encore mieux – on l'espère – avec C++ 17). Nous avons de solides spécifications techniques pour expérimenter. Nos programmes sont plus faciles à lire, à écrire et à entretenir.

Toutefois, de nombreuses personnes écrivent du C++ d'une autre époque, et « se font mal » par des pratiques archaïques. Le code peut être plus simple, sans perte d'efficacité.

Le but qu'il propose est de faire émerger de C++ un langage plus petit, plus simple, à partir de recommandations de bonnes programmation. Ce « plus petit langage » sera 100% compatible avec le langage pris dans son entièreté, par définition. Le travail initial est commencé, d'ailleurs :

Évidemment, les gens n'aiment pas les recommandations de saine programmation (les « règles »). Ces règles insistent souvent sur le nommage et l'indentation, pas sur les principes de fond. Ces règles ont aussi tendance à offrir de mauvais conseils (p. ex. : forcer une programmeuse ou un programmeur C++ à écrire du pseudo Java... alors que Java fait du bon Java, et qu'il est préférable d'écrire du code C++ dans le respect des idiomes de C++).

Autre problème : les recommandations tendent à devenir désuètes. Ce qui était sain en 1986 ne l'est plus nécessairement aujourd'hui. Elles tendent à être spécialisées, mal comprises, et à être mal supportées par les outils de développement.

Ce qu'on vise ici est un ensemble de recommandations qui soit :

Un cadre de pensée pour les humains, donc, basé sur des règles de bas niveau qui peuvent être vérifiées par analyse statique. Ces règles ne visent pas à former un ensemble minimal ou orthogonal.

Bjarne Stroustrup explique la structure d'une règle (vous pouvez voir le document entier sur https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md pour mieux comprendre).

Évidemment, nous avons aussi besoin de règles de niveau « expert », C++ étant ce qu'il est. La bibliothèque standard permet d'harmoniser ces recommandations. On veut atteindre une forme de « C++ sur stéroïdes », et les règles reposent sur la bibliothèque standard (des choses comme vector<T> et unique_ptr<T> par exemple, sans grande surprise puisque ce sont des bijoux).

Avec ces règles, Bjarne Stroustrup se dit d'avis qu'on accroîtra la productivité des gens. Personne ou presque ne sait vraiment ces choses que « tout le monde sait »; en simplifiant l'expérience de programmation, on pense mener à une réduction des erreurs, une accroissement de la vitesse d'apprentissage et une simplification du code, sans compromettre l'efficience des programmes. Bjarne Stroustrup dit souhaiter éloigner les gens des coins plus obscurs du langage.

Est-ce que Bjarne Stroustrup est devenu fou? Il pense que non, mais rappelle l'importance des outils pour mener à bien la démarche de simplification dans laquelle il s'est engagé.

Bjarne Stroustrup présente sommairement les Core Rules, cet ensemble de règles « fondamentales » de bonne programmation du langage, qui permettent d'éviter les fuites et les pointeurs flottants. Faire disparaître new et delete derrière des abstractions plus fécondes. On sait comment faire cela, et tous les outils sont là; il faut éduquer les gens. Utiliser (correctement) des pointeurs intelligents, encodant la sémantique de responsabilité sur les pointés à même les types, règle cette classe de problèmes. Simplement : chaque objet a un propriétaire, et les pointeurs bruts ne devraient pas franchir la frontière de ce propriétaire (sauf exception, évidemment). Cette règle dépasse le seuil des pointeurs en se plaçant sous l'angle de la responsabilité, et touche ainsi aux références, aux conteneurs, et même aux pointeurs intelligents. Évidemment, C++ permet de réaliser cette abstraction sans coût en temps ou en espace.

Bjarne Stroustrup parle de owner<T>, sémantiquement équivalent à T*, mais dont le type dicte la responsabilité sur le pointé. Ce simple outil permet à un analyseur statique de constater que des règles de saine programmation sont brisées. Évidemment, owner<T> est un mécanisme de bas niveau, et il y a mieux, mais cela dicte un chemin vers une transition du code ancien au code moderne.

Bjarne Stroustrup rappelle de nombreuses manières de mal utiliser les pointeurs, et parle du coût des tests dynamiques. Utiliser le système de types pour soutenir de bonnes pratiques est en soi une pratique efficace. Il parle un peu de array_view<T>, pour améliorer l'interface de fonctions qui auraient, autrement, accepté un tableau brut.

Discussion par la suite de nullptr est des problèmes que cela entraîne, et montre qu'on peut écrire not_null<T> qui encode un requis à même un type. Simple et efficace : une bonne idée.

Une fois les bases solidement en place, Bjarne Stroustrup pense qu'on sera mieux équipés pour attaquer les questions d'optimisation et autres.

Petite parenthèse sur la question de l'abus de shared_ptr<T>. On tend à passer par ce type pour des raisons irrationnelles (craintes?). Bjarne Stroustrup pense que les outils pourront nous guider à réduire le recours à cet outil à la fois nécessaire et surutilisé / mal compris. Il en profite pour mentionner des cas où un pointeur brut (mais sans responsabilité sur le pointé) est pertinent.

Les compilateurs devraient-ils imposer les règles? Bjarne Stroustrup pense que non, quand bien même ce ne serait que parce que les règles évoluent avec le temps, sont extensibles et parce qu'on ne veut pas de faux positifs. Par contre, il recommande de passer par la bibliothèque standard chaque fois que cela s'avère possible.

On ne veut pas que les novices doivent apprendre toutes les règles. C'est inhumain de demander ça à quelqu'un. Ce qu'on souhaite par contre est un accompagnement des programmeuses et des programmeurs par leurs outils, sur la base des règles. Des conseils naissant de l'analyse statique.

Bjarne Stroustrup se dit ambitieux, et souhaite changer la manière dont les gens (même ceux dans la salle ce matin) programment. Il ne souhaite pas un seul style de programmation, mais souhaite une disparition d'erreurs bêtes qui tiennent à des pratiques archaïques.

Selon Bjarne Stroustrup, le modèle de base de C++ est maintenant complet. Le langage est correct, Type-Safe et Resource-Safe étant donné de saines pratiques, tout en permettant d'aller plus bas quand le besoin s'en fait sentir. Pour construire l'édifice des saines pratiques communes et pour les mettre en pratique, il demande de l'aide de la communauté. On ne fera pas un  nouveau langage pour fracturer la communauté : le but est de « dompter la bête ».

Questions

Q : pourquoi voudrait-on un propriétaire pour une ressource?

R : trop de gens écrivent du code « à la C » où la gestion des ressources est manuelle et prête aux erreurs. Je souhaite faire disparaître ces considérations derrière des abstractions efficaces.

Q : à propos du type owner<T>, est-ce un truc qui influence le temps d'exécution?

R : c'est strictement statique et sans coût. On enrichit le système de types pour affirmer l'intention. Je mentionne au passage que l'analyse statique sur laquelle repose nos règles est locale et rapide, nous avons fait attention

Q : que se passe-t-il si on applique le mouvement à un non_null<T>? (belle question!)

R : je ne suis pas certain (c'est une classe écrite par Herb Sutter) mais nous en discuterons plus tard cette semaine. On ne peut briser la condition d'un non_null<T>

Q : que fait-on quand on interface avec une API de C?

R : je ne planifie pas écrire de règles en ce sens, mais je serai ouvert à des sections sur l'interopérabilité avec C, Java et d'autres langages d'une manière qui se prêterait à l'analyse statique.

Q : les règles touchent-elles aux concepts?

R : oui (il donne quelques exemples). L'une des règles fondamentales est de les utiliser!

Q : ceci invalide-t-il le livre C++ Coding Standards?

R : je ne sais pas, mais on ne va pas au même niveau dans nos règles que dans ce livre (Herb Sutter ajoute que les règles parlent de ce dossier)

Q : comment éviter la complexité que Rust a atteint dans la gestion des ressources?

R : en reposant beaucoup sur l'analyse statique et en mettant de l'avant de saines pratiques plutôt que des obligations langagières. La quantité de code C++ existant dépasse par plusieurs ordres de magnitude la quantité de Rust existant, on ne peut aborder les deux de la même manière

Q : adresse-t-on les questions de concurrence dans les considérations de responsabilité?

R : explique la philosophie dans les règles à ce sujet (ce sera plus intéressant à lire ici)

Q : a-t-on réfléchi aux particularités du calcul scientifique?

R : pour la finance, les calculs scientifiques et d'autres domaines spécialisés (systèmes embarqués, systèmes à basse-latence), nous avons des groupes d'étude qui réfléchissent activement à ce qui doit être fait. Dans les règles, nous avons une question spécifiquement sur l'arithmétique

Q : dans le domaine de l'aviation, nous avons appliqué les conseils de Herb Sutter sur les mots const et mutable, mais nous avons eu des difficultés avec les pointeurs intelligents...

R : je vais vous recommander de participer aux travaux sur la concurrence cette semaine. Nous sommes conscients de certaines de ces difficultés mais nous sommes actifs de ce côté. Des choses comme la détection statique et l'évitement d'interblocages; la recherche nous dit que c'est possible

Q : pourquoi non_null<T> quand on a T&?

R : parce que certaines conversions demandent des pointeurs pour l'instant. Sachez que nos débattons de références intelligentes présentement en vue de C++ 17, ce qui ouvrirait de nouvelles avenues, mais pour le moment les pointeurs demeurent nécessaires dans certains cas

Q : peut-on faire détecter certains de ces irritants par le compilateur plutôt que par un analyseur statique?

R : je préfère ne pas aller là. Je veux une compilation rapide

Q : devrait-on s'inspirer des règles de C# ou de Java?

R : je me concentre sur C++

Q : quel est le rôle des outils tiers d'analyse statique dans le futur selon vous?

R : je pense qu'il y a un marché là pour accompagner ce que les vendeurs de compilateurs nous donneront par défaut

Q : pour les références intelligentes, pourrons-nous surcharger l'opérateur .?

R : je le souhaite. On travaille là-dessus. Plusieurs utilisent des pointeurs intelligents là où il faudrait vraiment des références

Q : et la portabilité?

R : je ne souhaite pas que l'on commence à recommander une pratique pour supporter de vieux compilateurs et leurs bogues. Si votre compilateur est vieux, faites une mise à jour

Q : peut-on ajouter des trucs dans la bibliothèque standard qui remplaceraient des règles?

R : ça prend des années pour faire entrer un nouveau composant dans la bibliothèque standard. Nous voulons du C++ moderne aujourd'hui!

Q : comment voyez-vous les règles comme appui à l'enseignement?

R : j'aimerais beaucoup que les enseignants essaient d'adapter leurs pratiques à la hauteur des règles que nous proposons

Q : merci d'avoir fait de ceci un outils tiers; passer ces règles à travers un processus de revue pour fins de sécurité sera une tâche très complexe

R : oui, j'en ai eu vent. On ne veut pas obliger les gens mais on veut encourager les bonnes pratiques. Par défaut, ça devrait fonctionner. Herb Sutter ajouter que le site de la GSL permet de rapporter des problèmes et décrit les problèmes ouverts qui sont déjà connus

Q : dans cinq ans, aurons-nous encore des débats philosophiques sur « comment utiliser la GSL »?

R : je pense que oui. Notre communauté est une communauté vibrante et complexe

Q : existe-t-il un processus pour déprécier une règle qui ne serait plus à propos?

R : nous savons que nous en aurons besoin. Nous n'avons pas encore décidé comment nous gérerons cela

Fin du contenu technique

C'était intéressant tout ça. Le langage semble avoir atteint un seuil de maturité longtemps espéré. Bravo! Phrase lancée par Bjarne Stroustrup : « le compilateur ne lit pas la documentation, et moi mon plus ».

On se déplace vers la prochaine salle... Échange avec le toujours chic Michael Caisse et avec Gor Nishanov sur le chemin. Semble que le cours de Michael ait été un franc succès, avec 72 personnes dans la salle... Wow!

Pour voir sa présentation : https://www.youtube.com/watch?v=G96QYlsfy_o&feature=youtu.be

Sumant Tambe : Reactive Stream Processing in Industrial IoT using DDS and Rx.cpp

La salle est plutôt pleine, une belle surprise. Si vous êtes curieuses ou curieux d'en savoir plus à son sujet, son blogue est http://cpptruths.blogspot.com/ et pour votre information, IoT signifie Internet of Things (l'Internet des objets).

Début du contenu technique

Sumant Tambe demande aux gens présents s'ils sont familiers avec la programmation fonctionnelle. . La réponse de la salle est positive.

On parlera de systèmes réactifs, de l'IoT, de systèmes de distribution de données entre processus, des extensions réactives et de leur implémentation avec Rx.cpp. Une démonstration visuelle sera faite en fin de présentation.

L'Industrial IoT est ce qui touche aux Smart Cars, Smart Factories, Smart Transportation, etc. et des capteurs qui y participent, auxquels s'ajoutent le Cloud. On pense que c'est le volet industriel, plus que le volet domiciliaire, qui apportera 80% de la valeur du IoT.

Un système IoT industriel ne peut arrêter de traiter des données. Le calcul se fait sur la périphérie du système; il y a trop de données produites pour les envoyer dans le Cloud. Parle de Edge Computing, de Fog Computing.

La clé est d'être Responsive, Resilient, Scalable, Event-Driven. Le côté Event-Driven (messages asynchrones, faible couplage) est la clé; le Reactive Manifesto met cela de l'avant.

La concurrence est importante à ce modèle, mais ne suffit pas quand les besoins croissent; il faut y adjoindre un modèle de programmation. Sumant Tambe utilise DDS, un intergiciel réactif, un modèle d'abonnement (Publish-Subscribe), avec un bus de messages.

Le modèle de communication de DDS repose sur un Global Data Space, sorte de base de données clé / valeur répartie de triplets {domaine, sujet, clé}. Les abonnements et la publication sont découplés, les contacts reposent sur une forme de qualité de service, et on a la découverte automatique. DDS est implémenté dans plusieurs langages, dont C++. Sumant Tambe a choisi de ne pas utiliser l'API standard de DDS, pour privilégier les flux réactifs avec une approche fonctionnelle.

Les flux constituent une architecture reposant sur le mouvement continu de données. Sumant Tambe présente l'enchaînement de commandes avec tuyaux (Pipes) sous Unix à titre d'exemple.

Pour programmer, il modèle un réseau de pipelines décrivant des chemins de mouvement / traitement de données. Ceci maximise le débit parallèle du système et permet de séparer le traitement sur plusieurs machines.

Les extensions réactives sont le fruit des travaux d'Erik Meijer chez Microsoft. On parle d'une API asynchrone pour composer observables et ordonnanceurs. La composition implique des filtres, des sélecteurs, des agrégations (Reduce) , et des opérations associées à des moments dans le temps. L'ordonnanceur repose sur des mécanismes de contrôle de concurrence et des regroupements de threads. Les observables sont ce qui circule : tout prend des observables et retourne un observable. C'est très fonctionnel, très monadique

Un exemple C# est présenté, le design original d'Erik Meijer étant fait pour ce langage, et présente la dualité Pull / Push dans ce langage (IEnumerator<T> + IEnumerable<T> vs IObserver<T> + IObservable<T>)). Sumant Tambe fait ensuite le lien avec les futures de C++, puis avec rxcpp::observable<T>

Un exemple est proposé avec un observateur sur un observable reposant sur un intervalle de valeurs (évaluation paresseuse). L'observateur accepte un abonnement qui réagira à l'aide de λ sur la base de la signature des rappels. Sumant Tambe ajoute ensuite des map et des filter pour enrichir le traitement réalisé. Sa démonstration est animée avec http://rxmarbles.com/, c'est très bien et ça ressemble aux schémas que l'on utilise en première session au cégep pour expliquer les expressions relationnelles. Enfin, il ajoute des objets représentant des moments (std::chrono::seconds{2} par exemple) et introduit un élément de réaction au passage du temps dans le modèle. La combinaison de plusieurs sources génère un tuple.

S'ajoute RX4DDS, truc multilangage pour intégrer flux et réactivité. Tout ce qui produit des données est un observable. DDS distribue les données, Rx assure le traitement. Sumant Tambe présente un tableau décrivant la force de l'architecture résultant de la conjonction de ces deux outils, puis donne une démonstration interactive.

Truc amusant : faute de pouvoir surcharger l'opérateur ., Sumant Tambe a surchargé l'opérateur >> dans certains cas et nous invite à le voir comme une sorte de .

Il construit un flux de données qui filtre tout ce qui est mauvais et vante le fait que le fruit du traitement est un flux de données « propres » et directement utilisables.

Il parle de « l'opérateur » tap qui pige des données du flux et affiche tout ce qui en sort. Son exemple est monadique : il a des formes géométriques, et les transformations sont de retourner une forme comme celle reçue en paramètre mais juste un peu plus loin.

Sumant Tambe fait un commentaire éditorial sur les abus du mot clé auto. James McNellis serait content!

Autre exemple, plus complexe, avec plusieurs formes concurrentes. Intéressant, et met en relief l'indépendance de plusieurs entités actives malgré un lien positionnel entre certaines d'entre elles. Ensuite, il montre l'impact de retirer un objet duquel d'autres « dépendaient » (faible couplage!)

Étape suivante : grouper des observables pour qu'ils aient un comportement cohérent. Ça donne des enchaînements complexes mais ça se lit bien (on voit le pipeline « à l'oeil »).

Sumant Tambe ajouter un corrélateur dynamique. Il place plusieurs carrés, et insère un triangle dont la position s'adapte dynamiquement pour être la moyenne de celle des carrés. Il montre l'adaptation dynamique du triangle au nombre de carrés et à leur mouvement (ou non).

Il termine avec des recommandations éditoriales. L'une d'elles est charmante : les types sont la meilleure documentation.

Questions

Q : le modèle de verrous est-il Real-Time Safe?

R : je ne pense pas que ce soit le cas. Il faudrait un mécanisme d'inversion de priorités au niveau du système d'exploitation

Q : quel est le poids de cette approche?

R : je ne sais pas, il faut mesurer. Pour Rx.cpp, il n'y a pas nécessairement d'appels indirects (c'est optionnel avec as_dynamic). On évite std::function quand on évite as_dynamic

Q : avez-vous fait des Benchmarks?

R : j'ai de bons résultats côté débit de production, même avec un seul thread, en C# (la personne qui a posé la question trouve que les chiffres sont plutôt bas, en fait)

Q : a-t-on vraiment besoin de DDS si on n'utilise qu'une seule machine? Est-ce modulaire?

R : Rx.cpp ne dépend pas de DDS, mais mes travaux visent leur intégration

Q : (moi) à la diapo 48, pourquoi n'a-t-on pas de conditions de course?

R : explication claire. Bien.

Petite conversation avec Sumant Tambe sur certaines considérations plus près du IoT. Sa présentation était excellente pour l'approche réactive, mais plus mince sur l'aspect massivement réparti, faibles ressources par noeuds du IoT. en gros :

Ce fut intéressant, cela dit. Ça valait la peine

Fin du contenu technique

Petite jasette avec Alex Boulanger et Félix-Antoine Ouellet, qui semblent avoir apprécié leur matinée. On bavarde sur la présentation de Bjarne Stroustrup qui les a laissés un peu perplexe quant à ce qui est vraiment visé, et sur les présentations auxquelles ils ont participé. Je mange rapidement mon wrap, j'achète un livre qui était sur ma liste dans Amazon (petite folie), et je fonce vers la présentation suivante, à laquelle j'arrive en retard.

Sa présentation n'a pas été enregistrée (je pense que c'est la seule de la conférence dans cette situation)

Jon Kalb : C++ Today: The Beast is Back

Nous sommes dans une salle de type « théâtre ». Je trouve une prise de courant dans une allée et je m'asseois en pente. On parle d'une présentation de type « contenu ouvert », qui n'a pas la prétention d'être aussi rigoureuse que celles plus standards qui nous sont proposées dans le reste du colloque.

Début du contenu technique

Jon Kalb donne une présentation enlevante sur le rôle de C++ dans un contexte historique. Il parle du volet POO, populaire dans les années 90, de l'avènement de la STL et du rôle des principaux acteurs politiques dans ce dossier Andrew Koenig, Alex Stepanov), de l'avènement de Boost et du rôle de Beman Dawes, etc. Puis, l'impact de Java sur C++, alors que Java se présentait comme une alternative plus moderne à C++.

Intéressant impact : au début des années 2000, le côté glamour de Java a découragé bien des gens, et le comité de standardisation de C++ a vu sa taille se réduire. Ce qui a sauvé C++ est, du moins en partie, le contrôle sur les paramètres d'exécution (vitesse, consommation d'énergie, consommation de mémoire, etc.) avec la multiplication des appareils mobiles. La productivité du programmeur avec des composants tout faits mais suboptimaux est redevenue secondaire face aux besoins du nouveau matériel.

Arrive C++ 11. Un gros coup, incluant une simplification du langage et un accroissement de la productivité. Un autre gros truc fut Clang, avec LLVM, une compétition extrêmement sérieuse pour les compilateurs existants. Comme le rappelle Jon Kalb, Clang est bien plus qu'un compilateur : c'est une boîte à outils de laquelle surgissent des tas d'outils merveilleux. Tous bénéficient de Clang, que nous l'utilisions ou non, grâce à l'impact de la compétition. Après C++ 11, le comité de standardisation a grossi plutôt que rapetisser.

Herb Sutter a ensuite mis de l'avant que le comité de standardisation a pour rôle de standardiser, pas de promouvoir, et a mis sur pied https://isocpp.org/ qui fait un excellent travail en ce sens.

Jon Kalb présente ensuite des statistiques démographiques sur la communauté de programmeuses et de programmeurs C++, et parle de nouveaux projets intéressants (http://cppcast.com/, http://en.cppreference.com/w/, https://www.jetbrains.com/clion/ et d'autres) de même que les groupes d'usagers et les colloques comme CppCon ou Meeting C++ (dont s'occupe Jens Weller).

Fin du contenu technique

La séance de questions / réponses est plus amusante que pertinente, car l'audience est plus convaincue que critique et le propos était plus historique que technique. Jon Kalb ne se cache pas pour ce qui est du facteur d'attraction qui tient au fait que C++ est le langage pour écrire les jeux les plus sophistiqués; même dans la tempête, cette réalité est demeurée.

Pour voir sa présentation : https://www.youtube.com/watch?v=8KIvWJUYbDA

Pour voir les diapos de sa présentation : http://schd.ws/hosted_files/cppcon2015/72/Memory%20and%20C++%20debuging%20at%20EA%20-%20Scott%20Wardle%20-%20CppCon%202015.pptx

Scott Wardle : The Current Memory and C++ Debugging Tools Used at Electronic Arts

Michael Wong est présent; j'en profite pour bavarder avec lui et m'assurer de préparer le nécessaire pour mercredi. C'est d'ailleurs à lui que revient la tâche de « présenter le présentateur », qu'il a rencontré à CppCon 2014 quand on a demandé qui était canadien dans la salle. On aura donc la première présentation du monde du jeu pour CppCon 2015. Scott Wardle est surtout connu pour son travail sur la série Thief, que mon adorable et adorée épouse Za aaime beaucoup.

Début du contenu technique

Scott Wardle parlera de l'histoire des outils de débogage dans le monde du jeu, pour montrer ce qui se faisait avant et ce qui se fait maintenant, avec le changement des consoles et l'évolution des technologies. Il se présente comme fortement dyslexique.

Il parlera d'allocation de mémoire, d'arénas et de tas. Sa définition d'aréna est un ensemble d'intervalles d'adresses dans lequel on peut allouer de la mémoire.

En 2000, la STL n'était pas utilisée, il n'y avait pas de véritable mémoire virtuelle sur une console (un pur système embarqué), 32 Mo de mémoire vive. On définissait l'allocation de mémoire à l'aide de macros insérant des méthodes une classe à la fois. Déboguer impliquait passer un nom et des fanions à new pour qu'il soit possible de repérer l'aréna d'origine (par son nom). La mémoire disponible était essentiellement un seul gros tas. Un allocateur de petits blocs accompagnait tout cela, et on se battait fort contre la fragmentation de la mémoire... Tout allait bien avec un seul processeur.

Avec la XBox 360 et la PS3, les consoles se sont mises à supporter plusieurs coeurs et il a fallu repenser les pratiques. Il a fallu utiliser plusieurs allocateurs, incluant des allocateurs avec estampillage, un suivi de la mémoire allouée (avec EASTL). Ils utilisaient un allocateur polymorphique lors du new, mais le delete était désagréable à utiliser (des macros et tout le tralala; ils font encore ça aujourd'hui). Les tas et les arénas sont alors découpés en fonction :

La fragmentation rend le découpage par équipes périlleux... Quand un problème survient, à qui la faute?

Ils utilisent un tas distinct pour l'information de débogage, pour éviter que la corruption de mémoire dans le jeu ne salisse les infos de débogage justement. Le tas de débogage est occasionnellement sérialisé sur disque, et le fichier résultant est analysé par des outils externes pour visualiser en temps réel l'état de la situation. On peut alors voir :

Pour les allocateurs d'estampillage, chaque page allouée est estampillée pour faciliter le dépistage de corruptions de mémoire, ce qui est particulièrement utile pour les consoles en fin de vie, quand les ressources se font rares.

Scott Wardle explique la douleur des pointeurs avec sémantique de partage (trop facile de créer des cycles), et souligne qu'un bon outil de diagnostic aiderait (sinon, un moteur de collecte d'ordures...)

Avec EASTL, dont une version de 2010 est disponible à travers WebKit, Scott Wardle estime qu'il y a, encore aujourd'hui, des cas d'utilisation pour lesquels cette version « maison » donne de meilleurs résultats que la STL. Ils vont publier EASTL en code ouvert. Scott Wardle indique qu'une des raisons pour lesquelles ils sont plus rapides est qu'ils font beaucoup de copier / coller, car dans leur code l'inlining est difficile à réaliser pour un compilateur. Ils ont eu les mêmes problèmes d'effacement de types pour les allocateurs dans les conteneurs, du fait que l'allocateur fait partie du type. Pour résoudre leurs ennuis, ils ont changé l'ordre des paramètres dans leur propre implémentation et pallié les irritants avec des macros

Aujourd'hui, ils ont plus de mémoire, des disques rigides, des registres 64 bits, beaucoup de mémoire virtuelle... Alors il est temps de revoir les mécanismes de débogage et de gestion de la mémoire. Ils utilisent des objets représentant des portées, et utilisent plus de mémoire locale aux threads. Ils permettent de vérifier l'aréna dans laquelle un allocateur pige sa mémoire, et faire allouer d'autres objets au même endroit. Ça laisse des questions ouvertes (p. ex. : que faire quand l'objet est alloué sur la pile? Il y a un coût à tout ce suivi... Que faire avec le mouvement?)

Côté outils, Scott Wardle présente leur outil nommé Delta Viewer, et explique les caractéristiques clés des diagnostics que cet outil permet de réaliser. Entre autres : grouper les données par zone de mémoire, représenter l'allocation sur une ligne du temps, intégrer avec un outil de profilage, etc. Leur profilage permet d'évaluer la charge de travail par thread et par trame d'affichage, tout en ciblant les trames plus coûteuses pour mieux comprendre ce qui les cause. Se superposent à ces données les appels de fonctions, présentées visuellement.

La combinaison de multiples vues permet de comparer des sources possibles de problèmes (décompression de données, accès disques, application d'une texture, etc.). Scott Wardle fait remarquer qu'encode aujourd'hui, une partie importante de l'exécution d'un jeu dépend du processeur plutôt que du GPU. Un affichage par processeur est possible.

Pour dépister les fuites, Scott Wardle parle de repérer les débuts et les fins de scènes puis de voir ce qui n'est pas libéré lors du passage de l'une à l'autre. Leur outil permet, par l'identification des allocateurs, de repérer qui fait quoi, et de voir (par exemple) la charge de travail des allocateurs de petits, moyens et gros objets à travers le temps.

Un constat : généralement, dans un jeu, il y a peu de code, beaucoup de données.

C'était extrêmement pertinent pour moi, cette présentation. Ça touche directement à plusieurs de mes cours, et à ce que je fais au quotidien.

Questions

Q : allez-vous livrer le profileur en version à code ouvert? C'est très chouette!

R : j'en doute. Peut-être un jour

Q : pourriez-vous publier une vidéo dont on pourrait s'inspirer?

R : j'en doute. Ça prend de très gros écrans (beaucoup de données)

Q : pouvez-vous utilisez les pointeurs intelligents standards?

R : on a nos propres versions pour EASTL

Q : vous nous avez dit que la STL est beaucoup plus lent que EASTL en mode Debug. Avez-vous examiné le niveau de débogage des itérateurs?

R : on débranche tout ça

Q : avez-vous des chiffres sur les bogues que ces pratiques vous ont épargné?

R : non. L'allocateur avec estampillage est miraculeux, par contre

Q : avec EASTL, quelles sont les décisions qui vous ont apporté ces gains de vitesse?

R : je ne me souviens pas de tout, mais on dépend moins d'inlining et plus de copier / coller. On a aussi plus de pointeurs bruts et moins d'itérateurs représentés par des objets

Q : avez-vous beaucoup de conteneurs intrusifs? Chez nous, à Blizzard, on se bat avec une map intrusive et c'est difficile à bien implémenter

R : je pense qu'on n'a que list

(Michael Wong rappelle que SG14 est intéressé aux conteneurs intrusifs)

Q : à quel point le suivi possible par vos outils ralentit-il l'exécution?

R : je ne peux pas tout activer en même temps, mais c'est plus rapide que je ne l'aurais cru de prime abord. Je perds peut-être 10%, ce qui est étonnant dans les circonstances

Q : combien de temps investissez-vous dans le développement d'outils plutôt que dans le développement de jeux?

R : très peu. C'est une des raisons pour lesquelles on utilise des moteurs tout faits : les outils viennent avec

Q : est-ce que vous utilisez vos journaux d'exécution pour identifier les régressions dans le temps avec les mises à jour?

R : oui, mais on fait nos choix par équipe

Fin du contenu technique

Ouf, c'était bon ça! Ça sent le travail pratique pour mes étudiant(e)s!

En allant aux toilettes, j'ai croisé Paul McKenney et j'en ai profité pour lui dire à quel point je suis curieux de savoir ce qu'il compte nous révéler à propos de memory_order_consume plus tard cette semaine. Il l'a trouvé drôle et on s'est serrés la main. Si vous ne savez pas de quoi je parle, sachez que c'est un sujet tellement complexe que même pour des experts (dont je fais partie ici), c'est tout juste sur la frontière de la magie noire.

Pour voir sa présentation : https://www.youtube.com/watch?v=lVBvHbJsg5Y

Fedor Pikus : Live Lock-Free or Deadlock (Practical Lock-Free Programming), part I

Le sujet de la programmation sans verrous est sûrement l'un des plus délicats qui soient. On va se gâter cet après-midi.

Début du contenu technique

Fedor Pikus présente le plan de match. Il est chargé. Pour faire exprès, un de ses programmes a planté en début de présentation et on s'est tous bidonnés. La salle est pleine.

On parle ici de programmation concurrente et de saines pratiques dans les applications de tous les jours. Il vise l'exactitude mais pas toujours la précision, dans une optique pragmatique.

Il mentionne d'office que dans sa compagnie, le parallélisme sur des milliers de coeurs est normal, avec des milliards d'objets. Le coût d'une erreur est de l'ordre de 100 M$, et plusieurs de leurs clients sont tels que C++ 11 n'est pas une option (ils utilisent de trop vieux systèmes d'exploitation).

Écrire du code sans verrous est difficile. Écrire du code sans verrous corrects est plus difficile encore. Faut s'y mettre seulement s'il y a un besoin mesurable, et mesuré

On veut aller plus vite. Faut toujours, toujours, toujours mesurer (règle #1)

Petite note sur les atomiques de C++ 11 :

Petite mention de la concurrence par analogie avec la signalisation pour la circulation. Il aborde ensuite le Double-Checked Locking, avant et depuis C++ 11, sur la base d'un singleton dynamique. Il analyse l'initialisation des variables statiques (initialisées par l'éditeur de lien, traditionnellement). Pour un pointeur, le test (pointeur est nul?) et sa conséquence (l'initialiser) ne sont pas atomiques, un TOCTTOU classique. Il montre une solution qui fonctionne (verrouiller systématiquement les accès) mais qui coûte cher. Il montre le Double-Checked Locking classique, qui ne fonctionne pas avant C++ 11 de manière portable. Il découpe ensuite l'initialisation de deux manières :

Il montre toutefois que l'ordre suivant est aussi possible :

Il montre ensuite qu'on peut tricher le compilateur en écrivant le code manuellement, mais nous montre que le compilateur peut nous déjouer. Autre manoeuvre, travailler avec un pointeur volatile. Ouf. Malheureusement, une fois le code généré, le concept de volatile disparaît alors le processeur peut nous déjouer.

On fait entrer les variables atomiques, et le singleton qu'il cherche à présenter devient un pointeur atomique. Ça semble beau, mais malheureusement, arrive la Cache. Les atomiques, sans le modèle mémoire de C++ 11, ne sont pas séquentiellement cohérentes. Le matériel nous déjoue, et deux processeurs peuvent voir les opérations dans deux ordres différents.

Comment fonctionnent les verrous alors? Fedor Pikus présente les clôtures mémoire. Il n'y avait pas de clôtures mémoire portables dans le langage avant C++ 11. Fedor Pikus se limitera aux clôtures Acquire et Release, mais il en existe d'autres :

Le recours aux clôtures dépend du fait que les deux processeurs touchés doivent générer les clôtures, sinon ça ne donne rien. Faut un AcquireLoad(x) et un ReleaseStore(x) sur le même x.

La programmation sans verrous est 90% une question de visibilité de la mémoire et d'ordre des accès. Les opérations atomiques sont la partie facile (ouch!). La programmation sans verrous est une question d'ordonnancement des opérations sur la mémoire : qu'est-ce qui est visible, et quand

Avec C++ 11, le Double-Checked Locking est moins pertinent (les variables statiques sont initialisées de manière Thread-Safe). Toutefois, Fedor Pikus souligne que le Double-Checked Locking ne sert pas vraiment à l'initialisation des singletons; son vrai rôle est de gérer les cas rares ou exceptionnels de manière efficace. Et si typiquement, le cas exceptionnel ne peut plus survenir une fois une certaine étape franchie dans l'exécution du programme, en pratique le cas exceptionnel peut survenir plusieurs fois.

Son exemple est :

Un cas illustratif simple est l'allocation dynamique de mémoire : reste-t-il de la mémoire? Si oui, on essaie de l'allouer, mais il se peut qu'il n'en reste plus...

Fin du contenu technique

On prend une pause; après la pause, on abordera le code sans verrous avec une file.

Pour voir sa présentation : https://www.youtube.com/watch?v=1obZeHnAwz4

Fedor Pikus : Live Lock-Free or Deadlock (Practical Lock-Free Programming), part II

Jasette avec Félix-Antoine Ouellet sur divers sujets techniques, sur la vie, sur sa carrière, etc.

Début du contenu technique

Fedor Pikus présente une file d'attente sans verrous, plusieurs producteurs et plusieurs consommateurs. Tous les producteurs compétitionnent pour insérer, tous les consommateurs compétitionnent pour extraire.

Ça s'écrit bien avec des verrous, évidemment. Le problème, c'est que c'est terriblement inefficace.

Fedor Pikus enlève les verrous. C'est truffé de conditions de course.

Il ajoute un compteur atomique de la taille de la file. On n'a rien gagné.

Fedor Pikus recommande de penser en termes de transactions. L'outil clé est CAS (Compare and Swap). Cette fonction permet d'implémenter tous les algorithmes sans verrous. Il explique comment ça fonctionne.

Il montre par la suite que boucler sur un CAS ressemble drôlement à un verrou (c'est un SpinLock). Fedor Pikus remet de l'avant l'analogie avec les autoroutes, où les voitures peuvent rouler même si d'autres tournent dans l'espoir de faire leur entrée en toute sécurité. Il code un SpinLock avec un entier atomique et un AtomicExchange.

Un programme est Wait-Free si les threads se complètent tous dans un temps maximal connu a priori. Un programme est Lock-Free s'il n'a pas de verous et si un thread est toujours en train de progresser. Un programme est Obstruction-Free si un thread progresse dans la mesure où personne d'autre ne touche à des données que les deux partagent.

Les programmes munis de verrous peuvent subir de l'interblocage. C'est très vilain, et on ne sait pas toujours qu'on en cause : ça peut survenir bêtement parce qu'on appelle des fonctions tierces; ça peut survenir dû à un signal survenant, par exemple, pendant un malloc() où on a (indirectement) verrouillé quelque chose et dans le traitement duquel on aurait alloué de la mémoire – par exemple, en appelant printf(). Fedor Pikus parle de Convoying, où les verrous sont pris dans un même ordre par tous les threads, mais explique que cela peut ralentir les threads les plus rapides.

Fedor Pikus fait remarquer que (a) sans verrous ne veut pas nécessairement dire plus rapide, et (b) il existe d'autres verrous que les mutex. Toutefois, en pratique, le code sans verrous peut être plus simple (et plus rapide) que le code avec verrous.

Problème concret : comment incrémenter deux entiers 64 bits de manière atomique? Fedor Pikus propose quelques avenues (un CAS 128 bits, parfois disponible; un algo subtil avec un troisième entier et CAS, etc.) mais mentionne qu'il est souvent plus rapide de... ne pas incrémenter atomiquement les deux entiers! Par exemple :

La complexité de ce type de solution peut croître, alors mieux vaut être prudents. Aussi, on ne peut pas se permettre de telles manoeuvres si on écrit une bibliothèque générique. Fedor Pikus suggère de simplifier le problème, de viser des solutions spécifiques. Dans son expérience, une liste générique sans verrous n'est typiquement pas plus rapide qu'une std::list protégée par un SpinLock. Dans la programmation sans verrous, la connaissance des détails du problème permet de battre le code générique.

Fedor Pikus recommande d'écrire des structures de données sans verrous plutôt que des algorithmes sans verrous. Il dit aussi que pour démontrer qu'un tel programme est correct, il vaut mieux en réduire la portée à quelque chose de simple et de bien défini.

Une autre approche qu'il propose est d'ajouter aux éléments une liste de pointeurs sur les éléments pour alléger certaines opérations.

Fedor Pikus rappelle que ce qui ralentit les programmes est le partage de données. Il montre des chiffres et ça fait peur. Un graphique montre très visiblement les passages de Cache L1, L2, L3 et à la mémoire vive (de beaux plateaux). Il montre entre autres que sur sa machine à 128 coeurs, il suffit de deux threads qui écrivent à temps plein pour saturer le bus de données. Une des raisons pour lesquelles la synchronisation par verrous coûte plus cher est qu'elle implique, par définition, au moins une autre variable partagée en écriture (le verrou).

Fedor Pikus revient sur std::queue et demande ce qi'il faut faire pour le rendre Thread-Safe. Suffit-il d'ajouter un mutex et de le verrouiller dans chaque méthode? Insuffisant (comportement indéfini lors du pop() à cause du TOCTTOU entre le test pour voire si le conteneur est vide et le retrait effectif de la valeur). Le problème est l'interface du conteneur, qui ne convient pas au problème : le pop() doit être transactionnel et nous dire si le tout a fonctionné ou non.

Fedor Pikus nous rappelle qu'en situation de concurrence, poser la question « A s'est-il fait avant B » implique sérialiser les opérations. Le problème est « que signifie 'avant'? ». Même le return d'un pop peut entraîner un délai et changer la perception d'ordre des opérations du point de vue du code client! Il ne faut pas baser notre perception de « correct » sur la base FIFO (First In, First Out) avec une file concurrente, avec ou sans verrous d'ailleurs. Dans ses mots : « si votre programme concurrent dépend d'un ordre d'extraction total, les attentes de votre programme sont incorrectes ».

Il y a de la résistance de la foule sur ce point, un peu comme quand je tiens le même discours en lien avec ma thèse : cette réalité des systèmes répartis échappe à bien des gens, incluant bien des spécialistes. Paul McKenney ajoute que dans certains cas, sur la base de données empiriques on a même de « meilleurs » ordonnancements en sortie pour des files faiblement ordonnancées que pour des files fortement ordonnancées, contrairement à une espèce d'intuition un peu fausse mais qui semble raisonnable en surface. Le propos reste la même : ne comptez pas là-dessus; c'est une présomption incorrecte.

Fedor Pikus nous l'annonce : on ne peut pas échapper à ce destin. Mieux vaut l'apprécier pleinement ». La « simultanéité » est imperceptible (si elle existe), même entre deux verrous. Enfiler peut même échouer, alors mieux vaut y penser dans l'interface de la file. Il suggère que si Enfiler échoue, c'est probablement qu'on est plus rapide pour produire que pour consommer, mais mentionne qu'une solution simple est alors de transformer dynamiquement un (ou plusieurs) producteur(s) en consommateur(s).

Devrait-on reprendre la recherche du dernier point accédé (en ajout / en suppression)? Ça dépend, car ça implique des variables accédées concurremment, alors il faut essayer; si on part systématiquement de la position zéro, tous les threads vont collisionner là alors c'est pas terrible; si on part d'un indice par thread, ça prend une variable locale au thread un accès de l'ordre de 40 nanosecondes dans son expérience.

Une question de la salle : pourquoi utiliser une file alors? Mais la clé est d'avoir des attentes convenables étant donné le contexte. S'attendre à FIFO est mal définir le problème; en pratique, on ne l'aura pas.

Fedor Pikus revient sur le Double-Checked Locking : si une file (implémentée sur un tableau) doit croître en taille, on a un cas de Stop The World entre les mains (sauf dans un système en temps réel). C'est le type de cas rare et subtil pour lesquels le Double-Checked Locking a été pensé.

Questions

Q : pourquoi ne pas tirer le point de départ d'une recherche dans la file au hasard?

R : le démarrage des threads est aléatoire de toute manière (aussi, générer un nombre pseudoaléatoire est plus lent que le traitement requis pour chercher une position)

Q : avez-vous essayé d'y aller dans une autre direction, soit avoir la moitié des threads qui partent de la fin et l'autre moitié qui part du début?

R : je n'ai pas essayé, faudrait le mesurer

Q : il me semble que le problème n'est pas propre aux files

R : en effet. C'est un problème de structures de données concurrentes en général

Q : si on a plusieurs producteurs et un consommateur, aura-t-on un modèle FIFO?

R : posez-vous la question suivante : si cette supposition ne tient pas, pourriez-vous le détecter? (oh, que j'aime cette réponse!)

Q : le SpinLock présenté pourrait-il causer un interblocage, puisqu'il n'avait pas de yield?

R : techniquement, non, on ne peut pas causer d'interblocage sur un seul SpinLock. On peut avoir une anomalie d'ordonnancement, mais outre ce genre de bogue d'ordonnanceur, on aura éventuellement le verrou. En pratique, pour être efficaces, il faudra insérer un mécanisme de yield approprié pour la plateforme, surtout en situation de forte contention (il relate un comportement particulier de Linux qui peut mener à une anomalie).

Q : la mémoire transactionnelle peut-elle régler ces problèmes?

R : ça permettrait de le faire exécuter plus rapidement, mais il y a plus sous la couverture à expliquer que ce que je peux faire ici dans le temps que nous avons. On aurait besoin de moins de verrous, surtout si le support à la mémoire transactionnelle est matériel.

Fin du contenu technique

Ouf et re-ouf : nous avons été gâtés côté contenu cet après-midi. Juste pour cette journée, ça valait le prix d'entrée, et la semaine commence à peine...


Enfin, j'ai quelques minutes pour appeler mon amoureuse, prendre de ses nouvelles, des nouvelles des enfants. Ma famille me manque. Heureusement, ça vaut vraiment la peine ici.

Vers 19h50, je m'installe pour le panel. Herb Sutter joue (très bien) du piano pour accueillir les gens. La salle est beaucoup moins pleine qu'en après-midi, mais en même temps, ce fut une grosse journée et il y a sûrement des gens qui sont allés se reposer. Je dois avouer que ça m'a aussi tenté (évidemment, je suis ici pour tirer le maximum de l'expérience alors je suis resté fidèle au poste).

Pour voir ce panel : https://www.youtube.com/watch?v=PqU_ot4BlNQ

Panel : Grill the Committee

On bavarde un peu avec le très chic John McFarlane en attendant que ça commence. Jon Kalb nous informe que tout joueur de piano peut, comme Herb Sutter, profiter du piano sur place dans la mesure où il s'inscrit au préalable.

Début du contenu technique

Jon Kalb présente les membres du comité sur la scène, et les identifie un à un :

Jon Kalb demande à Michael Wong pourquoi on serait membre de WG21. Est-ce pour aller à Hawaii?

Michael Wong : imaginez aller jusque là bas, et vous enfermer dans une salle pour ne voir que des néons pendant une semaine...

Marshall Clow : c'est exactement ce qui se passe : « Na na, je suis à Hawaii et pas vous », suivi d'une photo d'une pièce sans fenêtres pleine de gens avec des laptops

Chandler Carruth : la plupart des suppositions des gens à propos de WG21 sont fausses

Richard Smith : les gens pensent que c'est des vacances, mais en pratique c'est six jours consécutifs de travail 12 à 14 heures par jour. C'est épuisant

Gabriel Dos Reis : la première fois que j'y ai participé, je pensais que c'était des vacances. À Hawaii, je n'ai jamais vu la plage de jour

Beman Dawes : je pense que les programmeuses et les programmeurs C++ comprennent mieux aujourd'hui ce que fait vraiment le comité. Nous faisons un meilleur travail pédagogique aussi

Herb Sutter : faut aussi savoir qu'on ne va à Kona qu'une fois aux quatre ans environ. Les gens pensent que nous sommes une équipe de design, que nous préparons un produit, mais c'est faux. On s'en rapproche grâce à Bjarne Stroustrup, Ville Voutilainen et les autres responsables des groupes de travail, mais en pratique on examine de près une longue liste de propositions pointues et nous essayons d'harmoniser le tout

Bjarne Stroustrup : il y a plusieurs présomptions erronnées. Plusieurs programmeurs ne savent même pas que WG21 existe; plusieurs autres nous prennent pour des idiots malicieux et vendus car nous ne faisons pas ce qu'ils veulent. Les gens sur la scène ne couvrent pas l'une des six équipes de WG21 qui travaillent en parallèle lors de ces rencontres

Ville Voutilainen : je dirais que les deux principales conceptions erronnées sont (a) que C++ est du « design par comité », alors que nous ne faisons par vraiment de design, et que (b) nous vivons dans une tour d'ivoire

Lawrence Crowl : la principale supposition erronée est que le comité a « un plan » (an Agenda), alors que nous travaillons à partir de ce qui nous est apporté

Bjarne Stroustrup : je pense que la plupart des membres de WG21 ont « un plan », mais que ces plans ne concordent pas vraiment

Lawrence Crowl : ce qu'on a de commun est le souhait de régler des problèmes

Herb Sutter : le gens pensent qu'ils peuvent nous envoyer une suggestion et qu'on va le faire, que c'est évident, puis sont surpris que leur proposition esquissée sur quelques pages n'est pas prise en charge et mise en application rapidement. Nous apprécions les propositions et les gens qui viennent devant le comité pour faire évoluer le langage, cela dit

Chandler Carruth : les gens pensent que les membres du comité sont là par magie. Pourtant, il est possible de joindre le comité, vous pouvez essayer

Jon Kalb : combien êtes-vous payés pour participer au comité?

Chandler Carruth : un gros nombre négatif

Bjarne Stroustrup : pour être sur le comité, il faut payer (aux É.-U.) 1280$ par an, et ce pour venir travailler. Les jours sont longs, le travail est bénévole, mais nous pensons que nous faisons quelque chose de signifiant. Nous essayons d'être ouverts et accueillants, nous ne travaillons pas à huis-clos

Beman Dawes : le comité de standardisation de C++ est en pratique un très gros processus à code ouvert

Gabriel Dos Reis : qui peut voter sur le comité?

Bjarne Stroustrup : il n'y a pas de standard pour écrire un standard. Quand WG21 se réunit, nous nous séparons en groupes dans cinq à huit salles, plus des groupes d'étude plus informels. Des votes informels sont pris à certains endroits, de la forme SF-F-N-A-SA (où SA signifie over my dead body) et nous prenons nos décisions par consensus, sinon les gens vont créer des dialectes et il faudra tout recommencer. Une fois que nous avons atteint un consensus par petits groupes, nous prenons un vote collectif en grand groupe mais à ce moment, il y a peu de frictions, le travail de terrain ayant été fait. Et oui, nous commençons au déjeuner et nous terminons parfois après minuit

Michael Wong : il y aura une rencontre officielle de SG14 mercredi. SG14 est un groupe d'étude de WG21, alors les curieuses et les curieux pourront venir assister à nos débats

Bjarne Stroustrup : pendant cette rencontre, vous voudrez aussi participer à d'autres rencontres, ce qui est typique de WG21 où plusieurs choses passionnantes se produisent en même temps.

Q : je travaille avec plusieurs langages et je m'intéresse à l'interopérabilité entre les langages. Je constate que plusieurs gens se refusent d'utiliser des caractéristiques plus évoluées de C++ pour faciliter l'interopérabilité avec d'autres langages. Pensez-vous que la communauté pourrait poser des gestes pour faciliter l'interopérabilité binaire entre les langages malgré tout?

Lawrence Crowl : plusieurs choses dans le standard de C++ ont été ajoutées pour aider en ce sens. Les références interfacent très bien avec Fortran, par exemple. Il nous manque extern "fortran" pour finir le travail. On pourrait en arriver à quelque chose de semblable avec d'autres langages, p. ex. : extern "java". Nous aimerions avoir une proposition en ce sens. Évidemment, qui peut interopérer avec C peut aussi interopérer avec C++.

Chandler Carruth : le défi selon moi est la correspondance des types, et le système de types de C++ est particulièrement riche. La solution typique est de descendre vers un dénominateur commun, et celui-ci tend à être C. Couvrir tous les cas à un plus haut niveau est sans doute faisable, mais me fait peur.

Bjarne Stroustrup : pour ceux parmi nous qui apprécient les abstractions de haut niveau, ce problème d'interopérabilité est un irritant, mais il est difficile pour WG21 de régler ce problème. Il nous faudrait une proposition de mapping entre langages pour travailler.

Q : dans les dernières années, plusieurs propositions ne sont ni acceptées, ni suivies, et tombent un peu dans l'oubli. Y a-t-il un processus pour savoir ce qui arrive à ces propositions?

Ville Voutilainen : il existe une Evolution Issues List disponible dans Internet pour faire un suivi. Dans le cas qui vous intéresse spécifiquement ici, si ma mémoire est bonne, une approche alternative nous avait semblé supérieure

Herb Sutter : il n'y a pas de processus de retrait. Une proposition ne prend effet que si elle est acceptée

Ville Voutilainen : il nous arrive aussi de prendre une proposition et de la marquer comme Not a Defect

Bjarne Stroustrup : une question à se poser est « pourquoi cette proposition serait-elle l'une des vingt choses les plus importantes que nous pourrions faire pour le prochain standard »? Et pourquoi? Intégrer un nouvel élément au standard demande beaucoup de travail.

Ville Voutilainen : on traite en moyenne 45 demandes à chaque rencontre pour neuf rencontres, et ce seulement pour EWG

Q : qu'advient-il de restrict?

Michael Wong : nous analysons le besoin et dans ce cas, nous avons une proposition sur la table qui couvre les particularités de C++ qui sont plus riches à bien des égards que celles de C. Pour la question précédente, j'aimerais ajouter que parfois, une proposition « oubliée » reprend vie ou mène à un renouveau d'intérêt des années plus tard, pour différentes raisons.

Ville Voutilainen : pour restrict, la proposition est passée à travers EWG et s'en va à Core

Bjarne Stroustrup : la proposition de noalias ne peut être reçue, mais nous avons une meilleure solution

Q : à propos des systèmes embarqués, que pouvons-nous faire pour que C++ demeure pertinent malgré les restrictions?

Bjarne Stroustrup : selon moi, le dialecte Embedded C++ ne devrait pas exister. Cette chose a été poussée par des gens qui n'arrivaient pas à implémenter un compilateur pour le langage dans un délai raisonnable. Le langage permet déjà de couvrir les besoins des systèmes embarqués. Le monde des systèmes embarqués est vaste, nous avons plusieurs experts du domaine sur WG21, mais je pense que nous ne donnons pas assez d'attention à ce dossier

Ville Voutilainen : nous pourrions avoir plus d'experts, cela dit

Beman Dawes : le langage entier est le seul langage dont s'occupe WG21. Nous ne traitons pas de dialectes

Herb Sutter : en général, la meilleure manière de tuer quelque chose est d'en faire un dialecte. On comprend le côté pragmatique de certains gestes, mais ce n'est pas ce que l'on encourage. On voit une différence entre utiliser un sous-ensemble recommandé, ce que Bjarne Stroustrup et moi-même mettons de l'avant cette semaine, et créer un dialecte

Bjarne Stroustrup : il y a une bibliothèque que j'aimerais voir, c'est-à-dire un ensemble de conteneurs qui ne demandent pas d'allocation dynamique de mémoire. Ça peut être fait, et ce serait pertinent pour les systèmes embarqués

Lawrence Crowl : il y a une dizaine d'années, nous avons produit le Performance Technical Report qui explorait ces questions. Le langage n'a pas changé, mais ce document a joué un rôle pédagogique

Gabriel Dos Reis : pour C++ 11, nous n'avons pas eu le temps de réexaminer ce rapport, pour traiter par exemple d'expressions λ ou de constexpr. Il nous faudra le faire

Ville Voutilainen : il y a des travaux en cours pour examiner l'espace de design des conteneurs sans allocation dynamique de mémoire et sans exceptions. Si tout va bien, nous pourrions avoir une proposition sommaire dès cette semaine

Herb Sutter : c'est un autre cas où pour que ça avance, il faut que quelqu'un fasse le travail

Q : pourquoi l'ordre d'initialisation des variables statiques est-il encore un problème? Les modules régleront-ils ce problème?

Chandler Carruth : les modules règleront tous les problèmes! (rires généralisés dans la salle) Il existe des outils d'analyse statique pour détecter ce type de problème

Gabriel Dos Reis : en général, c'est un problème difficile

Q : les conteneurs dont Ville Voutilainen parlait, est-ce des conteneurs intrusifs comme en avait EASTL?

Ville Voutilainen : il est trop tôt pour dire. Nous avons quelques questions de design à régler au préalable, et nous devons discuter avec LEWG

Michael Wong : nous discutons de ces dossiers dans SG14. Plusieurs des problèmes qu'adressait EASTL sont déjà réglés par C++ 11, cela dit

Q : y a-t-il des liens entre le Keynote de Bjarne Stroustrup ce matin et celui de Herb Sutter demain?

Herb Sutter : oui, nous sommes coordonnés

Bjarne Stroustrup : je vois une différence entre ce qui revient au compilateur et ce qui revient à des outils d'accompagnement. La GSL me semble mieux desservie par des outils

Q : avec le raffinement de constexpr dans C++ 14 et Concepts Lite dans C++ 17, nos outils de vérification statique se sont significativement améliorés. Irons-nous encore plus loin en ce sens?

Gabriel Dos Reis : nous souhaitons que le compilateur ait un maximum d'information pour faire son travail efficacement. La version de constexpr que nous avions en C++ 11 était est le mieux que nous avions réussi à faire avec les moyens que nous avions. Je suis reconnaissant à Richard Smith d'avoir démontré ce que nous pouvions faire et d'avoir pavé la voie pour faire mieux.

Richard Smith : la prochaine étape est les λ constexpr. Par contre, constexpr prend du temps à la compilation alors il ne faut non plus déborder dans l'excès sur ce plan

Bjarne Stroustrup : j'abonde dans le même sens. Les modules vont aussi nous donner de meilleurs temps de compilation, mais je veux que la compilation demeure raisonnablement rapide. Je souhaite que ce qui sera fait à la compilation demeure prévisible du point de vue des programmeuses et des programmeurs

Gabriel Dos Reis : le compilateur doit évaluer une fonction pour savoir si elle peut être traitée à la compilation, et cetre fonction doit éviter le comportement indéfini. Mon groupe d'étude travaille pour réduire ces irritants, et les travaux faits sur Clang nous ont aussi beaucoup aidé ici

Richard Smith : constexpr était terriblement difficile à implémenter

Herb Sutter : les invariants ont un composant dynamique, qui nous mène vers les contrats

Bjarne Stroustrup : allez à la présentation de Gabriel Dos Reis, ça vaut la peine

Lawrence Crowl : les contrats sont la contrepartie dynamique des concepts pour ce qui est de valider le respect de contraintes

Bjarne Stroustrup : obtenir un consensus est difficile. Vouloir une particularité dans le langage ne signifie pas que l'on va l'avoir. On propose quelque chose, tous aiment l'idée en principe, puis nous entrons dans les détails, dans l'analyse des coûts, et... ça peut prendre dix ans à atteindre un consensus... ou pas

Beman Dawes : il y a aussi une considération de risque. C++ est un langage de production, pas une expérience académique. Les concepts sont un exemple clair : nous avions quelque chose de pas mal, mais les préoccupations qui demeuraient laissaient craindre des dégâts si nos craintes devaient s'avérer, et nous avons choisi de prendre un peu de recul

Bjarne Stroustrup : à la toute fin, j'ai écrit un papier portant sur trois irritants de ce que nous avions réussi à faire. Nous avons fait le choix d'en faire moins, mais de mieux le faire. Nous faisons beaucoup d'analyse de risques

Q : tout le monde veut les concepts, les modules... Quand une idée est dans l'air et est voulue par tous, est-ce plus une question d'identifier la meilleure approche technique ou d'atteindre un consensus?

Lawrence Crowl : c'est un problème de vocabulaire. Tous veulent les modules, mais il y a plusieurs acceptions de ce que signifient les modules. Nous avons vécu quelque chose de semblable avec les λ par le passé, et il a fallu joindre les propositions pour régler les problèmes des diverses communautés qui les souhaitaient. On aura quelque chose de semblable avec les modules, les contrats, etc. Et il faudra écrire les spécifications techniques qui les accompagneront

Marshall Clow : le standard est une spécification, qui doit bien exprimer les intentions, pas une implémentation de cette spécification. Cela relève des vendeurs

Bjarne Stroustrup : nous ne standardisons pas quelque chose parce que c'est à la mode. Nous avons commencé le travail sur les λ en 2002, les modules depuis 2005, les contrats depuis... Définir quelque chose qui dessert bien la communauté prend du temps

Q : nous voulons que les itérateurs dans un vecteur soient des pointeurs. Que faire?

Chandler Carruth : &*it. Ça fonctionne (sauf pour end(), mais c'est data() + size(), sauf si begin()==end())

Bjarne Stroustrup : les intervalles nous aideront ici

Chandler Carruth : sur notre implémentation, les itérateurs de vecteurs sont des pointeurs et nous le garantissons

Q : il me semble y avoir une tendance pour que les bibliothèques standards soient immenses. Celle de C++ est plus frugale. Pourquoi?

Bjarne Stroustrup : la principale raison est l'argent. Le comité est bénévole; nous payons pour travailler. D'autres langages sont la propriété d'entreprises

Marshall Clow : le LWG peine à bien traiter les propositions massives. C'est long et complexe à traiter. Nous sommes plus efficaces avec les petites propositions, mais celles-ci ne font pas évoluer la bibliothèque par grands bons. Si on prend Python par exemple, la bibliothèque de traitement des URL est à la version 3, et pour la version 2 le message est « piark, n'y touchez pas ». Nous ne sommes pas parfaits mais nous essayons très fort d'éviter cela

Beman Dawes : nous examinons chaque proposition au mérite, et nous en débattons. Le seul cas où nous avons fait virage majeur et subit était l'avènement de la STL, une oeuvre de génie

Fin du contenu technique

J'ai dû quitter vers 21h50 pour aller prendre l'autobus.

De retour à la chambre d'hôtel, j'écris un petit mot à mon amoureuse et je me prépare un petit souper. Une biere d'Alaska, pas vilaine, pour accompagner le tout. Une journée chargée, mais qui en valait la peine.

Jour 2 22 septembre 2015

Coûts du séjour pour aujourd'hui :

Debout à 5h15 du matin, et petit échange avec ma chic épouse qui s'en va sur le terrain pour apprendre à soigner des animaux de ferme. L'air de rien, c'est tout un monde! Je t'aime, mon amour, et je suis fier de toi.

Depuis mon arrivée ici, je prends régulièrement l'autobus et il se trouve que mes autobus sont souvent hybrides. Ça fait étrange d'avoir un autobus dont le moteur s'éteint à chaque fois que l'on s'arrête, à un feu de circulation ou pour embarquer / débarquer des passagères et des passagers.

Il y a un chic torontois francophile ici dont le nom m'échappe mais que je croise régulièrement. Ce matin, nous sommes arrivés ensemble lui et moi et il m'a dit avoir trouvé un café pas si mal non loin du lieu où se tient le colloque (il ne boit que de l'espresso, mais dans la région ici il est ardu de trouver autre chose qu'un Starbuck's).

Je me suis assis pour travailler un peu (j'ai eu une idée sympa dans la douche et j'ai fait une petite mise à jour sur h-deb) et Jason Turner était déjà présent. On bavarde de sa participation à une présentation sur la communauté des programmeuses et des programmeurs C++.

Kate Gregory arrive. Il est encore tôt. Elle blague sur le décalage horaire et gens de la côte Est comme elle et moi qui sont debout à des heures impossibles.

Pour voir cette présentation : à venir...

SG14 Meeting Wednesday: Towards Better Support in C++ for Games and Finance

La salle est plutôt pleine pour une présentation aussi sommaire.

Début du contenu technique

Sean Middleditch et Nicolas Guillemot sont nos hôtes ce matin. Leur but est de présenter SG14, les objectifs, la composition, etc.

Le monde du jeu est, avec le monde de la finance, l'un des plus importants domaines d'application de C++.

Nicolas Guillemot : à CppCon 2014, j'ai posé une question pour savoir combien de gens dans la salle oeuvraient dans le monde du jeu. Michael Wong m'a approché pour que l'on travaille à améliorer C++ en fonction des besoins des systèmes à basse-latence comme on en trouve dans le monde du jeu.

Nicolas Guillemot : nous avons mis en place des outils pour échanger et publié un article déclarant notre intention. Cet article a été présenté à Lenexa en mai, puis SG14 a été créé pour adresser les considérations qui y ont été soulevées.

Nicolas Guillemot : nous aurons deux rencontres officielles. La première se tiendra demain, ici, et la seconde sera à GDC, un colloque du monde du jeu organisé par Sony.

Nicolas Guillemot : nous souhaitons entre autres faciliter la communication entre l'industrie et le comité de standardisation. Évidemment, nous acceptons les propositions d'articles

Sean Middleditch : en effet, tout ce que vous pouvez nous donner pour nous alimenter est apprécier

Nicolas Guillemot : plusieurs domaines sont connexes au nôtre. La simulation interactive, l'affichage en temps réel, les calculs à basse latence, les systèmes embarqués, etc

Sean Middleditch : voici un bref survol de ce dont nous discuterons demain :

Michael Wong : en plus des changements dans les bibliothèques, nous examinons aussi des changements au niveau du langage, ce qui nous occupera en deuxième partie de la journée demain. Par exemple, bien intégrer le recours au GPU plutôt que déléguer à un langage tiers (je déteste ça, même si je suis le Chair d'OpenMP)

Q : allez-vous traiter d'exceptions?

Michael Wong : oui, c'est un des sujets clés. Nous savons que plusieurs d'entre vous mettent ce mécanisme à Off

Q : et à propos de la mémoire « chaude » ou « froide », des trucs comme Likely ou Unlikely?

Sean Middleditch : nous allons y arriver. Nous sommes ouverts aux propositions

Q : est-ce que SG14 est le « parapluie » pour les systèmes embarqués, la finance, etc.?

Michael Wong : il y a plusieurs groupes d'étude, mais ma perception est que SG14 est particulier, regroupant une communauté d'intérêt plutôt que cherchant à résoudre un problème spécifique

Q : avez-vous une échéance à rencontrer?

Michael Wong : si vous voulez quelque chose pour C++ 17, il faut que ce soit petit et présenté à Kona, sinon ça ira à C++ 20

Michael Wong : la rencontre de demain sera plus courte qu'une rencontre de WG21, où nous commençons tôt et nous finissons tard, avec peu de pauses. Nous prendrons un moment pour assister au Keynote de Sean Parent, entre autres, mais nous pensons parvenir à être efficaces

Q : pour ceux parmi nous qui ne sont familiers avec le processus de soumission d'une proposition, comment peut-on s'instruire?

Michael Wong : je vous présenterai un exemple

Q : vendredi matin à 9h, verra-t-on simplement un retour sur la journée de mercredi?

Michael Wong : non, il y aura plus que cela, mais je ferai un rapport des événements, c'est mon rôle

Michael Wong : en passant, notre échéance pour soumettre une proposition pour Kona est ce vendredi. On a très peu de temps (Michael Wong relate le cheminement d'une proposition à travers le comité)

Q : y aura-t-il des minutes de la rencontre?

Michael Wong : absolument. C'est une rencontre officielle

Sean Middleditch : notre temps pour ce matin est écoulé

Fin du contenu technique

On a un problème dans l'API de threading standard du langage (un truc manquant, qui bloque l'adoption de nos outils dans certains milieux dont celui du jeu) et pour lequel j'ai reçu plusieurs commentaires déjà. Je vais écrire la proposition cette semaine, probablement tantôt pour un premier jet. Je suis allé consulter Howard Hinnant et Marshall Clow et pour savoir à que groupe (LWG ou LEWG) le soumettre; les deux sont d'avis qu'il faut « sortir » la proposition à temps, et qu'on la routera vers le bon destinataire ensuite (c'est pas grave).

Pour vour sa présentation : https://www.youtube.com/watch?v=zt7ThwVfap0

Stephan T. Lavavej : <functional>: What's New, and Proper Usage

La salle est pleine, sans surprises

Début du contenu technique

Stephan T. Lavavej commence à l'heure. Il se présente, et se dit optimiste que l'on livre C++ 17 en 2017

Tout ce qu'il présentera aujourd'hui est standard; les trucs spécifiques à Microsoft Windows seront présentés pour expliquer son implémentation

Stephan T. Lavavej commence par un retour sur les λ génériques et les captures. Il donne un exemple qui trie de manière stable des chaînes de caractères en fonction de leur longueur

Une λ définit une classe et construit un objet. C'est une syntaxe utile, pas de la magie. Toutefois, une λ est un concept de niveau langage alors que std::function est un objet de la bibliothèque standard

Une λ sans états se convertit en pointeur de fonction, mais c'est facile. Une λ n'est pas une fonction anonyme; si vous prétendez ça, Stephan T. Lavavej va grogner

Stephan T. Lavavej parle ensuite de invoke() dans C++ 17

Un Function Object est utilisable comme une fonction, et ça inclut les pointeurs de fonctions, les foncteurs (incluant les λ) et et les classes qui ont un opérateur de conversion en pointeur de fonction (mais c'est obscur)

On peut utiliser une référence à une fonction de manière analogue même si une référence n'est pas un objet

Un objet appelable s'utilise avec des parenthèse. Ça inclut les pointeurs aux membres d'instance (avec qualifications cv!) et les foncteurs. Ici, Core veut une syntaxe différente mais la bibliothèque standard veut une syntaxe homogène, d'où INVOKE (imaginaire avec C++ 11 et C++ 14) et invoke(callable, args...) (réel en C++ 17). C'est très polyvalent, très intelligent, et ça marche même avec des pointeurs intelligents ou tout ce qui est déréférençable

Il existe plusieurs trucs dans la STL qui utilisent invoke() (liste d'une douzaine de trucs à l'écran)

Dans du code non-générique, invoke() est d'une utilité limitée, mais ça peut simplifier la vie. Dans du code générique, par contre, c'est vraiment chic

Stephan T. Lavavej parle ensuite de result_of (avec SFINAE et result_of_t)

Cet outil est dans <type_traits>, et permet de répondre à la question « quel sera le type de l'appel suivant avec ces paramètres-ci? ». Ça utilise declval<T>() et decltype. Stephan T. Lavavej présente un exemple complexe qui implique decay_t pour éviter de générer un vecteur de références

Il se trouve que result_of est délicat : ça nous informe sur le résultat d'une invocation, mais avec une autre syntaxe que celle de l'invocation. C'est un outil pré-decltype, et ça a mal vieilli. On préfère auto, decltype et decltype(auto) dans la majorité des cas

Stephan T. Lavavej parle ensuite de mem_fn(), qui a remplacé des trucs désuets de C++ 98, pour invoquer une méthode d'instance. Stephan T. Lavavej blâme Core encore pour la syntaxe

Le problème avec mem_fn() est que c'est résistant aux optimisations (ça tend à nous ralentir) et que c'est grognon face aux surcharges (faut des static_cast...). Avec invoke(), men_fn() devient redondant. Avec std::bind ou std::function, qui « parlent invoke() », ça ne nous aide pas vraiment. Utilisez des λ, en particulier les λ génériques. Pour quelques caractères de plus, vous allez gagner en simplicité et en vitesse

Les foncteurs transparents suivent (greater<>{} par exemple, plutôt que greater<int>). Stephan T. Lavavej donne quelques liens à ses présentations précédentes. Stephan T. Lavavej recommande les « diamants transparents » par défaut. Pour ces foncteurs, les bibliothèques connaissent tous les cas a priori et génèrent du code parfait

Stephan T. Lavavej en arrive à std::bind()

Ça a des qualités : c'est concis, c'est polyvalent. Il résume tout ce que ça fait sur une diapo mais elle est chargée. std::bind() entrepose par copie ou par mouvement ses paramètres à la construction, et prend ses paramètres en tant que lvalues pour éviter le mouvement potentiellement destructif. Il mentionne les bind() appliqués à des bind() qui génèrent du Perfect Forwarding et rendent fous quand on les regarde

Le problème est que bind() est surprenant. C'est un peu lent (à cause des éléments entreposés en tant qu'attributs d'instance), ça se comporte vilainement avec des trucs comme unique_ptr à cause du passage des paramètres en tant que lvalues. C'est une sorte de mini langage, en particulier avec bind sur bind. Les λ sont tellement plus simples, plus rapides... Stephan T. Lavavej dit avoir vu Scott Meyers et Herb Sutter être perplexes devant std::bind()! Il est même possible, si on est assez pervers, de faire deux std::move() sur un même objet avec std::bind(), car std::bind() prédate la sémantique de mouvement. C'était une bonne idée en 2005, c'est une mauvaise idée en 2015

Nous arrivons à reference_wrapper, tout petite classe qui se comporte comme un T& dont on peut remplacer le référé et qui est appelable. On l'instancie avec std::ref

La majorité des algorithmes prennent leurs Function Objects par copie (outre for_each() et shuffle()), mais reference_wrapper permet de jouer sur ce point. Faut être prudents avec make_pair(), make_tuple() et bind()

Dans <functional>, on a enlevé des trucs (mais je les connais bien)

Enfin, on arrive à std::function (avec SFINAE et tout le tralala). C'est un wrapper qui entrepose un Callable par effacement de type, et ça permet d'entreposer une λ, de joindre des entités de types distincts mais appelables avec une même signature, de joindre du code séparemment compilé, des méthodes virtuelles même si on ne peut pas avoir de templates virtuels, etc.

Il faut que le Callable soit CopyConstructible, même si std::function n'utilise que std::move pour l'entreposage et même si on ne copie jamais le std::function. La raison est que le Callable n'est instancié que si on l'appelle, alors on doit avoir les fonctions dont on pourra un jour avoir besoin avant d'en effacer le type. Conséquemment, on ne peut pas actuellement y entreposer un Callable qui serait move-only

On y applique le Small Functor Optimization (SFO), mais il faut que le Callable soit is_nothrow_move_constructible (à cause de std::swap()). C'est garanti pour reference_wrapper et les pointeurs de fonctions, mais pour les autres cas (incluant les pointeurs de méthodes d'instance) c'est à la discrétion du vendeur

Stephan T. Lavavej présente des chiffres pour contextualiser SSO et SFO

On a une belle amélioration pour la surcharge de fonctions prenant une std::function en paramètre quand plusieurs signatures sont possibles (ambigu en C++ 11, légal en C++ 14)

On a quelques trucs agaçants :

Stephan T. Lavavej recommande d'utiliser std::function quand on a un besoin. C'est cool, mais c'est pas gratuit du tout! C'est aussi le seul vrai cas de Code Bloat existant dans le standard aujourd'hui, car les Callable doivent être pleinement générés « juste au cas » quand on les place dans un std::function

Dans VS2015, il manque result_of avec Expression SFINAE alors c'est pas encore exactement complet, mais il ne manque plus grand chose

Questions

Q : l'avez-vous utilisé avec Boost?

Stephan T. Lavavej : oui. Il y a des différences mineures mais outre quelques extensions de Boost, l'essentiel fonctionne tel quel. Le standard est plus récent que la version de Boost

Q : à quel point a-t-on encore besoin de result_of avec l'avènement de void_t?

Stephan T. Lavavej : void_t est prévu pour C++ 17

Q : à propos des Callable move-only...?

Stephan T. Lavavej : c'est une contrainte de design. On n'a pas de wrapper pour les objets move-only dans le moment. Je ne pense pas qu'on l'ait pour C++ 17

Q : est-ce que la bibliothèque standard de VS2015 est encore basée sur Dinkumware?

Stephan T. Lavavej : oui, mais j'ai presque tout changé au fil du temps, avec l'évolution du langage, les templates variadiques, etc.

Q : comment bien écrire un algorithme qui prend des λ?

Stephan T. Lavavej : vous pouvez y aller avec des copies ou des Callable&& (c'est probablement mieux)

Fin du contenu technique

Ouf. Comme toujours avec Stephan T. Lavavej, ça roulait à fond de train!

En me déplaçant vers la prochaine présentation, j'ai bavardé un peu avec Jason Turner, que je croise partout et qui est chouette, et j'ai profité du moment pour indiquer à Sean Middleditch que j'apprécie (sincèrement) le ton qu'il adopte lorsqu'il intervient sur la liste de diffusion de SG14, même face à des intervenants agressifs.

Pour voir la présentation : https://www.youtube.com/watch?v=hEx5DNLWGgA

Pour voir les diapos de la présentation : https://github.com/isocpp/CppCoreGuidelines/blob/master/talks/Sutter%20-%20CppCon%202015%20day%202%20plenary%20.pdf

Keynote – Herb Sutter : Writing Good C++ 14 by Default

Tout le monde est installé. Il y avait des croissants, des muffins et des fruits.

Début du contenu technique

Jon Kalb prend la scène, comme à l'habitude lors des Keynotes. Il recommande d'aller examiner l'horaire de la journée, dans lequel il y a eu quelques changements, puis il présente Herb Sutter.

Herb Sutter : j'espère que vous avez apprécié la présentation de Bjarne Stroustrup hier. Nous savons que vous avez voulu explorer ce qu'il proposait car notre document a été le plus populaire sur GitHub dans le monde hier, au-dessus du nouveau iOS

Herb Sutter montre du code « ancien » et du code « moderne » et demande, à main levée, qui écrit « comme la version moderne ». Dans la salle, c'est une forte majorité

Herb Sutter : la compatibilité est importante, mais peut-on vraiment enlever des éléments à C++? Ou encore, peut-on rendre « moderne » l'option par défaut?

Herb Sutter commence par des remerciements à une vaste quantité d'individus ayant participé à la GSL

Herb Sutter : on veut des remplacements sécuritaires pour tous les éléments dangereux. La GSL, la Type-Safety, les modules, les concepts, les contrats, les intervalles, la gestion de la durée de vie

Herb Sutter : Type-Safety et Memory-Safety : respecter les types, la durée de vie, les frontières, éviter les fuites, etc.

Herb Sutter : quand on programme en C++ dans le noyau sécuritaire, ce choix n'est jamais la cause de bris de sécurité (sauf exceptions explicitement documentées)

Herb Sutter : nous voulons de la sécurité par construction

Herb Sutter : propose des profils de sécurité (frontières, portée, types). Il y en a d'autre (arithmétique, concurrence, etc.)

Herb Sutter : un exemple est « ne pas laisser dans un espace de type T une valeur de type» (fait référence au travail sur std::variant pour remplacer les union et les varags, et au sain usage du transtypage). Il se dit d'avis qu'on aura une résolution sur std::variant à Kona

Herb Sutter : pour les frontières, il présente string_view et array_view qui sont déjà sous forme de spécification technique. Il note que array_view et not_null sont les deux types proposés dans la GSL qui ont un coût à l'exécution. Les types que nous ajoutons sont des « types vocabulaires », connus du compilateur, et ils se prêtent à l'analyse statique. Passer par le système de types réduit en même temps le travail de l'analyseur statique

Herb Sutter : propose les annotations [[suppress(profile)]] et [[suppress(rule)]] pour contourner des règles dans un contexte ciblé

Herb Sutter : pour passer un tableau brut, un std::array ou un std::vector, on peut passer un std::array_view dans la signature d'une fonction. Idem pour std::string_view qui peut couvrir pas mal toutes les string, incluant les implémentations maison (nombreuses, à ce qu'on peut voir dans la salle)

Herb Sutter fait une blague sur la simplicité de la gestion de la durée de vie, faisant semblant qu'on a un problème réglé... alors que c'est épouvantablement difficile comme problème, tous langages confondus. On a beaucoup travaillé sur la durée de vie en C, mais C++ est un autre langage. C++ nous donne plus d'information sur les objets que C. En C++, on veut l'abstraction à coût nul, en espace ou en temps

Herb Sutter : plusieurs options existent. WPO, mais ça ne tient pas la route pour un gros programme. Les annotations, comme fait Rust, mais ça alourdit le travail. Nous pensons avoir une solution de meilleure qualité en C++ avec ce que le code source nous donne déjà

Herb Sutter : les pointeurs sont le mal (bien sûr que non, c'est pas si simple). Les pointeurs intelligents sont pertinents, les références aussi, et parfois les pointeurs bruts sont la chose à utiliser

Herb Sutter : owner<T*> documente une sémantique de responsabilité sans entraîner de coûts, alors que T* est ambigu sur le plan de la responsabilité. Les outils connaissent owner<T*>

Herb Sutter : on veut des règles locales, appuyées sur le plan statique. Une responsabilité claire, et peu d'annotations. Un comportement par défaut correct

Herb Sutter : dans un appel de fonction, on considère les paramètres indépendants et localement valides par défaut. Pour un objet englobant et des objets englobés, on suivra l'englobant

Herb Sutter : trois étapes :

Herb Sutter : présente divers cas d'analyse de dépendances et de responsabilité avec pointeurs, références, pointeurs sur des pointeurs, pointeurs sur des pointeurs intelligents, etc. On a une démo « live » (cool!)

Herb Sutter : présente un autre exemple, tiré d'une question sur Stack Overflow. L'idée est que le compilateur, sur la base de la GSL, puisse expliquer les problèmes dans le code

Herb Sutter : présente un autre exemple avec un shared_ptr<vector<int>>, du déréférencement, des prises d'adresses et des indirections par indice de tableau

Herb Sutter : autres aspects analysés : branchements, répétitives, pointeurs nuls, levées d'exceptions et blocs catch, etc.

Herb Sutter : pour les appels de fonctions, surtout avec des pointeurs passés en paramètres, on souhaite éviter de se faire mordre par un effet de bord qui invaliderait le pointé. Encore une fois, on a une démo « live » d'analyse statique vraiment chouette. Il reste des points à parfaire, mais on a de beaux outils d'analyse statique qui se dessinent à l'horizon...

Herb Sutter fait un bref exposé des risques de mauvaise utilisation de pointeurs intelligents

Herb Sutter explique comment renverser les comportements par défaut. Il propose une annotation [[lifetime(this)]] et [[lifetime(arg)]] pour une méthode insert() d'une std::map, qui ajoute de la sémantique pour guider l'analyse

Herb Sutter : pour les valeurs retournées de fonctions, en particulier s'il s'agit de pointeurs, la question de la source demeure, de même que celle de la responsabilité. Il s'avère que dans ce cas, pour la majorité des cas de figure, on s'en sort pas si mal

Herb Sutter se dit d'avis qu'il y a trop d'annotations dans certains langages (il revient sur Rust). Le code source devrait suffire dans la majorité des cas

Herb Sutter discute des objets propriétaires comme aimants forts ou faibles pour les temporaires qui cherchent à s'attacher à des objets. C'est intéressant, il y a de la pédagogie à faire là-dessus. Il trace une analogie avec vector<T>::operator[]() qui retourne un T&

Herb Sutter parle d'Andrei Alexandrescu qui l'achale annuellement pour que le comité corrige std::min() (qu'on ne peut convenablement appeler avec des ref-vers-const de manière sécurtaire), et consulte Gabriel Dos Reis (évidemment, c'est « arrangé avecle gars des vues »). Une démo « live » montre une identification analytique du problème avec des temporaires. Oh, celle-là est cool!

Herb Sutter : ce qu'on vient de montrer est un prototype. Ce n'est pas disponible tout de suite, mais bientôt (un CTP peut-être d'ici la fin de 2015)

Herb Sutter se dit d'avis que si le projet atteint ses objectifs, on pourra remplacer get() dans les pointeurs intelligents par des conversions implicites en pointeurs bruts

Fin du contenu technique

J'ai un début de rhume qui s'annonce. Je manque de sommeil... Tristement, on n'a pas de séances de questions / réponses après cette présentation (il n'y a plus de temps). J'ai croisé Michael Caisse en allant à la salle de bains, et je lui ai partagé mon impression que ce que l'on vient de voir est une sorte d'assaut frontal sur Clang dans un de ses créneaux dominants. Nous avons échangé des sourires et des commentaires politiquement corrects sur le sujet.

Pour voir ces présentations : à venir...

Kate Gregory : Lightning Talks

J'aurais beaucoup voulu y aller. Kate Gregory est une personne d'une grande pertinence. Malheureusement, je planche sur une proposition qui doit absolument être prête pour demain...

Jens Weller vient s'asseoir avec moi pendant que je me chamaille avec mon texte. On bavarde un peu, c'est sympa, mais on doit ensuite se dire au revoir car nous allons tous deux à des présentations distinctes (et les deux sont tentantes)

Michael Wong est venu me voir pour m'avertir d'être prêt demain car le sujet qui m'incombe prêt à controverse. Je lui ai demandé un numéro de proposition pour mon travail sur les paramètres de démarrage des threads.

Pour voir sa présentation : à venir...

Michael Wong : C++ 11/ 14/ 17 Atomics the Deep Dive: the gory details, before the Story Consumes You!

Un gentil monsieur m'a laissé sa prise de courant; je suis disfonctionnel sans courant.

Début du contenu technique

Michael Wong : pourquoi êtes-vous ici? Vous voulez sûrement être rapides, portables... et corrects. Il est facile d'avoir un programme parallèle qui soit rapide et incorrect

Michael Wong : nous avons un modèle mémoire parce que nous voulons aller rapidement. Nous voulons des programmes parallèles, corrects... et plus simples à écrire

Michael Wong : à une autre époque, conduire une automobile (une Ford T, par exemple) était difficile. Aujourd'hui, nous avons des voitures qui se conduisent presque toutes seules

Michael Wong : le modèle mémoire de C++ vise la « performance » maximale tout en demeurant portable

Michael Wong : le triangle est « performance », généralité/portabilité et productivité. Il est difficile d'avoir les trois

Michael Wong : et la facilité d'entretien? La robustesse? Le code correct? On a besoin de cela, mais en général, selon moi, pas seulement dans le monde du parallélisme

Michael Wong : et la productivité alors? Et la généralité? Ce sont des objectifs difficiles à atteindre, donc nous leur portons une attention particulière

Michael Wong présente des exemples corrects (en posant la question à la foule, qui ne répond pas) et demande s'ils sont équivalents

Michael Wong : que veut-on dire par équivalents? Même comportement? Même vitesse d'exécution? L'une des deux a une atomique SC (simple, clair, par défaut... et plus lent possible dans les circonstances) et l'autre implémente des opérations Acquire-Release

Michael Wong donne une liste des éléments clés de la concurrence avec C11, C++ 11, C++ 14, C++ 17 (avant ça, la question ne se posait même pas). Dans la liste, aujourd'hui, on ne parlera que des atomiques et du modèle mémoire

Michael Wong : C++ 14 a clarifié plusieurs aspects du modèle (Out of Thin Air Values, par exemple). Il reste encore les atomiques de modèle memory_order_consume qui posent problème, mais Paul E. McKenney en parlera tantôt

Michael Wong : décrit la cohérence séquentielle telle que présentée par Leslie Lamport en 1978 (il indique 1979 sur sa diapo)

Michael Wong : dans un programme monothread de quatre instructions à peine, sur le plan abstrait, les instruction sont présumées exécutées dans l'ordre selon lequel elles ont été séquencées, du moins pour ce qui est observable

Michael Wong : avec deux threads, même sans réordonnancement, on a 2 de 4! enchevêtrements distincts possibles des mêmes instructions

Michael Wong : on peut injecter des clôtures pour réduire le champ des possibles, mais à moins d'injecter une clôture après chaque opération, il y a encore des enchevêtrements possibles. En restreignant les options, il devient par contre possible de raisonner sur le code source et de poser certaines affirmations sur le programme

Michael Wong : le réordonnancement que fait le processeur est contraint par le modèle mémoire. Un modèle mémoire est un contrat entre les implémenteurs et les programmeurs qui permet aux programmeuses et aux programmeurs d'éviter de réfléchir aux caractéristiques opératoires du matériel

Michael Wong décrit le changement de contexte entre threads

Michael Wong décrit la hiérarchie de la mémoire quand on a des antémémoires (des Caches), avec une jolie animation pour expliquer l'accès aux données une Cache Line à la fois, et pour expliquer le coût d'un Cache Miss

Michael Wong a une image d'Albert Einstein et une autre de Stephen Hawking sur sa diapo. Pourquoi? Parce que tout dans la vie a trait à ces deux individus... Mais plus sérieusement, c'est parce que la vitesse de la lumière est un obstacle ici

Michael Wong : le modèle mémoire est un aspect invisible du langage, mais aussi un aspect essentiel de l'exécution du type de programme qui nous intéresse ici. Il prévient certaines optimisations et permet de raisonner localement sur des données mutables partagées

Michael Wong : les threads qui se parlent sont comme des entités qui se passent des messages (en écrivant dans une atomique ou en prenant un verrou au préalable). On parle d'Acquire (lire) et de Release (écrire)

Michael Wong : un lieu en mémoire est un objet (on évite les bitfields ici)

Michael Wong : une condition de course est (a) un accès non-atomique dans un thread, (b) un accès non-atomique de ce lieu dans un autre thread, (c) sans relation de synchronisation de type Happens-Before entre eux. On a alors du comportement indéfini

Michael Wong : une volatile atomique est possible. Ça réduit les opportunités d'optimisation encore plus

Michael Wong : une atomique statique doit être initialisée de manière statique. On veut d'elles une vitesse raisonnable pour des néophytes et la capacité d'écrire du code sans verrous pour les experts

Michael Wong : être séquentiellement cohérent signifie que ce qu'on observe du système est cohérent avec le programme qui a été écrit. C'est le modèle par défaut, mais les modèles plus faibles peuvent donner du code plus rapide alors ils sont accessibles... sur demande

Michael Wong : une atomique peut être accédée concurremment sans provoquer de condition de course. Elles sont implémentées sans verrous si le matériel le permet, et ne peuvent être observées comme ayant été à moitié réalisées. L'implémentation « bibliothèque » permet d'éviter d'insérer plus de mots clés dans le langage, mais en pratique les atomiques sont typiquement implémentées directement par le compilateur

Michael Wong : il n'y a pas de type atomic<float> ou autre

Michael Wong : l'atomique minimale est atomic_flag. C'est le seul garanti pour être sans verrous. Pour des fanions, Michael Wong recommande atomic<bool>, atomic<int> ou atomic<void*>

Michael Wong : atomic<bool> permet atomic_exchange_weak(), qui peut échouer de manière épisodique. Ce qui provoque ceci est que l'opération se faisait dans le thread et qu'il y a eu un changement de contexte, donc que le thread ne peut garantir que l'opération apparemment réussie a été faite par lui

Michael Wong : pour la force relative des ordonnancements mémoire possibles, Michael Wong fait remarquer que les exigences peuvent varier selon les opérations. Dans un compare_exchange_weak(expected,true,si_succes,si_echec), le modèle applicable lors d'un succès ne peut être plus fort que celui applicable lors d'un échec

Michael Wong : quand on fait du code sans verrous, on vise à éviter les crashes et il faut qu'au moins un des threads progresse. C++ 14 dit shall be obstruction free et should be lock-free (on n'a pas vraiment de mots dans le standard pour Wait-Free)

Michael Wong : pour les opérations d'ordonnancement, on a trois modèles mémoires et six contraintes d'ordonnancement (certaines seront couvertes par Paul E. McKenney tantôt) :

Michael Wong : on n'a plus de sequence points, mais on a :

Michael Wong : fait un lien avec la présentation de Fedor Pikus hier, pour montrer un synchronizes-with entre un store_rel et un ld_acq dans le Double-Checked Locking (même code des deux côtés, atomic<bool>)

Michael Wong : SC implique un ordonnancement global total des opérations

Michael Wong : donne un exemple à quatre threads, six opérations au total. La foule est perplexe

Michael Wong : donne ensuite un exemple d'atomiques relaxées. Frissons...

Fin du contenu technique

Je bavarde un peu avec Félix-Antoine Ouellet pendant que j'ajoute des liens sur la présente page. Il me raconte un peu ce qui s'est passé dans la présentation sur les modules.

Pour voir sa présentation : https://www.youtube.com/watch?v=ZrNQKpOypqU

Paul E. McKenney: C++ Atomics: The Sad Story of memory_order_consume: A Happy Ending at Last?

L'un des trucs que j'avais hâte de voir aujourd'hui.

Début du Début du contenu technique

Paul E. McKenney : on utilise memory_order_consume typiquement sur des listes chaînées, quand on veut que le matériel et le compilateur respectent des dépendances de données pour nous. Faut vouloir aller vite, sinon il y a beaucoup de manières d'avoir moins de problèmes. En même temps, on veut probablement plus que simplement la haute vitesse à tout prix (on n'est pas en train d'écrire du code assembleur manuellement).

Paul E. McKenney : on veut donc maximiser la performance sans perdre de productivité / facilité d'entretien / portabilité

Paul E. McKenney : il nous faut une bonne API pour atteindre cet équilibre

Paul E. McKenney : pourquoi se préoccuper de memory_order_consume? (il montre un schéma avec un dependency-ordered-before et un carries-dependency). Pour avoir un ordonnancement entre threads, il faut que les deux collaborent.

Paul E. McKenney : on n'a pas de memory_order_consume efficace pour le moment. Typiquement, on demande ça et on obtient un memory_order_acq_rel

Paul E. McKenney : la présence d'une dépendance de données entre deux threads est est pourtant un signal dont on aimerait pouvoir profiter. Avec memory_order_consume, on peut avoir des opérations très rapides, mais il faut qu'elles introduisent une dépendance entre des données (p. ex. : utiliser un pointeur sur un struct puis accéder à ses membres)

Paul E. McKenney : nous avons de grosses machines aujourd'hui, et la plupart des structures de données sont principalement accédées en lecture. Les mécanismes de synchronisation qui sont read-mostly sont donc importants

Paul E. McKenney : pourquoi travailler fort pour éliminer une seule instruction? Il donne un exemple d'une fonction du noyau de Linux qui épargne un load et un store sur la pile, non-atomiques. Certains individus sont très préoccupés par la vitesse, et il se trouve que dans ce cas, on pouvait observer la différence de vitesse même en User Mode.

Paul E. McKenney : les usagers qui veulent que tout aille rapidement ne seront pas heureux si on ajoute des clôtures mémoire superflues dans le code, et m'en informent parfois de manière... vocale

Paul E. McKenney : pour ces raisons, nous avons memory_order_consume, mais comment l'utiliser?

Paul E. McKenney : le cas type d'utilisation pour memory_order_consume est RCU, mais on pourrait aussi l'appliquer dans de la collecte d'ordures, la mémoire immortelle, etc. Les primitives sont rcu_read_lock() (qui est un noop), rcu_read_unlock() (un autre noop), rcu_dereference() (qui est un acquire-load) et rcu_assign_pointer() (qui est un release-store). À son avis, si bien utilisés, ces mécanismes sont pratiquement optimaux

Paul E. McKenney :  exemple de RCU pour accès concurrent à une structure de liste chaînée. Puisque rcu_read_lock() est un noop, les lecteurs peuvent entrer n'importe quand. Pas besoin de faire payer les lecteurs lors d'une insertion

Paul E. McKenney : pour écrire dans la liste, on a list_del_rcu(), synchronize_rcu() (qui fait un rendez-vous avec d'autres threads) et kfree()

Paul E. McKenney : on attend les lecteurs préexistants avec QSBR (Quiescent State-Based Reclamation) dans un environnement non-préemptif. Dans le noyau de Linux, il est interdit de bloquer

Paul E. McKenney : comment se synchronise-t-on avec RCU si rcu_read_lock() et rcu_read_unlock() ne font rien? On fait du Social Engineering et on opère sur la programmeuses et sur le programmeur. On peut implémenter RCU strictement pas Social Engineering si on a memory_order_consume (sinon, les fonctions auront un peu de code)

Paul E. McKenney : présente des chiffres et un  schéma de la machine. C'est à voir, sérieusement. Clair, efficace. Il montre qu'avec RCU et memory_order_consume, il parvient à faire une fouille à vitesse supralinéaire dans un arbre, et trois fois mieux avec une hash table

Paul E. McKenney : RCU est bon pour lire des données dépassées et incohérentes (ce qui est souvent suffisant!); correct lecture-surtout et données cohérentes; et peut-être correct pour lecture-écriture avec données cohérentes

Paul E. McKenney : c'est applicable pour avoir :

Quelqu'un vient informer Paul E. McKenney qu'il n'a plus de temps, Zut! Il accélère et parle d'annoter les variables qui sont [[carries_dependency]], mais on manque au moins une bonne dizaine de diapos... Zut!

Fin du contenu technique

Pour voir sa présentation : https://www.youtube.com/watch?v=mPxIegd9J3w

Bien qu'Artur Laksberg doive prendre le plancher dans la salle où nous étions, ma prochaine présentation n'est que dans une quinzaine de minutes alors je prends le temps d'avaler une grignotine (ils ont des macarons, mioum!)

Pour voir sa présentation : https://www.youtube.com/watch?v=9QGsEkB4Rfs

Paul Fultz II : Reflection Techniques in C++

Arrivé dans la salle où Paul Fultz II compte nous entretenir de réflexivité, surtout pour fins de sérialisation.

Début du contenu technique

Paul Fultz II présente la réflexivité comme une forme d'introspection sur les types. Jusque là, c'est un problème réglé. Le problème devient plus croustillant quand on veut itérer sur les membres d'un type.

Paul Fultz II ne proposera pas d'introspection basée sur des prédicats. Il présentera les données sous forme de classes, et visera une réflexivité statique

Paul Fultz II dit qu'on se limitera à ce que supporte déjà C++, et le langage n'offre pas encore de support à la réflexivité. Nous allons donc annoter notre code avec des métadonnées

Les cas d'utilisation incluent :

Les techniques que nous explorerons seront :

Boost.Fusion propose des algorithmes pour opérer sur des séquences hétérogènes (des tuple). Les exemples utilisent des λ génériques. On voit des macros pour adapter un struct et en faire un tuple. On peut accéder aux éléments par leur indice, mais on préférerait y aller par nom; il y a un service pour cela (struct_member_name<person,1>::call()). On examine ensuite comment zipper des morceaux ensemble, à l'aide de Boost.MPL. Ça fait le travail.

On peut ensuite faire des séquences associatives (des tuple associatifs), sortes de std::map indicées par types. Il existe des adaptateurs ici aussi. Les techniques avec Boost.Fusion sont similaires.

On peut ensuite annoter les membres d'instance de nos classes par des types (struct primary_key{}; template<int N>struct max_length; etc.) en dérivant nos clés des attributs, et vérifier la présence ou non d'une annotation en examinant la présence ou non du parent souhaité.

Sa fonction create_table() construit la commande avec cet échafaudage et une sérialisation dans une std::stringstream.

Paul Fultz II propose quelques bibliothèques tierces qui cohabitent bien avec Boost.Fusion : CPPAN, Boost.Hana (Louis Dionne est dans la salle), Hero (projet de Paul Fultz II)

Avec des visiteurs, chaque classe exposera une fonction visit qui acceptera un visiteur et l'appliquera à chacun de ses membres. Paul Fultz II l'implémente avec un foncteur interne générique, implémenté avec une version const et une version non-const

 Ici, les annotations peuvent être des objets, pas juste des types. Il propose une technique variadique sympathique pour identifier le paramètre dans une liste de paramètres qui serait une clé primaire. Pour visiter, il utilise visit_select<T>(obj, f) T est le type à visiter dans obj et f la fonction à lui appliquer. Sa technique pour chercher une annotation est semblable

Pour le Do-It-Yourself maintenant, Paul Fultz II propose d'écrire une macro REFLECTABLE et fait quelques mauvais coups avec des macros variadiques. Et quelques-unes de moins jolies. Hum. La salle réagit

Une passe intéressante : pour appliquer f à args... dans l'ordre, il crée une (void)initializer_list<int>{(f(forward<decltype(arg)>(arg))...,0)} pour forcer l'ordre. Avec sa Fold Expression, il se retrouve avec une longue liste de zéros, mais on s'en fout parce qu'il ne fait rien avec. À retenir

Fin du contenu technique

Je reste sur place une fois la présentation terminée pour fignoler un premier jet de proposition pour paramétrer la taille d'une pile d'exécution pour un thread dès sa construction.

Prochaine étape : aller finir de préparer mon matériel pour demain.

Pour voir ces présentations :

Kate Gregory : Lightning Talks

On a eu une alarme d'incendie, mais ça n'a pas duré. Ouf!

Kate Gregory est notre « maître de cérémonie » ce soir.

Début du contenu technique

Phil Nash – The stand up

On a un véritable show d'humour pour geeks  Ensuite, on a droit à une recommandation de passer moins de temps assis. C'est étonnant comme prestation. Phil nous a fait lever, a parlé de l'impact de la sédentarité, et on a fini par apprendre qu'il a perdu 50 Kg en un an environ.

Piotr Padlewski – C++ WAT

Une série de trucs suspects du langage. Amusant! Et très, très pervers...

Greg Law – Give me fifteen minutes and I'll change your view of GDB

Greg Law est le président fondateur d'UndoDB. On l'utilise à travers l'interface de GDB. Il montre que GDB est beaucoup moins déplaisant qu'on ne pourrait le penser au préalable, surtout sur le plan de l'interface usager. Il contient même un interpréteur Python! GDB est capable d'enregistrer et de rejouer des passages de l'exécution du programme. Il peut même revenir dans le temps!

Roland Bock – Kiss Templates

Je veux générer du texte (HTML, , etc.) et je veux un système de modèles général pour y arriver. Il a son propre mini-langage qui transforme un modèle en code C++, duquel il génère les données sérialisées.

Jens Weller – TextEditor Needed

Il développe son propre CMS en C++, rien de moins, et en est venu à se coder un éditeur de texte avec Qt. Il relate ses recherches et ses choix d'outils, incluant l'intégration de C++ avec JavaScript. Le gros du code montre comment l'interaction entre ces deux langages se passe.

Matt P. Dziubinski – Algorithmic Differentiation

On a des données. On veut les comprendre, les expliquer, prédire la suite. Ça prend un modèle d'habitude, et un veut one connexion entre le modèle et les données. Une fonction de coût à minimiser. Utile dans plein de domaines (estimation, calibration, apprentissage, etc.). Il présente les règles, l'influence du temps. (je dois quitter pour prendre l'autobus).

Fin du contenu technique

J'ai travaillé fort au retour, et fait un peu de lessive. Petite nuit à l'horizon.

Jour 3 23 septembre 2015

Coûts du séjour pour aujourd'hui :

Ce fut effectivement une petite nuit d'un peu moins de trois heures, et je ne suis pas tout à fait prêt encore. C'est une chose de faire des tests et de produire des métriques, mais encore faut-il bien le faire et tirer des informations pertinentes de ces efforts. J'ai découvert des trucs amusants et d'autres... beaucoup moins. Il va y avoir de l'action aujourd'hui.

Je suis arrivé tôt, écrit un test supplémentaire, tiré des statistiques, produit des graphiques (mais j'ai pas fini)... Ça ne sera pas ma journée la plus « sociale » cette semaine,

SG14 – matin

Michael Wong explique aux gens comment se passe une rencontre de WG21, avec le rythme particulier (beaucoup plus « relaxe » à CppCon que dans une vraie rencontre de WG21, mais tout de même) et présente l'ordre du jour.

Nous sommes une cinquantaine dans la salle. Quelques membres réguliers de WG21 comme moi, Michael Wong, Lawrence Crowl, Ville Voutilainen; plusieurs gens de l'industrie. Au moins un autre universitaire. Paul E. McKenney est là aussi. Des gens curieux, des gens du monde des cartes graphiques. C'est Michael Wong qui anime. Je constate qu'il a ajouté ma proposition envoyée hier soir à l'ordre du jour; c'est apprécié. Je constate que Bjarne Stroustrup va se joindre à Gabriel Dos Reis, moi et Alex Rosenberg (de Sony) pour la partie controversée (finalement, vous le verrez plus bas, Bjarne Stroustrup et Gabriel Dos Reis se sont joints à nous mais tardivement, pour prendre des nouvelles, et c'est plutôt Sean Parent qui est venu réfléchir avec nous).

Michael Wong informe les gens qui doivent s'absenter pendant la journée qu'ils doivent être présents lorsque nous discuterons de leurs propositions, et donc qu'ils doivent pouvoir être rejoints.

Début du contenu technique

On a plusieurs sujets à l'ordre du jour. Certains ont été ajoutés cette semaine, suite à des interventions sur divers forums ou à des questions posées lors de conférences. Michael Wong signale qu'il est ouvert à les traiter aujourd'hui dans la mesure où quelqu'un est disposé à prendre le relais et à expliquer le contexte / le problème / à situer la discussion. On parle ici de :

Les propositions qui seront acceptées aujourd'hui doivent être révisées au plus tard jeudi soir pour partir vendredi en vue de Kona.

Fixed Point Real Numbers – John McFarlane

Michael Wong demande à Lawrence Crowl s'il est ouvert à présenter sa propre proposition, déjà devant un autre groupe d'études. Lawrence Crowl dit oui.

John McFarlane présente son implémentation. C'est très technique, très mathématique, et on a des questions sur les erreurs d'arrondis (il existe des solutions, mais on est archi prudents sur le nombre d'instructions qui sera requis, p. ex. : arrondir peut impliquer une alternative – un if – pour traiter le cas des négatifs, ce qui serait un irritant important ici).

John McFarlane mentionne que le plus grand irritant dont il a eu vent avec sa proposition tient à la représentation de l'exposant dans le type, mais mentionne qu'il propose une fonction make_fixed<>() pour alléger cette tâche.

Il travaille encore fort sur certains cas de comportement indéfini, et des difficultés avec certaines opérations qu'il voudrait constexpr. Il lui reste des fonctions clés à exprimer (p. ex. : des fonctions trigonométriques). Il montre des assertions statiques validant certaines de ses opérations comme la conversion d'un nombre à virgule flottante vers un nombre à virgule fixe sans décimales. C'est chouette!

Q : que fais-tu quand on a une multiplication par exemple, et quand tu as besoin d'une variable temporaire de plus grande « capacité »?

R : je m'en occupe (il explique comment)

Q : quelle latitude a-t-on pour le type sous-jacent?

R : ça va bien avec des entiers primitifs. C'est plus compliqué avec des trucs comme des entiers atomiques

Q : c'est bien un nombre à virgule fixe binaire, pas décimal, n'est-ce pas?

R : oui. Pour des applications financières, avec dollars et sous, ce n'est pas le bon type.

Lawrence Crowl prend ensuite le plancher pour présenter sa propre proposition. Son type ne vise pas le même créneau : c'est fait pour des valeurs entre et , et des sommes inférieures ou égales à . Sa proposition examine les plages de bits des opérandes pour éviter les débordements; elle évite d'ailleurs les débordements en tout temps, sauf (a) lors d'une affectation ou (b) lors d'une conversion. La perte d'information résultante doit être faite selon un mode choisi par le code client et est représentée par des types (fastest, negative, truncated, near_odd, etc. incluant impossible si, sur le plan analytique, on peut démontrer qu'il n'y en aura pas). C'est pas toujours supporté par le matériel mais on peut toujours le faire raisonnablement bien en assembleur.

Q : côté vitesse?

R : avec le mode « pas cher », soit truncate, on a le même code machine qu'avec un type de nombre à point fixe codé manuellement

Q : quel est le comportement opératoire par défaut?

R : je préconise near_odd. C'est le plus cher mais le plus précis; je pense que les gens qui ont besoin de vitesse voudront choisir le mode qui leur convient, et que « plus précis par défaut » est le choix le plus sain.

Q : pensez-vous couvrir les points fixes décimaux, pour le monde de la finance?

R : on a eu des propositions en ce sens au comité, et je ne serais pas surpris d'en voir une être adoptée dans le proche futur

Michael Wong reprend le collier pour voir s'il y a de l'intérêt. Lawrence Crowl suggère que ce dossier soit poussé vers le groupe d'étude sur les questions numériques; selon lui, SG14 souhaite que le problème soit réglé, mais une salle de spécialistes de calculs numériques serait probablement le bon forum pour étude approfondie et une éventuelle adoption. Il y a un sentiment positif dans la salle; les deux propositions ont des forces complémentaires. La complexité des calculs à point fixe est, selon les termes choisis par l'audience, terrifiante; Lawrence Crowl lance à la blague (ou pas, mais en souriant) qu'il y a une raison pour laquelle les nombres à virgule flottante ont « gagné la guerre ».

JF Bastien recommande qu'on fasse générer du code machine par quelques compilateurs pour voir si on obtient quelque chose de raisonnable; un autre mentionne que l'exactitude est essentielle à ses yeux. JF Bastien indique que memory_order_consume est un cas d'espèce : on pensait bien que c'était faisable et on sait qu'on peut le faire « à bras » mais on a eu une surprise en pratique. Faudrait s'assurer, avec ces types, que c'est possible.

Q : est-ce un cas de bibliothèque ou a-t-on besoin d'un support du langage?

R : il nous manque un truc dans le langage et c'est le Rounding Right Shift. SG1 a approuvé, mais faut voir si les fournisseurs de matériel l'implémenteront.

David Sankel mentionne qu'en général, à WG21, on ne regarde pas trop le code machine, mais que dans un monde comme celui du jeu, il se peut qu'on ait à changer notre mode de pensée. Un autre mentionne que dans le monde du jeu, pour un type comme celui-ci, le type sera très spécifique et codé manuellement, probablement en assembleur. Un autre indique qu'avec l'implémentation la plus rapide, ce qu'il voit est pas mal ce qu'il veut alors il est à l'aise avec les propositions.

Fin du contenu technique

On doit s'arrêter pour aller au Keynote. Il nous en reste encore beaucoup à faire...

Pour voir sa présentation : https://www.youtube.com/watch?v=sWgDk-o-6ZE&feature=youtu.be

Pour voir les diapos de sa présentation : https://github.com/sean-parent/sean-parent.github.io/wiki/presentations/2015-09-23-data-structures/data-structures.pdf

Keynote – Sean Parent: Better Code: Data Structures

Petite jasette avec un chic type du gouvernement canadien; il sort d'une rencontre à propos des exceptions, alors je prête l'oreille puisque cet après-midi, je dois discuter du coût de ce mécanisme. Ce matin, on nous sert des bagels; j'en mange un en vitesse (je n'ai pas eu le temps de déjeuner; c'est une très grosse journée).

Début du contenu technique

Jon Kalb prend le pouls de la salle. C'est enthousiaste. Il présente Sean Parent mais tout le monde le connaît.

Sean Parent explique brièvement ce qu'il fait ces jours-ci. Il mentionne une de ses conférences l'an passé, et dit avoir commencé à écrire un livre, qu'il enrichit à chaque conférence.

Sean Parent : le but proposé aujourd'hui est No Incidental Data Structures. Il pensait en faire un tutoriel, mais il se ramasse à faire un Keynote, par la faute de Jon Kalb

Sean Parent : un but n'est pas la même chose qu'un conseil. Un but, ça peut être difficile à atteindre, mais on essaie fort fort

Sean Parent : qu'est-ce qu'une structure de données? « A format for organizing and storing data » selon la littérature. Il n'est pas 100% satisfait

Sean Parent : qu'est-ce qu'une structure? « Things related to other things »

Sean Parent : un architecte se préoccupe de relations

Sean Parent : malheureusement, une informaticienne ou un informaticien, c'est traditionnellement pas bon avec les relations

Sean Parent propose une diapo blanche, suivie d'une autre avec quatre bits (), qui représentent quatre bananes... ou bleu... ou ... La relation sémantique entre l'entité et ces quatre bits. Aussi, collectivement, ces quatre bits ont une forme, et peuvent représenter une plage de à inclusivement (un nybble signé; il s'amuse)

Sean Parent : on souhaite préserver la relation sémantique entre l'écriture et ce qu'elle représente. Perdre la relation, c'est perdre la capacité de déterminer la validité d'une valeur

Sean Parent : discute de validité, par exemple pour un itérateur dans un vecteur. Bouger un vecteur ou le redimensionner brise la relation entre lui et ses itérateurs (du moins ceux en cours d'utilisation). La validité d'une valeur peut aussi être non-spécifiée, suite à un mouvement (Moved-From) ou à une levée d'exception. Valide mais non-spécifié est un peu contradictoire; la relation sémantique est perdue, on est en pratique invalide. Sean Parent parle d'objets partiellement formés et cite Alexander Stepanov

Sean Parent : un invariant est une propriété qui doit tenir pour qu'une valeur soit valide, pour qu'elle préserve son sens

Sean Parent ajoute une autre valeur, , et décrit des relations que l'on peut établir (, par exemple, ou hash()!=hash()).

Sean Parent montre un élargissement de l'environnement de ces bits et parle d'espace adressable. Un entier sur la pile qui n'est pas initialisé n'a pas de sens; valeur implique sens

Sean Parent dit que Jon Kalb et Marshall Clow sont dans une relation. Disons une relation physique (les gens rient; Sean Parent dit qu'il se venge sur Jon Kalb et présente ses excuses à Marshall Clow). De même, les objets 0011 et 0100 ont une relation spatiale, décrite par leurs adresses. On peut décrire une relation entre les lieux physiques des adresses, et enrichir le sens du discours. Sean Parent qualifie de puritains les gens (ou les langages) qui nient les relations physiques (rires!)

Sean Parent : une autre relation est fonctionnelle, soit . Il arrive qu'un résultat soit non-spécifié, donc que la sémantique de la relation ne puisse être établie

Sean Parent : une autre relation est Whole-Part. Cette relation a quatre propriétés :

Ces quatre propriétés permettent à un type de se comporter comme un type régulier. Les conteneurs standards sont de tels types

Sean Parent : qu'est-ce qu'une structure de données? Elle utilise des valeurs et des relations physiques pour encoder des relations sémantiques sur des collections d'objets. Les choix d'encodage peuvent avoir un impact considérable sur la vitesse des opérations.

Sean Parent parle de l'impact de la hiérarchie de la mémoire sur la vitesse, avec des chiffres. Il montre que le log d'un trillion est , alors que la différence entre un accès en Cache L1 ou en mémoire vive est un facteur d'environ . Brrr... Il parle ensuite de l'impact de vector dans Photoshop (Sean Parent est le Principal Scientist chez Adobe)

Sean Parent parle de stable_partition() et de son impact. Il dit qu'on lui a déjà affirmé que les algorithmes sont très compliqués, et que stable_partition() est difficile à écrire. Sean Parent dit « mais non » et montre comment le faire :

Sean Parent en arrive à un truc tout simple. Il mentionne qu'on peut écrire reverse() en termes de rotate() et que le résultat est et fonctionne sur un forward_list

Sean Parent renomme son prédicat stable_partition_position() et montre qu'en retirant une indirection dans l'algorithme, on peut en faire un outil pour réaliser une projection d'un espace vers l'autre.

Sean Parent : exemple d'algorithmes et de travail minimal. Il part d'un vecteur de nombres mélangés et d'un intervalle à trier. Marshall Clow recommande partial_sort(), et Sean Parent dit qu'on en aura besoin mais c'est pas notre point de départ. On commence avec nth_element(). Il se trouve qu'un effet secondaire de cet algorithme est de partitionner l'espace (les plus petits que l'élément en question avant, les plus grands après, mais dans le désordre). L'algorithme partial_sort() intervient ensuite. Il obtient sort_subrange() avec six lignes de code. Effet de bord : notre algorithme partitionne lui-aussi l'espace, par définition

Sean Parent : nous établissons des relations spatiales entre nos objets, et ce faisant nous créons du sens

Sean Parent : qu'est-ce qu'une Incidental Data Structure? C'est une structure de données sans relation Whole-Part. Une telle structure de données nous empêche de raisonner sur notre code. Le plus vilain coupable de ce type de pêché est la structure de données autoréférentielle. Un conteneur qui peut contenir des éléments mais qui est aussi un élément. On a souvent ça en pratique. Sean Parent montre que ça donne des graphes complexes avec des cycles, et que ça brise la relation claire de responsabilité... ça fait du spaghetti!

Sean Parent : les hiérarchies sont importantes. Il y en a partout, et on tend à faire des structures de données intrusives et à briser notre capacité à raisonner correctement. On a l'impression que les trucs arborescents sont -ish, mais en pratique ils sont plus -ish. On veut des structures de données parallélisables comme des Quad Trees.

Sean Parent : dans une séquence de éléments, il y a positions. Dans une hiérarchie, le concept est beaucoup moins clair. Il montre une illustration fabuleuse avec un lacet et des billes... Wow! Et ça montre qu'une hiérarchie sur un lacet est en fait une séquence, qui décrit un parcours unidirectionnel... On peut donc la naviguer! Il montre comment éliminer des éléments en soulevant le lacet et en regardant ce qui tombe...

Sean Parent : il y a deux semaines, ma femme est tombée sur le lacet et les billes. Je me suis dit qu'un jour, on mettra peut-être les lacets de Sean Parent dans un musée. Je voulais apporter le lacet au colloque. Elle m'a regardé avec une sorte de dégoût et m'a enlevé le lacet. Comme je le disais au début, les informaticien(ne)s sont mauvais avec les relations

Sean Parent : en conclusion :

Questions

Q : outre la STL, avez-vous d'autres exemples de bibliothèque de qualité qu'on pourrait prendre à titre d'exemple?

Sean Parent : Boost et d'autres, mais c'est souvent tellement optimisé que ça devient difficile à lire. Les versions originales sont plus épurées. Les cours en ligne d'Alex Stepanov sont très bons

Q : allez-vous écrire un livre?

Sean Parent : ça s'en vient. Reste juste à l'écrire

Q : vos conférences les plus récentes me semblent suggérer que vous voyez le code comme une sorte de structure de données, et que vous voyez les boucles « brutes » sont des Incidental Data Structures. Est-ce le cas?

Sean Parent : oui (il cite quelques sources). Dans un sens plus général, tout ça est une question de relations. Il existe plusieurs sortes de relations dont on peut tirer profit. On veut en arriver à des fonctions qu'on peut lire en comprendre, dont on peut tirer du sens

Q : une des Incidental Data Structures les plus connue est l'itérateur. Votre avis?

Sean Parent : faut les utiliser correctement, les encapsuler. C'est une abstraction utile mais de bas niveau

Sean Parent s'excuse d'avoir fini un peu plus tôt que prévu. Moi, sérieusement, j'ai trouvé ça brillant comme truc.

Fin du contenu technique

J'ai mangé une bouchée rapidement et je suis retourné à ma préparation de chiffres, schémas et analyse pour cet après-midi. Le document est sur ../Developpement/Exceptions-Costs.html si vous êtes curieuses ou curieux.

Pendant que je travaille non-loin de la salle où nous travaillerons tantôt, un petit attroupement de programmeurs fonctionnels haut de gamme bavarde de λ constexpr derrière moi : Louis Dionne, Paul Fultz II, David Sankel, Richard Smith et quelques autres. C'est amusant.

SG14 – après-midi

Petite jasette avec le très sympathique Matt P. Dziubinski.

Début du contenu technique

On reprend où on a laissé ce matin.

Flat Map Container Design – Sean Middleditch

Sean Middleditch : explique le plan de match, les avantages et les inconvénients.

Q : quelles sont les différences en termes d'interface avec les conteneurs standards?

R : ils sont contigus en mémoire et ils sont ordonnancés (nécessaire pour certains cas d'utilisation)

Q : que se passera-t-il si quelqu'un utilise un adaptateur « flat » sur un substrat qui n'est pas contigu en mémoire?

R : ça se vérifie à la compilation

Q : je constate qu'on peut être Cache-Sensitive pour les parcours ou pour les fouilles. Peut-on faire un choix d'ordonnancement, par politique?

R : j'aurais fait deux adaptateurs distincts mais je suis ouvert aux politiques

Q : permettra-t-on un Delayed Insert ou un Delayed Sort?

R : dans ma compagnie, on l'a mais personne ne s'en sert. Peut-être n'est-ce qu'une question d'éducation?

Q : les adaptateurs me préoccupent, car un tiers pourrait utiliser le substrat, par exemple pour faire des insertions en bloc, et briser les invariants de l'adaptateur

Ville Voutilainen : ça dépend de l'interface de l'adaptateur

Q : quelles sont les garanties face aux exceptions?

R : j'en ai encore à apprendre sur le sujet. Puisque les adaptateurs « flat » font des modifications sur place, je crains qu'on ne puisse pas faire mieux. Mais je ne suis pas certain...

Q : les algos standards ne sont pas nécessairement optimisés pour traverser un substrat segmenté comme un std::deque; si on permet ça, les caractéristiques de « performance » des Flat Containers vont souffir.

R : noté

Q : que faire si le conteneur est dans un état indéterminé?

R : je fermerais le programme si ce n'était que de moi

Q : tiendras-tu un backup des valeurs juste au cas?

R : non

Q : tu peux tout mettre noexcept alors, ainsi si quelqu'un lève une exception, le programme va mourir

R : si on faisait ça, on ne pourrait même pas mettre un std::string dans un Flat Container

Q : faut que l'objet puisse être détruit pour être Exception-Safe, garantie de base. Une solution serait de détruire tout ce qui dérange

R : pas fou

Patrice Roy : c'est une facilité spécialisée, pas un outil généraliste. Peu importe ce à quoi on arrivera, faudra avertir tout le monde que placer un élément dont la copie ou le mouvement lève une exception dans un Flat Container, c'est courir après le trouble

Lawrence Crowl : tu peux documenter que si une exception est levée, le conteneur sera vidé. Simple et clair

David Sankel : on peut même faire du l'état post-exception une question de QoI.

Lawrence Crowl : je ne pense pas qu'on veuille laisser flou l'état du conteneur. On peut au moins indiquer « le conteneur n'est pas utilisable mais est destructible ». Comme ça, on n'aura pas d'attentes non-portables

Q : séparer les clés et les valeurs peut être intéressant, mais dans ce cas il se peut que flat_map ne soit pas le bon terme (ça briserait les attentes de gens qui utilisent std::map)

On bavarde un peu de choix d'implémentation. C'est intéressant. Quelqu'un suggère plusieurs conteneurs selon l'organisation du substrat, et une interface commune pour les parcourir

Michael Wong explique la procédure de votation. On vote. C'est un pour majoritaire. Il reste du travail à faire par contre, et les gens expliquent ce qu'il reste à faire selon eux.

Je serai celui qui devra porter cette proposition à Kona, apparemment.

Extending raw_storage_iterator – Brent Friedman

Brent Friedman : le type raw_storage_iterator existe mais est peu utilisé et j'essaie de le rafistoler. Il permet de construire des objets sur de la mémoire non-initialisée, mais seulement par copie. Je propose qu'on y ajoute la construction par mouvement. Ville Voutilainen indique qu'on en parle déjà à LEWG. Brent Friedman dit cool! Michael Wong dit next! Brent Friedman dit qu'il manque aussi une fonction de fabrication, qu'il propose, et un mécanisme d'emplacement.

Q : je viens de l'implémenter ce matin et il m'a semblé qu'une autre approche était préférable. On utilise surtout raw_storage_iterator avec std::transform()

R : oui, je vois l'intérêt (on jase de cas d'utilisation)

Vote : approuvé

Extending Memory Management Tools – Brent Friedman

Brent Friedman : je propose les algorithmes suivants, opérant sur de la mémoire brute :

Brent Friedman : je sais que les noms peuvent être imparfaits.

Brent Friedman : j'ai vu dans la bibliothèque de Dinkumware un uninitialized_move(), alors je ne suis pas le seul à vouloir cela, mais c'est pas standard

Q : on aurait aussi besoin d'un uninitialized_transform()

R : oui

Vote : approuvé

Unstable Remove Algorithms – Brent Friedman

Brent Friedman : celui-ci est important pour moi. Ces algorithmes peuvent être significativement plus rapides que leurs équivalents « stables ».

Brent Friedman : cette proposition amène unstable_remove() et unstable_remove_if() mais on pourrait en imaginer d'autres

Q : combien de fois appliques-tu le prédicat à chaque élément?

R : une fois. Bouger à la fin peut être plus rapide que faire des swap(). Outre ça, c'est comme unstable_partition()

Q : bonne idée!

Vote : approuvé

(pause)

On prend une brève pause vers 15h5. Je vais déplacer mes documents dans un GitHub sous peu (là, ils sont sur h-deb pour dépanner – document en anglais)

(fin de pause)

On continue...

Rolling Queues / Rings – Guy Davidson

Guy Davidson présente le problème. Un veut un tampon circulaire qui ne fragmentera pas la mémoire. Pas besoin de circuler de manière bidirectionnelle. La proposition est un adaptateur qui se comporte comme std::queue mais push() peut échouer parce que le substrat est plein.

Guy Davidson : il existe des tas de ring dans le monde. C'est un exercice classique à l'école. Dans un de mes jeux, on en a trois implémentations distinctes (c'est gênant!). Il y a donc clairement un besoin

Guy Davidson : présente la proposition formelle. Il a mis des implémentations de référence à la disposition des gens. Le static_ring est complet, le dynamic_ring pas tout à fait.

Q : pourquoi ne pas paramétrer le substrat?

R : oups! Je pensais l'avoir fait

Q : y a-t-il une différence fondamentale dans l'interface?

R : sur un tableau, la taille du tableau influence la taille de ring. Sur d'autres substrats, il faut suppléer la taille à la construction

Lawrence Crowl : SG1 a une proposition de concurrent_queue, très axée sur la gestion de la concurrence. Il serait peut-être sage de faire converger les interfaces

Michael Wong : le problème de concurrent_queue est de bien gérer les suppressions concurrentes

Lawrence Crowl : il est presque prêt, sauf pour un détail agaçant

Michael Wong : il faudrait donc regarder l'autre?

Guy Davidson : le but de ma proposition est d'éliminer complètement l'allocation dynamique de mémoire

Lawrence Crowl : faut juste être cohérents

Q : offres-tu des itérateurs? (dans le code, oui, mais ça semble accidentel)

R : je pensais que non, parce que je cherchais à suivre l'interface de std::queue

Q : tu pourrais faire du Perfect Forwarding du substrat et avoir un seul ring, qui serait de taille fixe si le substrat ne peut croître

R : intéressant

Q : as-tu pensé à fixed_ring plutôt que static_ring?

R : j'aime!

Q : as-tu pensé lui confier, dans le cas « fixe », de la mémoire brute?

R : veux-tu un job?

JF Bastien : je ne passerais pas trop de temps à chercher des noms ici. Le comité va les changer et sait quoi faire

Q : je viens de m'apercevoir qu'avec de la mémoire brute, le choix d'un substrat (tableau, vecteur) rend la question de l'initialisation des éléments confuse à mes yeux. Que retournerait la méthode size()? Au fond, c'est jamais vide, non? Et un emplace() est un peu confus comme choix de nomenclature...

Ville Voutilainen : on pourrait utiliser uninitialized_storage au lieu d'un tableau, simplement.

Il y a plusieurs considérations techniques à débattre pour ce conteneur. Le fait qu'il soit de capacité fixe (potentiellement) influence son interface. Des trucs comme begin() et end() sont délicats, conceptuellement (comment distinguer un anneau plein d'un anneau vide?). Il y a de la réflexion à faire... Quelqu'un a suggéré un ring_view, mais ce serait une proposition distincte

Ville Voutilainen : on pourrait déplacer le subtrat dans le ring pour éviter des allocations

Guy Davidson : je pense que je vais recentrer cette proposition pour éviter qu'elle ne se transforme en une espèce de couteau suisse

Thread-Safe STL – (nom m'a échappé)

La STL telle qu'elle existe présentement ne comprend pas assez de mécanismes de synchronisation. Je veux ajouter ce qui manque

Q : je ne comprends pas ce que tu veux faire. Peux-tu préciser? (la réponse est vague; il veut aider)

Michael Wong : on entend le souhait. Faudrait préciser l'intention

Gor Nishanov : je suggère que tu précises le problème à résoudre. Ce serait un bon point de départ

Controlling Thread Stack Size at Creation Time – Patrice Roy

Ce fut intéressant. Mon texte était un ballon d'essai (je l'ai écrit en une heure ou deux hier), et j'ai eu des réactions pertinentes. En résumé :

On va poursuivre les échanges sur la liste de diffusion de SG14

Je me sens un peu mal; j'ai mis un peu de pression pour que ça bouge et j'ai bousculé des gens qui ne l'ont pas vu venir. Quand l'un des intervenants (Lawrence Crowl, que j'aime beauoup) a dit que le concept de pile ouvre une boîte de Pandore, et qu'à moins que je ne trouve quelqu'un dans Core pour m'aider... j'ai répondu « heureusement, je suis dans Core » et je suis passé à un autre appel.

J'ai eu plusieurs visiteuses et visiteurs pendant la pause, que ce soit pour parler philosophie (Gor Nishanov, brillant), pour faire connaissance (Nicolas Guillemot) ou pour m'offrir de contribuer (plusieurs personnes, mais je n'ai pas les noms... Il y a un vrai problème ici, mais il est subtil).

(pause)

Ok. Ici, je dois indiquer un détail : nous avons pris une brève pause vers 16h30, puis le reste de la journée a été un feu roulant pour moi. J'ai lancé les débats sur un sujet controversé (je le savais, c'était mon rôle, j'étais prêt), sujet qui a occupé la totalité du temps restant en après-midi. Plusieurs sujets ont été remis à plus tard, soit :

Tout ça, tristement, a « pris le bord ».

(fin de pause)

C'est parti...

Exception costs – Patrice Roy, Alex Rosenberg, Gabriel Dos Reis et Bjarne Stroustrup

J'ai rayé Gabriel Dos Reis et Bjarne Stroustrup car ils sont venus, mais à la toute fin, et ont surtout écouté, n'ayant pas participé aux débats. Par contre, Sean Parent est venu réfléchir avec nous. Il est resté dans la salle mais nous avons échangé à quelques reprises.

J'ai pris le début de cette rencontre en charge. J'ai présenté du code de test sur le coût des exceptions (visible sur ../Developpement/Exceptions-Costs.html si vous voulez voir), avec une mauvaise nouvelle (le coût de ce mécanisme est non-nul, et on paie probablement trop cher pour le noment) et une bonne nouvelle (il y a de l'espoir, pour celles et ceux qui utilisent ce mécanisme, car il y a clairement place à amélioration; les implémentations que j'ai mesurées varient radicalement en qualité pour des cas d'optimisation distincts).

J'ai présenté chiffres, graphiques, code de test. Pris les questions. Répondu aux questions. C'était intéressant mais je savais ce que j'allais entendre. Les plus éveillés ont suggéré des pistes de tests intéressantes, mais les chiffres et les graphiques parlaient d'eux-mêmes. Sean Parent suggère d'ajouter un test où il n'y a aucun throw malgré un try pour voir comment les compilateurs s'en tirent en analysant les chemins d'exécution pour optimiser le code inutile; c'est une bonne idée. Le problème bien entendu est qu'une fonction qui n'annonce rien peut lever n'importe quoi, et que je ne pourrai utiliser aucun des outils usuels pour ce genre de test (string, vector<int>) car ils ne sont pas noexcept pour la plupart de leurs opérations, étant susceptibles d'avoir recours à l'allocation dynamique de mémoire. Je vais organiser quelque chose.

Plusieurs sont surpris par l'ampleur des variations, et constatent avec moi que les coûts en temps dépassent ce à quoi il semble raisonnable de s'attendre. En retour, les coûts en espace, qui sont bien réels, sont de moins grande envergure que ce qu'on m'avait prédit. C'est encourageant sur ce plan. Aussi, j'ai du code plus rapide avec exceptions que sans exceptions dans le cas de std::string sans SSO, et ce de manière systématique mais seulement sur l'un des compilateurs testés.

Alex Rosenberg est venu par la suite. On parle ici d'un programmeur / gestionnaire important dans le monde du jeu. Il travaille pour Sony. Il est honnête : pour l'industrie, les exceptions, c'est Over My Dead Body. On échange, on examine diverses options, on regarde les conséquences de ne pas en avoir, mais je comprends aussi son point de vue : pour plusieurs compagnies de jeu vidéo (pas toutes), les outils et bibliothèques utilisées ne sont pas Exception-Safe, alors pour eux, intégrer le support aux exceptions est un retour négatif sur l'investissement, un coût qu'ils ne paieront pas. Ils voient le support aux exceptions dans la bibliothèque standard comme un facteur de ralentissement pour une caractéristique dont ils ne veulent pas, et souhaite standardiser des mécanismes pour le « mettre à Off ». J'ai vérifié auprès d'Alex Rosenberg et il a été honnête : il n'en voudrait pas même si ça accélérait ses jeux en comparaison avec ses approches actuelles. C'est viscéral.

Au moins une personne dans la salle indique avoir livré un jeu avec exceptions actives dernièrement et rapporte que le jeu fonctionne très bien. Un autre souligne que DirectX, avec la version 12, lève des exceptions lors d'un problème (je n'ai pas vérifié, mais il y avait du mécontentement dans la salle).

On a ensuite examiné les options qui s'offrent à nous, car la communauté de développement de jeux est une partie importante de la communauté de programmeuses et de programmeurs C++ au sens large (c'est pas un sous-ensemble strict, mais pas loin, du moins pour les jeux dits AAA). Il y en a plusieurs, mais faut voir ce qui serait préférable :

Après les échanges, qui ont pris la totalité de la fin de l'après-midi, Michael Wong a demandé aux gens de se porter volontaires pour résumer (un paragraphe ou deux) chaque avenue mise de l'avant, pour une éventuelle proposition exploratoire commune qui sera apportée devant EWG. On a attribué ces responsabilités aux intéressés. Derrière la salle, on trouvait entre autres Bjarne Stroustrup, Gabriel Dos Reis, David Sankel, Ville Voutilainen et moi, tous de WG21, et Gor Nishanov qui y est presque. Va falloir réfléchir à cette question dès maintenant.

Fin du contenu technique

Après toutes ces aventures, il était 18h20. Michael Wong m'a approché pour me demander d'être sur un panel d'experts du monde du jeu à 19h. Bon, changement de plan, alors on fonce.

Pour voir ce panel : à venir...

SG14 – Panel

J'ai donc pris la scène avec Michael Wong et des collègues (très pertinents et intelligents) de SG14 pendant une heure environ. Liste incomplète : Sean Middleditch, Guy Davidson, John McFarlane, Nicolas Guillemot, Scott Wardle, Alex Rosenberg, mais il m'en manque. Voir https://twitter.com/meetingcpp/status/646873772289486848/photo/1 pour une image.

Vous comprendrez que je n'ai pas pris de notes pendant cette période, étant quelque peu sollicité, alors ce qui suit correspond aux grandes lignes de ce que j'ai retenu, et ne doit pas être considéré pour autre chose qu'un bref résumé.

Début du contenu technique

En gros, ce qui s'est passé :

On a fini sur une phrase amusante. À une question de la salle (je ne me souviens même plus du sujet), Scott Wardle a lancé « moi, je règle ça en me codant une macro ». On s'étouffe de rire, fatigués. Je lance à Scott Wardle « tu ne viens pas de finir le panel avec ça, c'est pas sérieux? », il y pense, on éclate de rire.

Fin du contenu technique

Pour voir ces présentations :

Kate Gregory : Lightning Talks

Suite au panel, une série de petites présentations. Je suis resté en attendant l'autobus, mais j'ai dû quitter en cours de route.

Début du contenu technique

Edouard Alligand Joel Falcou – Brigand

Présentation de leur chic bibliothèque de métaprogrammation.

Jens Weller – A Different Way to use Boost Serialization

L'ami Jens Weller prend le temps de nous expliquer comment il a réglé un bogue un peu compliqué (pour lequel on avait échangé des idées lui et moi plus tôt cette année).

(je n'ai pas vu les autres présentations; j'étais brûlé et je suis allé prendre mon autobus)

Fin du contenu technique

Une fois arrivé, je me suis acheté un saucisson, j'ai fait cuire mon reste de pâtes, je me suis coupé une tomate et un peu de fromage pour me faire une sorte de salade tousski en prenant une bière. Enfin, tombé d'épuisement.

Jour 4 24 septembre 2015

Coûts du séjour pour aujourd'hui :

Dur matin. J'ai un début de rhume qui n'arrête pas de « début-de-rhumer », et le manque de sommeil commence à m'affecter. Ça aura été très intense comme semaine.

Belle journée de conférences en vue, par contre.

Pour voir sa présentation : à venir...

Chuck Allison: Project-Based C++, a project-based learning approch to learning modern C++

Chuck a quitté l'industrie il y a une quinzaine d'années pour enseigner à UTAH University. Il reçoit des étudiant(e)s « intermédiaires », qui ont fait un cours de structures de données et quelques cours de programmation structurée.

Début du contenu technique

Chuck Allison raconte. À son université, le début de la formation se fait en C# là-bas, puis C++ prend le relais

Il se donne pour objectif de les amener vers une meilleure maîtrise du langage

Il insiste sur la saine gestion de la mémoire, sur RAII.

Il utilise la bibliothèque standard, les conteneurs, les algorithmes, et la programmation concurrente

Ses cours sont une séquence de projets

Un projet commence par un problème à résoudre, pour focaliser l'attention des étudiant(e)s et encadrer leur pensée

Il leur donne d'office une « rubrique » pour qu'elles / ils puissent évaluer la qualité de leurs résultats, de leur travail : un niveau « base » (p. ex. : aucune constante littérale), un niveau « intermédiaire » (pas de code superflu; utiliser les algorithmes standards au lieu de faire des boucles) et un niveau « efficace » (valider les préconditions des fonctions).

Quelqiues projets proposés :

Pour la deque, son expérience est que les étudiant(e)s, même après un cours de structures de données, ne maîtrisent pas les types de mémoire à leur disposition (tas, pile, statique) et la gestion de cette mémoire. Il leur explique l'enjeu (insérer et retirer efficacement aux deux extrémités), et pourquoi vector ou un tableau ne feront pas le travail. Il leur donne une interface à laquelle se conformer. Il constate que les étudiant(e)s tendent à démarrer au centre d'un petit tableau, et allouent + chaînent les blocs quand ils frappent une extrémité. Pour simplifier le problème, il leur rend la classe incopiable et ne se préoccupe pas de const (les étudiant(e)s arrivent de C#).

Il leur donne ensuite les sujets qui les aideront à comprendre ce qu'ils font : lvalues, rvalues, arithmétique de pointeurs, pointeurs const, RAII, etc. Il leur explique la métaphore des séquences à demi ouvertes.

À la fin du projet, il prend les réflexions des étudiant(e)s. Un des constats amusants est que plusieurs remarquent l'intérêt de réfléchir sur papier, et la satisfaction de réussir.

Pour le groupement de mémoire, il commence par expliquer la différence entre new et new[], et discute de delete et de delete[]. Le problème posé est que chaque new coûte un peu plus que ce qui est demandé, alors comment peut-on mieux administrer la mémoire? Il en profite pour montrer le new positionnel.

Dans leur réflexion a posteriori, la compréhension des pointeurs et de reinterpret_cast semble nettement meilleure chez ses étudiant(e)s.

Le troisième projet implique de consommer des enregistrements de taille fixe et des chaînes de caractères. Il leur fait consommer du XML (limité), pour pratiquer la manipulation de chaînes de caractères, puis leur fait écrire des enregistrements binaires de taille fixe. Il s'assure qu'il y ait des erreurs dans le flux en entrée pour qu'il y ait de la gestion d'erreurs, et s'organise pour leur faire utiliser des unique_ptr. Certain(e)s étudiant(e)s habitué(e)s avec C# se sont questionnés sur l'incapacité de copier un unique_ptr...

Le quatrième projet, portant sur le traitement de données numériques, tend à mettre en valeur les forces de C++ quand on utilise les algorithmes. Il part d'un fichier contenant des données qui représentent des variations de voltage, et cherchent des « pics » d'une certaine amplitude et calculent la surface sous la courbe. Ils commencent par réduire le bruit dans la courbe. Il leur dit quels algorithmes il a personnellement utilisé, et les laisse faire leurs choix.

Le suivant est de repérer les mots dans un fichier, puis d'afficher les mots avec les lignes et le nombre d'occurrences par ligne. Les mots de casse distincte doivent être distincts mais groupés ensemble. Il préconise un map<string,map<int,int>> et leur fait écrire le comparateur qui va avec.

On passe vite sur les autres (le temps file). Il aime bien la structure que cette approche donne à ses cours.

Q : c'est un cours de quel format?

R : six heures par semaine, sept semaines, l'été

Q : les étudiant(e)s utilisent-ils des Frameworks de tests?

R : 55 lines of C++. C'est mon propre Framework. Regardez sur Google

Q : taille des groupes?

R : 45 étudiant(e)s environ

Q : comment assurez-vous le suivi de leurs apprentissages?

R : beaucoup de courriels

Fin du contenu technique

C'était intéressant. Je vais essayer de reparler avec lui d'ici la fin de la journée.

Pour voir sa présentation : https://www.youtube.com/watch?v=cg1wOINjV9U

Louis Dionne : Metaprogramming: a Paradigm Shift

On se déplace vers la salle où Louis Dionne s'apprête à nous envoyer quelque chose de costaud. Je bavarde avec Matthew Karas du recours aux outils de test comme Valgrind dans l'enseignement, et avec Alex Boulanger de la vie en général.

Début du contenu technique

Louis Dionne se présente, et présente sa vision de ce qui est à son avis un nouveau paradigme de métaprogrammation.

Il Il parle de quadrants de programmation :

Runtime Computation : séquences de type homogène (p. ex. : vector<int>), Runtime Functions, Runtime Algorithms (qui peuvent faire de la prog de haut niveau avec des fonctions passées en paramètres)

constexpr Computation : des séquences constexpr, des fonctions constexpr et des algorithmes constexpr (qui ne sont pas standards mais sont implémentables)

Heterogeneous Computation : des séquences hétérogènes (tuple), des fonctions hétérogènes (template functions, foncteurs avec méthodes génériques) et des algorithmes hétérogènes (non-standards ici encore, comme prendre un tuple de différents types et générer un tuple de plusieurs string)

Affirmation : on a besoin d'algorithmes sur des séquences hétérogènes

Type-Level Computation : séquences MPL, métafonctions, traits, algorithmses sur les types (MPL aussi)

Affirmation : MPL est redondant. La programmation sur des tuple est plus générale que la programmation sur les types, et la subsume

Affirmation : C++ 14, avec auto pour les types de retour et les paramètres, change tout

Exemple : tester la présence d'un membre (un has_xxx). Avec C++ 17, void_t allège cela, mais on peut déjà le faire. Louis Dionne préconise un idiome plus simple encore :

auto has_xxx = is_valid([](auto t) -> decltype(t.xxx){});

Introspection : Louis Dionne montre comment faire avec Boost.Fusion, mais avec Boost.Hana avec des std::string évaluées à la compilation.

Générer du JSON? C'est pas nécessairement beau « à bras », mais avec Boost.Hana, on y arrive avec to_json(). Il montre comment faire.

Qualié des messages d'erreur? Traditionnellement, vraiment pas beau, mais avec static_assert, devient très clair

Temps de compilation : significativement meilleur, parce que l'implémentation est beaucoup plus simple depuis C++ 14

Affirmation : nous devons repenser la métaprogrammation

Comment? Il présente rapidement integral_constant. L'arithmétique traditionnelle prend deux constantes et génère un type qui représente (par exemple) leur somme. Il suggère une constexpr auto operator+() sur deux integral_constant distinctes, et qui retourne un integral_constant. On crée des objets, mais on raisonne sur le decltype des résultats. Par exemple :

static_assert(decltype(integral_constant<int,2> + integral_constant<int,3> == integral_constant<int,5>)::value, "");

C'est beau! Ou encore (à cause des conversions constexpr vers le substrat des integral_constant), ceci :

static_assert(integral_constant<int,2> + integral_constant<int,3> == integral_constant<int,5>, "");

... ou encore alléger avec des alias pour avoir :

static_assert(int_c<2> + int_c<3> == int_c<5>, "");

... ou encore, en codant l'opérateur template<char ...c>constexpr auto operator ""_c(), on a ceci :

static_assert(2_c + 3_c == 5_c, "");

... oh, j'aime!!! Sucré, mais vraiment chouette!

Ensuite, Louis Dionne calcule la distance euclidienne. Il montre le code avant (ouf!), puis le code après avec des constexpr auto et des paramètres génériques (ça suppose un sqrt() constexpr, mais il a codé ça). Ça prend, pour bien faire, C++ 14 pour créer des variables temporaires. Côté cool : ces nouveaux outils de « niveau valeur » vont aussi fonctionner à l'exécution, car constexpr permet ça.

On continue : il code times(f) pour faire du Loop Unrolling, genre int_c<5>.times(f);

On continue : on peut définir un operator[] sur un tuple qui prend un integral_constant, p. ex. : values[1_c] avec values de type tuple<...>

On a ratio et integer_sequence. Louis Dionne critique l'interface de std::ratio, qui bénéficierait de ses techniques, et recommande les [] sur un integer_sequence

Pour aborder les traits, on peut y aller de même :

template <class> struct type{};
template <class T> constexpr type<T*> add_pointer(type<T> const&) { return {}; }
template <class T> constexpr false_type is_pointer(type<T>) { return {}; }
template <class T> constexpr true_type is_pointer(type<T*>) { return {}; }

On peut maintenant manipuler des types comme s'il s'agissait d'objets!

Il s'est amusé avec Boost.Proto pour montrer que sa proposition s'adapte bien et permet une meilleure réutilisation du code existant.

Il fait une map type,valeur

Ensuite, il fait un static_switch (switch_) sur unBoost.Any et associe des λ à des cas (incluant default_ qui est un case_<default_t> et empty_ qui est un case_<void>). Son switch_ retourne une λ qui traite les cas. C'est une étude de cas intéressante, mais je vous invite à regarder ses diapos puisqu'il y a des subtilités qu'il vaut mieux voir dans le détail.

Il s'en sort avec à peu près 70 lignes de code au total, et c'est presque accessible au commun des mortels.

Q : temps de compilation?

R : une seconde, à peu près, mais j'ai beaucoup de tests unitaires

Louis Dionne fait un bref tour de Boost.Hana, avec ses conteneurs (incluant des string, set et map à la compilation, et un tuple supérieur à std::tuple à plusieurs égards)

Ça ne compile que sur Clang pour le moment. Louis Dionne dit que gcc 5 lui donne un peu d'espoir

Louis Dionne finit avec un plaidoyer pour que l'on pousse nos compagnies à adopter C++ 14, et nos vendeurs de compilateurs à se conformer au standard.

Q : quels éléments manquent au langage pour t'aider?

R : je veux une λ dans un contexte non-évalué (un decltype(λ)). Selon Richard Smith, on est rendus là. Je veux pouvoir opérer plus normalement sur des tuple et des integer_sequence (ça compilerait plus vite)

Q : accéder à un élément d'un parameter pack par indice?

R : transforme ton parameter pack en séquence avant de l'utiliser

Pablo Halpern : qu'est-ce qui fait que tu compiles plus vite que la compétition?

R : parce qu'on a de meilleures techniques d'implémentation

Q : as-tu essayé de faire un switch sur un Boost.Variant?

R : non, mais ça ne devrait pas être beaucoup plus difficile que pour Boost.Any (quelques échanges s'ensuivent)

(c'est fini, mais il montre quelques techniques d'implémentation d'algorithme alors je reste un peu)

Fin du contenu technique

C'était bien, ce truc. Quelques bonnes idées pour mes cours plus pointus.

Pour voir sa présentation : https://www.youtube.com/watch?v=nXaxk27zwlk&feature=youtu.be

Keynote – Chandler Carruth : Tuning C++: Benchmarks, and Compilers, and CPUs! Oh My!

Jasette avec Félix-Antoine Ouellet qui est allé à la présentation de Titus Winters, de Google, sur les pratiques de test et le contrôle de la qualité dans une entreprise de grande envergure. Il dit avoir eu beaucoup d'idées pour son entreprise; bonne chose qu'il y ait un retour de ce genre sur l'investissement ici.

Début du contenu technique

Jon Kalb prend le plancher pour donner les nouvelles du jour.

Chandler Carruth : il nous avertit qu'il y aura beaucoup de texte écrit en petit sur les diapos

Chandler Carruth : je suis un gars de Linux et de x86 alors ça va transparaître beaucoup. Il va falloir que vous adaptiez à vos propres réalités. Aussi, je ne ferai pas le même genre de présentation que Bjarne Stroustrup et Herb Sutter. Ça ne sera pas toujours propre

Chandler Carruth : Performance Matters. On a un problème de batterie et il faut tirer le maximum du matériel. On n'a pas assez d'éclectricité, pour les petits appareils comme pour les Server Farms

Chandler Carruth : quel code C++ devriez-vous prendre le temps de chouchouter? Ça m'a frappé il y a huit ans quand j'ai commencé à Google, fraîchement sorti de l'université. À la deuxième semaine, je commençais à socialiser, puis mon patron est venu me demander de jeter un coup d'oeil à du code suspect (lire : t'es le p'tit nouveau...). C'était un truc trop lent, un goulot d'étranglement, dans un outil interne à la compagnie qui est beaucoup utilisé. Fait par un « inconnu » nommé Ken Thompson, que je ne connaissais pas... Mon patron m'a dit « c'est un ingénieur sénior » :)

Chandler Carruth : il existe du code C terrible. Pas terrible parce que c'est C, mais parce que terrible. Le code de Ken Thompson, lui, était une beauté. Il y avait une petite implémentation d'une expression régulière, qui a accéléré l'exécution par un facteur de 20

Chandler Carruth : plus tard, je parle à un collègue qui me dit s'être aperçu que la plupart des requêtes envoyées à ce programme posaient la même question. Il a mis la règle correspondante au début et ça va maintenant 100 fois plus vite. Il y a une leçon là-dedans

Chandler Carruth : faire du Macro Benchmarking est important, mais moi, je vais parler de Micro Benchmarks. Faut toujours mesurer d'abord

Chandler Carruth : j'ai plus de diapos  On va coder « live » vous et moi

Chandler Carruth : je vais utiliser https://github.com/google/benchmark (il fait un tour rapide de comment s'en servir)

À partir d'ici, Chandler Carruth code « live » alors je vais prendre des idées plutôt que le détail de ce qu'il raconte.

Il fait un « benchmark » appelant push_back() sur un vecteur créé dans la boucle, or ce qui coûte cher est l'allocation dynamique sous-jacente au premier (et seul) push_back(), ce qui donne des comportements décevants

Il sort la création du vecteur et ça dit « temps de 0 μs ». Le constructeur par défaut de vector ne fait rien, alors ça se comprend

Il ajoute un reserve(1) au constructeur + push_back(). Amusant : constructeur 0, reserve... 0, push_back() dix fois plus vite! Là, faut comprendre ce qui se passe

Pour comprendre, il faut un profileur. Lui utilise perf stat. Même mécanique sous-jacente que VTune, mais cool dans un terminal. Il y a aussi perf record pour savoir le détail de ce qui s'est passé, puis perf report pour le présenter. C'est bien mais ça manque de contexte; on veut un graphe d'appels (ajouter -g à perf record et à perf report)

Il regarde le résultat; on a un graphe d'appels pour le système d'exploitation, mais pas pour notre programme. Il n'y a pas d'informations pour générer le profil par défaut quand on compile, faut l'ajouter (option --fno-omit-frame-pointer). Ça mange un registre, ce qui explique son absence par défaut.

On regarde : aucun malloc() dans push_back(), aucun malloc() dans reserve(). Chandler Carruth fait remarquer que le graphe d'appels généré l'est du point de vue des appelés, pas des appelants, ce qui a l'air étrange mais est, apparemment, la chose à faire selon les experts

Il ajoute à perf report -g l'option 'graph,0.5,caller' pour que ce soit plus lisible

Le rapport généré est imprécis car il se base sur une instrumentation la moins intrusive possible. Faut s'attendre à voir quelques artéfacts de la mesure

On appuie sur 'a' et on descend dans le code assembleur. Beau truc : le code assembleur présenté comprend des lignes pour aider à suivre les branchements et les suivre! Et ce qu'on constate, c'est une boucle vide car l'optimiseur s'est aperçu que le code n'avait pas d'effet et l'a enlevé. Un classique

Faut battre l'optimiseur. Chandler Carruth dit « j'écris un optimiseur alors ce que je vais vous montrer... utilisez-le pour faire le bien! »

Il ajoute ceci (ouch!) :

static void escape(void *p) {
   asm volatile("" : : "g"(p) : "memory");
}

Le volatile dit au compilateur « le code assembleur qui suit a un effet de bord observable qui va t'échapper ». C'est le genre de passe qu'un auteur de compilateur JIT, cherchant à générer du code précis, pourrait faire. Le "memory" dit « ça peut toucher à n'importe quel endroit dans la mémoire ».

static void clobber() {
   asm volatile("" : : : "memory");
}

... qui fait croire qu'il a lit et écrit partout en mémoire.

Dans le benchmark, il appelle escape(v.data()) entre le reserve() et le push_back(), puis il fait clobber() pour que le compilateur ne sache pas si la mémoire associée est encore la même.

On reteste et les chiffres sont plus raisonnable. Constat ici, push_back() est pas mal vite (27 ns), mais en examinant le profil, le code de benchmark nuit à nos métriques un peu

Que fait reserve()? On va dans le code machine, il alloue de la mémoire, puis la libère. On constate que vector interagit avec un allocateur ensuite même si on a fait reserve... C'est pas cool

Quand on fait reserve() puis push_back(), l'inlining ne fait pas la même chose que si on fait le reserve() implicitement dans le push_back(). Pourquoi? Parce que l'allocation dans push_back() est conditionnelle, pas explicite et imposée

Un autre exemple pour le plaisir. Chandler Carruth prétend avoir inventé le modulo le plus rapide au monde, mais veut en tirer des métriques (il fait une passe avec un ternaire pour éviter le modulo s'il est « superflu »)

Pour faire des tests, il mentionne l'importance d'utiliser des données pseudoaléatoires

Il descend dans le code machine et on constate qu'il y a une interférence de l'outil de benchmarking avec le code testé 

Chandler Carruth fait remarquer que le code du modulo (et le saut pour le contourner) est répété dans le code machine. C'est à cause du Loop Unrolling fait par l'optimiseur.

(il nous fait un petit commentaire éditorial sur Clang Format qui reformate une macro multiligne au passage)

Il fait ensuite du Loop Unrolling manuel dans son code. L'optimiseur déroulait par un facteur de 2, il le fait « à bras » par un facteur de 4. Il teste : c'est plus lent. On regarde le code machine, et escamoter le code pour accélérer le modulo cause des Instruction Cache Misses! L'optimiseur ne fait pas cette erreur dans la boucle. Chandler Carruth modifie sa macro en ajoutant un UNLIKELY sur la partie la moins probable du calcul, et construit son UNLIKELY(x) sur __builtin_expected(...)

On remarque l'impact sur la vitesse d'exécution résultant du biais explicite. On examine le code pour voir les conséquences

Ce qu'on a « oublié » de faire : mesurer le code sans optimisations. Mais il fait des tests et son optimisation est bel et bien plus rapide. C'est weird... Les processeurs sont des bestioles étranges. Chandler Carruth dit avoir attrapé son air quand il a mesuré et a constaté que ses attentes n'étaient pas rencontrées. Il reste du travail d'optimisation à faire

Questions

(j'escamote les trucs sur tel ou tel outil, telle ou telle option qui se répondent en lisant la documentation)

Q : dans perf, tu avais les vrais noms de fonctions... Comment?

R : perf est capable de fair l'unmangling des noms dans le binaire

Q : peux-tu utiliser des outils standards pour tes mesures?

R : oui, mais c'est ce que nos benchmarks utilisent sous la couverture

Q : la nuance entre hot, warm, cold, en tenez-vous compte?

R : pas avec 27 millions de tests comme ce que je viens de faire

Q : pourquoi ne pas enlever les optimisations?

R : parce qu'on les veut; on veut supprimer des trucs très précis qui nous nuisent, sans plus

Q : on aurait pu faire une entrée/sortie aussi pour forcer la génération du code, non?

R : il y a plusieurs techniques et outils. Un autre truc simple est d'utiliser des variables volatile, mais ça a ses inconvénients...

Q : pour escape(), tu passais un pointeur, mais le code assembleur ne connaît pas la taille du pointé, non?

R : ...ça explique le recours à clobber()

Q : fais-tu des tests de régression sur tes benchmarks?

R : pas spécifiquement, mais on analyse les données à travers le passage du temps

Q : devrait-on isoler le code à tester ou le tester en contexte?

R : les deux

Q : le compilateur peut-il te contredire quand tu fais un Likely ou un Unlikely

R : je pense que VTune le fait, masi je suis « Old School »

Fin du contenu technique

Un des trucs que je constate cette semaine est que (a) le benchmarking est un art sombre et que (b) je suis un des meilleurs pour le faire. J'en ai beaucoup faits, pour mes cours et cette semaine, mais j'ai la même mécanique que Chandler Carruth qui est un artiste dans le genre. C'est une bonne nouvelle!

Pour voir sa présentation : https://www.youtube.com/watch?v=LIb3L4vKZ7U&feature=youtu.be

Andrei Alexandrescu : std::allocator is to Allocation what std::vector is to Vexation

Sans surprises, c'est plein à craquer.

Début du contenu technique

Andrei Alexandrescu : mon titre de travail était ... what Alligator is to Allegation. Mais je peux alléguer des trucs comme « Cet alligator a mangé mes Crocs »!

Andrei Alexandrescu : aussi, Design Allocators that Don't Not Work. C'est pas exactement correct sur le plan grammatical, mais ça dit ce que ça a à dire

Andrei Alexandrescu : je ne suis pas venu en paix. Je suis ici pour détruire! Je veux que ce soit clair

Andrei Alexandrescu : 1983, on aime malloc(). 1993, on remplace malloc(). 2003, on aime malloc(). 2013, on ajoute à malloc(). L'allocation de mémoire, c'est un truc cyclique

Andrei Alexandrescu : au début, malloc() était nouveau. C'était exotique, même en Pascal. Et dans la programmation système, ouf!

Andrei Alexandrescu montre les signatures de malloc() et de free(), et fait remarquer que malloc() a la taille et free() ne l'a pas. C'est un boulot de plus pour la mécanique. C'était pas mal à l'époque, mais ça a mal vieilli, et c'est une approche inefficace

Andrei Alexandrescu : si c'était à refaire, malloc() retournerai un bloc qui connaît sa taille et a un pointeur brut, et free() accepterait un bloc

Andrei Alexandrescu : nouvelle génération, operator new. Il y a un realloc() mais pas un renew()... Il se trouve que new travaille bien avec malloc(). Il y a sussi « The Great Array Distraction » à considérér. Il y a un problème de fond avec new[] selon lui. En particulier, pour du travail sérieux, on n'utilise pas new (Andrei Alexandrescu nous invite à le citer là-dessus)

Andrei Alexandrescu : arrive std::allocator, qui n'est pas vraiment là pour allouer de la mémoire mais bien pour les pointeurs (NEAR, FAR, HUGE, etc.)

Andrei Alexandrescu : est que std::allocator est bon ou mauvais? Réfère à la présentation d'Alisdair Meredith à CppCon 2014, et au titre... On parle en 2014 de faire fonctionner un truc standardisé en 1998!

Andrei Alexandrescu : en fait, std::allocator n'est pas un bon allocateur car il n'a pas été pensé pour cette tâche. Quelques erreurs de design :

Andrei Alexandrescu : les allocateurs doivent être composables, en fonction de diverses caractéristiques (taille, alignement, vitesse, gestion de la concurrence). C'est la clé, et c'est ce qui manque le plus. Faut pouvoir les organiser en fédérations

Andrei Alexandrescu : quel est l'allocateur composable le plus simple? Le Null-Allocator, bien entendu, qui ne fait rien et le fait bien. Il a une mémoire nulle ou infinie, choisissez votre définition. On le met à la fin du chaînon

Andrei Alexandrescu : ensuite, on a le Fallback, qui essaie une approche, puis essaie la suivante. On prend le Null comme fin de séquence

Andrei Alexandrescu suggère qu'on implémente allocate() et deallocate(); allocate() est simple : tu fais le premier, puis si ça échoue tu fais le deuxième. Pour deallocate(), c'est évidemment plus subtil (qui va désallouer?). Il suggère d'ajouter un prédicat owns() que les allocateurs implémenteraient (il parle de MDFINAE – Method Definition FINAE – car FallbackAllocator::owns(blk)<==>P::owns(blk)||F::owns(blk)), et le dernier en bout de ligne avant Null risque d'être malloc()

Andrei Alexandrescu : ajoute un StackAllocator<size_t> et un Mallocator pour démarrer la chaîne d'un LocalAllocator. Ça fait un exemple opérationnel. Il suggère d'en utiliser un dans la plupart des fonctions qui en ont besoin.

Andrei Alexandrescu : implémente ensuite une Free List. Débat amusant entre lui, Fedor Pikus et John Lakos sur les forces et les faiblesses de l'approche

Andrei Alexandrescu implémente une FreeList<A,Sz> malgré les faiblesses de la technique. Il discute de quelques améliorations possibles

John Lakos : quand libères-tu un des éléments alloués?

Andrei Alexandrescu : tu le remets dans la liste, tu ne le libères pas individuellement

Andrei Alexandrescu : et un AffixAllocator, pour ajouter des blocs au début et à la fin (p. ex. : pour déboguer)? Une application amusante est de placer le fichier et la ligne dans lesquels l'allocation a été faite dans ces blocs.

Andrei Alexandrescu : et un AllocatorWithStats, qui collecte des infos sur les autres sans vraiment allouer lui-même

(il s'aperçoit qu'il reste moins de cinq minutes, et nous demande de couper cinq minutes de la « pause »; tout le monde dit oui)

Andrei Alexandrescu : avec AllocatorWithStats, tu beurres dans un bloc de mémoire statique, incluant les pointeurs sur les vraies données. À la fin, t'as une liste chaînée de tout ce qui s'est passé.

Andrei Alexandrescu : un BitmappedBlock garde un bit par bloc (pris ou non). Ça garde les métadonnées ailleurs que les données, une bonne chose. C'est pas fin pour le multithreading

Andrei Alexandrescu : un CascadingAllocator (sur échec, on bascule)

Andrei Alexandrescu : un Segregator (petit, un allocateur, gros, un autre; la frontière est un paramètre du template). Cool, il compose avec lui-même; tu peux faire un arbre binaire de tailles!

Andrei Alexandrescu : un Bucketizer, avec un pas pour séparer les catégories. On pourrait aussi y aller avec une croissance logarithmique

Andrei Alexandrescu : ça couvre presque tous les cas pertinents!

Andrei Alexandrescu propose une API qu'il juge correcte et l'explique sommairement

Andrei Alexandrescu : le truc, c'est la composabilité

Fin du contenu technique

Ouf, c'était cool mais il ne reste que quelques secondes avant la prochaine présentation. Richard Smith était juste à côté de moi alors j'ai pris quelques secondes pour lui parler du problème de la spécification de caractéristiques des threads au démarrage, en particulier (pour Core) le fait qu'on cherche à faire une demande ferme de taille de pile même si le concept-même de pile ne fait pas partie des objets standardisés. On va y réfléchir tous les deux d'ici Kona.

Pour voir sa présentation : https://www.youtube.com/watch?v=W3xI1HJUy7Q

John Lakos : Value Semantics: it ain't about the Syntax! I

Le temps d'aller chercher un café et on recommence!

Début du contenu technique

John Lakos explique avoir essayé de lire Elements ... d'Alexander Stepanov, ne pas avoir compris, avoir fini par faire une entrevue avec Alexander Stepanov pour son deuxième livre, avoir du relire le tout, et s'être rendu compte qu'il raconte lui-même la même chose, mais avec d'autres mots.

(John Lakos utilise des centaines de diapos et parle vite, alors je ne pourrai pas prendre autant de notes que pour d'autres conférences)

John Lakos : questionnement de fond, « que signifie dire que deux objets sont la même chose »? C'est une question complexe et importante, car ça définit le sens-même de valeur. Que fait le constructeur de copie? Après son action, on peut substituter un objet pour l'autre. C'est pas juste une question d'états, car certaines caractéristiques ne sont pas manifestes (pensez à deux string, qui « contiennent » le même texte... Elle ont comme états des pointeurs, distincts!). Et pour le « même comportement observable », c'est pas clair non plus (pensez à reserve() pour un vector<T>).

John Lakos : le même quoi? Faut quelque chose qui se comprend... raisonnablement facilement. Faut que les objets représentent la même valeur.

John Lakos : sur le plan mathématique / platonique, un type correspond à un ensemble de valeurs uniques. C'est un isomorphisme. Chaque valeur peut être décrite indépendamment de ses représentations. Un type s'accompagne d'opérations. Un type de C++ est typiquement une approximation d'un idéal mathématique. Il se trouve que int, short, long, etc. sont des approximations d'un autre type que unsigned, qui a sa propre algèbre. Il présente une date avec des accesseurs identiques mais des représentations internes distinctes, et prétend que ces types sont « la même chose », indépendemment des représentations. La clé est les propriétés manifestes, ou Salient Properties, du type.

John Lakos : sa question suivante est est-ce qu'une std::string de valeur "Fred" et un const char* pointant sur "Fred" représentent la même valeur. Il prétend que oui. Ensuite, il demande si int et int mod 5 représentent le même type; sa réponse est non, car ils modélisent deux types disticts, deux algèbres. Pour un vector<T>, les propriétés manifestes sont le nombre d'éléments et les valeurs, pas la capacité. La seule manière de savoir est de lire la documentation.

Réflexion personnelle : les propriétés manifestes sont probablement celles qui devraient être utilisées pour tenir compte des opérateurs relationnels.

John Lakos parle des conséquences de ce concept sur les Object-Relational-Mappings

John Lakos : ce ne sont pas tous les objets qui représentent une valeur. Les pointeurs sont proches. En général, faut probablement être capable de les copier, ou à tout le moins les modéliser de manière indépendante du matériel. Il y a une différence entre représenter une valeur et offrir un service, être un mécanisme.

John Lakos : quelques questions :

John Lakos : on ne peut se baser sur le constructeur de copie pour déterminer ce qui fait la valeur d'un objet, mais operator== est un bon test (yes, j'avais deviné!). Il se demande si operator== est un bon critère

John Lakos : il existe aussi des types semi réguliers, auxquels il manque == et !=

John Lakos : si deux objets représentent la même valeur et vivent la même opération, alors ils devraient encore représenter la même valeur par la suite

(pause)

Je suis arrivé trop tard pour prendre une bouchée de pita et d'hummus, mais j'ai pu manger un macaron, alors ça pourrait être pire.

Je baille beaucoup. La fatigue commence à paraître beaucoup...

Pour voir sa présentation : https://www.youtube.com/watch?v=0EvSxHxFknM

John Lakos : Value Semantics: it ain't about the Syntax! II

J'ai Chuck Allison près de moi, conférencier du début de la journée qui parlait de l'enseignement de l'informatique à l'aide de pédagogie par projets. Comme promis, je suis allé lui expliquer ce que je fais pour faire comprendre la fragmentation de la mémoire à mes étudiant(e)s. Il prend des notes. C'est un chic type qui semble sincèrement passionné par l'enseignement de l'informatique.

(retour de la pause)

John Lakos commence par récapituler les éléments clés de la première partie de sa présentation, car nous avons quelques nouveaux visages dans la salle.

John Lakos : question profonde ici. Pour un rationnel, prend-on la paire numérateur, dénominateur comme valeur ou évalue-t-on le rapport avant de les comparer? Il fait remarquer que, si on est imprudents, et pris comme « de même valeur » peut surprendre si on élève les deux à une puissance élevée (l'un déborderait, l'autre non). Pour un graphe, comment définit-on les propriétés manifestes? Comment implémenterait-on operator==? On peut le faire de manière efficace en imposant des contraintes structurelles internes, mais si on cherche à décrire deux graphes comme étant égaux s'ils sont isomorphiques, on se tape un operator== de complexité CO-NP

John Lakos : parfois, on peut omettre une fonction s'il n'y a pas de solution efficace. On laisse operator== tranquille; si on veut autre chose, on le code dans une fonction globale (note personnelle : à réfléchir pour mon doctorat, où j'ai un cas...)

John Lakos : qu'en est-il des expressions régulières, qui décrivent un langage régulier? Sur l'ensemble des opérations exposées, lesquelles sont manifestes, et décrivent ce qui est essentiel à l'objet? On peut se baser sur le texte qui la décrit, ou sur le langage qu'elle accepte... mais on n'a pas d'accesseur pour le connaître. Cette valeur n'intervient qu'à la construction. L'opérateur == est PSPACE-Complete alors je pense qu'on va oublier ça

John Lakos : ça ne veut pas dire que ce n'est pas une valeur, mais elle ne sera pas régulière

John Lakos : étonnamment, la construction par copie et l'affectation n'est jamais un problème. Il y a pas mal toujours une solution de complexité linéaire

John Lakos : qu'en est-il d'une priority_queue? Elles sont égales si elles ont le même nombre d'éléments dans le même ordre, valeur par valeur? En fait, le piège ici est que les opérations clés push(), pop() et top() sont les propriétés manifestes. Quel serait le coût d'implémenter operator==? Linéaire, en pratique (si les éléments dans le tableau sous-jacent sont dans le même ordre, on est en business) pour une propriété suffisante, mais il y a des substrats distincts qui « popperaient » dans le même ordre, alors c'est pas nécessaire... Si on a une solution qui fonctionne 99,9% du temps, on ne code pas operator== (on code autre chose peut-être, mais pas ça). Il; se trouve que John Lakos a une preuve par construction que c'est (un flo qui est entré à Carnegie Mellon à 11 ans et travaille maintenant pour lui l'a trouvé).

John Lakos fait un petit wrap-up. On est à plus de 580 diapos... Le concept de valeur est un concept sémantique, pas syntaxique.

Questions

Rien de public. On est tous fatigués, je pense.

Fin du contenu technique

J'ai le souper au Earl's Kitchen +  Bar à 18h30. Il est 17h50. Je vais y aller tranquillement, marcher me fera du bien.

Finalement, j'ai bavardé avec mon épouse (qui me manque, et a remarqué l'usure sur mon visage), puis je suis allé avec mes collègues à l'endroit attendu. On a eu du plaisir, mais on a parlé fort pour améliorer ce qui est perfectible.

J'ai, honnêtement, passé un bon moment. Petit reproche : le plat servi par le resto était dispendieux (16,50 USD pour une petite assiette, comprenant essentiellement de la roquette... J'adore la roquette, mais je peux nourrir ma famille de roquette pour une semaine avec 3-4 CAD.

CppCon 2016 Kick-Off Meeting

On se retrouve sur les lieux du colloque par la suite. Ce qui suit est spécifique mais pas technique.

La bouffe et le café; ça arrive par bloc. On devrait toujours en avoir un petit peu.

L'information sur la présence ou non de nourriture était confuse. Y avait-il un déjeuner? Un dîner? (le plan de Jon Kalb était que ce soit une grignotine; la perception des gens est que c'était des goûters).

Kate Gregory : peu importe le reste, la technique était meilleure cette année.

Plusieurs ont apprécié la pièce 409 (la plus loin, qui a servi pour SG14 et pour faire des tests)

Michael Caisse : tout s'est bien passé, mais la journée où j'ai eu un bris, je ne trouvais pas d'aide.

Le band de musique était bon mais la musique était trop forte avant les Keynotes; après, c'était moins grave.

Un autre dit que c'était trop fort après les Keynotes, car des gens posaient des questions aux présentateurs.

Je pense que les diapos étaient souvent trop chargées. Ce serait bien que (a) les présentateurs envoient leurs diapos d'avance ou (b) qu'il y ait des guidelines

Kate Gregory : on pourrait accompagner les présentateurs, mais faudrait voir le matériel un peu avant.

Il y avait une forte variation dans le niveau technique des présentations. Une forme de catégorisation serait apprécié

Avons-nous une distinction entre « débutant(e) » et « expérimenté(e) »? Et avons-nous des qualifications pour jeu, métaprogrammation ou d'autres sujets?

Jon Kalb : nous avons des étiquettes mais nous ne les publions pas; nous cherchons à éviter les conflits

Les codes de couleur pourraient nous aider à nous orienter si leur sémantique était plus claire

Chandler Carruth : il va arriver que la présentatrice ou le présentateur ne soit pas d'accord avec le comité de programme. Je ne suis pas terriblement offensé si des gens tombent parfois dans « la mauvaise salle ». On enregistre tout ici, alors vous ne manquerez rien

Jens Weller : on pourrait avoir une piste « apprentissage » et une piste « jeu ».

Kate Gregory : on pourrait aussi avoir une piste « découverte ».

On pourrait avoir des propositions de « vous pourriez aimer... »

Une piste « découverte » serait une bonne idée, incluant pour les réfugiés d'autres langages

Fedor Pikus : on avait un 75% de programmeuses / programmeurs C++. J'ai l'impression qu'il nous manque des gens ici qui profiteraient de ce qui était offert ici

Quel est le but officiel du colloque? (R : d'être le « go to place » pour la communauté)

Jon Kalb : on a peu de présentatrices et de présentateurs passionné(e)s de C++ 98

Je suggère des niveaux (démon, tutoriel, lectures, etc.). Parfois, je vais à une présentation et je sais déjà tout

Dans ma compagnie. je ne peux pas utiliser ce que j'ai vu ici. J'ai eu du plaisir, je suis content, mais pour moi ce n'est pas applicable

Jens Weller : on devrait insister sur un Student Program, question d'avoir ici au moins 50 étudiant(e)s par année.

Chandler Carruth : je ne suivrais pas les préoccupations de Fedor Pikus pour le moment. À mes yeux, c'est cool si on penche un peu « vers l'avant » ici. Globalement, je pense que l'on offre une bonne variété. C'est cool qu'on pousse un peu l'industrie vers l'avant

Il nous manque des marchés ici, par exemple l'industrie médicale

Fedor Pikus trace une différence entre le langage et ce qu'on fait avec le langage

Jens Weller : qui voudrait parler de C++ 98?

Fedor Pikus : moi, demain!

Chandler Carruth : c'est la preuve que le colloque ne bloque pas ces présentations!

Jon Kalb : autres sujets?

Parfois, la gestion du temps laissait à désirer

(on jase de mécanique)

Pourquoi n'y a-t-il pas de pause pour manger?

Jon Kalb : mangez un déjeuner!

(c'était pas clair, je pense que c'est clair)

C'était juste un bogue de communication, à mon avis

Kate Gregory : que peut-on faire, nous, ici, pour accroître la diversité d'audience et de présentatrices / présentateurs?

Jon Kalb : on devrait travailler fort pour qu'elles ou ils viennent. À mon avis, ce n'est pas une question genrée

(on parle de financement pour les présentatrices et les présentateurs)

(on discute organisation pour l'an prochain)

Une « Poster Session » pour étudiant(e)s?

Jon Kalb : pour les inscriptions, Marshall Clow a besoin d'aide. Il est très occupé (on a une proposition)

Jon Kalb : Kate Gregory en fait beaucoup et a besoin d'aide (on a des propositions)

Jon Kalb : ça nous prend un(e) responsable du marketing (on en trouve pour Reddit, Twitter, Facebook et le courriel)

(on a encore de la mécanique à roder mais je dois aller prendre l'autobus) 

Fatigué. J'ai un peu de lessive à faire. Dernier dodo avant le retour à la maison. Ce fut une excellente semaine pour moi, mais il est temps qu'elle se termine.

Jour 5 25 septembre 2015

Ça a commencé par un petit matin tranquille. J'ai mangé quelques restes (un wrap tomates/laitue/fromage avec un peu de hummus) et j'ai fait mon Check-Out en offrant aux employés de l'hôtel de prendre ce que je n'ai pas pu utiliser cette semaine (il me reste une tomate, du sel, du poivre, on peu d'huile d'olive, du savon à lessive...) pour éviter de gaspiller. J'ai paqueté mes trucs, fait un dernier tour de la chambre pour m'assurer de ne rien avoir oublié, puis je suis parti vers mon autobus pour le dernier matin du colloque.

Un chic type qui a pris l'autobus avec moi toute la semaine s'est aperçu, juste avant d'embarquer, qu'il avait oublié son portefeuille chez lui. Il me restait de la monnaie alors je lui ai donné.

J'ai travaillé un peu en attendant le début de la prochaine conférence. Petit salut à Jason Turner que j'ai côtoyé entre deux conférences toute la semaine et qui a fait un détour exprès pour dire « allo! » ce matin.

Beau moment : Beman Dawes passe dans le coin et vient s'asseoir avec moi, juste pour le plaisir de raconter son expérience. C'est un grand monsieur que celui-là, et il est visiblement ravi de ce qu'il a vécu cette semaine.

Ensuite, Billy Baker est venu s'asseoir. Un gars de l'aviation et de la simulation, un peu comme moi à l'origine. On a parlé des voyages, des enfants (il en a trois, mais la plage chez lui va de 21 ans à deux ans alors on se comprenait), du peu de vacances... Tout le monde ici a un peu le même profil, du moins ceux qui travaillent sur WG21 : nous sommes tous des bénévoles qui veulent bien faire pour la communauté.

Pour voir cette présentation : https://www.youtube.com/watch?v=0tFxdreVx6s

Michael Wong, Nicolas Guillemot et Sean Middleditch: The Birth of SG14: Better C++ Support for Game Developers with Low Latency Needs

La salle est à moitié pleine ce matin. Je pense que plusieurs se demandent pourquoi on a un groupe spécial comme SG14 malgré toute la pédagogie qui a été faite cette semaine. J'ai la chance de bavarder un peu avec Alex Boulanger et Félix-Antoine Ouellet, ce qui est toujours agréable.

Sean Middleditch et Nicolas Guillemot se présentent. Michael Wong est ici, mais n'est pas sur la scène

Sean Middleditch explique le plan de la présentation :pourquoi SG14? métriques et « performance », tests et fiabilité, etc.

Sean Middleditch : la communauté des programmeuses et des programmeurs de jeu est la troisième plus grande communauté dans le monde de C++, après les banques et la finance

Nicolas Guillemot trace un historique bref de ce qui a donné naissance à SG14 lors de CppCon 2014

On a publié N4456 pour étaler les problèmes connus sur la place publique. Présenté à Lenexa, bien reçu

Il y a deux rencontres officielles de SG14 en 2015, soit celle de cette semaine et celle de GDC 2015 dont Sony sera l'hôte

Nicolas Guillemot : nous avons constaté que les problèmes d'autres domaines (systèmes embarqués, finance, simulation) sont proches de ceux du monde du jeu

Sean Middleditch : pour programmer un jeu, il nous faut un contrôle chirurgical sur le matériel. Nous avons un budget de mémoire fixe. Nous partageons de la mémoire entre le GPU et le CPU. Nous n'avons pas de Swap Space... et nous n'avons pas l'option de dire aux usagers d'améliorer leur appareil s'ils utilisent une console

Sean Middleditch : certains compilateurs fournissent des itérateurs de débogage, une nuisance pour nous. Le dynamic_cast et RTTI sont trop coûteux pour nos besoins et nous devont implémenter nos propres versions. Enfin, il y a une différence pour nous entre std::map et une éventuelle std::flat_map, même si deux opérations sont de complexité

Sean Middleditch : pourquoi un conteneur vide devrait-il avoir le droit d'allouer de la mémoire? Comment contrôler le taux de croissance d'un vecteur? Comment s'assurer des paramètres de SSO et de Small Object Optimizations de manière portable?

Sean Middleditch : est-ce que std::async utilise un Thread Pool ou non? On se trouve à réécrire la roue, et souvent...

Sean Middleditch : les méthodes virtuelles ne sont pas gratuites, mais c'est moins grave que par le passé (sur certaines plateformes, c'est presque gratuit). L'inlining n'est pas toujours aussi bon qu'on ne le croirait; tous les jeux que je connais utilisent une macro pour rendre le Force Inline « portable ». Les exceptions et le Stack Unwinding coûtent cher.

Sean Middleditch : pour les exceptions, les « mettre à Off » se fait, mais agir ainsi a des conséquences non-spécifiées.

Sean Middleditch : je remarque que ni LLVM, ni Google n'utilisent les exceptions...

Sean Middleditch : à propos des métriques et de la « performance », plusieurs trucs. Nous avons une mémoire limitée (de manière rigide!) et nos programmes traitent des masses importantes de données. Nous avons donc plusieurs outils « maison » d'analyse et de profilage

Sean Middleditch : nous utilisons des allocateurs maison, et nous spécialisons new et delete sur une base « par classe » dans pratiquement tous les jeux.

Sean Middleditch : on utilise par contre peu les allocateurs standards. On n'y contrôle pas assez finement l'alignement, et nous trouvons lourd d'annoter les conteneurs par des allocateurs typés (c'est lourd). C'est un problème d'interface

Sean Middleditch : certaines machines ne font que peu ou pas de Branch Prediction; profiter de la localité de la Cache est de plus en plus critique. Nous devons être rapides, même lorsque nous déboguons.

Sean Middleditch : la consommation de mémoire et la vitesse sont fortement couplés. Aussi, le matériel change et évolue, et nos structures de données / nos algorithmes doivent évoluer aussi

Sean Middleditch : il nous manque des algorithmes (un radix_sort; des algorithmes géométriques, des algorithmes mathématiques plus rapides et moins précis)

Sean Middleditch : des conteneurs manquants à nos yeux : conteneurs intrusifs, une hash table plus Cache-Friendly, plus de conteneurs contigüs en mémoire, plus de conteneurs qui utilisent la pile.. (note personnelle, faut que je montre à Sean Middleditch que c'est facile maintenant)

Sean Middleditch : on a une contrainte de WCET ferme. Faut pas rendre les gens malades, surtout dans un environnement de réalité virtuelle. On utilise C++ entre autres parce qu'on se passe de collecte d'ordures (ça pourrait donner un meilleur débit moyen, à vérifier, mais ça nous nuirait pour le respect du WCET).

Nicolas Guillemot : pour le plaisir et la productivité, le respect de la créativité des programmeuses et des programmeurs, on compile trop longtemps. Les templates, <memory>, std::unique_ptr/std::array sont plus longs à compiler que des tableaux bruts et des classes « classiques »

Nicolas Guillemot : les entrés/ sorties, la grammaire complexe du langage, l'instantiation des templates, l'optimisation... Tout ça nous ralentit

Nicolas Guillemot : charger un jeu est long. Un compilateur qui permettrait du « Edit and Continue » serait apprécié

Nicolas Guillemot : aujourd'hui, que fait-on? On a eu une rencontre mercredi :

Sean Middleditch : pour le futur, d'autres trucs s'annoncent :

Sean Middleditch invite les gens à contribuer

Questions

Q : utilisez-vous des outils pour améliorer les temps de compilation?

R : oui

Q : vous soulevez un problème avec les stratégies d'allocation des vecteurs. Selon vous, doit-on raffiner std::vector ou faire un nouveau type?

R : je ne sais pas, faut qu'on en parle. Il y a plusieurs approches, faut voir la meilleure

Q : si on lève une exception, on peut tuer le processus. Y avez-vous pensé?

R : oui, c'est une des approches dont on parle. Pour le moment, si on éteint les exceptions, un throw ou un try provoque une erreur de compilation. On parle aussi de dire au compilateur que des régions de code complètes sont noexcept(true)

Q : le Boost.FlatMap existe sur un tableau

R : oui, j'ai exploré cela. On regarde les designs possibles pour voir ce qui conviendra. Les algos qu'on utilise beaucoup, comme set_union() et set_difference(), vont nous aider à faire des choix informés

Petite dernière jasette avec les gens que j'ai croisé cette semaine. Je serre la main des collègues de SG14, remercie Michael Wong et je me dirige vers le Keynote.

Pour voir sa présentation : https://www.youtube.com/watch?v=mFUXNMfaciE&feature=youtu.be

Keynote – Eric Niebler: Ranges and the Future of the STL

Le Keynote d'Eric Niebler sera excellent, mais je dois prendre le taxi vers l'aéroport vers 10h55 et le tout commence à 10h30. Heureusement, je connais bien les travaux d'Eric Niebler (c'est pour ça que je sais que ça va être excellent!)

Début du contenu technique

Eric Niebler remercie d'abord la communauté du langage D, sur les travaux desquels il a construit son superbe projet d'intervalles.

Eric Niebler : je vais passer avec vous à travers le code d'un programme de génération de calendrier

Il commence par view::iota(), qui retourne une vue paresseuse. C'est le modèle préconisé pour view, les évaluations paresseuses. Technique qui vise la composabilité maximale

Il voudrait créer un intervalle de dates, mais ça ne fonctionne pas tel quel (les dates ne modèlent pas les bons concepts). Il fait un hack pour ajouter les opérateurs manquants et ça compile

Il groupe les dates par mois, avec view::group_by(), et affiche le premier jour de chaque mois. Par la suite, il fait une petite fonction pour appeler view::group_by() dans le but d'accroître la lisibilité. Un peu comme Louis Dionne, Eric Niebler utilise beaucoup des fonction qui retournent auto

(je dois quitter pour prendre mon avion; Eric Niebler fait un excellent travail)

Fin du contenu technique

En attendant mon avion, j'ai continué de travailler, et je n'étais pas le seul; des gens comme Michael Wong, John McFarlane et Guy Davidson (entre autres) demeuraient actifs et créatifs. Ce fut une semaine fort intéressante... et fort occupée.


Valid XHTML 1.0 Transitional

CSS Valide !