Retour au catalogue
Season 34 7 Épisodes 23 min 2026

NumPy

v2.4 — Édition 2026. Un cours audio d'introduction à NumPy, expliquant ses hautes performances, ses tableaux multidimensionnels et son rôle critique dans l'écosystème Python. (v2.4, Édition 2026)

Science des données Fondamentaux de Python
NumPy
Lecture en cours
Click play to start
0:00
0:00
1
L'identité fondamentale : ndarray
Cet épisode couvre l'objet ndarray, les types de données homogènes et l'allocation de mémoire fixe. Vous apprendrez pourquoi les listes Python standard sont inefficaces pour les mathématiques à grande échelle et comment NumPy résout ce problème en s'appuyant sur du code C compilé.
3m 11s
2
Invoquer des tableaux : Création et forme
Cet épisode explore comment créer correctement des tableaux multidimensionnels à l'aide de fonctions intrinsèques. Vous apprendrez à utiliser des outils comme zeros, arange et linspace pour générer des jeux de données instantanément.
3m 21s
3
Sous le capot : Mémoire, strides et vues
Cet épisode plonge dans l'architecture interne de NumPy, en se concentrant sur le data buffer et les strides. Vous apprendrez pourquoi des opérations comme le slicing et la transposition sont pratiquement instantanées car elles renvoient des vues de la mémoire, et non des copies.
3m 22s
4
Fonctions universelles : Les mathématiques sans boucles
Cet épisode couvre les Universal Functions (ufuncs) et la manière dont elles vectorisent les opérations. Vous apprendrez à éliminer complètement les boucles for de Python en appliquant des mathématiques élément par élément et des réductions basées sur les axes.
3m 05s
5
Broadcasting : La magie des formes incompatibles
Cet épisode explique les règles exactes du Broadcasting. Vous apprendrez comment NumPy étire conceptuellement des tableaux de formes incompatibles afin qu'ils puissent être traités ensemble sans gaspiller de mémoire.
3m 51s
6
Filtrage de précision : Masquage booléen
Cet épisode se concentre sur le masquage booléen avancé pour filtrer des jeux de données complexes. Vous apprendrez à extraire des points de données très spécifiques à partir de tableaux massifs en utilisant une simple logique conditionnelle.
2m 56s
7
Le traducteur universel : Interopérabilité
Cet épisode révèle pourquoi NumPy reste l'épine dorsale de la science des données en Python. Vous apprendrez comment DLPack et l'array interface permettent le partage de mémoire zero-copy entre des outils comme Pandas et PyTorch.
3m 21s

Épisodes

1

L'identité fondamentale : ndarray

3m 11s

Cet épisode couvre l'objet ndarray, les types de données homogènes et l'allocation de mémoire fixe. Vous apprendrez pourquoi les listes Python standard sont inefficaces pour les mathématiques à grande échelle et comment NumPy résout ce problème en s'appuyant sur du code C compilé.

