Utilisez ces techniques pour exécuter du code simultanément et offrir une expérience utilisateur plus fluide.

Points clés à retenir

  • La concurrence et le parallélisme sont des principes fondamentaux de l’exécution des tâches en informatique, chacun ayant ses caractéristiques distinctes.
  • La concurrence permet une utilisation efficace des ressources et une meilleure réactivité des applications, tandis que le parallélisme est crucial pour des performances et une évolutivité optimales.
  • Python fournit des options pour gérer la concurrence, telles que le threading et la programmation asynchrone avec asyncio, ainsi que le parallélisme à l'aide du module multitraitement.

La concurrence et le parallélisme sont deux techniques qui vous permettent d'exécuter plusieurs programmes simultanément. Python propose plusieurs options pour gérer les tâches simultanément et en parallèle, ce qui peut prêter à confusion.

Explorez les outils et bibliothèques disponibles pour implémenter correctement la concurrence et le parallélisme dans Python, et en quoi ils diffèrent.

instagram viewer

Comprendre la concurrence et le parallélisme

La concurrence et le parallélisme font référence à deux principes fondamentaux de l'exécution des tâches en informatique. Chacun a ses caractéristiques distinctes.

  1. Concurrence est la capacité d'un programme à gérer plusieurs tâches en même temps sans nécessairement les exécuter exactement au même moment. Il s’articule autour de l’idée d’entrelacer les tâches, en basculant entre elles d’une manière qui semble simultanée.
  2. Parallélisme, en revanche, implique d’exécuter plusieurs tâches véritablement en parallèle. Il profite généralement de plusieurs cœurs de processeur ou processeurs. Le parallélisme permet une véritable exécution simultanée, vous permettant d'effectuer des tâches plus rapidement et est bien adapté aux opérations gourmandes en calcul.

L'importance de la concurrence et du parallélisme

La nécessité de la concurrence et du parallélisme dans l’informatique ne peut être surestimée. Voici pourquoi ces techniques sont importantes :

  1. Utilisation des ressources: La concurrence permet une utilisation efficace des ressources système, garantissant que les tâches progressent activement plutôt que d'attendre oisivement des ressources externes.
  2. Réactivité: La concurrence peut améliorer la réactivité des applications, en particulier dans les scénarios impliquant des interfaces utilisateur ou des serveurs Web.
  3. Performance: Le parallélisme est crucial pour obtenir des performances optimales, en particulier dans les tâches liées au processeur telles que les calculs complexes, le traitement des données et les simulations.
  4. Évolutivité: La concurrence et le parallélisme sont essentiels pour créer des systèmes évolutifs.
  5. Pérennité: Alors que les tendances matérielles continuent de favoriser les processeurs multicœurs, la capacité à exploiter le parallélisme deviendra de plus en plus nécessaire.

Concurrence en Python

Vous pouvez obtenir la concurrence en Python en utilisant le threading et la programmation asynchrone avec la bibliothèque asyncio.

Threading en Python

Le threading est un mécanisme de concurrence Python qui vous permet de créer et de gérer des tâches au sein d'un seul processus. Les threads conviennent à certains types de tâches, en particulier celles qui sont liées aux E/S et peuvent bénéficier d'une exécution simultanée.

Python filetage module fournit une interface de haut niveau pour créer et gérer des threads. Bien que le GIL (Global Interpreter Lock) limite les threads en termes de véritable parallélisme, ils peuvent toujours atteindre la concurrence en entrelaçant efficacement les tâches.

Le code ci-dessous montre un exemple d'implémentation de la concurrence à l'aide de threads. Il utilise la bibliothèque de requêtes Python pour envoyer une requête HTTP, une tâche courante de blocage d'E/S. Il utilise également le module time pour calculer le temps d'exécution.

import requests
import time
import threading

urls = [
'https://www.google.com',
'https://www.wikipedia.org',
'https://www.makeuseof.com',
]

# function to request a URL
defdownload_url(url):
response = requests.get(url)
print(f"Downloaded {url} - Status Code: {response.status_code}")

# Execute without threads and measure execution time
start_time = time.time()

for url in urls:
download_url(url)

end_time = time.time()
print(f"Sequential download took {end_time - start_time:.2f} seconds\n")

# Execute with threads, resetting the time to measure new execution time
start_time = time.time()
threads = []

for url in urls:
thread = threading.Thread(target=download_url, args=(url,))
thread.start()
threads.append(thread)

