in

“Optimiser les performances en combinant Multiprocessing et Asyncio en Python | Par Peng Qian | Mai 2023”


COMBINER MULTIPROCESSING ET ASYNCIO EN PYTHON POUR DES PERFORMANCES AMÉLIORÉES

Grâce à GIL, utiliser plusieurs fils d’exécution pour effectuer des tâches liées au CPU n’a jamais été une option en Python. Cependant, avec la popularité des processeurs multicœurs, Python offre une solution de multiprocessus pour effectuer des tâches liées au CPU. Mais jusqu’à présent, il y avait encore des problèmes avec l’utilisation directe des API liées à la multiprocessus.

PROBLÈMES AVEC LA MULTIPROCESSUS

Avant de commencer, examinons un petit morceau de code pour aider à la démonstration : la méthode prend un argument et commence à accumuler de zéro jusqu’à cet argument. Elle imprime le temps d’exécution de la méthode et renvoie le résultat.

Le code montre que nous créons et démarrons directement plusieurs processus, puis appelons les méthodes start et join de chaque processus. Cependant, il y a quelques problèmes ici :

• La méthode join ne peut pas retourner le résultat de l’exécution de la tâche.
• La méthode join bloque le processus principal et l’exécute de manière séquentielle.

Même si les tâches ultérieures s’exécutent plus rapidement que les précédentes, comme le montre la figure suivante, le processus B doit encore attendre le processus A.

PROBLÈMES LIÉS À POOL

Si nous utilisons multiprocessing.Pool, il y a également des problèmes : la méthode apply de Pool est synchrone, ce qui signifie que vous devez attendre que la tâche précédente se termine avant que la tâche suivante ne puisse commencer à s’exécuter.

Bien sûr, nous pouvons utiliser la méthode apply_async pour créer la tâche de manière asynchrone. Mais encore une fois, vous devez utiliser la méthode get pour obtenir le résultat de manière bloquante. Cela nous ramène au problème avec la méthode join.

PROBLÈME AVEC L’UTILISATION DE PROCESSPOOLEXECUTOR DIRECTEMENT

Et si nous utilisons concurrent.futures.ProcesssPoolExecutor pour exécuter nos tâches liées au CPU ? Tout semble génial et est appelé exactement comme asyncio.as_completed. Mais regardez les résultats ; ils sont encore récupérés dans l’ordre de démarrage. Ce n’est pas du tout la même chose qu’asyncio.as_completed, qui obtient les résultats dans l’ordre où ils ont été exécutés.

UTILISER LA MÉTHODE RUN_IN_EXECUTOR D’ASYNCIO POUR RÉSOUDRE LES PROBLÈMES

Heureusement, nous pouvons utiliser asyncio pour gérer les tâches liées à l’entrée-sortie et sa méthode run_in_executor pour invoquer des tâches multiprocessus de la même manière qu’asyncio. Cela permet non seulement d’unifier les API concurentes et parallèles, mais aussi de résoudre les différents problèmes rencontrés ci-dessus.

Depuis que l’article précédent s’est concentré sur la simulation de ce que nous devrions appeler des méthodes de processus concurrentes, beaucoup de lecteurs ont encore besoin d’aide pour comprendre comment l’utiliser dans le codage réel après l’avoir appris. Après avoir compris pourquoi nous avons besoin d’effectuer des tâches parallèles liées au CPU dans asyncio, nous allons utiliser un exemple réel pour expliquer comment utiliser asyncio pour gérer simultanément des tâches liées à l’entrée-sortie et au CPU, et apprécier l’efficacité d’asyncio pour notre code.

Sources :
– Combining Multiprocessing and Asyncio in Python for Performance Boosts | by Peng Qian | May, 2023
– https://docs.python.org/3/library/asyncio-task.html

What do you think?

Written by Barbara

Leave a Reply

Your email address will not be published. Required fields are marked *

Compagnon de voyage d’intelligence artificielle conversationnelle Wanderbot

Les efforts de rebranding de Peloton en 2023 mettront en avant les abonnements.