Télécharger
Salut, ici Alex de DEV STORIES DOT EU. NumPy, épisode 1 sur 7. La list Python standard est très flexible, mais dès que tu essaies de faire des calculs sur un million d'éléments, tu te heurtes à un mur de performances. Tu finis par payer une énorme taxe sur les pointers juste pour multiplier des nombres entre eux. La solution à ce bottleneck est le moteur central du calcul scientifique en Python : le ndarray. Pour comprendre pourquoi le ndarray existe, tu dois regarder ce que font les lists standards sous le capot. Une list Python ne stocke pas de nombres bruts. Elle stocke des pointers. Chaque pointer dirige le système vers un emplacement dispersé en mémoire où réside un objet Python complet. Si tu écris une loop standard pour multiplier deux séquences d'un million de nombres, l'interpréteur Python travaille énormément. Pour chaque élément, il récupère le pointer, localise l'objet, vérifie son data type pour confirmer que c'est bien un nombre, fait le calcul, et stocke le nouvel objet. Faire ça un million de fois introduit un énorme overhead. Ce cycle de pointer-chasing et de type-checking est la raison pour laquelle les loops standards sont tout simplement trop lentes pour les grandes opérations mathématiques. Le ndarray, qui signifie N-dimensional array, abandonne cette flexibilité en échange d'une vitesse brute. La partie N-dimensional signifie que cet objet peut représenter une séquence plate de nombres, une grille en deux dimensions, ou une matrice mathématique multi-dimensionnelle complexe. Peu importe le nombre de dimensions que tu définis, sous le capot, il fonctionne selon deux règles strictes. Premièrement, il exige des data types homogènes. Chaque élément dans un ndarray doit être exactement du même type, comme un float soixante-quatre bits. Deuxièmement, il utilise une taille mémoire fixe. Quand tu crées un ndarray, NumPy réserve un seul bloc de mémoire continu. Il n'y a pas de pointers. Les nombres bruts sont stockés de manière compacte, les uns à côté des autres, dans la mémoire système. Voici l'idée clé. Parce que NumPy connaît le data type exact et le memory layout exact, il peut complètement contourner le lent interpréteur Python. Quand tu multiplies deux ndarrays contenant un million de nombres, tu n'écris pas de loop. Tu écris simplement array A multiplié par array B. Ce processus s'appelle la vectorization. NumPy prend ta commande et confie le calcul réel à du code C précompilé. Le code C traverse ce bloc de mémoire continu à la vitesse du hardware. Il saute le type-checking et les recherches de pointers pour chaque élément individuel, parce que la mémoire est parfaitement uniforme. Le trade-off pour cet énorme gain de vitesse est la rigidité structurelle. Parce que la mémoire est un seul bloc continu, tu ne peux pas juste faire un append d'un nouveau nombre à un ndarray comme tu le fais avec une list Python. Si tu as besoin d'un array plus grand, NumPy doit généralement allouer un tout nouveau bloc de mémoire et y copier les anciennes données. Tu construis le conteneur à la taille exacte dont tu as besoin, et ensuite tu lances tes opérations sur tout le bloc en une seule fois. La list Python standard est une collection d'objets isolés répartis en mémoire. Le ndarray de NumPy est un bloc dense et uniforme de données brutes, conçu pour être traité instantanément par du code C optimisé. Si tu aimes ces épisodes et que tu veux soutenir l'émission, tu peux chercher DevStoriesEU sur Patreon. C'est tout pour celui-ci. Merci d'avoir écouté, et continue de créer !
2

Invoquer des tableaux : Création et forme

3m 21s

Cet épisode explore comment créer correctement des tableaux multidimensionnels à l'aide de fonctions intrinsèques. Vous apprendrez à utiliser des outils comme zeros, arange et linspace pour générer des jeux de données instantanément.

