Met Python mul­ti­pro­ces­sing kunt u de werklast over meerdere processen verdelen, waardoor de totale uit­voe­rings­tijd wordt verkort. Dit is vooral handig voor het uitvoeren van zware be­re­ke­nin­gen of het verwerken van grote datasets.

Wat is Python-mul­ti­pro­ces­sing?

Mul­ti­pro­ces­sing in Python verwijst naar het ge­lijk­tij­dig uitvoeren van meerdere processen, waardoor u optimaal gebruik kunt maken van multicore-systemen. In te­gen­stel­ling tot single-threaded methoden die taken één voor één af­han­de­len, zorgt mul­ti­pro­ces­sing ervoor dat ver­schil­len­de delen van het programma parallel kunnen worden uit­ge­voerd, elk op zichzelf. Elk proces krijgt zijn eigen ge­heu­gen­ruim­te en kan op af­zon­der­lij­ke pro­cess­or­ker­nen worden uit­ge­voerd, waardoor de uit­voe­rings­tijd voor zware of tijd­ge­voe­li­ge be­wer­kin­gen aan­zien­lijk wordt verkort.

Python mul­ti­pro­ces­sing heeft een breed scala aan toe­pas­sin­gen. Mul­ti­pro­ces­sing wordt vaak gebruikt bij ge­ge­vens­ver­wer­king en -analyse om grote datasets sneller te verwerken en complexe analyses te ver­snel­len. Mul­ti­pro­ces­sing kan ook worden gebruikt in si­mu­la­ties en mo­del­le­rings­be­re­ke­nin­gen (bij­voor­beeld in we­ten­schap­pe­lij­ke toe­pas­sin­gen) om de uit­voe­rings­tijd van complexe be­re­ke­nin­gen te verkorten. Naast het mogelijk maken van web­scra­ping door te­ge­lij­ker­tijd gegevens van meerdere sites op te halen, verhoogt het ook de ef­fi­ci­ën­tie bij beeld­ver­wer­king en com­pu­ter­vi­sie, wat re­sul­teert in een snellere beeldana­ly­se.

Hoe Python mul­ti­pro­ces­sing te im­ple­men­te­ren

Python biedt ver­schil­len­de opties voor het im­ple­men­te­ren van mul­ti­pro­ces­sing. In de volgende pa­ra­gra­fen laten we je ken­nis­ma­ken met drie veel­ge­bruik­te tools: de multiprocessing, de concurrent.futures en het joblib.

multiprocessing module

De module multiprocessing is de stan­daard­mo­du­le voor mul­ti­pro­ces­sing in Python. Met deze module kunt u processen aanmaken, gegevens tussen deze processen delen en ze syn­chro­ni­se­ren met behulp van locks, wacht­rij­en en andere hulp­mid­de­len.

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

In het bo­ven­staan­de 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­ï­ni­ti­a­li­seerd, wachten we tot ze zijn voltooid voordat we doorgaan met het hoofd­pro­gram­ma. Het resultaat wordt weer­ge­ge­ven met behulp van een f-string, een Python-string­for­maat­me­tho­de die ex­pres­sies bevat. Het is ver­mel­dens­waard dat de volgorde van de uitvoer wil­le­keu­rig en niet-de­ter­mi­nis­tisch is. Je kunt ook een pro­ces­pool maken met Python multiprocessing:

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

Met pool.map() wordt de functie task() toegepast op een reeks gegevens, en worden de re­sul­ta­ten verzameld en uit­ge­voerd.

concurrent.futures bi­bli­o­theek

Deze module biedt een hoog­waar­di­ge interface voor asyn­chro­ne uit­voe­ring en pa­ral­lel­le ver­wer­king 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 een­vou­di­ge­re manier om asyn­chro­ne taken te verwerken en is in veel gevallen ge­mak­ke­lij­ker te hanteren dan de Python multiprocessing.

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
python

De code gebruikt de concurrent.futures module om taken parallel met de ProcessPoolExecutor te verwerken. De functie task(n) wordt door­ge­ge­ven voor getallen van 1 tot 5. De methode as_completed() wacht tot de taken zijn voltooid en geeft de re­sul­ta­ten in wil­le­keu­ri­ge volgorde weer.

joblib pakket

joblib is een externe Python-bi­bli­o­theek die is ontworpen om pa­ral­lel­le ver­wer­king in Python te ver­een­vou­di­gen, bij­voor­beeld voor her­haal­ba­re taken zoals het uitvoeren van functies met ver­schil­len­de in­voer­pa­ra­me­ters of het werken met grote hoe­veel­he­den gegevens. De be­lang­rijk­ste functies van joblib zijn het pa­ral­le­li­se­ren van taken, het cachen van func­tie­re­sul­ta­ten en het op­ti­ma­li­se­ren van geheugen en re­ken­kracht.

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
python

De uit­druk­king Parallel(n_jobs=4)(delayed(task)(i) for i in range(1, 11)) start de pa­ral­lel­le uit­voe­ring van de functie task() voor de getallen van 1 tot 10. Parallel is ge­con­fi­gu­reerd met n_jobs=4, wat betekent dat er maximaal vier pa­ral­lel­le taken kunnen worden verwerkt. Door delayed(task)(i) aan te roepen, wordt de taak aan­ge­maakt die parallel moet worden uit­ge­voerd voor elk getal i in het bereik van 1 tot 10. Dit betekent dat de functie task() te­ge­lij­ker­tijd wordt aan­ge­roe­pen voor elk van deze getallen. De re­sul­ta­ten voor de getallen 1 tot en met 10 worden op­ge­sla­gen in results en uit­ge­voerd.

Ga naar hoofdmenu