Qu'est-ce que le parallélisme en programmation?
sobes.tech IA
Réponse de l'IA
Le parallélisme en programmation est l'exécution de plusieurs tâches simultanément ou l'apparence d'une exécution simultanée, ce qui permet d'améliorer la performance et la réactivité des applications.
On distingue plusieurs types de parallélisme :
-
Multiprocessing : Utilise plusieurs processus indépendants, chacun avec son propre espace d'adressage. Cela contourne la limitation du GIL (Global Interpreter Lock) dans CPython et convient aux tâches intensives en CPU.
import multiprocessing import time def worker(num): """Un certain travail""" time.sleep(1) print(f'Worker {num} terminé') if __name__ == '__main__': processes = [] for i in range(5): p = multiprocessing.Process(target=worker, args=(i,)) processes.append(p) p.start() for p in processes: p.join() print("Tous les workers ont terminé") -
Multithreading : Utilise plusieurs threads au sein d'un même processus, partageant le même espace d'adressage. En raison du GIL dans CPython, les threads ne s'exécutent pas en parallèle sur différents cœurs pour les tâches CPU-bound, mais sont efficaces pour les tâches I/O-bound.
import threading import time def worker(num): """Un certain travail""" time.sleep(1) # Simulation d'une opération I/O print(f'Thread {num} terminé') threads = [] for i in range(5): t = threading.Thread(target=worker, args=(i,)) threads.append(t) t.start() for t in threads: t.join() print("Tous les threads ont terminé") -
Programmation asynchrone (Asyncio) : Utilise un seul thread et une boucle d'événements (event loop) pour gérer l'exécution des tâches. Convient pour les applications I/O-bound à haute charge et les serveurs web. Ne bloque pas l'exécution en attendant l'I/O.
import asyncio import time async def worker(num): """Un certain travail asynchrone""" await asyncio.sleep(1) # Attente asynchrone d'I/O print(f'Worker asynchrone {num} terminé') async def main(): tasks = [] for i in range(5): task = asyncio.create_task(worker(i)) tasks.append(task) await asyncio.gather(*tasks) print("Tous les workers asynchrones ont terminé") if __name__ == '__main__': asyncio.run(main())
Le choix de l'approche dépend de la nature de la tâche :
| Approche | Tâches CPU-bound | Tâches I/O-bound | GIL | Utilisation de la mémoire |
|---|---|---|---|---|
| Multiprocessing | Excellent | Bon | Le contourne | Grande (son propre processus) |
| Multithreading | Mauvais (à cause du GIL) | Excellent | Bloque | Petite (processus partagé) |
| Asynchrone | Mauvais | Excellent | Ne bloque pas | Petite (un seul thread) |
Le parallélisme nécessite une gestion prudente de la synchronisation et des ressources pour éviter les conditions de course et les blocages mutuels.