5 points par GN⁺ 2023-10-22 | 1 commentaires | Partager sur WhatsApp
  • Les GPU sont conçus pour privilégier le débit massivement parallèle plutôt qu’une faible latence sur une instruction unique, ce qui les rend très efficaces pour les charges de travail qui exécutent en grande quantité le même type d’opérations, comme le deep learning, le graphisme et le calcul numérique
  • Alors que les CPU réduisent la latence d’exécution séquentielle grâce au pipelining, à l’exécution out-of-order, à l’exécution spéculative et aux caches multiniveaux, les GPU masquent la latence avec de nombreuses ALU et de nombreux threads afin d’augmenter le débit
  • En précision 32 bits, le Nvidia Ampere A100 atteint 19,5 TFLOPS, contre 0,66 TFLOPS pour un processeur Intel 24 cœurs en 2021, et l’écart de débit en calcul numérique continue de se creuser
  • Dans un kernel CUDA, le code hôte sur CPU prépare l’exécution, tandis que le code device sur GPU s’exécute selon une structure grid·block·thread, les threads étant regroupés par warp de 32 et traités selon le modèle SIMT
  • Les performances réelles dépendent fortement de la manière dont on répartit les registres, la mémoire partagée, les emplacements de blocs et les emplacements de threads d’un SM ; si l’occupancy est faible, il devient difficile de masquer la latence et d’atteindre le débit maximal

Différence d’objectifs de conception entre CPU et GPU

  • Les CPU sont principalement conçus pour exécuter rapidement des instructions séquentielles
    • Ils utilisent des techniques comme l’instruction pipelining, l’exécution out-of-order, l’exécution spéculative et les caches multiniveaux pour réduire la latence d’exécution des instructions
    • Une opération unique comme l’addition de deux nombres, ou une courte séquence d’opérations, peut être traitée avec une latence plus faible par un CPU que par un GPU
  • Les GPU sont conçus autour du parallélisme massif et d’un débit élevé
    • Cette architecture est bien adaptée aux tâches qui doivent exécuter rapidement un grand nombre d’opérations d’algèbre linéaire et de calcul numérique, comme les jeux vidéo, le graphisme, le calcul scientifique et le deep learning
    • Lorsqu’il s’agit de millions ou de milliards d’opérations du même type, un GPU peut traiter la charge bien plus vite qu’un CPU grâce à son parallélisme massif
  • Les performances en calcul numérique se mesurent en FLOPS, c’est-à-dire en nombre d’opérations en virgule flottante par seconde
    • Le Nvidia Ampere A100 offre un débit de 19,5 TFLOPS en précision 32 bits
    • En 2021, un processeur Intel 24 cœurs se situait autour de 0,66 TFLOPS en précision 32 bits
    • L’écart de débit entre GPU et CPU s’accroît d’année en année

Comment les GPU masquent la latence

  • Même si la latence d’une instruction individuelle est élevée, les GPU assurent une forte tolérance à la latence en exploitant un grand nombre de threads et de ressources de calcul
  • Pendant qu’un thread attend le résultat d’une instruction, le GPU exécute d’autres threads qui ne sont pas en attente
  • Grâce à cet ordonnancement, les unités de calcul continuent à fonctionner autant que possible et maintiennent un débit élevé

Architecture de calcul des GPU

  • Un GPU est composé d’un ensemble de multiprocesseurs de flux (SM)
  • Chaque SM contient plusieurs streaming processors, cœurs et threads
    • Le Nvidia H100 dispose de 132 SM, chacun avec 64 cœurs, soit un total de 8 448 cœurs
  • Chaque SM possède une quantité limitée de mémoire on-chip partagée par tous les cœurs
    • Cette mémoire est appelée shared memory ou scratchpad
  • Les ressources de l’unité de contrôle du SM sont également partagées entre les cœurs
  • Chaque SM dispose d’un thread scheduler matériel pour exécuter les threads
  • Selon la charge de travail, on peut aussi trouver des unités spécialisées ou des accélérateurs de calcul comme les tensor cores ou les unités de ray tracing

