Utilizza queste tecniche per eseguire il codice simultaneamente e fornire un'esperienza utente più fluida.
Punti chiave
- La concorrenza e il parallelismo sono principi fondamentali dell'esecuzione delle attività nell'informatica, ciascuno con le sue caratteristiche distinte.
- La concorrenza consente un utilizzo efficiente delle risorse e una migliore reattività delle applicazioni, mentre il parallelismo è fondamentale per prestazioni e scalabilità ottimali.
- Python fornisce opzioni per gestire la concorrenza, come il threading e la programmazione asincrona con asyncio, nonché il parallelismo utilizzando il modulo multiprocessing.
Concorrenza e parallelismo sono due tecniche che consentono di eseguire più programmi contemporaneamente. Python ha più opzioni per gestire le attività contemporaneamente e in parallelo, il che può creare confusione.
Esplora gli strumenti e le librerie disponibili per implementare correttamente la concorrenza e il parallelismo in Python e come differiscono.
Comprendere la concorrenza e il parallelismo
Concorrenza e parallelismo si riferiscono a due principi fondamentali dell'esecuzione delle attività nell'informatica. Ognuno ha le sue caratteristiche distinte.
- Concorrenza è la capacità di un programma di gestire più attività contemporaneamente senza necessariamente eseguirle esattamente nello stesso momento. Ruota attorno all'idea di interlacciare i compiti, passando da uno all'altro in modo che appaia simultaneo.
- Parallelismo, d'altro canto, implica l'esecuzione di più attività effettivamente in parallelo. In genere se ne approfitta più core o processori CPU. Il parallelismo raggiunge una vera esecuzione simultanea, consentendo di eseguire attività più velocemente ed è particolarmente adatto per operazioni ad alta intensità di calcolo.
L'importanza della concorrenza e del parallelismo
La necessità di concorrenza e parallelismo nell’informatica non può essere sopravvalutata. Ecco perché queste tecniche sono importanti:
- Utilizzo delle risorse: La concorrenza consente un utilizzo efficiente delle risorse di sistema, garantendo che le attività procedano attivamente anziché attendere pigramente risorse esterne.
- Reattività: La concorrenza può migliorare la reattività delle applicazioni, soprattutto in scenari che coinvolgono interfacce utente o server Web.
- Prestazione: Il parallelismo è fondamentale per ottenere prestazioni ottimali, in particolare nelle attività legate alla CPU come calcoli complessi, elaborazione dati e simulazioni.
- Scalabilità: Sia la concorrenza che il parallelismo sono essenziali per costruire sistemi scalabili.
- A prova di futuro: Poiché le tendenze hardware continuano a favorire i processori multicore, la capacità di sfruttare il parallelismo diventerà sempre più necessaria.
Concorrenza in Python
Puoi ottenere la concorrenza in Python utilizzando il threading e la programmazione asincrona con la libreria asyncio.
Discussione in Python
Il threading è un meccanismo di concorrenza Python che consente di creare e gestire attività all'interno di un singolo processo. I thread sono adatti per determinati tipi di attività, in particolare quelle legate a I/O e che possono trarre vantaggio dall'esecuzione simultanea.
Di Pitone filettatura modulo fornisce un'interfaccia di alto livello per la creazione e la gestione dei thread. Sebbene il GIL (Global Interpreter Lock) limiti i thread in termini di vero parallelismo, possono comunque raggiungere la concorrenza interlacciando le attività in modo efficiente.
Il codice seguente mostra un esempio di implementazione della concorrenza utilizzando i thread. Utilizza la libreria di richieste Python per inviare una richiesta HTTP, un'attività comune di blocco I/O. Utilizza anche il modulo temporale per calcolare il tempo di esecuzione.
import requests
import time
import threadingurls = [
'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")
Eseguendo questo programma, dovresti vedere quanto sono più veloci le richieste in thread rispetto alle richieste sequenziali. Anche se la differenza è solo di una frazione di secondo, si ha una chiara sensazione del miglioramento delle prestazioni quando si utilizzano i thread per attività legate all'I/O.
Programmazione asincrona con Asyncio
asincio fornisce un ciclo di eventi che gestisce attività asincrone chiamate coroutine. Le coroutine sono funzioni che puoi mettere in pausa e riprendere, rendendole ideali per attività legate all'I/O. La libreria è particolarmente utile per scenari in cui le attività implicano l'attesa di risorse esterne, come le richieste di rete.
È possibile modificare l'esempio di invio della richiesta precedente con cui lavorare asincio:
import asyncio
import aiohttp
import timeurls = [
'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")
Utilizzando il codice, è possibile scaricare contemporaneamente pagine Web utilizzando asincio e sfruttare le operazioni di I/O asincrone. Questo può essere più efficiente del threading per le attività legate a I/O.
Parallelismo in Python
Puoi implementare il parallelismo usando Di Pitone multielaborazione modulo, che consente di sfruttare appieno i processori multicore.
Multiprocessing in Python
Di Pitone multielaborazione Il modulo fornisce un modo per ottenere il parallelismo creando processi separati, ciascuno con il proprio interprete Python e spazio di memoria. Ciò bypassa efficacemente il Global Interpreter Lock (GIL), rendendolo adatto per attività legate alla CPU.
import requests
import multiprocessing
import timeurls = [
'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()
In questo esempio, multielaborazione genera più processi, consentendo il URL_download funzione da eseguire in parallelo.
Quando utilizzare la concorrenza o il parallelismo
La scelta tra concorrenza e parallelismo dipende dalla natura delle attività e dalle risorse hardware disponibili.
È possibile utilizzare la concorrenza quando si gestiscono attività legate a I/O, ad esempio leggere e scrivere su file o effettuare richieste di rete e quando i limiti di memoria sono un problema.
Utilizzare il multiprocessing quando si hanno attività legate alla CPU che possono trarre vantaggio dal vero parallelismo e quando si dispone di un solido isolamento tra le attività, in cui l'errore di un'attività non dovrebbe influire sugli altri.
Sfrutta la concorrenza e il parallelismo
Il parallelismo e la concorrenza sono modi efficaci per migliorare la reattività e le prestazioni del codice Python. È importante comprendere le differenze tra questi concetti e selezionare la strategia più efficace.
Python offre gli strumenti e i moduli necessari per rendere il tuo codice più efficace attraverso la concorrenza o il parallelismo, indipendentemente dal fatto che tu stia lavorando con processi legati alla CPU o legati all'I/O.