Découper un calcul pour plusieurs processus
Un processus est un programme en cours d’exécution, avec sa propre mémoire. Pour accélérer un calcul, on le découpe en morceaux que plusieurs processus traitent en même temps, puis on rassemble les résultats.
Un service de paie calcule 4 000 bulletins. Chaque agence peut traiter son lot sans attendre les autres, puis le total est additionné à la fin. Le labo n’a pas de GPU : il le fait avec des processus Python.
À la fin de cette leçon
Remarque
Je peux découper un calcul en morceaux et rassembler les résultats.
Mots clés
| Mot | Ce que ça veut dire |
|---|---|
| Processus | un programme en cours d’exécution, avec sa propre mémoire |
| Fil d’exécution | une suite d’instructions qui partage la mémoire de son processus |
| Morceau | une tranche consécutive des données |
| Somme partielle | le résultat obtenu sur un seul morceau |
| Fusion | l’étape qui rassemble les résultats partiels |
| Réserve de processus | un groupe de processus qui se partagent les morceaux |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Processus : mémoire séparée, fil : mémoire partagée
Deux processus ont chacun leur mémoire : ils ne peuvent pas se gêner, mais ils doivent s’envoyer leurs données. Deux fils d’un même processus partagent la mémoire : c’est léger, mais deux fils qui écrivent la même variable peuvent se gêner.
L’interpréteur Python usuel laisse un seul fil exécuter du code Python à la fois. Le labo utilise donc des processus.
Exemple : processus contre fil
| Question | Processus | Fil d’exécution |
|---|---|---|
| Mémoire | Séparée | Partagée avec son processus |
| Échange de données | Il faut les envoyer | Directement dans la mémoire commune |
| Risque principal | Le coût des échanges | Deux fils écrivent la même variable |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
On découpe en morceaux, puis on fusionne
Trois étapes suffisent. Un : couper les données en morceaux consécutifs. Deux : chaque processus calcule une somme partielle sur son morceau. Trois : la fusion additionne les sommes partielles.
Cela marche quand chaque morceau se calcule sans connaître les autres. Avec 40 nombres et 4 morceaux de 10, chaque morceau en contient 10.
Couper en morceaux et fusionner
# Couper les nombres de 1 à 40 en morceaux de 10, puis rassembler.
donnees = list(range(1, 41))
taille = 10
morceaux = []
debut = 0
while debut < len(donnees):
morceaux.append(donnees[debut:debut + taille])
debut = debut + taille
sommes = []
for morceau in morceaux:
sommes.append(sum(morceau))
print("sommes partielles :", sommes)
print("total :", sum(sommes))
# Changez la taille en 20 : il reste deux morceaux, et le total ne change pas.
Le labo confie les morceaux à deux processus
Le script chunks.py coupe les nombres de 1 à 40 en 4 morceaux de 10. Une réserve de 2 processus se les partage. Les résultats reviennent toujours dans l’ordre des morceaux, quel que soit le processus qui finit le premier.
Le script affiche des mots en anglais : « chunk » veut dire morceau, et « partial sum » veut dire somme partielle.
Lancer le découpage du labo
docker exec jupyter python3 steps/chunks.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.
Exemple : ce que le script affiche
| Morceau | Nombres | Somme partielle |
|---|---|---|
| 0 | 1 à 10 | 55 |
| 1 | 11 à 20 | 155 |
| 2 | 21 à 30 | 255 |
| 3 | 31 à 40 | 355 |
| Total | 1 à 40 | 820 : comme la somme faite d’un seul bloc |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une erreur fréquente
Attention
On croit souvent qu’un processus par donnée est le meilleur découpage. Envoyer un morceau et récupérer son résultat a un coût. Si les morceaux sont minuscules, ce coût peut dépasser le calcul lui-même : coupez en morceaux assez gros.