Hiérarchie mémoire des GPU

  • Registres

    • Chaque SM possède un grand nombre de registres
    • Les Nvidia A100 et H100 disposent de 65 536 registres par SM
    • Les registres sont partagés entre les cœurs et alloués dynamiquement selon les besoins des threads
    • Les registres attribués à un thread donné pendant l’exécution sont exclusifs à ce thread, et aucun autre thread ne peut les lire ni les écrire
  • constant cache

    • Il met en cache les données constantes utilisées par le code exécuté sur le SM
    • Le programmeur doit déclarer explicitement un objet comme constant dans le code pour que le GPU puisse le placer dans le constant cache
  • shared memory

    • Il s’agit d’une SRAM on-chip programmable, petite, rapide et à faible latence, présente dans chaque SM
    • Elle est partagée par les thread blocks exécutés sur un même SM
    • Quand plusieurs threads utilisent le même fragment de données, un seul thread peut le lire depuis la global memory puis le partager avec les autres, ce qui réduit les chargements redondants
    • Elle sert aussi de mécanisme de synchronisation entre les threads au sein d’un thread block
  • L1 cache et L2 cache

    • Chaque SM possède un L1 cache qui conserve les données fréquemment accédées depuis le L2 cache
    • Le L2 cache est partagé par tous les SM et met en cache les données fréquemment lues depuis la global memory afin de réduire la latence
    • Les L1 et L2 cache fonctionnent de manière transparente pour les SM, qui ont donc l’impression de recevoir les données depuis la global memory
  • global memory

    • Un GPU dispose d’une global memory hors puce, sous la forme d’une DRAM de grande capacité et à large bande passante
    • Le Nvidia H100 offre 80 Go de HBM et une bande passante de 3000 Go/s
    • La global memory est éloignée des SM, ce qui augmente la latence, mais la hiérarchie mémoire on-chip et le grand nombre d’unités de calcul aident à la masquer

Kernels CUDA et structure des threads

  • CUDA est une interface de programmation pour écrire des programmes destinés aux GPU Nvidia
  • Les calculs exécutés sur le GPU sont exprimés sous forme de kernel, similaire à une fonction C/C++
    • Un exemple classique est un kernel d’addition de vecteurs qui prend deux vecteurs en entrée, additionne leurs éléments un à un et écrit le résultat dans un troisième vecteur
  • Lors de l’exécution d’un kernel, plusieurs threads sont lancés, et l’ensemble est appelé grid
    • Une grid est composée d’un ou plusieurs thread blocks
    • Chaque thread block est composé d’un ou plusieurs threads
  • Le nombre de blocs et le nombre de threads dépendent de la taille des données et du niveau de parallélisme souhaité
    • Pour une addition de vecteurs de dimension 256, on peut créer un bloc de 256 threads afin que chaque thread traite un élément du vecteur
    • Sur des problèmes plus grands, le nombre de threads disponibles sur le GPU peut être insuffisant, et chaque thread peut alors traiter plusieurs points de données
  • Une implémentation CUDA se divise en deux parties
    • Le host code s’exécute sur le CPU et prend en charge le chargement des données, l’allocation de mémoire GPU et le lancement du kernel avec la grid de threads configurée
    • Le device code s’exécute sur le GPU et définit la fonction kernel proprement dite

