
Pour bien comprendre comment Spark fonctionne, il faut dâabord explorer son architecture. Heureusement, puisque nous avons dĂ©jĂ vu ensemble les diffĂ©rents composants du calcul distribuĂ©, vous allez tout de suite vous y retrouver ! Il suffit de donner un nouveau nom Ă chacun des concepts, et hop, je vous prĂ©sente lâĂ©quipe de travail Spark. Cette Ă©quipe est composĂ©e de trois acteurs principaux : le Driver, les Executors, et le Cluster Manager. Chacun joue un rĂŽle clĂ© pour que tout fonctionne de maniĂšre fluide et efficace. đÂ
Vous vous souvenez du nĆud maĂźtre, qui coordonne et distribue les tĂąches? Chez Spark, il s'appelle le Driver. Il agit comme le cerveau de lâapplication, transformant votre code en un plan dâexĂ©cution, qui prend la forme dâun graphe orientĂ© acyclique , ou Directed Acyclic Graph (DAG). Nous reviendrons plus prĂ©cisĂ©ment sur ce point dans la section suivante.
Allez, assez parlĂ© du Driver, passons aux Executors. Ce sont les travailleurs du cluster (les nĆuds esclaves), exĂ©cutant les tĂąches assignĂ©es et retournant les rĂ©sultats au Driver.Â
Enfin, le petit dernier, vous lâaurez sĂ»rement un peu moins attendu, jâai nommĂ© le Cluster Manager. Souvenez-vous, dans la premiĂšre partie de ce cours, je vous disais:
Le nĆud maĂźtre doit donc surveiller constamment la mĂ©moire disponible et ajuster les allocations en consĂ©quence.
Et bien, pour Spark, ce nâest pas au noeud maĂźtre de se soucier de cela, mais au Cluster Manager. Il joue le rĂŽle de gestionnaire des ressources, allouant la mĂ©moire et le CPU nĂ©cessaires aux Executors et au Driver, tout en surveillant lâĂ©tat du cluster. Ensemble, ces composants permettent Ă Spark de parallĂ©liser les calculs et de traiter efficacement des volumes massifs de donnĂ©es.
Voici donc ce qui se passe Ă chaque fois que Spark distribue un calcul pour vous:
Le Driver reçoit votre programme et le transforme en un DAG.
Le Cluster Manager alloue les ressources nécessaires (mémoire, CPU) aux Executors.
Les Executors exécutent les tùches assignées par le Driver et renvoient les résultats.
Le Driver collecte les résultats et les retourne à votre programme.
Avec PySpark, votre point d'entrĂ©e pour manipuler cette architecture est lâobjet SparkSession. Voici comment le configurer :
from pyspark.sql import SparkSession
# Créer une SparkSession avec une configuration
spark = SparkSession.builder \
.appName("MonAppSpark") \ # Nom de l'application
.master("local[*]") \ # Mode d'exĂ©cution (local ou cluster) (ici, local avec tous les cĆurs disponibles) (vous pouvez mettre un chiffre Ă la place de lâĂ©toile pour indiquer le nombre de coeurs Ă utiliser si vous prĂ©fĂ©rez)
# Configuration de la mémoire
.config("spark.driver.memory", "4g") \ # Mémoire allouée au driver
.config("spark.executor.memory", "8g") \ # Mémoire allouée à chaque executor
# Vous pouvez ajouter Ă cela autant de points de config que vous souhaitez.
# Quand vous avez mis toutes les points de config souhaités, créer ou récupérer la session Spark
.getOrCreate()Pas de souci si vous ne connaissez pas encore les RDD ! On va découvrir ça ensemble.
Maintenant que vous connaissez les acteurs principaux de lâarchitecture Spark, plongeons dans son fonctionnement interne. Spark repose sur deux concepts clĂ©s : le DAG (Directed Acyclic Graph) et les RDD (Resilient Distributed Datasets). Ces deux Ă©lĂ©ments sont les piliers qui permettent Ă Spark dâĂȘtre aussi rapide et efficace. đ
Le DAG (ou graphe orientĂ© acyclique) est le plan dâexĂ©cution que Spark crĂ©e pour organiser les tĂąches de votre programme.
Voici un exemple de DAG:

