# Wat is Python multiprocessing en hoe gebruik je het?

Met Python multiprocessing kunt u de **werklast over meerdere processen** verdelen, waardoor de totale uitvoeringstijd wordt verkort. Dit is vooral handig voor het uitvoeren van zware berekeningen of het verwerken van grote datasets.

## Wat is Python-multiprocessing?

Multiprocessing in Python verwijst naar het gelijktijdig uitvoeren van meerdere processen, waardoor u optimaal gebruik kunt maken van **multicore-systemen**. In tegenstelling tot single-threaded methoden die taken één voor één afhandelen, zorgt multiprocessing ervoor dat verschillende delen van het programma parallel kunnen worden uitgevoerd, elk op zichzelf. Elk proces krijgt zijn eigen geheugenruimte en kan op afzonderlijke processorkernen worden uitgevoerd, waardoor de uitvoeringstijd voor zware of tijdgevoelige bewerkingen aanzienlijk wordt verkort.

Python multiprocessing heeft een breed scala aan toepassingen. Multiprocessing wordt vaak gebruikt bij gegevensverwerking en -analyse om grote datasets sneller te verwerken en complexe analyses te versnellen. Multiprocessing kan ook worden gebruikt in **simulaties en modelleringsberekeningen** (bijvoorbeeld in wetenschappelijke toepassingen) om de uitvoeringstijd van complexe berekeningen te verkorten. Naast het mogelijk maken van webscraping door tegelijkertijd gegevens van meerdere sites op te halen, verhoogt het ook de efficiëntie bij beeldverwerking en computervisie, wat resulteert in een snellere beeldanalyse.

## Hoe Python multiprocessing te implementeren

Python biedt verschillende opties voor het implementeren van multiprocessing. In de volgende paragrafen laten we je kennismaken met drie veelgebruikte tools: de `multiprocessing`, de `concurrent.futures` en het `joblib`.

### `multiprocessing` module

De module `multiprocessing` is de **standaardmodule voor multiprocessing in Python**. Met deze module kunt u processen aanmaken, gegevens tussen deze processen delen en ze synchroniseren met behulp van locks, wachtrijen en andere hulpmiddelen.

```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()
```

In het bovenstaande voorbeeld gebruiken we de klasse `multiprocessing.Process` om processen te spawnen en uit te voeren die de functie `task()` uitvoeren, die het kwadraat van een bepaald getal berekent. Nadat we de processen hebben geïnitialiseerd, wachten we tot ze zijn voltooid voordat we doorgaan met het hoofdprogramma. Het resultaat wordt weergegeven met behulp van een **f-string**, een Python-stringformaatmethode die expressies bevat. Het is vermeldenswaard dat de volgorde van de uitvoer willekeurig en niet-deterministisch is. Je kunt ook een procespool maken met Python `multiprocessing`:

```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]
```

Met `pool.map()` wordt de functie `task()` toegepast op een reeks gegevens, en worden de resultaten verzameld en uitgevoerd.

### `concurrent.futures` bibliotheek

Deze module biedt een hoogwaardige interface voor asynchrone uitvoering en parallelle verwerking van processen. Het maakt gebruik van de **Pool Executor** om taken uit te voeren op een pool van processen of threads. De `concurrent.futures` is een eenvoudigere manier om asynchrone taken te verwerken en is in veel gevallen gemakkelijker te hanteren dan de Python `multiprocessing`.

```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
```

De code gebruikt de `concurrent.futures module` om taken parallel met de `ProcessPoolExecutor` te verwerken. De functie `task(n)` wordt doorgegeven voor getallen van 1 tot 5. De methode `as_completed()` wacht tot de taken zijn voltooid en geeft de **resultaten in willekeurige volgorde** weer.

### `joblib` pakket

`joblib` is een externe Python-bibliotheek die is ontworpen om parallelle verwerking in Python te vereenvoudigen, bijvoorbeeld voor herhaalbare taken zoals het uitvoeren van functies met verschillende invoerparameters of het werken met grote hoeveelheden gegevens. De belangrijkste functies van `joblib` zijn het paralleliseren van taken, het **cachen van functieresultaten** en het optimaliseren van geheugen en rekenkracht.

```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
```

De uitdrukking `Parallel(n_jobs=4)(delayed(task)(i) for i in range(1, 11))` start de parallelle uitvoering van de functie `task()` voor de getallen van 1 tot 10. `Parallel` is geconfigureerd met `n_jobs=4`, wat betekent dat er maximaal vier parallelle taken kunnen worden verwerkt. Door `delayed(task)(i)` aan te roepen, wordt de taak aangemaakt die parallel moet worden uitgevoerd voor elk getal i in het bereik van 1 tot 10. Dit betekent dat de functie `task()` tegelijkertijd wordt aangeroepen voor elk van deze getallen. De resultaten voor de getallen 1 tot en met 10 worden opgeslagen in `results` en uitgevoerd.


This is a markdown version of: [https://www.ionos.com/nl-be/digitalguide/websites/webontwikkeling/python-multiprocessing/](https://www.ionos.com/nl-be/digitalguide/websites/webontwikkeling/python-multiprocessing/) for AI/LLM consumption.