Я не бачив чітких прикладів із випадками використання для 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Однак ви просто можете використовувати в цій ситуації.
Щодо applyvs 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?