Я не бачив чітких прикладів із випадками використання для Pool.apply , Pool.apply_async та Pool.map . Я в основному використовую Pool.map
; які переваги інших?
Я не бачив чітких прикладів із випадками використання для Pool.apply , Pool.apply_async та Pool.map . Я в основному використовую Pool.map
; які переваги інших?
Відповіді:
Ще в старі часи Python, для виклику функції з довільними аргументами, ви використовуєте apply
:
apply(f,args,kwargs)
apply
все ще існує в Python2.7, хоча не є в Python3, і, як правило, більше не використовується. У наш час
f(*args,**kwargs)
є кращим. У multiprocessing.Pool
модулях намагаються забезпечити подібний інтерфейс.
Pool.apply
є як Python apply
, за винятком того, що виклик функції виконується в окремому процесі. Pool.apply
блокує, поки функція не буде виконана.
Pool.apply_async
також як вбудований Python apply
, за винятком того, що дзвінок повертається негайно, замість того, щоб чекати результату. AsyncResult
Об'єкт повертається. Ви викликаєте його get()
метод для отримання результату виклику функції. У get()
методі блокується , поки ця функція буде завершено. Таким чином, pool.apply(func, args, kwargs)
еквівалентно pool.apply_async(func, args, kwargs).get()
.
На відміну Pool.apply
від Pool.apply_async
методу також є зворотний виклик, який, якщо він надається, викликається, коли функція завершена. Це можна використовувати замість дзвінка get()
.
Наприклад:
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()
може дати такий результат, як
[1, 0, 4, 9, 25, 16, 49, 36, 81, 64]
Зауважте, на відміну від цього pool.map
, порядок результатів може не відповідати порядку, в якому здійснювались pool.apply_async
дзвінки.
Отже, якщо вам потрібно запустити функцію в окремому процесі, але хочете, щоб поточний процес блокувався, поки ця функція не повернеться, використовуйте Pool.apply
. Мовляв Pool.apply
, Pool.map
блокує, поки не повернеться повний результат.
Якщо ви хочете, щоб пул робочих процесів виконував безліч викликів функцій асинхронно, використовуйте Pool.apply_async
. Порядок результатів не гарантується бути такою ж , як і порядок дзвінків в Pool.apply_async
.
Зауважте також, що ви можете зателефонувати на декілька різних функцій Pool.apply_async
(не всі дзвінки повинні використовувати одну і ту ж функцію).
На відміну від цього, Pool.map
застосовується та ж функція до багатьох аргументів. Однак, на відміну від Pool.apply_async
, результати повертаються у порядку, що відповідає порядку аргументів.
Pool.map(func,iterable)
еквівалентно Pool.map_async(func,iterable).get()
. Таким чином, зв'язок між Pool.map
і Pool.map_async
є подібним до Pool.apply
та Pool.apply_async
. Ці async
команди повертають негайно, в той час як не- async
команди блокувати. Ці async
команди також мають функцію зворотного виклику.
Pool.map
та Pool.apply
подібним до вирішення, коли використовувати map
або apply
в Python. Ви просто використовуєте інструмент, який відповідає роботі. Вибір між використанням async
та не- async
версією залежить від того, чи хочете виклик заблокувати поточний процес та / або ви хочете використовувати зворотний дзвінок.
apply_async
повертає ApplyResult
об'єкт. Виклик , який ApplyResult
«S get
метод поверне значення, що повертається асоційованої функції (або рейз , mp.TimeoutError
якщо час-виклик з.) Так що, якщо ви поклали ApplyResult
з в упорядкованому списку, то виклик їх get
методи будуть повертати результати в тому ж порядку. pool.map
Однак ви просто можете використовувати в цій ситуації.
Щодо apply
vs map
:
pool.apply(f, args)
: f
виконується лише в ОДИН із працівників пулу. Отже ОДИН із процесів у пулі буде запускатися f(args)
.
pool.map(f, iterable)
: Цей метод розбиває ітерабельний ряд на кілька фрагментів, які він подає до пулу процесів як окремі завдання. Таким чином, ви скористаєтеся всіма процесами в пулі.
apply_async()
8 разів? Чи автоматично оброблятиме його з чергою?
Ось короткий огляд у вигляді таблиці для того , щоб показати різницю між Pool.apply
, Pool.apply_async
, Pool.map
і Pool.map_async
. Вибираючи один з них, ви повинні враховувати багатоагрегати, паралельність, блокування та замовлення:
| 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
і Pool.imap_async
- лазерна версія карти та map_async.
Pool.starmap
метод, дуже схожий на метод map, крім того, що він приймає кілька аргументів.
Async
методи подають всі процеси одразу та отримують результати, як тільки вони закінчуються. Для отримання результатів використовуйте метод get.
Pool.map
(або Pool.apply
) методи дуже схожі на вбудовану карту Python (або застосувати). Вони блокують основний процес, поки всі процеси не завершаться і повернуть результат.
Викликається за перелік робочих місць за один раз
results = pool.map(func, [1, 2, 3])
Можна закликати лише до однієї роботи
for x, y in [[1, 1], [2, 2]]:
results.append(pool.apply(func, (x, y)))
def collect_result(result):
results.append(result)
Викликається за перелік робочих місць за один раз
pool.map_async(func, jobs, callback=collect_result)
Можна викликати лише одну роботу та паралельно виконувати завдання у фоновому режимі
for x, y in [[1, 1], [2, 2]]:
pool.apply_async(worker, (x, y), callback=collect_result)
Це варіант, pool.map
який підтримує кілька аргументів
pool.starmap(func, [(1, 1), (2, 1), (3, 1)])
Поєднання starmap () та map_async (), яке перетворює ітерабельні ітерабелі та викликає функцію з розпакованим ітерабелем. Повертає об'єкт результату.
pool.starmap_async(calculate_worker, [(1, 1), (2, 1), (3, 1)], callback=collect_result)
Повну документацію можна знайти тут: https://docs.python.org/3/library/multiprocessing.html
if __name__=="__main__"
ранішеapply_async_with_callback()
в Windows?