Bonjour! Je m'appelle Oleksandr Kaleniuk et je suis un passionné de C++. J'écris en C++ depuis 17 ans et pendant toutes ces 17 années j'ai essayé de me débarrasser de cette dépendance dévastatrice.
Tout a commencé en 2005 avec un moteur de simulation spatiale 3D. Le moteur avait tout ce que C++ avait en 2005. Des pointeurs à trois étoiles, huit couches de dépendance et des macros de style C partout. Il y avait aussi des morceaux d'assemblage. Itérateurs à la Stepanov et méta-code à la Alexandrescu. Le code avait tout. Sauf, bien sûr, pour la réponse à la question la plus importante : pourquoi ?
En peu de temps, même cette question a trouvé une réponse. Pas comme "pour quoi faire" mais plutôt comme "comment ça se fait". Il s'est avéré que le moteur a été écrit pendant environ 8 ans par 5 équipes différentes. Et chaque équipe a apporté sa lubie préférée au projet en enveloppant l'ancien code dans des emballages fraîchement stylés, ajoutant seulement environ 10 à 20 microcarmacks de fonctionnalités.
Au début, j'essayais honnêtement de comprendre chaque petite chose. Ce n'était pas une expérience gratifiante, pas du tout, et à un moment donné, j'ai abandonné. Je fermais toujours des tâches et corrigeais des bogues. Je ne peux pas dire que j'ai été très productif, mais suffisamment pour ne pas me faire virer. Mais ensuite, mon patron m'a demandé : "Voulez-vous réécrire une partie du code de shader d'Assembly vers GLSG ?" Je pensais que Dieu sait à quoi ressemble ce GLSL, mais il ne pouvait pas être pire que C++ et j'ai dit oui. Ce n'était pas pire.
Et ce genre de est devenu un modèle. J'écrivais encore principalement en C++, mais chaque fois que quelqu'un me demandait "voulez-vous faire ce truc non-C++ ?" J'étais sur!" et j'ai fait cette chose quoi que ce soit. J'ai écrit en C89, MASM32, C #, PHP, Delphi, ActionScript, JavaScript, Erlang, Python, Haskell, D, Rust et même ce langage de script InstallShield outrageusement mauvais. J'ai écrit en VisualBasic, en bash et dans quelques langages propriétaires dont je ne peux même pas parler légalement. J'en ai même fait un moi-même par accident. J'ai créé un simple interpréteur de style lisp pour aider les concepteurs de jeux à automatiser le chargement des ressources, et je suis parti en vacances. Quand j'étais de retour, ils écrivaient toutes les scènes du jeu dans cet interprète, nous avons donc dû le soutenir jusqu'à, au moins, la fin du projet.
Donc, au cours des 17 dernières années, j'ai honnêtement essayé d'arrêter le C++ mais à chaque fois, après avoir essayé une nouvelle chose brillante, je revenais. Néanmoins, je pense qu'écrire en C++ est une mauvaise habitude. C'est dangereux, pas aussi efficace qu'on le pense, et cela gaspille une quantité terrible de la capacité mentale d'un programmeur sur des choses qui n'ont rien à voir avec la création de logiciels. Savez-vous que dans MSVC uint16_t(50000) + uin16_t(50000) == -1794967296
? Est-ce que tu sais pourquoi? Ouais, c'est ce que je pensais.
Je crois qu'il est de la responsabilité morale des programmeurs C++ de longue date de décourager la jeune génération de faire du C++ leur métier à peu près comme c'est la responsabilité morale des alcooliques qui ne peuvent pas arrêter d'avertir les jeunes du danger.
Mais pourquoi est-ce que je ne peux pas arrêter ? Quel est le problème? Le fait est qu'aucun des langages, en particulier les soi-disant "tueurs de C++", ne donne un réel avantage sur le C++ dans le monde moderne. Tous ces nouveaux langages visent principalement à tenir un programmeur en laisse pour leur propre bien. C'est bien, sauf qu'écrire du bon code avec de mauvais programmeurs est un problème du XXe siècle lorsque les transistors ont doublé tous les 18 mois et que le nombre de programmeurs a doublé tous les 5 ans.
Nous vivons en 2023. Nous avons plus de programmeurs expérimentés dans le monde que jamais auparavant dans l'histoire. Et nous avons plus que jamais besoin de logiciels efficaces.
Les choses étaient plus simples au XXe siècle. Vous avez une idée, vous l'intégrez dans une interface utilisateur et la vendez en tant que produit de bureau. Est-ce lent ? On s'en fout! Dans dix-huit mois, les ordinateurs de bureau deviendront de toute façon 2 fois plus rapides. Ce qui compte, c'est d'entrer sur le marché, de commencer à vendre des fonctionnalités, et de préférence sans bugs. Dans ce climat, bien sûr, si un compilateur empêche les programmeurs de créer des bogues, tant mieux ! Parce que les bogues ne rapportent pas d'argent, et vous devez payer vos programmeurs s'ils ajoutent des fonctionnalités ou des bogues de toute façon.
Maintenant, les choses sont différentes. Vous avez une idée, vous l'emballez dans un conteneur Docker et l'exécutez dans un cloud. Maintenant, vous obtenez vos revenus des personnes qui exécutent votre logiciel si cela résout leurs problèmes. Même s'il fait une chose mais le fait bien, vous serez payé. Vous n'avez pas besoin de bourrer votre produit de fonctionnalités inventées juste pour en vendre une nouvelle version. D'un autre côté, celui qui paie pour l'inefficacité de votre code, c'est maintenant vous-même. Chaque routine sous-optimale apparaît dans votre facture AWS.
Ainsi, dans le nouveau climat, vous avez maintenant besoin de moins de fonctionnalités, mais de meilleures performances pour tout ce que vous avez.
Et soudain, il s'avère que tous les "tueurs de C++", même ceux que j'aime et respecte de tout mon cœur comme Rust, Julia et D, ne s'attaquent pas au problème du XXIe siècle. Ils sont toujours coincés dans le XX. Ils vous aident à écrire plus de fonctionnalités avec moins de bogues, mais ils ne sont pas d'une grande aide lorsque vous devez tirer le tout dernier flop du matériel que vous louez.
Ils ne vous donnent tout simplement pas un avantage concurrentiel sur C++. Ou, d'ailleurs, même les uns sur les autres. La plupart d'entre eux, par exemple, Rust, Julia et Cland partagent même le même backend. Vous ne pouvez pas gagner une course automobile si vous partagez tous la même voiture.
Alors, quelles technologies vous donnent un avantage concurrentiel sur C++ ou, en général, sur tous les compilateurs traditionnels à l'avance ? Bonne question. Heureux que vous ayez demandé.
Mais avant d'aller avec Spiral lui-même, vérifions si votre intuition fonctionne bien. Selon vous, qu'est-ce qui est le plus rapide : une fonction sinus C++ standard ou un modèle polynomial en 4 parties d'un sinus ?
auto y = std::sin(x); // vs. y = -0.000182690409228785*x*x*x*x*x*x*x +0.00830460224186793*x*x*x*x*x -0.166651012143690*x*x*x +x;
Question suivante. Qu'est-ce qui fonctionne le plus rapidement, utiliser des opérations logiques avec court-circuit ou tromper un compilateur pour l'éviter et calculer l'expression logique en masse ?
if (xs[i] == 1 && xs[i+1] == 1 && xs[i+2] == 1 && xs[i+3] == 1) // xs are bools stored as ints // vs. inline int sq(int x) { return x*x; } if(sq(xs[i] - 1) + sq(xs[i+1] - 1) + sq(xs[i+2] - 1) + sq(xs[i+3] - 1) == 0)
Et un de plus. Qu'est-ce qui trie les triplets plus rapidement : un tri par swap ou un tri par index ?
if(s[0] > s[1]) swap(s[0], s[1]); if(s[1] > s[2]) swap(s[1], s[2]); if(s[0] > s[1]) swap(s[0], s[1]); // vs. const auto a = s[0]; const auto b = s[1]; const auto c = s[2]; s[int(a > b) + int(a > c)] = a; s[int(b >= a) + int(b > c)] = b; s[int(c >= a) + int(c >= b)] = c;
Si vous avez répondu à toutes les questions de manière décisive et sans même réfléchir ou chercher sur Google, votre intuition vous a fait défaut. Vous n'avez pas vu le piège. Aucune de ces questions n'a de réponse définitive sans contexte.
Quel CPU ou GPU le code cible-t-il ? Quel compilateur est censé construire le code ? Quelles optimisations du compilateur sont activées et lesquelles sont désactivées ? Vous ne pouvez commencer à prédire que lorsque vous savez tout cela, ou mieux encore, en mesurant le temps d'exécution de chaque solution particulière.
Un modèle polynomial est 3 fois plus rapide que le sinus standard s'il est construit avec clang 11 avec -O2 -march=native et exécuté sur Intel Core i7-9700F. Mais si construit avec nvcc avec --use-fast-math et sur GPU à savoir GeForce GTX 1050 Ti Mobile , le sinus standard est 10 fois plus rapide que le modèle.
Échanger une logique court-circuitée contre une arithmétique vectorisée a également du sens sur i7. Rend l'extrait de code deux fois plus rapide. Mais sur ARMv7 avec le même clang et -O2, la logique standard est 25% plus rapide que la micro-optimisation.
Et avec le tri par index par rapport au tri par swap, le tri par index est 3 fois plus rapide sur Intel, et le tri par swap est 3 fois plus rapide sur GeForce.
Ainsi, les chères micro-optimisations que nous aimons tant peuvent à la fois accélérer notre code d'un facteur 3 et le ralentir de 90 %. Cela dépend du contexte. Comme ce serait merveilleux si un compilateur pouvait choisir la meilleure alternative pour nous, par exemple, le tri d'index se transformerait miraculeusement en tri d'échange lorsque nous changeons de cible de construction. Mais ça ne pouvait pas.
Même si nous permettons au compilateur de réimplémenter le sinus en tant que modèle polynomial, pour échanger la précision contre la vitesse, il ne connaît toujours pas notre précision cible. En C++, nous ne pouvons pas dire que "cette fonction est autorisée à avoir cette erreur". Tout ce que nous avons, ce sont des drapeaux de compilateur comme "--use-fast-math" et uniquement dans le cadre d'une unité de traduction.
Dans le deuxième exemple, le compilateur ne sait pas que nos valeurs sont limitées à 0 ou 1 et ne peut pas proposer l'optimisation que nous pouvons. Nous aurions probablement pu y faire allusion en utilisant un type booléen approprié, mais cela aurait été un problème complètement différent.
Et dans le troisième exemple, les morceaux de code sont très différents pour être reconnus comme synonymes. Nous avons trop détaillé le code. S'il ne s'agissait que de std::sort, cela aurait déjà donné au compilateur plus de liberté pour choisir l'algorithme. Mais il n'aurait pas choisi le tri d'index et le tri d'échange car ils sont tous deux inefficaces sur les grands tableaux et std :: sort fonctionne avec un conteneur itérable générique.
Et c'est ainsi que nous arrivons à Spiral . Il s'agit d'un projet conjoint de l'Université Carnegie Mellon et de l'Eidgenössische Technische Hochschule Zürich. TL&DR : les experts en traitement du signal se sont lassés de réécrire à la main leurs algorithmes préférés pour chaque nouveau matériel et ont écrit un programme qui fait ce travail pour eux. Le programme prend une description de haut niveau d'un algorithme et une description détaillée de l'architecture matérielle, et optimise le code jusqu'à ce qu'il réalise l'implémentation d'algorithme la plus efficace pour le matériel spécifié.
Une distinction importante entre Fortran et similaires, Spiral résout vraiment un problème d'optimisation au sens mathématique. Il définit le temps d'exécution comme une fonction cible et recherche son optimum global dans l'espace factoriel des variantes d'implémentation limitées par l'architecture matérielle. C'est quelque chose que les compilateurs ne font jamais réellement.
Un compilateur ne cherche pas le véritable optimum. Il optimise le code guidé par l'heuristique qui lui a été enseignée par les programmeurs. Essentiellement, un compilateur ne fonctionne pas comme une machine recherchant la solution optimale, il fonctionne plutôt comme un programmeur d'assemblage. Un bon compilateur fonctionne comme un bon programmeur en assembleur, mais c'est tout.
Spiral est un projet de recherche. Son périmètre et son budget sont limités. Mais les résultats qu'il montre sont déjà impressionnants. Sur la transformée de Fourier rapide, leur solution surpasse de manière décisive les implémentations MKL et FFTW. Leur code est ~2x plus rapide. Même sur Intel.
Juste pour souligner l'ampleur des réalisations, MKL est la bibliothèque Math Kernel d'Intel lui-même, donc par les gars qui savent le plus utiliser leur matériel. Et WWTF AKA "Fastest Fourier Transform in the West" est une bibliothèque hautement spécialisée des gars qui connaissent le mieux l'algorithme. Ils sont tous les deux champions dans ce qu'ils font et le fait même que Spiral les batte tous les deux est étonnant.
Lorsque la technologie d'optimisation utilisée par Spiral sera finalisée et commercialisée, non seulement C++ mais Rust, Julia et même Fortran feront face à une concurrence qu'ils n'ont jamais affrontée auparavant. Pourquoi quelqu'un écrirait-il en C++ si écrire dans un langage de description d'algorithme de haut niveau rend votre code 2 fois plus rapide ?
Le meilleur langage de programmation est celui que vous connaissez déjà bien. Pendant plusieurs décennies consécutives, le langage le plus connu de la plupart des programmeurs a été C. Il est également en tête de l'indice TIOBE avec d'autres C-likes qui peuplent étroitement le top 10. Cependant, il y a seulement deux ans, quelque chose d'inouï s'est produit. Le C a donné sa première place à autre chose.
Le "quelque chose d'autre" semblait être Python. Un langage que personne ne prenait au sérieux dans les années 90 car c'était encore un autre langage de script dont nous avions déjà beaucoup.
Quelqu'un dira : "Bah, Python est lent", et passera pour un imbécile puisque c'est un non-sens terminologique. Tout comme un accordéon ou une poêle à frire, une langue ne peut tout simplement pas être rapide ou lente. Tout comme la vitesse d'un accordéon dépend de qui joue, la "vitesse" d'un langage dépend de la rapidité de son compilateur.
"Mais Python n'est pas un langage compilé", quelqu'un peut continuer et rater une fois de plus. Il existe de nombreux compilateurs Python et le plus prometteur d'entre eux est à son tour un script Python. Laisse-moi expliquer.
Une fois, j'ai eu un projet. Une simulation d'impression 3D qui a été écrite à l'origine en Python, puis réécrite en C++ "pour les performances", puis portée sur GPU, tout cela avant mon arrivée. J'ai ensuite passé des mois à porter la version sur Linux, en optimisant le code GPU pour Tesla M60 puisqu'il était le moins cher d'AWS à l'époque, et validant toutes les modifications apportées au code C++/CU pour accompagner le code d'origine en Python. J'ai donc tout fait sauf les choses dans lesquelles je me spécialise normalement, à savoir la conception d'algorithmes géométriques.
Et quand j'ai enfin réussi à tout faire fonctionner, un étudiant de Brême, à temps partiel, m'a appelé et m'a demandé : "Donc, tu es doué pour les choses hétérogènes, peux-tu m'aider à exécuter un algorithme sur GPU ?" Bien sûr! Je lui ai parlé de CUDA, CMake, de la construction Linux, des tests et de l'optimisation ; passé peut-être une heure à parler. Il a écouté tout cela très poliment, mais à la fin il a dit : « Tout cela est très intéressant, mais j'ai une question très précise. J'ai donc une fonction, j'ai écrit @cuda.jit avant sa définition, et Python dit quelque chose sur les tableaux et ne compile pas le noyau. Savez-vous quel pourrait être le problème ici ? »
Je ne savais pas. Il l'a compris lui-même en une journée. Apparemment, Numba ne fonctionne pas avec les listes Python natives, il n'accepte que les données des tableaux NumPy. Il l'a donc compris et a exécuté son algorithme sur GPU. En Python. Il n'avait aucun des problèmes sur lesquels j'ai passé des mois. Vous le voulez sous Linux ? Pas de problème, il suffit de l'exécuter sous Linux. Voulez-vous qu'il soit cohérent avec le code Python ? Pas de problème, c'est du code Python. Voulez-vous optimiser pour la plate-forme cible ? Pas un problème à nouveau. Numba optimisera le code pour la plate-forme sur laquelle vous exécutez le code car il ne compile pas à l'avance, il compile à la demande lorsqu'il est déjà déployé.
N'est-ce pas génial? Et bien non. Pas pour moi en tout cas. J'ai passé des mois avec C++ à résoudre des problèmes qui ne se produisent jamais dans Numba, et un employé à temps partiel de Brême a fait la même chose en quelques jours. Cela aurait pu être quelques heures si ce n'était pas sa première expérience avec Numba. Alors, c'est quoi ce Numba ? De quel genre de sorcellerie s'agit-il ?
Pas de sorcellerie. Les décorateurs Python transforment chaque morceau de code en son arbre de syntaxe abstraite pour vous, afin que vous puissiez ensuite en faire ce que vous voulez. Numba est une bibliothèque Python qui souhaite compiler des arbres de syntaxe abstraite avec n'importe quel backend dont il dispose et pour n'importe quelle plate-forme qu'il prend en charge. Si vous souhaitez compiler votre code Python pour qu'il s'exécute sur des cœurs de processeur de manière massivement parallèle, dites simplement à Numba de le compiler ainsi. Si vous voulez exécuter quelque chose sur GPU, encore une fois, vous ne devez demander que .
@cuda.jit def matmul(A, B, C): """Perform square matrix multiplication of C = A * B.""" i, j = cuda.grid(2) if i < C.shape[0] and j < C.shape[1]: tmp = 0. for k in range(A.shape[1]): tmp += A[i, k] * B[k, j] C[i, j] = tmp
Numba est l'un des compilateurs Python qui rend C++ obsolète. En théorie, cependant, ce n'est pas mieux que C++ car il utilise les mêmes backends. Il utilise CUDA pour la programmation GPU et LLVM pour le CPU. En pratique, ne nécessitant pas de reconstruction en amont pour chaque nouvelle architecture, les solutions Numba s'adaptent mieux à chaque nouveau matériel et à ses optimisations disponibles.
Bien sûr, il serait préférable d'avoir un avantage de performance clair comme c'est le cas avec Spiral. Mais Spiral est plus un projet de recherche, il pourrait tuer C++ mais seulement éventuellement, et seulement s'il a de la chance. Numba avec Python étrangle C++ en ce moment, en temps réel. Parce que si vous pouvez écrire en Python et avoir les performances de C++, pourquoi voudriez-vous écrire en C++ ?
Jouons à un autre jeu. Je vais vous donner trois morceaux de code, et vous devinerez lequel d'entre eux, ou peut-être plus, est écrit en assembleur. Les voici:
invoke RegisterClassEx, addr wc ; register our window class invoke CreateWindowEx,NULL, ADDR ClassName, ADDR AppName,\ WS_OVERLAPPEDWINDOW,\ CW_USEDEFAULT, CW_USEDEFAULT,\ CW_USEDEFAULT, CW_USEDEFAULT,\ NULL, NULL, hInst, NULL mov hwnd,eax invoke ShowWindow, hwnd,CmdShow ; display our window on desktop invoke UpdateWindow, hwnd ; refresh the client area .while TRUE ; Enter message loop invoke GetMessage, ADDR msg,NULL,0,0 .break .if (!eax) invoke TranslateMessage, ADDR msg invoke DispatchMessage, ADDR msg .endw
(module (func $add (param $lhs i32) (param $rhs i32) (result i32) get_local $lhs get_local $rhs i32.add) (export "add" (func $add)))
v0 = my_vector // we want the horizontal sum of this int64 r0 = get_len ( v0 ) int64 r0 = round_u2 ( r0 ) float v0 = set_len ( r0 , v0 ) while ( uint64 r0 > 4) { uint64 r0 >>= 1 float v1 = shift_reduce ( r0 , v0 ) float v0 = v1 + v0 }
Alors, lequel, ou plus d'un, est en assemblage ? Si vous pensez que tous les trois, félicitations! votre intuition s'est déjà bien améliorée !
Le premier est dans MASM32. C'est un macroassembleur avec des "if" et des "while" dans lesquels les gens écrivent des applications Windows natives. C'est vrai, pas "utilisé pour écrire" mais "écrire" à ce jour. Microsoft protège avec zèle la rétrocompatibilité de Windows avec l'API Win32 afin que tous les programmes MASM32 jamais écrits fonctionnent également bien sur les PC modernes.
Ce qui est ironique, c'est que C a été inventé pour faciliter la traduction UNIX de PDP-7 vers PDP-11. Il a été conçu comme un assembleur portable capable de survivre à l'explosion cambrienne des architectures matérielles des années 70. Mais au XXIe siècle, l'architecture matérielle évolue si lentement, les programmes que j'ai écrits dans MASM32 il y a 20 ans s'assemblent et fonctionnent parfaitement aujourd'hui, mais je n'ai aucune confiance qu'une application C++ que j'ai construite l'année dernière avec CMake 3.21 se construira aujourd'hui avec CMake 3.25.
Le deuxième morceau de code est Web Assembly. Ce n'est même pas un assembleur de macros, il n'a pas de « si » ni de « tant que », c'est plutôt un code machine lisible par l'homme pour votre navigateur. Ou un autre navigateur. Conceptuellement, n'importe quel navigateur.
Le code Web Assembly ne dépend pas du tout de votre architecture matérielle. La machine qu'il sert est abstraite, virtuelle, universelle, appelez-la comme vous voulez. Si vous pouvez lire ce texte, vous en avez déjà un sur votre machine physique.
Mais le morceau de code le plus intéressant est le troisième. C'est ForwardCom – un assembleur qu'Agner Fog, un auteur renommé de manuels d'optimisation de C++ et d'assemblage, propose. Tout comme avec Web Assembly, la proposition ne couvre pas tant un assembleur que l'ensemble universel d'instructions conçues pour permettre non seulement la compatibilité ascendante mais aussi ascendante. D'où le nom. Le nom complet de ForwardCom est « une architecture de jeu d'instructions ouverte compatible avec l'avant ». En d'autres termes, ce n'est pas tant une proposition d'assemblée qu'une proposition de traité de paix.
Nous savons que toutes les familles architecturales les plus courantes : x64, ARM et RISC-V ont des jeux d'instructions différents. Mais personne ne connaît une bonne raison de le garder ainsi. Tous les processeurs modernes, à l'exception peut-être des plus simples, n'exécutent pas le code avec lequel vous l'alimentez, mais le microcode dans lequel ils traduisent votre entrée. Ainsi, ce n'est pas seulement M1 qui a une couche de compatibilité descendante pour Intel, chaque processeur a essentiellement une couche de compatibilité ascendante pour toutes ses propres versions antérieures.
Alors, qu'est-ce qui empêche les concepteurs d'architecture de s'entendre sur une couche similaire mais pour une compatibilité ascendante ? Hormis les ambitions contradictoires des entreprises en concurrence directe, rien. Mais si les fabricants de processeurs décident à un moment donné d'avoir un jeu d'instructions commun plutôt que d'implémenter une nouvelle couche de compatibilité pour tous les autres concurrents, ForwardCom ramènera la programmation d'assemblage au grand public. Cette couche de compatibilité ascendante guérirait la pire névrose de tous les programmeurs d'assemblage : "et si j'écrivais le code unique pour cette architecture particulière, et que cette architecture particulière deviendrait obsolète dans un an ?"
Avec une couche de compatibilité ascendante, il ne deviendra jamais obsolète. C'est le but.
La programmation en assembleur est également freinée par un mythe selon lequel écrire en assembleur est difficile et donc peu pratique. La proposition de Fog aborde également ce problème. Si les gens pensent qu'écrire en assembleur est difficile et qu'écrire en C ne l'est pas, eh bien, faisons en sorte que l'assembleur ressemble à C. Pas de problème. Il n'y a aucune bonne raison pour qu'un langage d'assemblage moderne ait exactement la même apparence que son grand-père dans les années 50.
Vous venez de voir vous-même trois échantillons d'assemblage. Aucun d'entre eux ne ressemble à un assemblage "traditionnel" et aucun ne devrait l'être.
Ainsi, ForwardCom est l'assemblage dans lequel vous pouvez écrire du code optimal qui ne deviendra jamais obsolète, et qui ne vous fait pas apprendre un assemblage « traditionnel ». Pour toutes considérations pratiques, c'est le C du futur. Pas C++.
Nous vivons dans un monde postmoderne. Plus rien ne meurt que les gens. Tout comme le latin n'est jamais mort, tout comme COBOL, Algol 68 et Ada, - C++ est voué à une demi-existence éternelle entre la vie et la mort. Le C++ ne mourra jamais réellement, il sera seulement poussé hors du courant dominant par de nouvelles technologies plus puissantes.
Eh bien, pas « sera poussé » mais « être poussé ». Je suis arrivé à mon travail actuel en tant que programmeur C++, et aujourd'hui ma journée de travail commence avec Python. J'écris les équations, SymPy les résout pour moi, puis traduit la solution en C++. Je colle ensuite ce code dans la bibliothèque C++ sans même prendre la peine de le formater un peu, car clang-tidy le fera de toute façon pour moi. Un analyseur statique vérifiera que je n'ai pas gâché les espaces de noms, et un analyseur dynamique vérifiera les fuites de mémoire. CI/CD se chargera de la compilation multiplateforme. Un profileur m'aidera à comprendre comment mon code fonctionne réellement, et désassembleur - pourquoi.
Si j'échange C++ pour "pas C++", 80% de mon travail restera exactement le même. C++ n'est tout simplement pas pertinent pour la plupart de ce que je fais. Cela pourrait-il signifier que pour moi, C++ est déjà mort à 80 % ?
Image de plomb développée par diffusion stable.