Ada dua perbedaan utama antara imap
/ imap_unordered
dan map
/ map_async
:
- Cara mereka mengonsumsi iterable yang Anda berikan kepada mereka.
- Cara mereka mengembalikan hasilnya kepada Anda.
map
mengkonsumsi iterable Anda dengan mengonversikan iterable ke daftar (dengan asumsi itu bukan daftar), memecahnya menjadi potongan-potongan, dan mengirimkan potongan-potongan itu ke proses pekerja di Pool
. Memecah iterable menjadi chunks berkinerja lebih baik daripada melewatkan setiap item di iterable antara proses satu item pada suatu waktu - terutama jika iterable besar. Namun, mengubah iterable menjadi daftar untuk memotongnya dapat memiliki biaya memori yang sangat tinggi, karena seluruh daftar harus disimpan dalam memori.
imap
tidak mengubah iterable yang Anda berikan menjadi daftar, juga tidak memecahnya menjadi potongan (secara default). Ini akan beralih pada elemen yang dapat diubah pada satu waktu, dan mengirimkannya masing-masing ke proses pekerja. Ini berarti Anda tidak mengambil memori hit dari mengubah seluruh iterable ke daftar, tetapi juga berarti kinerjanya lebih lambat untuk iterables besar, karena kurangnya chunking. Ini dapat dikurangi dengan memberikan chunksize
argumen yang lebih besar dari standar 1, namun.
Perbedaan utama lainnya antara imap
/ imap_unordered
dan map
/ map_async
, adalah bahwa dengan imap
/ imap_unordered
, Anda dapat mulai menerima hasil dari pekerja segera setelah mereka siap, daripada harus menunggu semuanya selesai. Dengan map_async
, sebuah AsyncResult
dikembalikan segera, tetapi Anda tidak dapat benar-benar mengambil hasil dari objek itu sampai semuanya diproses, pada titik mana ia mengembalikan daftar yang map
sama ( map
benar-benar diimplementasikan secara internal seperti map_async(...).get()
). Tidak ada cara untuk mendapatkan hasil parsial; Anda memiliki seluruh hasil, atau tidak sama sekali.
imap
dan imap_unordered
keduanya mengembalikan iterables segera. Dengan imap
, hasilnya akan dihasilkan dari iterable segera setelah mereka siap, sambil tetap mempertahankan urutan input iterable. Dengan imap_unordered
, hasil akan dihasilkan segera setelah siap, terlepas dari urutan input yang dapat diubah. Jadi, katakan Anda memiliki ini:
import multiprocessing
import time
def func(x):
time.sleep(x)
return x + 2
if __name__ == "__main__":
p = multiprocessing.Pool()
start = time.time()
for x in p.imap(func, [1,5,3]):
print("{} (Time elapsed: {}s)".format(x, int(time.time() - start)))
Ini akan menampilkan:
3 (Time elapsed: 1s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)
Jika Anda menggunakan p.imap_unordered
alih-alih p.imap
, Anda akan melihat:
3 (Time elapsed: 1s)
5 (Time elapsed: 3s)
7 (Time elapsed: 5s)
Jika Anda menggunakan p.map
atau p.map_async().get()
, Anda akan melihat:
3 (Time elapsed: 5s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)
Jadi, alasan utama untuk menggunakan imap
/ imap_unordered
lebih map_async
adalah:
- Iterable Anda cukup besar sehingga mengubahnya menjadi daftar akan menyebabkan Anda kehabisan / menggunakan terlalu banyak memori.
- Anda ingin dapat mulai memproses hasil sebelum semuanya selesai.
apply
mengirim satu tugas ke proses pekerja, dan kemudian memblokir sampai selesai.apply_async
mengirimkan satu tugas ke proses kerja, dan kemudian segera mengembalikanAsyncResult
objek, yang dapat digunakan untuk menunggu tugas selesai dan mengambil hasilnya.apply
diimplementasikan dengan hanya meneleponapply_async(...).get()
Pool
dokumentasi resmi dan bukan yang membosankan .