Télécharger
Salut, ici Alex de DEV STORIES DOT EU. NumPy, épisode 2 sur 7. En data science, tu saisis rarement tes données à la main. Tu as plutôt besoin d'invoquer de vastes grilles vides et des plages numériques en une seule commande. Parlons des fonctions intrinsèques qui te permettent de créer des arrays de zéro et de contrôler leur structure. Tout d'abord, une petite correction sur la création manuelle. Quand tu convertis une liste Python standard en array avec la fonction array de base, une erreur courante est de passer plusieurs arguments séparés pour créer plusieurs dimensions. La fonction attend une seule séquence. Pour faire un array en deux dimensions, tu passes une liste qui contient d'autres listes, et non deux listes séparées. Chaque array que tu crées transporte des métadonnées structurelles. Deux propriétés sont particulièrement importantes ici. La première est ndim, qui t'indique le nombre d'axes, ou de dimensions, de l'array. Une séquence plate a un ndim de un, tandis qu'une grille plate a un ndim de deux. La deuxième propriété est shape. Shape est un tuple d'entiers qui indique la taille exacte de l'array sur chaque dimension. Si tu as une matrice avec deux lignes et trois colonnes, son shape est de deux par trois. La longueur du tuple shape sera toujours égale à la valeur de ndim. Créer des arrays à partir de listes existantes, c'est bien pour des petits tests, mais le vrai travail exige de générer des arrays de façon programmatique. Si tu as besoin d'un placeholder à remplir de données plus tard, tu utilises les fonctions zeros ou ones. Tu passes simplement un tuple shape à ces fonctions, et elles te renvoient un array avec cette structure exacte, entièrement rempli de zéros ou de uns. Par défaut, ces fonctions créent des floats, mais tu peux contourner ça en spécifiant un data type différent. Quand tu as besoin d'une séquence de nombres, NumPy te fournit deux outils principaux. Le premier est arange, qui fonctionne un peu comme le range standard de Python. Tu lui donnes une valeur de départ, une valeur de fin et une taille de pas. Il génère un array de nombres espacés par ce pas. Même si arange est génial pour les entiers, l'utiliser avec des pas en float peut causer des résultats imprévisibles à cause de la façon dont les ordinateurs gèrent la précision décimale. Le nombre d'éléments que tu récupères peut varier légèrement en fonction d'erreurs d'arrondi microscopiques. Ce qui nous amène à linspace, qui résout le problème de précision des floats. Au lieu de définir la taille du pas, tu définis le nombre exact d'éléments que tu veux. Tu donnes à linspace une valeur de départ, une valeur de fin et le nombre total de points. NumPy calcule l'espacement exact pour toi. Imagine un scénario où tu évalues une fonction mathématique sur un intervalle spécifique. Tu veux calculer la fonction sur une grille lisse de coordonnées entre zéro et un. En utilisant linspace, tu peux générer exactement cent coordonnées espacées uniformément sur cet intervalle. Tu obtiens un array en une dimension parfaitement distribué, ce qui garantit que les limites de début et de fin sont toutes les deux incluses. C'est là que ça devient intéressant. La distinction entre ces deux générateurs de séquences dicte ton workflow. Utilise arange quand la taille exacte du pas compte, comme pour compter des entiers de deux en deux, mais utilise toujours linspace quand tu manipules des floats et des intervalles, pour pouvoir garantir exactement combien de data points tu obtiens et atteindre précisément tes limites. Merci pour ton écoute — à la prochaine.
3

Sous le capot : Mémoire, strides et vues

3m 22s

Cet épisode plonge dans l'architecture interne de NumPy, en se concentrant sur le data buffer et les strides. Vous apprendrez pourquoi des opérations comme le slicing et la transposition sont pratiquement instantanées car elles renvoient des vues de la mémoire, et non des copies.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. NumPy, épisode 3 sur 7. Tu as une matrice d'un milliard de pixels et tu dois inverser ses lignes et ses colonnes. Si tu fais ça en Python standard, ta machine va complètement ramer pendant qu'elle copie des gigaoctets de données. Avec NumPy, cette opération est instantanée. Réorganiser ces pixels ne déplace en fait pas un seul octet de mémoire. C'est possible grâce à la façon dont NumPy gère la mémoire, les strides et les views sous le capot. Pour comprendre pourquoi NumPy est si rapide, tu dois regarder la structure interne d'un array. Un array NumPy n'est pas un seul objet monolithique. Il est strictement séparé en deux parties. La première partie, c'est le data buffer. C'est un bloc contigu et plat de mémoire brute. C'est juste une ligne unidimensionnelle d'octets qui réside en RAM. Le raw buffer ne sait absolument rien des lignes, des colonnes ou des dimensions. La deuxième partie, ce sont les metadata. C'est un petit header, implémenté en interne comme une structure C, qui dit à NumPy comment interpréter cette ligne d'octets bruts. Les metadata contiennent un pointeur vers le début du data buffer, le data type, la shape de l'array, et les strides. Les strides sont le mécanisme qui transforme une ligne de mémoire plate en une grille multidimensionnelle. Un stride, c'est simplement le nombre d'octets que l'ordinateur doit avancer en mémoire pour trouver l'élément suivant sur un axe spécifique. Supposons que tu aies un array bidimensionnel d'entiers 64 bits. Chaque entier prend huit octets. Pour te déplacer d'une colonne vers la droite, le stride pourrait être de huit octets. Mais pour descendre à la ligne suivante, le stride pourrait être de quatre-vingts octets, parce qu'il doit sauter une ligne entière de données dans le raw buffer pour trouver le début de la suivante. Beaucoup de développeurs supposent que quand tu prends une slice d'un array, le système alloue de la nouvelle mémoire et y copie les données sélectionnées. C'est faux. Quand tu demandes une slice, NumPy laisse le raw data buffer complètement intact. À la place, il crée un nouveau header de metadata. Ce nouveau header pointe vers exactement le même bloc de mémoire, mais il change le pointeur de départ et modifie les strides pour ignorer les éléments que tu as exclus. C'est ce qu'on appelle une view. Voici le point clé. Comme les données brutes et les metadata sont gardées séparées, les opérations qui changent la shape ou l'ordre de l'array sont presque totalement gratuites. Repense à la transposition de cette énorme matrice d'un milliard de pixels. NumPy ne prend pas les données pour les réorganiser physiquement. Il échange simplement les valeurs des strides dans le nouveau header de metadata. Le nombre d'octets que tu sautais pour trouver la ligne suivante devient le nombre que tu sautes pour trouver la colonne suivante. Une structure d'array complètement différente est renvoyée à ton code, mais c'est juste une view qui regarde exactement la même mémoire physique. Cette séparation est la base de l'efficacité mémoire de NumPy. Tu peux découper un dataset massif en des dizaines de slices qui se chevauchent, les passer à différentes fonctions, et consommer zéro mémoire supplémentaire pour les données elles-mêmes. Tu génères uniquement de minuscules headers de metadata. Cependant, ça veut dire que tu partages le state. Modifier une valeur dans une slice va altérer l'array d'origine, parce qu'il n'y a qu'un seul vrai data buffer en dessous de tout ça. La séparation des octets bruts et des règles qui les régissent signifie que tes transformations de données les plus lourdes sont souvent juste de légers échanges de metadata. C'est tout pour cet épisode. Merci de m'avoir écouté, et continue de développer !
4

