pilotes graphiques et GPU "hardware scheduling"
#9
Je peux tenter une explication peut-être un peu plus digeste.

Historiquement, les unités de traitement GPU (la carte graphique) étaient cablées en "dur", autrement dit, imprimées dans le Silicium. Lorsque le programme principal (qui tourne lui sur le CPU) avait besoin d'envoyer quelque chose à l'écran, il devait tout calculer lui-même, sauf ce qui était mis à disposition par le GPU. Pour ça, il suffisait au programme d'envoyer les données "brutes" et les unités de traitement du GPU se chargeaient de les calculer.

En gros, la logique c'était : CPU (Programme maître + calculs) > GPU (seulement les calculs dédiés) > Ecran.

Mais, dès le départ, le GPU contenait plusieurs unités de calculs même quand les CPU n'avait qu'un seul cœur (voir même parfois un seul "thread"). Quand le CPU faisait une seule chose à la fois, le GPU pouvait déjà en faire plusieurs.

Alors bien sûr, c'était sans aucune souplesse, le GPU était (et est toujours) plus lent qu'un CPU mais en imaginant 80 unités de calcul qui puissent travailler en parallèle ... l'apport de ces GPU n'était pas anecdotique ...

Pratiquement, lorsque le CPU devait afficher 1000 triangles (les formes plus complexes en 3D sont réalisées à partir d'un maillage triangulaire), il envoyait le job de 1000 triangles et le GPU (s'il disposait par exemple de 80 unités) en traitait 80 à chaque passe, jusqu'à ce que le "pot" de 1000 soit vide.

On peut représenter cela par
CPU > Job1 (1000 tâches) > GPU > Ecran
GPU (1 à 80)
GPU (81 à 160)
GPU (161 à 240)
...
GPU (961 à 1000) (et oui, il y a 40 unités inutilisées dans ce cas. Evidemment, c'est seulement à ce stade que tout est envoyé à l'écran)

CPU > Job2 (450 tâches) > GPU > Ecran
GPU (1 à 80)
...

Dans un second temps, les GPU ont légèrement pu évoluer et accepter des paramètres. Même si c'est probablement un peu "didactique" comme approche, je m'en sers pour clarifier ce qui suit. La logique est toujours "CPU > GPU > Ecran" mais le programmeur pouvait quand même influer légèrement sur le comportement du GPU.

En gros, la logique d'une séquence était donc (je ne représente plus les passes par "80" mais évidemment elles sont le cœur du calcul) :
CPU > Param1 > GPU
CPU > Job1 > GPU > Ecran
CPU > Job2 > GPU > Ecran
CPU > Param2 > GPU
CPU > Job3 > GPU > Ecran

Donc tant que les paramètres n'étaient pas modifiés, tous les "jobs" utilisaient les précédents. Par contre les paramètres valaient pour toutes les unités de traitement des GPU. Pas question de dire tiens, ces 56 là travaillent avec un set de paramètres différents. Non, un seul set (à la fois) pour le GPU et donc toutes ses unités.

Et les constructeurs sont allés une étape plus loin, plutôt que de ne permettre que du paramétrage, ils ont carrément permis d'envoyer des programmes. Fini donc les limitations du câblage "en dur" et du simple paramétrage, non aujourd'hui il est possible d'utiliser les unités de traitement comme des minis-ordinateurs puisqu'on peut les programmer.

Je vais légèrement détailler la séquence en y introduisant le transfert de données et la compilation (transformation d'un programme lisible par l'humain en programme compréhensible par le GPU).

La logique c'est du coup complexifiée, une séquence devient donc :
CPU > Prog1 > GPU (+compilation1)
CPU > Data1 > GPU
CPU > Job1 > GPU > Ecran
CPU > Data2 > GPU
CPU > Job2 > GPU > Ecran
....
CPU > Prog2 > GPU (+compilation2)
CPU > Data8 > GPU
CPU > Job8 > GPU > Ecran

Les restrictions restent présentes, c'est à dire qu'un même "programme" s'applique à toutes les unités de traitement du GPU.

Mais ça, c'est juste ce que les amateurs d'images et de jeux vidéos utilisent, où est alors l'intérêt du GPGPU (nom qui regroupe CUDA et OpenCL) ?

L'intérêt est qu'il est possible de renvoyer les résultats du calcul au ... CPU ! Le GPU devient donc un "co"-processeur.

La séquence, vue des données devient donc :
CPU > Prog1 > GPU (+compilation1)
CPU > Data1 > GPU
CPU < Résultat1 < GPU
CPU > Prog2 > GPU (+compilation2)
CPU > Data2 > GPU
CPU < Résultat2 < GPU

Et c'est pourquoi, certaines cartes "graphiques" (GPU) n'ont même plus de sortie écran !

Ah oui, j'oubliais un "léger" détail. Il y a 5 ans, si les "bons" CPU étaient 6 coeurs (12 threads, soit 12 tâches en //), les "bonnes" cartes graphiques disposaient déjà de 1500 unités de traitement ... Aujourd'hui alors que les "bons" CPU ont vu leur nombre de tâches en parallèle passer à 20, les "bons" GPU ont 8000 unités de calculs. C'est quand même 400x plus. Donc à chaque "passe" 8000 données sont "moulinées" jusqu'à épuisement des tâches (parfois des millions, enfin tant que la mémoire du GPU est suffisante pour accueillir les données).

Alors, quelles sont les limites ?
- un GPU excelle dès qu'il y a de nombreux calculs répétitifs à effectuer.
- les données des tâches doivent être indépendantes. Le tâche 4351 n'a accès qu'aux jeu de données 4351. Il est par exemple tout à fait impossible de réaliser un "tri" ascendant ou descendant (sauf bien sûr si les données à trier sont dans le jeu 4351). Il est impossible de trouver la plus petite valeur parmi les 8000, ça c'est au CPU de s'en charger lorsque les résultats reviennent du GPU).
- Les 8000 unités sont "préchargées" avec le même "programme".

Et voilà !

Sethenès
Répondre



Messages dans ce sujet
RE: pilotes graphiques et GPU "hardware scheduling" - par Sethenès - 08-09-2020 10:41:11



Utilisateur(s) parcourant ce sujet : 1 visiteur(s)