ฉันไม่ได้เห็นตัวอย่างที่ชัดเจนกับกรณีการใช้งานสำหรับ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)
: วิธีนี้สับ 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
and Pool.imap_async
- รุ่นแผนที่ที่อ่อนแอกว่าและ map_async
Pool.starmap
วิธีการคล้ายกันมากกับวิธีการแผนที่นอกจากจะยอมรับการขัดแย้งหลาย
Async
วิธีการส่งกระบวนการทั้งหมดในครั้งเดียวและดึงผลลัพธ์เมื่อพวกเขาเสร็จสิ้น ใช้วิธีรับเพื่อรับผลลัพธ์
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 () ที่วนซ้ำ iterable ของ iterables และการโทร func ด้วยการทำซ้ำ iterables ส่งคืนวัตถุผลลัพธ์
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?