Fonctions universelles : Les mathématiques sans boucles

3m 05s

Cet épisode couvre les Universal Functions (ufuncs) et la manière dont elles vectorisent les opérations. Vous apprendrez à éliminer complètement les boucles for de Python en appliquant des mathématiques élément par élément et des réductions basées sur les axes.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. NumPy, épisode 4 sur 7. Si tu te retrouves un jour à écrire une boucle for pour multiplier des nombres dans un array, arrête tout de suite. Faire ça veut dire que tu paies l'overhead de l'interpréteur Python sur chaque élément, et que ton code tourne cent fois plus lentement que nécessaire. La solution, c'est d'utiliser des universal functions pour faire des maths sans boucles. Une erreur classique, c'est d'essayer de passer un array entier à une fonction du module math standard de Python. Si tu passes un million de relevés de capteurs à math dot sin, Python te sort une erreur. Le module math standard ne comprend que des valeurs scalaires uniques. Pour traiter un array, tu devrais normalement écrire une boucle. Mais Python est un langage dynamique. À l'intérieur d'une boucle, l'interpréteur évalue le data type à chaque itération avant de calculer le résultat. Quand tu traites des datasets massifs, ces minuscules pauses de type-checking s'accumulent et créent un bottleneck de performance important. Une universal function, ou ufunc, résout ce problème en opérant automatiquement sur les arrays, élément par élément. Quand tu appelles une ufunc, NumPy pousse l'exécution de la boucle vers du code C compilé. Comme les arrays NumPy ont un seul data type uniforme, le code C n'a pas besoin de faire de pause pour vérifier les types. Il itère sur des blocs de mémoire contigus et calcule le résultat aussi vite que ton processeur le permet. Prenons un scénario concret. Tu as un array qui contient des milliers de relevés de capteurs environnementaux, et tu dois appliquer une transformation mathématique à tous en même temps. Au lieu d'écrire une boucle, tu passes juste l'array entier à une universal function comme numpy dot exp ou numpy dot sin. L'ufunc prend ton array en input, exécute la boucle rapide au niveau C sur chaque élément, et retourne un tout nouvel array rempli avec les relevés transformés. C'est ça le plus important. Les ufuncs font bien plus que de simples transformations élément par élément. Elles contiennent des méthodes built-in pour collapse les données, en bypassant complètement Python pour les agrégations. La plus courante, c'est la méthode reduce. Supposons que tu as appliqué ta transformation mathématique, et que maintenant tu as besoin de la somme totale de tout l'array. Tu appelles la méthode reduce directement sur l'ufunc d'addition. Tu écris numpy dot add dot reduce, et tu lui passes ton array. La méthode reduce applique l'opération d'addition sous-jacente aux deux premiers éléments. Elle prend cette somme, l'ajoute au troisième élément, et continue ce schéma jusqu'à ce que tout l'array soit collapsed en une seule valeur scalaire. Si tes données ont plusieurs dimensions, tu peux contrôler comment ce collapse se produit. Si tes relevés de capteurs forment une grille en deux dimensions, où les lignes sont différents capteurs et les colonnes des timestamps individuels, réduire toute la grille à un seul nombre détruit cette structure. En fournissant un argument axis, tu contrôles la direction de l'opération. Si tu dis à la méthode reduce d'opérer le long de l'axis zéro, elle collapse les lignes, te laissant avec un array qui contient la somme de tous les capteurs à chaque timestamp individuel. À chaque fois que tu laisses une universal function gérer l'itération nativement, tu échanges les boucles Python lentes contre une exécution C optimisée pour le hardware. Merci d'avoir écouté. À la prochaine !
5

