Un noyau décrit le travail d’un seul fil
Un noyau est la petite fonction que chaque fil d’un GPU exécute sur son propre élément. Écrire un noyau, c’est dire ce que fait un seul fil : le lancement le répète ensuite des milliers de fois.
Un magasin additionne les stocks de deux entrepôts, case par case. Le labo n’a pas de GPU : une boucle simule le lancement, et le noyau est une vraie fonction Python.
À la fin de cette leçon
Remarque
Je peux écrire un noyau pour un calcul simple et le lancer.
Mots clés
| Mot | Ce que ça veut dire |
|---|---|
| Noyau | la fonction que chaque fil exécute |
| Lancement | le départ de tous les fils d’une grille |
| Garde | le test qui empêche un fil sans élément d’écrire |
| Taille de bloc | le nombre de fils dans chaque bloc |
| Sortie | le tableau où chaque fil écrit son résultat |
| Conflit d’écriture | deux fils qui écrivent la même case |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Un noyau calcule son indice puis son résultat
Un noyau fait trois choses. Un : il calcule son indice global avec son bloc et son fil. Deux : il vérifie que l’indice existe. Trois : il lit ses données et écrit son résultat dans la case de même indice.
Le noyau ne connaît pas les autres fils. Il ne voit que son élément.
Lire le noyau du labo
docker exec jupyter cat steps/kernel.pyAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Un noyau qui double des nombres
# Un noyau qui double chaque nombre, lancé par blocs de 2 fils.
entree = [3, 1, 4, 1, 5]
taille_bloc = 2
n = len(entree)
sortie = [0] * n
def noyau_doubler(bloc, fil):
i = bloc * taille_bloc + fil
if i < n:
sortie[i] = entree[i] * 2
nombre_blocs = (n + taille_bloc - 1) // taille_bloc
for bloc in range(nombre_blocs):
for fil in range(taille_bloc):
noyau_doubler(bloc, fil)
print(nombre_blocs, "blocs")
print(sortie)
# Remplacez i < n par i < n + 1 : le dernier fil plante. Pourquoi ?
La garde protège la fin des données
On lance toujours des blocs entiers. Pour 5 éléments et des blocs de 2 fils, on lance 6 fils : le dernier tombe à l’indice 5, qui n’existe pas.
La garde if i < n fait que ce fil ne fait rien. Sans elle, il écrit hors du tableau.
Exemple : cinq éléments, blocs de deux fils
| Bloc | Fil | Indice | Ce qui se passe |
|---|---|---|---|
| 0 | 0 et 1 | 0 et 1 | Il écrit les cases 0 et 1 |
| 1 | 0 et 1 | 2 et 3 | Il écrit les cases 2 et 3 |
| 2 | 0 | 4 | Il écrit la case 4 |
| 2 | 1 | 5 | La garde l’arrête : rien n’est écrit |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Chaque fil écrit sa propre case
Ce qui rend un noyau sûr, c’est que chaque fil écrit une case que personne d’autre n’écrit : celle de son indice. Les fils peuvent alors partir dans n’importe quel ordre.
Si tous les fils additionnent dans une même case, ils se gênent : c’est un conflit d’écriture, et le résultat devient imprévisible.
Une erreur fréquente
Attention
On croit souvent que le numéro de fil suffit pour choisir l’élément. Le numéro de fil recommence à 0 dans chaque bloc : tous les blocs écriraient les mêmes cases. Il faut l’indice global, bloc fois taille de bloc plus fil.