multiprocessing.Pool: Wann sollte apply, apply_async oder map verwendet werden?

Lesezeit: 7 Minuten

Benutzer-Avatar
Phyo Arkar Lwin

Ich habe keine klaren Beispiele mit Anwendungsfällen für gesehen Pool.apply, Pool.apply_async und Pool.map. Ich benutze hauptsächlich Pool.map; Was sind die Vorteile anderer?

Benutzer-Avatar
unutbu

In den alten Tagen von Python würden Sie verwenden, um eine Funktion mit beliebigen Argumenten aufzurufen apply:

apply(f,args,kwargs)

apply existiert immer noch in Python2.7, jedoch nicht in Python3, und wird im Allgemeinen nicht mehr verwendet. Heutzutage,

f(*args,**kwargs)

Ist bevorzugt. Das multiprocessing.Pool Module versucht, eine ähnliche Schnittstelle bereitzustellen.

Pool.apply ist wie Python applyaußer dass der Funktionsaufruf in einem separaten Prozess durchgeführt wird. Pool.apply blockiert, bis die Funktion abgeschlossen ist.

Pool.apply_async ist auch wie in Python eingebaut apply, außer dass der Aufruf sofort zurückkehrt, anstatt auf das Ergebnis zu warten. Ein AsyncResult Objekt wird zurückgegeben. Du nennst es get() -Methode, um das Ergebnis des Funktionsaufrufs abzurufen. Das get() Methode blockiert, bis die Funktion abgeschlossen ist. Daher, pool.apply(func, args, kwargs) ist äquivalent zu pool.apply_async(func, args, kwargs).get().

Im Kontrast zu Pool.applydas Pool.apply_async -Methode hat auch einen Rückruf, der, falls angegeben, aufgerufen wird, wenn die Funktion abgeschlossen ist. Dies kann anstelle des Anrufs verwendet werden get().

Zum Beispiel:

import multiprocessing as mp
import time

def foo_pool(x):
    time.sleep(2)
    return x*x

result_list = []
def log_result(result):
    # This is called whenever foo_pool(i) returns a result.
    # result_list is modified only by the main process, not the pool workers.
    result_list.append(result)

def apply_async_with_callback():
    pool = mp.Pool()
    for i in range(10):
        pool.apply_async(foo_pool, args = (i, ), callback = log_result)
    pool.close()
    pool.join()
    print(result_list)

if __name__ == '__main__':
    apply_async_with_callback()

kann ein Ergebnis wie z

[1, 0, 4, 9, 25, 16, 49, 36, 81, 64]

Beachten Sie, anders pool.mapentspricht die Reihenfolge der Ergebnisse möglicherweise nicht der Reihenfolge, in der die pool.apply_async Anrufe wurden getätigt.


Also, wenn Sie eine Funktion in einem separaten Prozess ausführen müssen, aber möchten, dass der aktuelle Prozess dies tut Block bis diese Funktion zurückkehrt, verwenden Pool.apply. Wie Pool.apply, Pool.map Blöcke, bis das vollständige Ergebnis zurückgegeben wird.

Wenn Sie möchten, dass der Pool von Arbeitsprozessen viele Funktionsaufrufe asynchron ausführt, verwenden Sie Pool.apply_async. Das bestellen der Ergebnisse stimmt nicht garantiert mit der Reihenfolge der Aufrufe überein Pool.apply_async.

Beachten Sie auch, dass Sie mehrere anrufen können anders funktioniert mit Pool.apply_async (Nicht alle Anrufe müssen dieselbe Funktion verwenden).