Broadcasting : La magie des formes incompatibles

3m 51s

Cet épisode explique les règles exactes du Broadcasting. Vous apprendrez comment NumPy étire conceptuellement des tableaux de formes incompatibles afin qu'ils puissent être traités ensemble sans gaspiller de mémoire.

Télécharger
Salut, ici Alex de DEV STORIES DOT EU. NumPy, épisode 5 sur 7. Que se passe-t-il quand tu essaies de multiplier une matrice en trois dimensions d'un million de pixels par un petit array de trois nombres ? Dans beaucoup de langages stricts, tu obtiens une erreur de shape mismatch. Avec NumPy, ça fonctionne tout simplement. Ce comportement s'appelle le broadcasting. Le broadcasting décrit comment NumPy traite les arrays avec des shapes différentes pendant les opérations arithmétiques. Il prend le plus petit array et l'étire conceptuellement sur le plus grand pour que leurs shapes s'alignent parfaitement. Les auditeurs pensent souvent à tort que cet étirement copie physiquement les données pour construire un nouvel array correspondant en mémoire. Ce n'est pas le cas. NumPy gère cet alignement implicitement au niveau du C. Il itère plusieurs fois sur les mêmes éléments avec zéro memory overhead, ce qui rend le broadcasting incroyablement rapide et très efficace. Pour l'utiliser, tu dois comprendre comment NumPy décide si deux arrays sont compatibles. Il ne regarde pas le nombre total d'éléments. Il regarde les shape tuples. NumPy aligne les shapes des deux arrays et les compare en commençant par les trailing dimensions, celles tout à droite, et remonte vers la gauche. Deux dimensions sont compatibles si elles remplissent l'une de ces deux conditions strictes. Elles doivent être exactement égales, ou l'une d'elles doit être le chiffre un. Si aucune de ces conditions n'est remplie à un moment donné de la comparaison, NumPy lève une ValueError et l'opération échoue. Appliquons cela à un scénario concret. Tu travailles avec une image RGB. Tu la charges dans un array NumPy avec une shape de 256 par 256 par 3. Le 3 représente les canaux de couleur rouge, vert et bleu à la fin de la shape. Maintenant, tu dois corriger les couleurs de cette image en appliquant une échelle différente à chaque canal de couleur. Tu définis un array en une dimension contenant trois poids de correction de couleur. La shape de cet array est juste 3. Quand tu multiplies l'énorme array de l'image par le tout petit array des poids, NumPy applique la règle de droite à gauche. Il place la shape de l'image, 256 par 256 par 3, au-dessus de la shape des poids, qui est juste 3. En commençant tout à droite, les trailing dimensions sont comparées. Les deux valent 3. Parce qu'elles sont égales, elles sont compatibles. Ensuite, NumPy se déplace vers la gauche. L'array de l'image a une dimension de 256, mais l'array des poids n'a plus du tout de dimensions. C'est là que la deuxième partie de la règle intervient. Quand un array a moins de dimensions que l'autre, NumPy ajoute implicitement des 1 au début de sa shape jusqu'à ce qu'elles aient la même longueur. La shape de l'array des poids est traitée comme 1 par 1 par 3. Maintenant, la comparaison continue. L'image a une dimension de 256, et l'array des poids a maintenant une dimension de 1. Parce que l'un d'eux est un 1, ils sont compatibles. L'array des poids est conceptuellement étiré sur les 256 lignes. Ça se produit à nouveau pour la dimension suivante. Les shapes s'alignent, et NumPy applique tes trois poids de couleur sur l'ensemble des soixante-cinq mille pixels de façon transparente. C'est la partie qui compte. La règle ne fonctionne que de droite à gauche. Si tu as un array en deux dimensions avec une shape de 5 par 4, et que tu essaies d'ajouter un array de shape 5, tu pourrais penser qu'il va s'étirer sur les colonnes. Ce ne sera pas le cas. En partant de la droite, NumPy compare 4 et 5. Ils ne sont pas égaux, et aucun des deux n'est un 1. L'opération échoue instantanément. Pour que ça marche, tu devrais d'abord reshape le deuxième array en 5 par 1. Le broadcasting te permet d'écrire du code propre, sans boucle, qui s'exécute à des vitesses compilées. La règle d'or, c'est toujours les trailing dimensions en premier : elles doivent correspondre exactement, ou l'une d'elles doit être le chiffre un. Merci d'avoir écouté. À la prochaine !
6

