Traitement parallèle en Python
Introduction
Dans l'environnement numérique actuel, en évolution rapide, il est essentiel pour les développeurs et les data scientists de réaliser efficacement des tâches informatiques difficiles. Heureusement, Python offre de solides capacités de traitement parallèle en raison de son adaptabilité et de son vaste écosystème. Nous pouvons obtenir d'importantes améliorations de performances en divisant les problèmes difficiles en activités plus petites et plus gérables qui peuvent être exécutées simultanément.
Les fonctionnalités de traitement parallèle de Python nous permettent de travailler plus rapidement et plus efficacement sur des activités telles que le web scraping, les simulations scientifiques et l'analyse de données en utilisant les ressources informatiques disponibles. Nous partirons pour un voyage via le traitement parallèle Python dans cet article. Nous examinerons de nombreuses approches, notamment le multi-traitement, la programmation asynchrone et le multi-threading, et apprendrons comment les utiliser efficacement pour contourner les barrières de performances de nos systèmes. Rejoignez-nous pour réaliser toute la puissance du traitement parallèle de Python et atteindre de nouveaux sommets de performances et de productivité.
Comprendre le traitement parallèle
Diviser une tâche en sous-tâches plus petites et les exécuter simultanément sur plusieurs processeurs ou cœurs est appelé traitement parallèle. Le traitement parallèle peut réduire considérablement le temps total d'exécution d'un programme en exploitant efficacement les ressources informatiques disponibles. La programmation asynchrone, le multitraitement et le multithreading ne sont que quelques-unes des méthodes de traitement parallèle proposées par Python.
Multi−Threading en Python
En utilisant l'approche multi-threading, de nombreux threads au sein d'un même processus s'exécutent simultanément tout en partageant la même mémoire. Le multi−threading peut être facilement implémenté en utilisant le module de threading de Python. Cependant, le multithreading en Python n'entraîne pas nécessairement une accélération des opérations liées au CPU en raison du Global Interpreter Lock (GIL), qui permet à un seul thread d'exécuter le bytecode Python à la fois. Le multi-threading, cependant, peut être utile pour les tâches liées aux E/S car il permet aux threads d'exécuter d'autres opérations en attendant la fin des opérations d'E/S.
Regardons une illustration où nous utilisons le multi−threading pour télécharger de nombreuses pages Web :
Exemple
import threading import requests
def download_page(url):
response = requests.get(url)
print(f"Downloaded {url}")
urls = [
"https://example.com",
"https://google.com",
"https://openai.com"
]
threads = []
for url in
urls:
thread = threading.Thread(target=download_page,
args=(url,)) thread.start() threads.append(thread)
for thread in threads:
thread.join()
Sortir
Downloaded https://example.com
Downloaded https://google.com
Downloaded https://openai.com
Plusieurs téléchargements peuvent avoir lieu simultanément grâce à l'extrait de code ci-dessus, qui télécharge chaque URL dans son propre fil de discussion. La fonction join() garantit que le thread principal attend que chaque thread soit terminé avant de continuer.
Multi−Traitement en Python
Le multi−traitement, contrairement au multi−threading, offre un véritable parallélisme en utilisant plusieurs processus, chacun avec son propre espace mémoire. Une interface de haut niveau pour implémenter le multi-traitement est fournie par le module multi-traitement de Python. Le multitraitement est approprié pour les activités liées au processeur puisque chaque processus s'exécute dans un interpréteur Python distinct, évitant ainsi la restriction multithread GIL.
Le multitraitement est utilisé dans le code ci-dessous. La charge est répartie entre les processus disponibles par la méthode map() une fois que la classe pool génère un pool de processus de travail. La liste des résultats est une collection de résultats.
Prenez en compte l'exemple ci-dessous, où nous utilisons le multi−traitement pour mettre au carré chaque entier d'une liste :
Exemple
import multiprocessing
def square(number):
return number ** 2
numbers = [1, 2, 3, 4, 5]
with multiprocessing.Pool() as pool:
results = pool.map(square, numbers)
print(results)
Sortir
[1, 4, 9, 16, 25]
Programmation asynchrone en Python
En exploitant les opérations non bloquantes, la programmation asynchrone permet l'exécution efficace des processus liés aux E/S. Les coroutines, les boucles d'événements et les futurs peuvent tous être utilisés pour créer du code asynchrone en Python grâce au package asyncio. La programmation asynchrone est devenue de plus en plus importante avec la popularité croissante des applications et des API en ligne.
La coroutine fetch_page() dans l'exemple de code ci-dessous utilise aiohttp pour récupérer des pages Web de manière asynchrone. La méthode main() génère une liste de tâches, qui sont ensuite exécutées simultanément à l'aide de asyncio.gather(). Pour attendre la fin des tâches et recevoir les résultats, utilisez le mot-clé wait.
Regardons un exemple d'obtention asynchrone de nombreuses pages Web à l'aide de asyncio et aiohttp :
Exemple
import asyncio
import aiohttp
async def fetch_page(url): async with aiohttp.ClientSession() as session: async with session.get(url) as response:
return await response.text()
async def main():
urls = [
"https://example.com",
"https://google.com",
"https://openai.com"
]
tasks = [fetch_page(url) for url in urls] pages = await asyncio.gather(*tasks)
print(pages)
asyncio.run(main())
Sortir
['<!doctype html>\n<html>\n<head>\n <title>Example Domain</title>\n\n <meta
charset="utf-8" />\n <meta http-equiv="Content-type"content="text/html; charset=utf-8" />\n <meta name="viewport" content="width=device-width, initialscale=1" />\n <style type="text/css">\n body {\n background-color: #f0f0f2;\n margin: 0;\n padding: 0;\n font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; }\n div {\n width: 600px;\n margin: 5em auto;\n padding: 50px;\n background-color: #fff;\n border-radius: 1em;\n }\n a:link, a:visited {\n color: #38488f;\n text-decoration: none;\n }\n @media (maxwidth: 700px) {\n body {\n background-color: #fff;\n }\n div {\n width: auto;\n margin: 0 auto;\n border-radius: 0;\n padding: 1em;\n }\n }\n </style> \n</head>\n\n<body>\n<div>\n <h1>Example Domain</h1>\n <p>This domain is for use in illustrative examples in documents. You may use this\n domain in literature without prior coordination or asking for permission.</p>\n <p><a href="https://www.iana.org/domains/example">More information...</a></p>\n</div>\n</body>\n</html>', '<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="en"><head><meta content="Search the world's information, including webpages, images, videos and more. Google has many special features to help you find exactly what you're looking for." name="description"><meta content="noodp" name="robots"><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/logos/doodles/2021/mom-
and-dad-6116550989716480.2-law.gif" itemprop="image"><link href="/logos/doodles/2021/mom-and-dad-6116550989716480.2-law.gif" rel="icon" type="image/gif"><title>Google</title><script nonce="sJwM0Ptp5a/whzxPtTD8Yw==">(function(){window.google={kEI:'cmKgYY37A7 K09QPhzKuACw',kEXPI:'1354557,1354612,1354620,1354954,1355090,1355493,13556
83,3700267,4029815,4031109,4032677,4036527,4038022,4043492,4045841,4048347,4
048490,4052469,4055589,4056520,4057177,4057696,4060329,4060798,4061854,4062 531,4064696,406 '
Choisir la bonne approche
Les techniques de traitement parallèle de Python varient en fonction des particularités de la tâche à accomplir. Voici quelques lignes directrices pour vous aider à prendre une décision éclairée :
Pour les activités liées aux E/S, où la majorité du temps d'exécution est passée à attendre les opérations d'entrée/sortie, le multi-threading est approprié. Il fonctionne bien pour des tâches telles que le téléchargement de fichiers, l'utilisation d'API et l'exploitation de fichiers. En raison du Global Interpreter Lock (GIL) de Python, le multi-threading peut ne pas accélérer considérablement les activités liées au CPU.
Le multitraitement, en revanche, est idéal pour les tâches liées au processeur et impliquant des calculs intensifs. Il permet un véritable parallélisme en utilisant plusieurs processus, chacun avec son propre espace mémoire, et contourne les limitations du GIL. Cependant, cela entraîne une surcharge supplémentaire en termes de consommation de mémoire et de communication inter-processus.
Pour les activités liées aux E/S impliquant des opérations réseau, la programmation asynchrone, effectuée à l'aide de bibliothèques comme asyncio, est utile. Il utilise des opérations d'E/S non bloquantes afin que les tâches puissent avancer sans avoir à attendre la fin de chaque opération. Cette méthode gère efficacement plusieurs connexions simultanées, ce qui la rend appropriée pour le développement de serveurs réseau, les interactions avec les API Web et le web scraping. La programmation asynchrone minimise les temps d'attente des opérations d'E/S, garantissant ainsi réactivité et évolutivité.
Conclusion
La capacité de traitement parallèle de Python offre la possibilité d'augmenter l'efficacité des tâches nécessitant un calcul complexe. Que vous choisissiez d'utiliser une programmation multithreading, multitraitement ou asynchrone, Python fournit les outils et modules nécessaires pour exploiter efficacement la concurrence. Vous pouvez maximiser les avantages du traitement parallèle et réduire les temps d’exécution en comprenant la nature de votre activité et en choisissant la technique appropriée. Alors allez-y, explorez et utilisez le parallélisme de Python au maximum de son potentiel pour créer des applications plus rapides et plus productives.