# Wait for all threads to complete
for thread in threads:
thread.join()

end_time = time.time()
print(f"Threaded download took {end_time - start_time:.2f} seconds")

En exécutant ce programme, vous devriez voir à quel point les requêtes threadées sont plus rapides que les requêtes séquentielles. Bien que la différence ne soit qu'une fraction de seconde, vous obtenez une idée claire de l'amélioration des performances lors de l'utilisation de threads pour des tâches liées aux E/S.

Programmation asynchrone avec Asyncio

asyncio fournit une boucle d'événements qui gère les tâches asynchrones appelées coroutines. Les coroutines sont des fonctions que vous pouvez suspendre et reprendre, ce qui les rend idéales pour les tâches liées aux E/S. La bibliothèque est particulièrement utile pour les scénarios dans lesquels les tâches impliquent l'attente de ressources externes, telles que les requêtes réseau.

Vous pouvez modifier l'exemple d'envoi de requête précédent pour travailler avec asyncio:

import asyncio
import aiohttp
import time

urls = [
'https://www.google.com',
'https://www.wikipedia.org',
'https://www.makeuseof.com',
]

# asynchronous function to request URL
asyncdefdownload_url(url):
asyncwith aiohttp.ClientSession() as session:
asyncwith session.get(url) as response:
content = await response.text()
print(f"Downloaded {url} - Status Code: {response.status}")

# Main asynchronous function
asyncdefmain():
# Create a list of tasks to download each URL concurrently
tasks = [download_url(url) for url in urls]

# Gather and execute the tasks concurrently
await asyncio.gather(*tasks)

start_time = time.time()

# Run the main asynchronous function
asyncio.run(main())

end_time = time.time()

print(f"Asyncio download took {end_time - start_time:.2f} seconds")

À l'aide du code, vous pouvez télécharger des pages Web simultanément en utilisant asyncio et profitez des opérations d'E/S asynchrones. Cela peut être plus efficace que le threading pour les tâches liées aux E/S.

Parallélisme en Python

Vous pouvez implémenter le parallélisme en utilisant Python multitraitement module, qui vous permet de profiter pleinement des processeurs multicœurs.

Multitraitement en Python

Python multitraitement Le module fournit un moyen d'atteindre le parallélisme en créant des processus séparés, chacun avec son propre interpréteur Python et son propre espace mémoire. Cela contourne efficacement le Global Interpreter Lock (GIL), ce qui le rend adapté aux tâches liées au processeur.

import requests
import multiprocessing
import time

urls = [
'https://www.google.com',
'https://www.wikipedia.org',
'https://www.makeuseof.com',
]

# function to request a URL
defdownload_url(url):
response = requests.get(url)
print(f"Downloaded {url} - Status Code: {response.status_code}")

defmain():
# Create a multiprocessing pool with a specified number of processes
num_processes = len(urls)
pool = multiprocessing.Pool(processes=num_processes)

start_time = time.time()
pool.map(download_url, urls)
end_time = time.time()

# Close the pool and wait for all processes to finish
pool.close()
pool.join()

print(f"Multiprocessing download took {end_time-start_time:.2f} seconds")

main()

Dans cet exemple, multitraitement génère plusieurs processus, permettant au URL_de téléchargement fonction à exécuter en parallèle.

Quand utiliser la concurrence ou le parallélisme

Le choix entre la concurrence et le parallélisme dépend de la nature de vos tâches et des ressources matérielles disponibles.

Vous pouvez utiliser la simultanéité lorsque vous traitez des tâches liées aux E/S, telles que lire et écrire dans des fichiers ou faire des requêtes réseau, et lorsque les contraintes de mémoire sont un problème.

Utilisez le multitraitement lorsque vous avez des tâches liées au processeur qui peuvent bénéficier d'un véritable parallélisme et lorsque vous disposez d'une isolation robuste entre les tâches, où l'échec d'une tâche ne devrait pas avoir d'impact sur les autres.

Profitez de la concurrence et du parallélisme

Le parallélisme et la concurrence sont des moyens efficaces d'améliorer la réactivité et les performances de votre code Python. Il est important de comprendre les différences entre ces concepts et de sélectionner la stratégie la plus efficace.

Python offre les outils et modules dont vous avez besoin pour rendre votre code plus efficace grâce à la concurrence ou au parallélisme, que vous travailliez avec des processus liés au processeur ou aux E/S.