2 points par GN⁺ 2024-04-27 | 1 commentaires | Partager sur WhatsApp

Vue d’ensemble de l’architecture de tiny-gpu

GPU

  • Construit pour exécuter un seul kernel à la fois
  • Pour exécuter un kernel, il faut effectuer les opérations suivantes :
    1. Charger la mémoire programme globale avec le code du kernel
    2. Charger la mémoire de données avec les données nécessaires
    3. Indiquer dans les registres de contrôle du périphérique le nombre de threads à exécuter
    4. Lancer le kernel en mettant le signal de démarrage à HIGH
  • Le GPU se compose des unités suivantes :
    1. Registres de contrôle du périphérique
    2. Dispatcher
    3. Un nombre variable de cœurs de calcul
    4. Contrôleur mémoire pour la mémoire de données et la mémoire programme
    5. Cache

Mémoire

  • Le GPU est conçu pour s’interfacer avec une mémoire globale externe
  • La mémoire de données et la mémoire programme sont séparées pour simplifier l’architecture
  • La mémoire globale dispose d’une bande passante fixe en lecture/écriture
  • Le contrôleur mémoire suit toutes les requêtes sortantes des cœurs de calcul vers la mémoire, régule ces requêtes selon la bande passante réelle de la mémoire externe, puis relaie les réponses de la mémoire externe vers les ressources appropriées
  • Le cache stocke les données demandées de façon répétée afin de réduire l’utilisation de la bande passante mémoire

Cœurs

  • Chaque cœur dispose de ressources de calcul
  • Dans ce GPU simplifié, chaque cœur traite un seul bloc à la fois et possède, pour chaque thread du bloc, un ALU, un LSU, un PC et un fichier de registres dédiés
  • Le scheduler gère l’exécution des threads et ne sélectionne pas de nouveau bloc avant d’avoir terminé le bloc en cours
  • Le fetcher récupère de manière asynchrone les instructions à partir du compteur ordinal courant
  • Le décodeur traduit les instructions récupérées en signaux de contrôle pour l’exécution des threads
  • Chaque thread possède son propre ensemble dédié de fichiers de registres
  • L’ALU est une unité arithmétique et logique dédiée à chaque thread
  • Le LSU est une unité load-store dédiée à chaque thread pour accéder à la mémoire de données globale
  • Le PC est un compteur ordinal dédié qui détermine la prochaine instruction à exécuter pour chaque thread

ISA

  • Implémentation d’une ISA simple de 11 instructions
  • Conçue pour des kernels simples comme l’addition et la multiplication de matrices
  • Prend en charge les opérations arithmétiques de base, les chargements/stockages mémoire, les branchements, le chargement de constantes, etc.

Exécution

  • Chaque cœur passe par les étapes fetch, decode, request, wait, execute et update pour exécuter les instructions
  • Chaque thread suit un chemin d’exécution afin d’effectuer des calculs sur les données du fichier de registres
  • Pour les capacités SIMD, des valeurs d’index de bloc, de dimensions et d’index de thread sont présentes dans des registres en lecture seule

Kernels

  • Des kernels d’addition et de multiplication de matrices ont été écrits dans l’ISA pour démontrer la programmation SIMD et l’exécution sur GPU
  • Avec les fichiers de test, il est possible de simuler entièrement l’exécution des kernels sur le GPU et de générer l’état de la mémoire de données ainsi qu’une trace d’exécution

Simulation

  • Après avoir installé iverilog et cocotb, il est possible d’exécuter la simulation des kernels avec la commande make
  • Le fichier de logs affiche l’état initial et final de la mémoire de données, ainsi que la trace complète d’exécution du kernel

Fonctionnalités avancées

  • De nombreuses fonctionnalités supplémentaires des GPU modernes, qui améliorent fortement les performances et les capacités, ont été omises pour simplifier le projet
  • Sont notamment évoquées des fonctionnalités comme les caches multi-niveaux et la mémoire partagée, la fusion mémoire, le pipelining, l’ordonnancement des warps, la divergence de branchement, la synchronisation et les barrières