Filtrage de précision : Masquage booléen

2m 56s

Cet épisode se concentre sur le masquage booléen avancé pour filtrer des jeux de données complexes. Vous apprendrez à extraire des points de données très spécifiques à partir de tableaux massifs en utilisant une simple logique conditionnelle.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. NumPy, épisode 6 sur 7. Récupérer chaque nombre négatif dans un array d'un milliard d'éléments n'est pas un problème de recherche. Ça ne devrait pas nécessiter de boucle, et ça ne devrait certainement pas ralentir ton application. C'est là qu'on utilise le filtrage de précision : le boolean masking. Le slicing de base récupère des blocs de données propres et prévisibles. Mais dans le monde réel, les données sont chaotiques. Tu veux rarement juste les dix premiers éléments. Tu cherches des éléments spécifiques basés sur une condition logique, et ces éléments peuvent être éparpillés au hasard dans ton dataset. Dans NumPy, récupérer des données de cette façon s'appelle l'advanced indexing, et le boolean masking est l'une de ses formes les plus puissantes. Prends un array massif de relevés de température. Tu dois isoler uniquement les valeurs qui descendent en dessous de zéro. Au lieu d'écrire une boucle pour vérifier chaque relevé un par un, tu utilises un masque. Un masque, c'est un array de valeurs booléennes, c'est-à-dire True ou False. Le point crucial, c'est que cet array booléen a exactement la même shape que ton array de données d'origine. Tu le crées en appliquant une condition inférieure à zéro directement sur l'array. NumPy évalue instantanément chaque élément. Si une température est en dessous de zéro, le masque enregistre un True à cette position exacte. Si la température est de zéro ou plus, il enregistre un False. Une fois que tu as ce masque, tu l'appliques sur l'array d'origine en le passant exactement là où tu mettrais normalement un index. NumPy lit le masque, récupère chaque élément où le masque est True, et laisse tomber le reste. L'opération te donne un tout nouvel array à une dimension qui ne contient que tes températures négatives. Ça se fait en une seule étape, exécutée sous le capot par du code C hautement optimisé. Fais bien attention à la distinction qui suit, parce qu'elle piège beaucoup de devs. Tu dois savoir exactement ce que NumPy te renvoie quand tu filtres des données. Le slicing de base renvoie une view. Si tu fais un slice des dix premiers éléments d'un array et que tu les modifies, l'array d'origine change. Le boolean masking se comporte de manière totalement différente. Comme le boolean masking est une forme d'advanced indexing, il renvoie toujours une copie des données, jamais une view. La raison, c'est l'architecture mémoire. Quand tu fais un slice, NumPy modifie juste les pointeurs vers un bloc de mémoire continu existant. Mais quand tu appliques un boolean mask, les éléments que tu sélectionnes sont complètement arbitraires. Ils ne sont plus sagement rangés les uns à côté des autres en mémoire. NumPy doit les rassembler et allouer un nouvel espace pour stocker le résultat. Ça veut dire que si tu modifies ton nouvel array filtré de températures négatives, ton dataset d'origine reste complètement intact. Tu peux aussi chain ces conditions. Si tu as besoin de températures en dessous de zéro mais strictement supérieures à moins dix degrés, tu combines les deux conditions logiques. NumPy évalue la logique combinée élément par élément et construit un seul masque précis. Quand tu appliques un boolean mask, tu échanges l'efficacité mémoire d'une view contre une précision de filtrage absolue, ce qui te donne une copie intacte et indépendante d'exactement les données que tu as demandées. C'est tout pour cet épisode. Merci d'avoir écouté, et continue de coder !
7