Le graphe acyclique est reprĂ©sentĂ© par les rectangles et les flĂšches que vous voyez ici. On peut Ă©galement parler de nĆuds et d'arĂȘtes. On voit bien quâil y a un sens Ă respecter, le graphe est donc orientĂ©. Et le plus important⊠on ne peut pas tourner en rond ! Bah oui, vous ne voudriez pas que vos nĆuds fassent la mĂȘme chose en boucle sans sâarrĂȘter đ±. Du coup, tout sâarrĂȘte quand on arrive Ă l'Ă©tape 3 đ. Le graphe doit absolument ĂȘtre sans cycle (acyclique) pour que tout se passe bien. Au final, câest comme une recette de cuisine : chaque Ă©tape est une tĂąche Ă accomplir, et les flĂšches reprĂ©sentent lâordre dans lequel ces tĂąches doivent ĂȘtre exĂ©cutĂ©es.
Pourquoi est-il si important ?
Il permet Ă Spark dâoptimiser lâexĂ©cution des tĂąches en Ă©vitant les calculs redondants.
Il garantit que les tĂąches sont exĂ©cutĂ©es dans le bon ordre, sans cycles ni boucles infinies (dâoĂč le terme acyclique).
Il facilite la tolérance aux pannes : si une tùche échoue, Spark peut la rejouer à partir du DAG.
Les RDD sont la structure de donnĂ©es fondamentale de Spark. Ils reprĂ©sentent des collections dâobjets distribuĂ©es sur le cluster et immutables (câest-Ă -dire quâils ne peuvent pas ĂȘtre modifiĂ©s aprĂšs leur crĂ©ation). Chaque RDD est divisĂ© en partitions, ce qui permet Ă Spark de parallĂ©liser les calculs.