Étapes d’exécution d’un kernel sur GPU

  • Copie des données du host vers le device

    • Avant d’exécuter un kernel, il faut copier les données nécessaires depuis la mémoire CPU vers la global memory du GPU
    • Sur le matériel GPU récent, il est aussi possible de lire directement depuis la mémoire hôte grâce à la unified virtual memory
  • Ordonnancement des thread blocks sur les SM

    • Une fois les données nécessaires prêtes en mémoire GPU, les thread blocks sont assignés aux SM
    • Tous les threads d’un même bloc sont traités simultanément sur le même SM
    • Avant l’exécution, le GPU doit réserver les ressources du SM nécessaires à ces threads
    • En pratique, plusieurs thread blocks peuvent être affectés simultanément au même SM
    • Comme le nombre de SM est limité et qu’un gros kernel peut comporter un très grand nombre de blocs, tous les blocs ne s’exécutent pas immédiatement
    • Le GPU maintient une liste de blocs en attente et, lorsqu’un bloc se termine, il affecte un bloc en attente à l’exécution
  • SIMT et warp

    • Les threads affectés à un SM sont ensuite regroupés par paquets de 32, appelés warp
    • La taille d’un warp sur les GPU Nvidia actuels est de 32, mais cela pourrait changer sur du matériel futur
    • Le SM récupère et émet la même instruction pour tous les threads d’un warp
    • Les threads exécutent donc la même instruction au même moment, mais sur des portions de données différentes
    • Ce modèle est appelé single instruction multiple threads (SIMT) et ressemble aux instructions SIMD des CPU
    • Les GPU récents depuis Volta disposent aussi d’un independent thread scheduling, qui permet une concurrence complète entre threads indépendamment des warps
  • Ordonnancement des warps et tolérance à la latence

    • Même si tous les processing blocks d’un SM peuvent prendre en charge des warps, seule une partie d’entre eux exécute effectivement des instructions à un instant donné
    • La raison est que le nombre d’unités d’exécution dans un SM est limité
    • Si un warp attend le résultat d’une instruction longue, le SM le met en attente et exécute d’autres warps qui n’ont pas besoin d’attendre
    • Chaque thread de chaque warp possède son propre jeu de registres, ce qui permet de passer d’un warp à l’autre sans surcoût particulier
    • À l’inverse, un changement de contexte entre processus sur un CPU est coûteux, car il faut sauvegarder les registres en mémoire principale puis restaurer l’état d’un autre processus
  • Copie des résultats du device vers le host

    • Une fois tous les threads du kernel terminés, les résultats sont recopiés vers la mémoire hôte

Répartition des ressources et occupancy

  • L’utilisation des ressources GPU se mesure avec un indicateur appelé occupancy
    • L’occupancy correspond au rapport entre le nombre de warps affectés à un SM et le nombre maximal de warps que ce SM peut prendre en charge
    • Pour atteindre le débit maximal, une occupancy de 100 % est souhaitable, mais elle n’est pas toujours possible en raison de diverses contraintes
  • Un SM dispose de ressources d’exécution fixes, comme les registres, la shared memory, les emplacements de thread blocks et les emplacements de threads
    • Ces ressources sont réparties dynamiquement selon les besoins des threads et les limites du GPU
  • Exemple avec le Nvidia H100
    • Chaque SM peut prendre en charge 32 blocs, 64 warps, soit 2048 threads
    • Il prend en charge jusqu’à 1024 threads par bloc
    • Si l’on exécute des blocs de 1024 threads, les 2048 emplacements de threads se répartissent en 2 blocs
  • Le partitionnement dynamique permet une utilisation plus efficace des ressources de calcul qu’un partitionnement fixe
    • Dans un partitionnement fixe, chaque thread block reçoit une quantité figée de ressources d’exécution
    • Dans certains cas, un thread peut se voir attribuer plus de ressources que nécessaire, ce qui provoque du gaspillage et une baisse de débit
  • Exemples de baisse d’occupancy
    • Si la taille des blocs est de 32 threads et qu’il faut 2048 threads au total, on obtient 64 blocs
    • Mais comme chaque SM ne peut traiter que 32 blocs à la fois, seuls 1024 threads s’exécutent réellement, et l’occupancy tombe à 50 %
    • Avec 65 536 registres par SM, exécuter 2048 threads simultanément signifie qu’on ne peut utiliser au maximum que 32 registres par thread
    • Si le kernel a besoin de 64 registres par thread, le SM ne peut exécuter que 1024 threads, et l’occupancy retombe à 50 %
  • Une occupancy faible empêche de masquer suffisamment la latence et peut aussi réduire le débit de calcul nécessaire pour atteindre le maximum théorique du matériel
  • Pour écrire des kernels GPU efficaces, il faut répartir soigneusement les ressources afin de maintenir une occupancy élevée tout en réduisant la latence
    • Utiliser beaucoup de registres peut accélérer le code lui-même, mais aussi faire baisser l’occupancy ; l’optimisation repose donc sur un équilibre