Le traducteur universel : Interopérabilité

3m 21s

Cet épisode révèle pourquoi NumPy reste l'épine dorsale de la science des données en Python. Vous apprendrez comment DLPack et l'array interface permettent le partage de mémoire zero-copy entre des outils comme Pandas et PyTorch.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. NumPy, épisode 7 sur 7. Avec les frameworks GPU modernes qui font le gros du travail en machine learning, tu pourrais penser que NumPy devient obsolète. Tu pourrais même supposer que convertir un CPU tensor PyTorch en array NumPy nécessite une copie mémoire lente, ce qui plombe ton pipeline. C'est faux dans les deux cas. En réalité, NumPy agit comme le traducteur universel : l'interopérabilité, qui maintient la cohésion de tout le data ecosystem Python. Pense à un pipeline de machine learning classique. Tu utilises Pandas pour charger et nettoyer un énorme dataset tabulaire. Tu extrais ces valeurs dans NumPy pour appliquer un filtre mathématique spécialisé. Enfin, tu passes ces données filtrées à PyTorch pour entraîner un réseau de neurones. Si chacune de ces libraries isolait ses données, passer d'une étape à l'autre reviendrait à dupliquer tout le dataset en mémoire encore et encore. Tu saturerais ta RAM et tu gaspillerais du temps de calcul juste pour déplacer des octets. Au lieu de ça, grâce à la magie de l'interopérabilité, les données ne bougent jamais vraiment. Pandas, NumPy et PyTorch partagent tout simplement exactement le même memory pointer sous-jacent. Quand PyTorch lit les données, il regarde exactement les mêmes adresses mémoire physiques que Pandas a allouées au départ. Ce partage zero copy est rendu possible par des protocoles mémoire standards. Le plus fondamental est l'array interface. Si un objet Python expose cette interface, il transmet en gros un petit dictionnaire de metadata. Ces metadata indiquent à NumPy exactement où les données brutes commencent en mémoire, quelle est leur shape, et quel data type elles contiennent. Quand tu appelles une fonction NumPy sur un objet compatible, NumPy lit ces instructions et enveloppe sa propre structure d'array autour du bloc mémoire existant. Il ne crée pas un nouvel array ; il crée juste une nouvelle view des anciennes données. Voici le point essentiel. L'array interface d'origine a été conçue principalement pour la mémoire système standard. Quand la data science est passée aux hardware accelerators, l'écosystème a eu besoin d'un moyen de partager les données résidant sur des GPUs ou des puces personnalisées sans les faire repasser par le CPU. C'est ce qui a conduit à l'adoption de DLPack. DLPack est un standard ouvert et moderne pour partager des arrays multidimensionnels entre différents frameworks. Il définit une structure stable que n'importe quelle library peut produire et consommer. Si tu as un tensor dans un framework comme PyTorch ou JAX, tu peux l'exporter en utilisant le protocole DLPack. NumPy peut ensuite l'ingérer de manière transparente grâce à sa fonction dédiée from dlpack. Même si NumPy lui-même fonctionne principalement sur le CPU, son support de DLPack signifie qu'il peut agir comme le hub de routage central. Tu peux passer un objet DLPack d'un framework de deep learning à NumPy, ou de NumPy vers un framework, le tout sans duplication de données coûteuse. Ça fait longtemps que NumPy n'est plus juste une library de maths. C'est le standard mémoire invisible qui empêche le data ecosystem Python de se fragmenter en îlots isolés et incompatibles. Je t'encourage à explorer la documentation officielle, à tester ces conversions zero copy toi-même dans ton propre terminal, ou à visiter devstories dot eu pour suggérer des sujets pour nos futures séries. C'est tout pour cet épisode. Merci pour ton écoute, et continue à développer !