Im Gegensatz, Pool.map wendet dieselbe Funktion auf viele Argumente an. Allerdings im Gegensatz Pool.apply_asyncwerden die Ergebnisse in einer Reihenfolge zurückgegeben, die der Reihenfolge der Argumente entspricht.

  • Sollte da sein if __name__=="__main__" Vor apply_async_with_callback() unter Windows?

    – jfs

    16. Dezember 2011 um 12:38 Uhr

  • Einblick multiprocessing/pool.py und das wirst du sehen Pool.map(func,iterable) ist äquivalent zu Pool.map_async(func,iterable).get(). Also das Verhältnis zwischen Pool.map und Pool.map_async ist ähnlich wie bei Pool.apply und Pool.apply_async. Das async Befehle werden sofort zurückgegeben, während die nichtasync Befehle blockieren. Das async Befehle haben auch einen Callback.

    – unutbu

    17. Dezember 2011 um 11:38 Uhr

  • Entscheidung zwischen der Verwendung Pool.map und Pool.apply ist ähnlich wie die Entscheidung, wann verwendet werden soll map oder apply in Python. Sie verwenden einfach das Werkzeug, das zum Job passt. Entscheiden Sie sich zwischen der Verwendung der async und nicht-async Version hängt davon ab, ob Sie möchten, dass der Aufruf den aktuellen Prozess blockiert und/oder ob Sie den Rückruf verwenden möchten.

    – unutbu

    17. Dezember 2011 um 11:39 Uhr


  • @falsePockets: Ja. Jeder Anruf an apply_async gibt ein zurück ApplyResult Objekt. Das nennen ApplyResult‘s get -Methode gibt den Rückgabewert der zugeordneten Funktion zurück (oder raise mp.TimeoutError wenn der Anruf abläuft.) Also, wenn Sie die setzen ApplyResults in einer geordneten Liste, dann Aufruf ihrer get Methoden geben die Ergebnisse in der gleichen Reihenfolge zurück. Du könntest einfach verwenden pool.map in dieser Situation jedoch.

    – unutbu

    22. Mai 2017 um 10:11 Uhr


  • @galactica: Jedes Mal, wenn die Worker-Funktion erfolgreich beendet wird (ohne eine Ausnahme auszulösen), wird die Callback-Funktion aufgerufen im Hauptprozess. Die Worker-Funktionen stellen Rückgabewerte in eine Warteschlange, und die pool._result_handler Thread im Hauptprozess verarbeitet die zurückgegebenen Werte einzeln und übergibt den zurückgegebenen Wert an die Callback-Funktion. So ist garantiert, dass die Callback-Funktion einmal für jeden zurückgegebenen Wert aufgerufen wird, und es gibt hier kein Parallelitätsproblem, da der Callback sequentiell von einem einzelnen Thread im Hauptprozess aufgerufen wird.

    – unutbu

    29. Juli 2019 um 22:46 Uhr


Benutzer-Avatar
René B.

Hier ist eine Übersicht in Tabellenform, um die Unterschiede aufzuzeigen Pool.apply, Pool.apply_async, Pool.map und Pool.map_async. Bei der Auswahl müssen Sie Multi-Args, Parallelität, Blockierung und Reihenfolge berücksichtigen:

                  | Multi-args   Concurrence    Blocking     Ordered-results
---------------------------------------------------------------------
Pool.map          | no           yes            yes          yes
Pool.map_async    | no           yes            no           yes
Pool.apply        | yes          no             yes          no
Pool.apply_async  | yes          yes            no           no
Pool.starmap      | yes          yes            yes          yes
Pool.starmap_async| yes          yes            no           no

Anmerkungen:

  • Pool.imap und Pool.imap_async – faulere Version von map und map_async.

  • Pool.starmap Methode, die der Kartenmethode sehr ähnlich ist, abgesehen davon, dass sie mehrere Argumente akzeptiert.

  • Async Methoden übermitteln alle Prozesse auf einmal und rufen die Ergebnisse ab, sobald sie abgeschlossen sind. Verwenden Sie die get-Methode, um die Ergebnisse zu erhalten.

  • Pool.map(oder Pool.apply)-Methoden sind der in Python integrierten map(or apply) sehr ähnlich. Sie blockieren den Hauptprozess, bis alle Prozesse abgeschlossen sind, und geben das Ergebnis zurück.