Avis de GN⁺

  • Le projet explique très bien, de façon simple et accessible, les bases de l’architecture GPU et du modèle de programmation SIMD. Les exemples de kernels de calcul matriciel montrent notamment clairement comment le traitement parallèle s’effectue sur un vrai GPU.
  • Les fonctionnalités avancées utilisées dans les GPU modernes sont également bien résumées, ce qui pourra aider à étudier des architectures GPU plus complexes après avoir compris tiny-gpu.
  • En revanche, les fonctions réelles du pipeline graphique sont absentes, donc le fonctionnement du matériel spécialisé pour le graphisme n’est pas abordé. Cela pourra frustrer les personnes surtout intéressées par le graphisme.
  • Une comparaison avec d’autres architectures GPU open source comme MIAOW ou GPGPU-Sim peut aider à comprendre des GPU plus réalistes.
  • Si des fonctionnalités comme la divergence de branchement, la fusion mémoire ou le pipelining sont ajoutées à l’avenir, le projet pourrait devenir un support d’apprentissage encore plus pratique. Le fait qu’il s’agisse d’un projet open source auquel on peut contribuer est aussi un atout.

1 commentaires

 
GN⁺ 2024-04-27
Commentaires sur Hacker News
  • Intel publie beaucoup de documentation technique sur ses GPU. On peut aussi trouver en ligne les manuels des 810/815. À l’exception des 855/910/915/945, la documentation est fournie de manière assez cohérente.

  • Encourage le travail sur les GPU open core.

  • Il existe un autre projet de GPU open source appelé NyuziProcessor. (https://github.com/jbush001/NyuziProcessor)

  • J’aimerais me lancer dans les FPGA, mais il est difficile de savoir par où commencer, et le domaine lui-même paraît intimidant.

  • L’objectif final est de créer une carte d’accélération pour les LLM (Large Language Model). En dehors de la partie déport de mémoire, il y aurait beaucoup de similitudes avec ce projet.

  • Demande pourquoi on mélange les opérateurs d’affectation non bloquante et bloquante dans un bloc always séquentiel.

  • J’avais fait quelque chose de similaire autrefois en VHDL. Il y avait un site appelé opencores avec divers projets HDL open source. Je me demande s’il existe aujourd’hui des simulateurs HDL distribués à grande échelle, de niveau HPC. Il serait logique d’utiliser des GPU modernes pour faire de la simulation au niveau RTL.

  • J’aime voir des projets matériels être ouverts. Mais on pourrait dire qu’il s’agit d’un coprocesseur SIMD. Pour être un GPU, il faudrait au moins une forme de sortie d’affichage. Ces derniers temps, avec Nvidia et d’autres qui vendent comme GPU des variantes serveur-only d’architectures graphiques, le terme est devenu un peu plus souple, mais la partie « graphique » de la conception d’un GPU représente toujours une part importante de la complexité.

  • Se demande s’il est courant qu’une ALU implémente directement l’instruction DIV au niveau matériel. Je me demande si c’est utilisé comme véritable instruction dans des éléments comme les cœurs CUDA modernes, ou si c’est généralement émulé en logiciel. Un vrai circuit matériel de division prend beaucoup de place, donc je ne m’y attendais pas dans une ALU de GPU. Il est facile d’écrire en Verilog DIV: begin alu_out_reg <= rs / rt; end, mais en silicium cela occupe beaucoup d’espace. Quelqu’un qui ne fait que simuler du Verilog peut toutefois ne pas s’en rendre compte.

  • Encore un autre « GPU » qui ne fournit pas de fonctions graphiques. Selon cet avis, ce genre de chose devrait être appelé autrement.

  • Il a simplifié en supposant que les threads sont traités en parallèle et qu’après chaque instruction, tous les threads « convergent » vers le même compteur ordinal. Sur un vrai GPU, des threads individuels peuvent bifurquer vers des PC différents, ce qui provoque de la branch divergence. Mieux vaudrait faire un peu de programmation GPU avant de fabriquer un GPU en silicium. Ce n’est même pas du SIMD. (La même personne que celle qui avait assemblé un circuit faisant clignoter une LED puis affirmé avoir fabriqué un CPU.)