# Il modulo multiprocessing in Python: l’elaborazione dei processi in parallelo

Con il modulo multiprocessing in Python è possibile **suddividere il carico di lavoro su più processi** per ridurre i tempi di esecuzione complessivi. Questa possibilità è particolarmente utile per i calcoli più complessi o per grandi quantità di dati.

## Che cos’è il modulo multiprocessing in Python?

Con multiprocessing in Python si indica la capacità di eseguire più processi contemporaneamente sfruttando in modo ottimale la potenza dei **sistemi multicore**. A differenza degli approcci single-thread, che elaborano i compiti in sequenza, con il multiprocessing è possibile eseguire parti diverse del programma in parallelo e indipendentemente le une dalle altre. Ciascun processo dispone di una propria area di memoria e può essere elaborato su core del processore separati. In questo modo si riducono notevolmente i tempi di esecuzione di operazioni che richiedono grande potenza di calcolo o in cui il tempo è un fattore fondamentale.

I campi di applicazione del multiprocessing in Python sono numerosi. Questo modulo trova spesso applicazione nell’elaborazione dei dati e nell’analisi per elaborare più velocemente grandi record di dati e velocizzare l’esecuzione di analisi complesse. Può essere utilizzato anche in ambiti come **simulazioni e calcoli di modellazione**, ad esempio in applicazioni scientifiche, per ridurre i tempi di esecuzione di calcoli complessi. Inoltre, è usato nel campo del web scraping per l’acquisizione simultanea di dati da diversi siti web, nell’elaborazione delle immagini o nella visione artificiale (“computer vision”) per aumentare l’efficienza delle operazioni per l’analisi delle immagini.

## In che modo è possibile utilizzare il multiprocessing in Python?

Python offre diverse opzioni per eseguire più processi contemporaneamente. Nelle parti seguenti ti mostriamo tre strumenti utilizzati comunemente: il modulo `multiprocessing`, la libreria `concurrent.futures` e il pacchetto `joblib`.

### Il modulo `multiprocessing`

Il modulo `multiprocessing` è il **modulo standard per eseguire più processi contemporaneamente in Python**. Permette la creazione di processi, lo scambio di dati fra tali processi e la sincronizzazione mediante blocchi, liste d’attesa e altri meccanismi.

```python
import multiprocessing
def task(n):
    result = n * n
    print(f"Result: {result}")
if __name__ == "__main__":
    processes = []
    for i in range(1, 6):
        process = multiprocessing.Process(target=task, args=(i,))
        processes.append(process)
        process.start()
    for process in processes:
        process.join()
```

Nell’esempio precedente utilizziamo la classe `multiprocessing.Process` per creare e avviare i processi che eseguono la funzione `task()`. Questa funzione calcola il quadrato del numero indicato. I processi vengono inizializzati e si attende la loro conclusione prima di proseguire con il programma principale. Per l’emissione del risultato utilizziamo una **f-string**, ossia un metodo di [formattazione delle stringhe in Python](https://www.ionos.it/digitalguide/siti-web/programmazione-del-sito-web/formattazione-delle-stringhe-in-python/) per il collegamento tra le espressioni. La sequenza è casuale e non deterministica.

È anche possibile creare un pool di processi con `multiprocessing` in Python:

```python
import multiprocessing
def task(n):
    return n * n
if __name__ == "__main__":
    with multiprocessing.Pool() as pool:
        results = pool.map(task, range(1, 6))
        print(results)  # Output: [1, 4, 9, 16, 25]
```

Con `pool.map()` si applica la funzione `task()` a una sequenza di dati e i risultati vengono quindi raccolti ed emessi.

### La libreria `concurrent.futures`

Questo modulo offre un’interfaccia di alto livello per l’esecuzione asincrona e l’elaborazione di processi in parallelo. Il modulo utilizza l’**esecutore di un pool** per eseguire i compiti su un pool di processi o thread. `concurrent.futures` è una soluzione semplice per elaborare compiti asincroni e in molti casi è più facile da gestire rispetto al modulo `multiprocessing` in Python.

```python
import concurrent.futures
def task(n):
    return n * n
with concurrent.futures.ProcessPoolExecutor() as executor:
    futures = [executor.submit(task, i) for i in range(1, 6)]
    for future in concurrent.futures.as_completed(futures):
        print(future.result()) # result in random order
```

Il codice utilizza il modulo `concurrent.futures` per elaborare i compiti in parallelo con `ProcessPoolExecutor`. A tal fine viene assegnata la funzione `task(n)` per numeri da 1 a 5. Il metodo `as_completed()` attende la conclusione dei compiti ed emette i **risultati in una sequenza a piacere**.

### `joblib`

La libreria esterna `joblib` di Python è stata sviluppata per facilitare l’elaborazione in parallelo in Python, ad esempio per compiti ripetibili come l’esecuzione di funzioni con diversi parametri d’ingresso o per lavorare con grandi quantità di dati. Le funzioni principali di `joblib` sono la parallelizzazione dei compiti, la **memorizzazione temporanea (caching) dei risultati di funzioni** e l’ottimizzazione delle risorse di memoria e di calcolo.

```python
from joblib import Parallel, delayed
def task(n):
    return n * n
results = Parallel(n_jobs=4)(delayed(task)(i) for i in range(1, 11))
print(results) # Output: Results of the function for numbers from 1 to 10
```

L’espressione `Parallel(n_jobs=4)(delayed(task)(i) for i in range(1, 11))` inizializza l’esecuzione della funzione `task()` per i numeri da 1 a 10. `Parallel` è configurata con `n_job=4` che permette di elaborare fino a quattro job in parallelo. Richiamando `delayed(task)(i)` si crea il compito da eseguire in parallelo per ciascun numero “i” nell’intervallo fra 1 e 10. In pratica, la funzione `task()` viene eseguita contemporaneamente per ciascuno di questi numeri. Il risultato per i numeri da 1 a 10 viene memorizzato in `results` e quindi emesso.


This is a markdown version of: [https://www.ionos.it/digitalguide/siti-web/programmazione-del-sito-web/multiprocessing-in-python/](https://www.ionos.it/digitalguide/siti-web/programmazione-del-sito-web/multiprocessing-in-python/) for AI/LLM consumption.