Pour aller plus loin

1 commentaires

 
GN⁺ 2023-10-22
Avis sur Hacker News
  • Quelqu’un a envoyé un e-mail pour protester au sujet de cet article : https://twitter.com/abhi9u/status/1715753871564476597
    C’est une violation des règles de HN. C’est en fait le seul point suffisamment important pour figurer à la fois dans les guidelines du site et dans la FAQ, et les utilisateurs de HN y sont très sensibles
    Q : Puis-je demander des upvotes pour mon article ?
    R : Non. Les utilisateurs doivent voter quand ils trouvent quelque chose intellectuellement intéressant, pas parce que quelqu’un a du contenu à promouvoir. Si vous enfreignez cette règle, votre post, votre compte ou votre site pourra être pénalisé ou banni ; ne le faites donc pas
    https://news.ycombinator.com/newsfaq.html
    Ne demandez pas de votes, de commentaires ni de soumissions. Les utilisateurs doivent voter et commenter lorsqu’ils trouvent personnellement intéressant quelque chose qu’ils ont rencontré eux-mêmes, et non dans un but promotionnel
    https://news.ycombinator.com/newsguidelines.html

    • Je ne connaissais pas cette règle, et je ne connais pas non plus la personne qui a posté l’article
      Maintenant je le sais, je ne le referai plus
  • J’ai été surpris de ne pas voir de copie asynchrone dans la partie « copie des données de l’hôte vers le périphérique ». Pour exploiter un GPU au maximum, il ne faut pas que le GPU reste inactif pendant qu’on copie des données entre l’hôte et le GPU
    Beaucoup de frameworks fournissent des mécanismes de planification de copies asynchrones pouvant s’exécuter avec des soumissions de travaux asynchrones. L’article est plutôt une introduction au GPU, mais en programmation GPU réelle, pour tirer jusqu’à la dernière goutte d’un GPU coûteux, il existe toutes sortes d’astuces et de techniques au-delà de ça. Comme pour la plupart des optimisations aujourd’hui, il y a beaucoup de falaises cachées et de non-linéarités, donc les outils de profiling aident beaucoup

    • Il utilisera probablement des nombres à virgule flottante 64 bits (double), et dans ce cas tous les GPU n’aideront pas énormément. C’est encore plus vrai face à un CPU puissant
      Cela dit, avec un GPU doté de nombreuses unités FP64, on peut obtenir de gros gains. En général ce ne sont pas des GPU gaming, mais si on a simplement une 4060 sous la main, ses performances FP64 sont d’environ 300 GFLOPS, donc probablement supérieures à celles d’un CPU. Les CPU modernes sont eux aussi puissants dans ce domaine, capables d’émettre plusieurs opérations FP64 par cycle sur chaque cœur
  • La première phrase, « la plupart des programmeurs comprennent le CPU en profondeur », est tellement manifestement fausse qu’il devient difficile de prendre le reste au sérieux, même si l’article est peut-être excellent

    • Et si on reformulait ainsi : « un nombre significatif d’informaticiens, d’ingénieurs en informatique, d’ingénieurs électriciens et de développeurs amateurs… »
      À l’université, j’ai suivi un cours de philosophie pour le plaisir, et j’y ai appris à ne pas rejeter immédiatement une phrase, mais à la relire sous une meilleure forme. Désormais, mon cerveau traduit automatiquement les généralisations excessives ou les affirmations manifestement fausses en propositions raisonnablement proches du vrai. Au fil de l’argumentation, je peux reconstruire ces idées et évaluer l’ensemble du texte comme logiquement cohérent
      Grâce à ça, même en lisant un mauvais texte, il me reste de nouvelles prémisses et affirmations vraies ou fausses sur un sujet qui m’intéresse, et mon univers mental s’en trouve élargi
    • Ce n’est certainement pas vrai pour la plupart des programmeurs, mais l’auteur voulait peut-être parler des ingénieurs ayant une formation en informatique. Quand on suit un cursus d’informatique classique, on finit par comprendre assez profondément les CPU, alors que les GPU sont souvent abordés bien plus superficiellement
    • Je ne comprends pas pourquoi il y a toujours au moins un commentaire du type « j’ai arrêté de lire à X » sous chaque article sur Internet. Ce genre de remarque n’apporte rien
    • Plus de la moitié de ce débat dépend probablement de la façon dont on définit comprendre en profondeur
      À l’université, j’ai appris les bases de l’architecture CPU, j’ai une vision très élémentaire du paysage général et je tombe parfois sur des mises à jour limitées de mes connaissances, mais je n’appellerais pas ça une « compréhension profonde ». « Une compréhension de base de la façon dont les CPU fonctionnent, sont conçus et sont utilisés » me semblerait plus juste
      Si l’on maîtrise l’assembleur, on pourrait peut-être dire qu’on « comprend en profondeur » comment utiliser un CPU à bas niveau, mais ça me paraît quand même un peu exagéré. Ce n’est pas non plus la même chose qu’être spécialiste de la conception de CPU/GPU
      Donc je suis d’accord. L’article reste toutefois intéressant, et les schémas sont particulièrement bons
    • J’ai appris les deux dans mon cursus et dans le cours Structure and Interpretation of Computer Programs, et je recommande ce cours à toute personne intéressée par le calcul bas niveau
  • Le passage disant que « les registres attribués à un thread en cours d’exécution sont réservés à ce thread, donc les autres threads ne peuvent ni les lire ni les écrire » admet des exceptions
    Les wave intrinsics de HLSL et les fonctionnalités similaires de CUDA permettent de lire les registres d’autres threads dans le wavefront courant. Et dans le paragraphe sur l’architecture mémoire, il vaudrait aussi la peine de mentionner que les caches ne garantissent pas la cohérence entre les threads d’un même dispatch/grid, mais qu’un bloc fonctionnel spécial, global à toute la puce, implémente les opérations atomiques sur la mémoire globale

  • La programmation SIMD, c’est vraiment brutal
    Vous voulez effectuer un calcul sur tous les pixels de l’écran ? Aucun problème
    Vous voulez ajouter une condition de branchement ? Aïe

    • Vous voulez mettre de l’eval ? Tout s’arrête
    • Pour être honnête, c’est logique. Prendre des décisions intelligentes est « plus difficile » que de répartir un calcul simple sur beaucoup de travailleurs
  • Pourquoi appelle-t-on encore ça un GPU ? PPU (unité de traitement parallèle) semblerait être un meilleur nom

    • Parce qu’en plus des fonctions GPU généralistes, il contient aussi du silicium dédié aux graphismes
    • Parce que quand on dit GPU, tout le monde comprend ce que ça veut dire
      C’est un peu comme la relation entre drone et quad-copter
    • Unité de traitement vectoriel serait plus approprié, à mon avis
    • Un CPU est aussi un PPU
    • General Processing Unit
  • Excellent article. Et les GPU, pour ce qu’ils font, sont plus avancés et plus performants que tout ce qui me vient à l’esprit.
    Mais j’aimerais classer le SIMD dans la catégorie des choses dont on n’a pas vraiment besoin une fois qu’on a appris d’autres paradigmes plus flexibles. Je préfère le MIMD et les clusters/transputers, qui semblent avoir disparu vers les années 2000. L’état actuel des choses exige des développeurs qu’ils déplacent eux-mêmes les données, écrivent des shaders sous des limites arbitraires sur le nombre d’emplacements mémoire accessibles simultanément, dupliquent le travail avec des langages séparés pour GPU/CPU, sachent quel matériel existe pour des fonctions comme le lancer de rayons, et restent enfermés dans des frameworks très prescriptifs comme OpenGL/Metal/Vulkan. Les GPU sont une branche latérale qui ne pourra jamais m’emmener là où je veux aller ; ces 25 dernières années, j’ai eu l’impression de vivre dans la mauvaise ligne temporelle.
    En gros, dans les contraintes de la fin de la loi de Moore, un CPU généraliste extensible devrait être multicœur avec mémoire locale, partager les données via une mémoire adressée par contenu en copie à l’écriture ou d’autres formes de cache, et fournir un espace d’adressage unique et unifié afin que l’utilisateur puisse explorer librement toutes les formes de calcul dans un environnement informatique de bureau. Il utiliserait un assembleur standard, mais serait généralement programmé avec des langages de programmation fonctionnelle comme Erlang/Go, Octave/MATLAB et, idéalement, Julia. Le rendu 3D et les bibliothèques d’IA seraient des couches au-dessus, pas des éléments fondamentaux.
    Fait intéressant, les GPU sont arrivés à peu près à la configuration multicœur dont je parle, mais les pilotes isolent l’utilisateur de l’accès bare metal nécessaire à un MIMD généraliste. Je pensais que les FPGA étaient le seul moyen de faire tomber la domination des GPU, mais il y a peut-être une occasion d’écrire des pilotes qui font ressembler le matériel GPU à du MIMD avec mémoire unifiée. Je ne sais pas à quel point les cœurs GPU gèrent bien les calculs entiers, mais on pourrait sans doute les approximer avec la partie entière 32 bits d’un flottant 64 bits. À cause de ce genre de compromis, une machine MIMD pourrait être 10 à 100 fois plus lente qu’un GPU, tout en restant 10 à 100 fois plus rapide qu’un CPU. Et elle resterait extensible sans dépendre excessivement de gros caches et de bus rapides, qui ont figé les CPU depuis environ 2007, quand le marché mobile a pris la main et que le prix et l’efficacité énergétique sont devenus prioritaires face aux performances. Des machines MIMD pourraient être mises en cluster pour créer des réseaux de calcul distribué à la SETI@home sans modification du code. Pour donner une idée de la puissance que cela offrirait aux utilisateurs ordinaires, c’est un peu comme comparer BitTorrent à FTP, mais pour le calcul plutôt que pour les données.

  • Je ne comprends pas bien en quoi l’architecture Apple Silicon diffère de celle de NVIDIA.
    Quand on lit « le GPU Nvidia H100 possède 132 SM, avec 64 cœurs par SM, soit 8448 cœurs au total », 8448 cœurs, c’est clairement impressionnant. Mais l’Apple M2 Ultra n’en a que 76 ?
    Comment le GPU NVIDIA H100 peut-il avoir plus de 110 fois plus de cœurs ? Il n’est évidemment pas 110 fois plus performant que le M2 Ultra, alors que se passe-t-il ici ?

    • De manière générale, un SM de NVIDIA correspond plutôt à une CU sur un GPU AMD, ou à un cœur sur un GPU Apple. Ici, les « cœurs » sont plutôt des sous-composants du SM qui effectuent des opérations individuelles.
      Voir ce diagramme du blog NVIDIA : https://developer-blogs.nvidia.com/wp-content/uploads/2021/g...
      (https://developer.nvidia.com/blog/nvidia-ampere-architecture...)
    • Le fait que NVIDIA appelle « cœurs » ce qui est en réalité des voies vectorielles, et utilise aussi le terme « threads » en SIMT pour désigner l’exécution d’une de ces voies vectorielles, est volontairement flou et, franchement, malhonnête.
      Bien sûr, on peut estimer qu’il y a une justification à appeler cela un « thread » puisque chaque voie prend en charge un compteur de programme distinct, mais au final ce qui compte, c’est la vitesse et le débit des ALU.
    • Un H100 peut servir à chauffer une pièce. Il consomme plus de dix fois plus d’énergie qu’un M2 Ultra.
  • Je comprends maintenant pourquoi le machine learning utilise des nombres à virgule flottante pour la précision. Ce n’était pas vraiment un choix : c’est parce que le code graphique les utilisait ainsi
    C’est une autre pièce du puzzle « pourquoi le machine learning est-il aussi inefficace ? »
    Je me demande quel est, en conditions réelles, le surcoût lié aux copies mémoire. Si ça se comporte comme d’habitude, ce serait très sévère. On va jusqu’à déporter le traitement TCP vers le matériel pour l’éviter. Ici, il y a beaucoup plus de données, même si elles sont traitées par blocs plus gros

    • Dans beaucoup de grands réseaux modernes, le temps de calcul GPU pour le calcul des gradients et la rétropropagation est tellement lent que la copie de données en virgule flottante sur le bus PCIe n’est pas le goulot d’étranglement
      Autrement dit, copier un mini-batch d’images en virgule flottante reste largement assez rapide. C’est l’itération gradients/SGD qui est lente et très coûteuse en calcul. Même avec de la précision mixte
      Pour des réseaux peu profonds, il peut être avantageux de ne copier que les données compressées d’origine dans la mémoire GPU, puis de faire la décompression, etc. sur le GPU. Mais si les GPU modernes n’ont pas encore adopté PCIe 5, c’est parce que les performances de calcul brutes comptent davantage
      Enfin, les Tensor Cores ont aussi eu un gros impact, et selon les réseaux ils peuvent être tellement rapides que leur taux d’utilisation devient très faible
    • Je ne considère pas que le choix d’utiliser des nombres à virgule flottante soit particulièrement inefficace. Si les frameworks avaient été en virgule fixe par défaut, il aurait été délicat d’ajuster la plage dynamique sur l’ensemble du réseau
      Les mathématiques de l’entraînement supposent aussi que les nombres sont continus
    • La virgule flottante est plus volumineuse, et ses opérations sont aussi plus difficiles
      Cela dit, je me demandais pourquoi les LLM sur CPU font de la quantification. Si j’ai bien compris, c’est un processus qui réduit la précision des poids pour utiliser moins de mémoire
      On ne sait pas clairement si le manque de précision fait une différence. Si c’est le cas, pourquoi utiliser de la virgule flottante au départ ? Si la précision n’est pas importante, la précision supplémentaire ne fait que consommer plus de ressources sans vraie raison, et probablement de plusieurs ordres de grandeur de plus que nécessaire
      Ce domaine n’a pas été lancé par des gens qui comprenaient les performances. Ils ont utilisé des outils pour construire quelque chose, mais sans le « pourquoi ». Ils l’ont fait ainsi parce que l’outil fonctionne ainsi
      Voilà pourquoi c’est important. Même sur un CPU généraliste, une façon d’accéder aux données peut être plusieurs ordres de grandeur plus rapide qu’une autre, mais encore faut-il le savoir. Ne voudrait-on pas réduire le coût des LLM de plusieurs ordres de grandeur ?
    • Qu’est-ce qui est inefficace dans la virgule flottante ? Le machine learning semble tirer un grand bénéfice de l’accès à une plage dynamique couvrant plusieurs ordres de grandeur
  • Cette présentation et ces slides d’il y a quelques années sur les aspects délicats des CPU et GPU valent aussi le détour
    Alexander Titov — Know your hardware: CPU memory hierarchy https://youtu.be/QOJ2hsop6hM
    https://github.com/alexander-titov/public/blob/master/confer...
    Know Your Hardware - CPU Memory Hierarchy -- Alexander Titov -- C%2B%2B Moscow Meetup March 2019.pdf
    https://github.com/alexander-titov/public/blob/master/confer...
    GPGPU - what it is and why you should care -- Alexander Titov -- CoreHard 2019.pdf