Et voici comment faire des partitions avec votre RDD :
from pyspark import SparkContext, SparkConf
conf = SparkConf().setAppName(âappNameâ).setMaster(âLocalâ)
sc = SparkContext(conf=conf)
rdd = sc.parallelize([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], numSlices=4) # Crée 4 partitions
rdd_repartitioned = rdd.repartition(2) # Réduit à 2 partitionsA ce stade, nous comprenons donc que Spark va utiliser le DAG comme une recette de cuisine lui permettant de savoir quoi faire, étape par étape, pour chaque partition du RDD.
Avant cela cependant, pour faire vos RDD, vous aurez surtout besoin de charger vos donnĂ©es avec Spark. Allez, voyons ça ensemble ! đ
Que vous travailliez avec des fichiers CSV, JSON, Parquet ou mĂȘme des bases de donnĂ©es SQL, Spark a tout prĂ©vu pour vous đ€. Ces formats couvrent la grande majoritĂ© des besoins, que vos donnĂ©es soient structurĂ©es ou semi-structurĂ©es, et ils sont donc tous inclus dans Spark.
Pour l'essentiel, voici comment vous pouvez facilement charger vos données avec Spark:
Vos données CSV:
# Charger un fichier CSV
csv_df = spark.read.csv("chemin/vers/fichier.csv", header=True, inferSchema=True)Vos données JSON:
# Charger un fichier JSON
json_df = spark.read.json("chemin/vers/fichier.json")Vos données Parquet:
# Charger un fichier Parquet
parquet_df = spark.read.parquet("chemin/vers/fichier.parquet")Vos données SQL:
csv_df.createOrReplaceTempView("ma_table")
result = spark.sql("SELECT colonne, AVG(valeur) FROM ma_table GROUP BY colonne")
result.show() Maintenant que vos donnĂ©es sont chargĂ©es dans un DataFrame, il est temps de leur donner vie grĂące aux transformations et aux actions qui façonneront votre DAG. PrĂȘt Ă explorer ces opĂ©rations clĂ©s pour orchestrer l'exĂ©cution de votre workflow Spark ? Allons-y ! đ
Plus prĂ©cisĂ©ment, les transformations sont les opĂ©rations qui dĂ©finissent les Ă©tapes du DAG. Elles dĂ©crivent comment les donnĂ©es doivent ĂȘtre modifiĂ©es ou transformĂ©es, mais elles ne sont pas exĂ©cutĂ©es immĂ©diatement. Chaque transformation crĂ©e un nouveau RDD (ou Dataframe / Dataset) Ă partir d'un RDD existant. Et oui, souvenez-vous, un RDD est immuable et donc non modifiable par une transformation ! đ€
Voici quelques exemples de transformations :
map: Applique une fonction à chaque élément du RDD.
filter: Filtre les éléments selon une condition.
groupBy: Regroupe les éléments par clé.
join: Combine deux RDD en fonction d'une clé commune.
Les actions sont les opérations qui déclenchent l'exécution du DAG. Elles demandent à Spark de calculer un résultat et de le retourner au programme. Les actions ne font pas partie des étapes du DAG, mais elles sont le point de départ de son exécution.
Exemples d'actions :
count: Compte le nombre d'éléments dans le RDD.
collect: RécupÚre tous les éléments du RDD sur le Driver.
saveAsTextFile: Sauvegarde les éléments du RDD dans un fichier.
show: Affiche les éléments du RDD (ou DataFrame).
Mais pourquoi le DAG ne s'exécute-t-il pas immédiatement ?
Parce quâil est comme vous, fin moi, fin⊠bref, fainĂ©ant quoi ! Spark utilise une Ă©valuation dite âparesseuseâ (lazy evaluation). Autrement dit, si on ne lui dit pas clairement et explicitement de sâactiverâŠ, bah il ⊠rĂ©flĂ©chit đ€. En effet, Spark passe son temps Ă essayer d'optimiser le DAG en regroupant les transformations et en Ă©vitant le plus possible les calculs inutiles. Donc sa fainĂ©antise nous est bien utile, alors que la nĂŽtre⊠đ đ.
Voici un petit code illustrant tout ce que nous venons dâĂ©noncer:
# Créer un RDD à partir d'une liste de nombres
rdd = sc.parallelize([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
# Appliquer des transformations
rdd_mapped = rdd.map(lambda x: x * 2) # Transformation 1 : Multiplier chaque élément par 2
rdd_filtered = rdd_mapped.filter(lambda x: x > 10) # Transformation 2 : Filtrer les éléments > 10
rdd_grouped = rdd_filtered.groupBy(lambda x: x % 2) # Transformation 3 : Grouper par pair/impair
# Appeler une action
result = rdd_grouped.count() # Action : Compter le nombre de groupesChaque Ă©tape (map, filter, groupBy) est un nĆud dans le DAG, et l'action count dĂ©clenche l'exĂ©cution du DAG.
Que diriez-vous dâun petit exercice? Super idĂ©e ! đ (Oui, je sais⊠đ) Rien de mieux quâun petit exercice pratique pour se familiariser avec PySpark. Et pour lâoccasion, prenons lâun des jeux de donnĂ©es les plus connus de Kaggle, Ă savoir: Dogs vs. Cats. đžâš
Voici nos objectifs:
Charger des images de chats et de chiens.
Extraire des caractĂ©ristiques Ă lâaide dâun modĂšle de machine learning prĂ©-entraĂźnĂ© (transfert learning).
EntraĂźner un modĂšle de classification automatique pour prĂ©dire si lâimage contient un chat ou un chien.
Notez les cellules sous les sous-titres âcalcul distribuĂ©â. Et bien câest lĂ que la âmagieâ de Spark entre en jeu. Et je reviendrai plus en dĂ©tails sur ce qui se passe dans les parties suivantes de ce cours. Mais voilĂ , vous avez rĂ©alisĂ© votre premier calcul distribuĂ© !
Reverrons le code ensemble dans ce screencast :
Vous voyez, rien de compliquĂ© ! Si vous avez lâhabitude de faire du machine learning en python, et bien vous nâavez quasiment rien Ă changer par rapport Ă ce que vous savez dĂ©jĂ faire. Câest lâun des avantages de PySpark, câest de vous permettre de faire du calcul distribuĂ© sans que vous ayez Ă y rĂ©flĂ©chir plus que ça.
Allez, pour cĂ©lĂ©brer lâoccasion, je vous propose de refaire exactement la mĂȘme chose mais avec vos scanners mĂ©dicaux. PrĂȘt ?

Vous vous souvenez de l'hĂŽpital qui souhaite centraliser lâanalyse des scans mĂ©dicaux. Et bien, il vient de vous contacter pour faire un premier poc pour prouver votre capacitĂ© Ă catĂ©goriser automatiquement ces scans. Au passage, faites vous la main en identifiant les diffĂ©rentes Ă©tapes du DAG et changez le nombre de partitions pour voir ce qui change.
Allez, au travail !
Voici les étapes pour réussir :
Trouvez un dataset. Vous pouvez utiliser un dataset public de scanners médicaux comme Chest X-Ray Images (pour des radiographies de la poitrine) par exemple.
Téléchargez le dataset et chargez une petite partie des images dans votre environnement de travail.
Utilisez PySpark pour distribuer le chargement des images ainsi que toute autre Ă©tape du travail qui pourrait constituer un goulot dâĂ©tranglement lorsque le volume dâimage augmentera.
Vous pouvez utiliser un modĂšle simple comme une rĂ©gression logistique ou un arbre de dĂ©cision avec les caractĂ©ristiques extraites. Pensez Ă diviser les donnĂ©es en jeux dâentraĂźnement et de test.Â
Voici un indice : vous aurez besoin de cet import supplémentaire =>
from pyspark.ml.feature import PCA
# Ă©crivez votre code ici pour compresser les imagesMaintenant, relancer le notebook que vous avez rĂ©alisĂ© plus tĂŽt pour classifier automatiquement des scanners mĂ©dicaux et essayer dâidentifier les diffĂ©rentes Ă©tapes du DAG. Changer le nombre de partitions et voyez ce qui change.
Pourquoi ne pas essayer de compresser vos images Ă lâaide dâune ACP avant de les sauvegarder ? LĂ aussi, voyez ce qui change en termes de DAG.
Lâarchitecture de Spark repose sur trois acteurs principaux : le Driver (coordination), les Executors (exĂ©cution des tĂąches), et le Cluster Manager (gestion des ressources).
Le DAG est le plan dâexĂ©cution de Spark, qui permet dâorganiser les tĂąches de maniĂšre efficace et dâoptimiser les calculs.
Les RDD sont la structure de données fondamentale de Spark, immuables et distribuées en partitions pour faciliter le traitement parallÚle.
Spark utilise des transformations (définition des étapes) et des actions (déclenchement des calculs) avec une évaluation paresseuse pour maximiser les performances.
Et voilĂ , vous maĂźtrisez maintenant les rouages internes de Spark ! Prochaine Ă©tape : vos gains de performances ! đÂ