Beispiele:

Karte

Wird für eine Liste von Jobs auf einmal aufgerufen

results = pool.map(func, [1, 2, 3])

anwenden

Kann nur für einen Job angerufen werden

for x, y in [[1, 1], [2, 2]]:
    results.append(pool.apply(func, (x, y)))

def collect_result(result):
    results.append(result)

map_async

Wird für eine Liste von Jobs auf einmal aufgerufen

pool.map_async(func, jobs, callback=collect_result)

apply_async

Kann nur für einen Job aufgerufen werden und führt parallel einen Job im Hintergrund aus

for x, y in [[1, 1], [2, 2]]:
    pool.apply_async(worker, (x, y), callback=collect_result)

Sternenkarte

Ist eine Variante von pool.map die mehrere Argumente unterstützen

pool.starmap(func, [(1, 1), (2, 1), (3, 1)])

starmap_async

Eine Kombination aus starmap() und map_async(), die über Iterable von Iterables iteriert und func mit den entpackten Iterables aufruft. Gibt ein Ergebnisobjekt zurück.

pool.starmap_async(calculate_worker, [(1, 1), (2, 1), (3, 1)], callback=collect_result)

Bezug:

Vollständige Dokumentation finden Sie hier: https://docs.python.org/3/library/multiprocessing.html

  • Pool.starmap() blockiert

    – Alan Evangelista

    20. März 2020 um 0:43 Uhr

  • Ich mag diese Antwort, +1

    – Shayan Amani

    13. April 2021 um 20:50 Uhr

  • Wenn apply keine Zustimmung hat, was ist dann sein Sinn? verwenden?

    – Ritwik

    2. Mai 2021 um 19:37 Uhr

  • Eine Tabelle/ein Bild sagt mehr als tausend Worte, ich komme immer wieder auf diese Antwort zurück, um die gewünschte Funktion auszuwählen.

    – Luchao-Qi

    2. Mai um 18:52 Uhr

Benutzer-Avatar
kakhkAtion

Bezüglich apply vs map:

pool.apply(f, args): f wird nur in EINEM der Worker des Pools ausgeführt. Einer der Prozesse im Pool wird also ausgeführt f(args).

pool.map(f, iterable)Hinweis: Diese Methode zerlegt das Iterable in eine Reihe von Chunks, die es als separate Tasks an den Prozesspool übermittelt. So nutzen Sie alle Prozesse im Pool.

  • Was ist, wenn das Iterable ein Generator ist?

    – RustyShackleford

    21. Juni 2017 um 19:36 Uhr

  • Hm… Gute Frage. Um ehrlich zu sein, habe ich noch nie Pools mit Generatoren verwendet, aber dieser Thread könnte hilfreich sein: stackoverflow.com/questions/5318936/…

    – kakhkAtion

    21. Juni 2017 um 20:10 Uhr

  • @kakhkAtion In Bezug auf gelten, wenn nur einer der Arbeiter die Funktion ausführt, was tun die restlichen Arbeiter? Muss ich mich mehrmals bewerben, damit der Rest der Mitarbeiter eine Aufgabe erledigt?

    – Moondra

    27. Juli 2017 um 17:33 Uhr

  • WAHR. Werfen Sie auch einen Blick auf pool.apply_async, wenn Sie Arbeiter asynchron zu Mittag essen möchten. “pool_apply blockiert, bis das Ergebnis fertig ist, also ist apply_async() besser geeignet, um parallel zu arbeiten”

    – kakhkAtion

    27. Juli 2017 um 18:50 Uhr


  • Was passiert, wenn ich doch 4 Prozesse angerufen habe apply_async() 8 mal? Wird es automatisch mit einer Warteschlange behandelt?

    – Saravanabalagi Ramachandran

    23. Dezember 2019 um 14:19 Uhr

1095960cookie-checkmultiprocessing.Pool: Wann sollte apply, apply_async oder map verwendet werden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy