Nie widziałem wyraźnych przykładów przypadków użycia dla Pool.apply , Pool.apply_async i Pool.map . Używam głównie Pool.map
; jakie są zalety innych?
Nie widziałem wyraźnych przykładów przypadków użycia dla Pool.apply , Pool.apply_async i Pool.map . Używam głównie Pool.map
; jakie są zalety innych?
Odpowiedzi:
W dawnych czasach Pythona, aby wywołać funkcję z dowolnymi argumentami, użyłbyś apply
:
apply(f,args,kwargs)
apply
nadal istnieje w Python2.7, ale nie w Python3 i generalnie nie jest już używany. Dzisiaj,
f(*args,**kwargs)
jest preferowany. Te multiprocessing.Pool
moduły stara się zapewnić podobny interfejs.
Pool.apply
jest jak Python apply
, z tym wyjątkiem, że wywołanie funkcji jest wykonywane w osobnym procesie. Pool.apply
blokuje do zakończenia funkcji.
Pool.apply_async
jest również podobny do wbudowanego w Pythona apply
, z tym wyjątkiem, że wywołanie natychmiast wraca zamiast czekać na wynik. AsyncResult
Zwracany jest obiekt. Wywołujesz jego get()
metodę, aby pobrać wynik wywołania funkcji. Te get()
metody bloki aż funkcja jest zakończona. Jest zatem pool.apply(func, args, kwargs)
równoważny z pool.apply_async(func, args, kwargs).get()
.
W przeciwieństwie do Pool.apply
The Pool.apply_async
metoda ma również wywołania zwrotnego, która, jeśli dostarczone, jest wywoływana, gdy funkcja jest kompletna. Można tego użyć zamiast dzwonić get()
.
Na przykład:
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()
może dać wynik taki jak
[1, 0, 4, 9, 25, 16, 49, 36, 81, 64]
Zwróć uwagę, w przeciwieństwie pool.map
do kolejności wyników, może nie odpowiadać kolejności, w której pool.apply_async
połączenia zostały wykonane.
Jeśli więc chcesz uruchomić funkcję w osobnym procesie, ale chcesz, aby bieżący proces był blokowany, dopóki funkcja nie powróci, użyj Pool.apply
. Jak Pool.apply
, Pool.map
bloki aż do całkowitego wyniku jest zwracana.
Jeśli chcesz, aby pula procesów roboczych wykonywała wiele wywołań funkcji asynchronicznie, użyj Pool.apply_async
. Kolejność wyników nie jest gwarantowana być taka sama jak kolejność wywołań Pool.apply_async
.
Zauważ też, że możesz wywołać wiele różnych funkcji za pomocą Pool.apply_async
(nie wszystkie połączenia muszą korzystać z tej samej funkcji).
Natomiast Pool.map
stosuje tę samą funkcję do wielu argumentów. Jednak w przeciwieństwie Pool.apply_async
do wyników zwracane są w kolejności odpowiadającej kolejności argumentów.
Pool.map(func,iterable)
jest to równoważne z Pool.map_async(func,iterable).get()
. Tak więc związek pomiędzy Pool.map
i Pool.map_async
jest podobny do tego z Pool.apply
i Pool.apply_async
. Te async
polecenia wrócić natychmiast, nieposiadający async
polecenia blokowania. Te async
polecenia mają też zwrotnego.
Pool.map
i Pool.apply
jest podobne do decydowania, kiedy użyć map
lub apply
w Pythonie. Wystarczy użyć narzędzia, które pasuje do pracy. Decyzja między użyciem wersji async
a async
wersją inną zależy od tego, czy chcesz, aby wywołanie blokowało bieżący proces i / lub czy chcesz użyć wywołania zwrotnego.
apply_async
zwraca ApplyResult
obiekt. Wywołanie że ApplyResult
„s get
metoda zwróci wartość zwracaną Associated funkcja (lub podbicie mp.TimeoutError
jeśli czasy-out połączenia). Więc jeśli umieścić ApplyResult
s w uporządkowanej listy, a następnie wywołanie ich get
metody zwróci wyniki w tej samej kolejności. Możesz jednak użyć pool.map
w tej sytuacji.
W odniesieniu apply
do map
:
pool.apply(f, args)
: f
jest wykonywany tylko w JEDNEJ z pracowników puli. Uruchomi się JEDEN z procesów w puli f(args)
.
pool.map(f, iterable)
: Ta metoda dzieli iterowalny fragment na kilka części, które przekazuje do puli procesów jako osobne zadania. Wykorzystujesz więc wszystkie procesy w puli.
apply_async()
8 razy? Czy automatycznie obsłuży to w kolejce?
Oto przegląd w formie tabeli w celu pokazania różnic między Pool.apply
, Pool.apply_async
, Pool.map
i Pool.map_async
. Wybierając jeden, musisz wziąć pod uwagę wiele argumentów, współbieżność, blokowanie i porządkowanie:
| 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
Pool.imap
oraz Pool.imap_async
- leniwsza wersja mapy i map_async.
Pool.starmap
metoda, bardzo podobna do metody mapy, poza tym akceptacja wielu argumentów.
Async
metody przesyłają wszystkie procesy naraz i pobierają wyniki po ich zakończeniu. Użyj metody get, aby uzyskać wyniki.
Pool.map
(lub Pool.apply
) metody są bardzo podobne do wbudowanej mapy Pythona (lub zastosowania). Blokują główny proces, dopóki wszystkie procesy się nie zakończą, i zwracają wynik.
Jest wywoływany do listy zadań w jednym czasie
results = pool.map(func, [1, 2, 3])
Można wezwać tylko do jednej pracy
for x, y in [[1, 1], [2, 2]]:
results.append(pool.apply(func, (x, y)))
def collect_result(result):
results.append(result)
Jest wywoływany do listy zadań w jednym czasie
pool.map_async(func, jobs, callback=collect_result)
Można wywołać tylko dla jednego zadania i równolegle wykonuje ono zadanie w tle
for x, y in [[1, 1], [2, 2]]:
pool.apply_async(worker, (x, y), callback=collect_result)
Jest wariantem, pool.map
który obsługuje wiele argumentów
pool.starmap(func, [(1, 1), (2, 1), (3, 1)])
Kombinacja starmap () i map_async (), która iteruje po iterable iterable i wywołuje func z iterables po rozpakowaniu. Zwraca wynikowy obiekt.
pool.starmap_async(calculate_worker, [(1, 1), (2, 1), (3, 1)], callback=collect_result)
Znajdź pełną dokumentację tutaj: https://docs.python.org/3/library/multiprocessing.html
if __name__=="__main__"
wcześniejapply_async_with_callback()
w systemie Windows?