Python heeft geen ingebouwde `parfor` zoals MATLAB. De dichtstbijzijnde equivalenten zijn het gebruik van multiprocessing-bibliotheken om parallel 'for'-lusgedrag te bereiken. De beste aanpak hangt af van de aard van uw taak:
1. `multiprocessing.Pool` voor CPU-gebonden taken:
Dit is geschikt wanneer uw lusiteraties onafhankelijk en rekenintensief zijn (CPU-gebonden). Het is efficiënt voor het verdelen van werk over meerdere CPU-kernen.
```python
multiprocessing importeren
def mijn_functie(i):
"""De functie die parallel moet worden uitgevoerd."""
# Uw code hier...
resultaat =i * 2 # Voorbeeld
resultaat terug
als __naam__ =='__hoofd__':
met multiprocessing.Pool(processes=multiprocessing.cpu_count()) als pool:
resultaten =pool.map(my_function, range(10)) # range(10) is uw 'for'-lusbereik
print(resultaten) # Uitvoer:[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
```
`multiprocessing.Pool.map` past `my_function` parallel toe op elk element in `range(10)`. `multiprocessing.cpu_count()` bepaalt het optimale aantal processen. Pas dit aan op basis van uw systeem en het aantal beschikbare cores. Onthoud dat het blok `if __name__ =='__main__':` cruciaal is voor een goede multiprocessing op Windows.
2. `concurrent.futures.ProcessPoolExecutor` (flexibeler):
Dit biedt meer controle en flexibiliteit dan 'multiprocessing.Pool', vooral als u meer fijnmazige controle of foutafhandeling nodig heeft.
```python
importeer gelijktijdige.futures
def mijn_functie(i):
# Uw code hier...
resultaat =ik * 2
return i, result # Het retourneren van de oorspronkelijke index en het resultaat is handig om bij te houden
als __naam__ =='__hoofd__':
met concurrent.futures.ProcessPoolExecutor() als uitvoerder:
resultaten =uitvoerder.map(mijn_functie, bereik(10))
voor i, resulteren in resultaten:
print(f"Invoer:{i}, Uitvoer:{resultaat}")
```
`executor.map` is vergelijkbaar met `pool.map`, maar maakt het mogelijk om uitzonderingen op te roepen en af te handelen. U kunt ook `executor.submit` gebruiken voor meer asynchrone controle.
3. `joblib` voor eenvoudigere syntaxis (vaak sneller):
`joblib` vereenvoudigt parallelle verwerking, vooral voor NumPy-arrays. Het presteert vaak beter dan 'multiprocessing' voor specifieke numerieke bewerkingen.
```python
van joblib import Parallel, vertraagd
def mijn_functie(i):
# Uw code hier...
resultaat =ik * 2
resultaat terug
als __naam__ =='__hoofd__':
resultaten =Parallel(n_jobs=multiprocessing.cpu_count())(vertraagd(mijn_functie)(i) voor i binnen bereik(10))
afdrukken(resultaten)
```
`joblib` handelt automatisch de taakverdeling en de aggregatie van resultaten af. `n_jobs` specificeert het aantal parallelle processen.
Belangrijke overwegingen:
* Overhead: Parallelle verwerking introduceert overhead van procescreatie en communicatie. Voor zeer kleine taken kan de overhead groter zijn dan de voordelen.
* Gegevens delen: Vermijd het rechtstreeks delen van veranderlijke gegevens tussen processen; geef in plaats daarvan indien nodig kopieën door of gebruik communicatiemechanismen tussen processen (wachtrijen, leidingen).
* Afhankelijkheden: Zorg ervoor dat uw functies en hun afhankelijkheden op de juiste manier zijn verpakt en beschikbaar zijn voor elk werkproces.
* I/O-gebonden taken: Als uw lus aanzienlijke I/O-bewerkingen omvat (bijvoorbeeld netwerkverzoeken, het lezen van bestanden), levert het gebruik van 'multiprocessing' mogelijk geen significante snelheden op. Overweeg in plaats daarvan 'asyncio' of 'threading' (hoewel 'threading' wordt beperkt door de Global Interpreter Lock (GIL) in CPython).
Kies de aanpak die het beste past bij uw behoeften en de kenmerken van uw taak. Voor eenvoudige gevallen biedt `joblib` vaak de gemakkelijkste en meest efficiënte oplossing. Voor complexere scenario's met asynchrone bewerkingen of fijnmazige controle is `concurrent.futures` krachtiger. Vergeet niet om uw code altijd te profileren om de daadwerkelijke prestatiewinst te bepalen. |