Ich würde nicht concurrent.futures
"fortgeschrittener" nennen - es ist eine einfachere Oberfläche, die sehr ähnlich funktioniert, unabhängig davon, ob Sie mehrere Threads oder mehrere Prozesse als zugrunde liegendes Parallelisierungs-Gimmick verwenden.
Wie bei praktisch allen Fällen einer "einfacheren Benutzeroberfläche" sind also die gleichen Kompromisse erforderlich: Sie weist eine flachere Lernkurve auf, zum großen Teil nur, weil so viel weniger zum Lernen verfügbar ist. Da es jedoch weniger Optionen bietet, kann es Sie möglicherweise in einer Weise frustrieren, wie es die umfangreicheren Schnittstellen nicht tun.
Was CPU-gebundene Aufgaben betrifft, ist dies viel zu wenig spezifiziert, um viel aussagekräftiges zu sagen. Für CPU-gebundene Aufgaben unter CPython benötigen Sie mehrere Prozesse anstelle mehrerer Threads, um eine Beschleunigung zu erzielen. Wie viel (wenn überhaupt) Sie beschleunigen, hängt jedoch von den Details Ihrer Hardware, Ihres Betriebssystems und insbesondere davon ab, wie viel prozessübergreifende Kommunikation Ihre spezifischen Aufgaben erfordern. Unter dem Deckmantel basieren alle prozessübergreifenden Parallelisierungs-Gimmicks auf denselben Betriebssystemprimitiven - die API auf hoher Ebene, die Sie verwenden, um diese zu erhalten, ist kein primärer Faktor für die Geschwindigkeit unter dem Strich.
Bearbeiten: Beispiel
Hier ist der endgültige Code, der in dem Artikel gezeigt wird, auf den Sie verwiesen haben, aber ich füge eine Importanweisung hinzu, die erforderlich ist, damit er funktioniert:
from concurrent.futures import ProcessPoolExecutor
def pool_factorizer_map(nums, nprocs):
# Let the executor divide the work among processes by using 'map'.
with ProcessPoolExecutor(max_workers=nprocs) as executor:
return {num:factors for num, factors in
zip(nums,
executor.map(factorize_naive, nums))}
Hier ist genau das Gleiche mit multiprocessing
stattdessen:
import multiprocessing as mp
def mp_factorizer_map(nums, nprocs):
with mp.Pool(nprocs) as pool:
return {num:factors for num, factors in
zip(nums,
pool.map(factorize_naive, nums))}
Beachten Sie, dass die Möglichkeit, multiprocessing.Pool
Objekte als Kontextmanager zu verwenden, in Python 3.3 hinzugefügt wurde.
Mit welchem ist es einfacher zu arbeiten? LOL ;-) Sie sind im Wesentlichen identisch.
Ein Unterschied besteht darin, dass Pool
so viele verschiedene Methoden unterstützt werden, dass Sie möglicherweise erst erkennen, wie einfach es sein kann , wenn Sie die Lernkurve deutlich nach oben geklettert sind.
Auch hier sind all diese unterschiedlichen Wege sowohl eine Stärke als auch eine Schwäche. Sie sind eine Stärke, da die Flexibilität in einigen Situationen erforderlich sein kann. Sie sind eine Schwäche, weil "vorzugsweise nur ein offensichtlicher Weg, dies zu tun". Ein Projekt, an dem ausschließlich (wenn möglich) concurrent.futures
festgehalten wird, wird auf lange Sicht wahrscheinlich einfacher zu warten sein, da es keine unbegründete Neuheit in der Verwendung seiner minimalen API gibt.