Une seule opération pour tout un tableau
La vectorisation remplace une boucle par une seule opération appliquée à tout un tableau de nombres. Elle permet de traiter des millions de valeurs sans écrire de boucle, et c’est l’idée de base d’un GPU.
Un magasin applique une remise de 10 % à 50 000 prix. Chaque prix se calcule seul : l’ordre n’a aucune importance. Le labo n’a pas de GPU, mais la bibliothèque NumPy applique déjà cette idée.
À la fin de cette leçon
Remarque
Je peux remplacer une boucle par une opération sur un tableau entier.
Mots clés
| Mot | Ce que ça veut dire |
|---|---|
| Tableau | une suite de nombres rangés côte à côte |
| Boucle | des instructions répétées, un élément après l’autre |
| Élément par élément | chaque case est calculée avec la case de même rang |
| Vectorisation | une opération qui traite tout le tableau d’un coup |
| Parallélisme de données | la même opération sur beaucoup de données |
| Produit scalaire | la somme des produits des cases de même rang |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une boucle traite un élément à la fois
Une boucle prend un prix, fait ses calculs, puis passe au suivant. Pour chaque prix, le programme exécute plusieurs instructions Python : c’est un travail de pilotage en plus du calcul.
Si le tableau compte 50 000 prix, ce pilotage se répète 50 000 fois.
Appliquer une remise avec une boucle
# Une remise de 10 % sur quatre prix en euros, avec une boucle.
prix = [12.0, 8.5, 20.0, 5.0]
remise = 10
nouveaux = []
operations = 0
for un_prix in prix:
nouveaux.append(round(un_prix * (100 - remise) / 100, 2))
operations = operations + 3 # une soustraction, une multiplication, une division
print(nouveaux)
print("opérations de calcul :", operations)
# Ajoutez deux prix à la liste : le nombre d'opérations monte de 6.
Une opération élément par élément
Additionner deux tableaux, c’est additionner les cases de même rang. Multiplier un tableau par 2, c’est doubler chaque case. On écrit l’opération une fois, et elle s’applique à toutes les cases.
Le résultat a la même taille que les tableaux de départ.
Exemple : trois opérations sur deux tableaux
| Opération | Avec a = [1, 2, 3] et b = [10, 20, 30] | Résultat |
|---|---|---|
| a + b | 1+10, 2+20, 3+30 | [11, 22, 33] |
| a * 2 | 1×2, 2×2, 3×2 | [2, 4, 6] |
| a * b | 1×10, 2×20, 3×30 | [10, 40, 90] |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Le labo compte les opérations Python
Le script vectors.py additionne les carrés de 1 à 1000 de deux façons. La première utilise une boucle, la seconde une seule opération NumPy. Il ne mesure aucun temps : il compte les opérations que Python pilote lui-même.
Le script affiche des mots en anglais : « loop » veut dire boucle, et « equal » veut dire égaux.
Lire le script avant de le lancer
docker exec jupyter cat steps/vectors.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.
Comparer la boucle et NumPy
docker exec jupyter python3 steps/vectors.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
| Méthode | Résultat | Opérations pilotées par Python |
|---|---|---|
| Boucle | 333833500 | 2000 |
| Une opération NumPy | 333833500 | 1 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une erreur fréquente
Attention
On croit souvent que vectoriser réduit le nombre de calculs. Non : il reste mille multiplications et mille additions. Ce qui change, c’est qui les pilote : une seule instruction lance tout le tableau, au lieu de mille tours de boucle. Les deux résultats sont égaux.
Quand ne peut-on pas vectoriser ?
Un solde de compte dépend du solde de la veille : chaque case a besoin de la case d’avant. On ne peut pas tout calculer d’un coup, car l’ordre compte.
Un calcul se vectorise quand chaque résultat ne dépend que de ses propres données. Un GPU a exactement besoin de cette propriété.