đa xử lý.Pool: Sự khác biệt giữa map_async và imap là gì?


184

Tôi đang cố gắng học cách sử dụng multiprocessinggói của Python , nhưng tôi không hiểu sự khác biệt giữa map_asyncimap. Tôi nhận thấy rằng cả hai map_asyncimapđược thực hiện không đồng bộ. Vậy khi nào tôi nên sử dụng cái này hơn cái kia? Và làm thế nào tôi nên lấy kết quả trả về map_async?

Tôi có nên sử dụng một cái gì đó như thế này?

def test():
    result = pool.map_async()
    pool.close()
    pool.join()
    return result.get()

result=test()
for i in result:
    print i

Câu trả lời:


492

Có hai điểm khác biệt chính giữa imap/ imap_unorderedmap/ map_async:

  1. Cách họ tiêu thụ lặp đi lặp lại bạn truyền cho họ.
  2. Cách họ trả lại kết quả cho bạn.

maptiêu thụ iterable của bạn bằng cách chuyển đổi iterable thành một danh sách (giả sử nó chưa phải là một danh sách), chia nó thành các khối và gửi các khối đó đến các quy trình worker trong Pool. Việc chia iterable thành các khối thực hiện tốt hơn so với việc chuyển từng mục trong lần lặp giữa các tiến trình một mục tại một thời điểm - đặc biệt nếu số lần lặp lớn. Tuy nhiên, biến iterable thành một danh sách để chunk nó có thể có chi phí bộ nhớ rất cao, vì toàn bộ danh sách sẽ cần phải được giữ trong bộ nhớ.

imapkhông biến iterable mà bạn đưa nó thành một danh sách, cũng không biến nó thành các khối (theo mặc định). Nó sẽ lặp đi lặp lại qua từng phần tử lặp và gửi chúng cho mỗi phần tử tới một quy trình worker. Điều này có nghĩa là bạn không sử dụng bộ nhớ để chuyển đổi toàn bộ lần lặp thành một danh sách, nhưng điều đó cũng có nghĩa là hiệu suất chậm hơn đối với các lần lặp lớn, vì thiếu đoạn mã. Điều này có thể được giảm thiểu bằng cách chuyển một chunksizeđối số lớn hơn mặc định là 1, tuy nhiên.

Sự khác biệt lớn khác giữa imap/ imap_unorderedmap/ map_async, là với imap/ imap_unordered, bạn có thể bắt đầu nhận kết quả từ nhân viên ngay khi họ sẵn sàng, thay vì phải đợi tất cả trong số họ kết thúc. Với map_async, một AsyncResulttrả về ngay lập tức, nhưng bạn thực sự không thể lấy kết quả từ đối tượng đó cho đến khi tất cả chúng được xử lý, tại đó nó trả về cùng một danh sách map( mapthực tế được thực hiện như trong map_async(...).get()). Không có cách nào để có được kết quả một phần; bạn có toàn bộ kết quả, hoặc không có gì.

imapimap_unorderedcả hai trả lại iterables ngay lập tức. Với imap, kết quả sẽ được mang lại từ lần lặp ngay khi chúng sẵn sàng, trong khi vẫn duy trì thứ tự của lần lặp đầu vào. Với imap_unordered, kết quả sẽ được mang lại ngay khi chúng sẵn sàng, bất kể thứ tự lặp lại đầu vào. Vì vậy, nói rằng bạn có điều này:

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)))

Điều này sẽ xuất ra:

3 (Time elapsed: 1s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)

Nếu bạn sử dụng p.imap_unorderedthay vì p.imap, bạn sẽ thấy:

3 (Time elapsed: 1s)
5 (Time elapsed: 3s)
7 (Time elapsed: 5s)

Nếu bạn sử dụng p.maphoặc p.map_async().get(), bạn sẽ thấy:

3 (Time elapsed: 5s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)

Vì vậy, lý do chính để sử dụng imap/ imap_unorderedhơn map_asynclà:

  1. Lặp lại của bạn đủ lớn để chuyển đổi nó thành một danh sách sẽ khiến bạn hết / sử dụng quá nhiều bộ nhớ.
  2. Bạn muốn có thể bắt đầu xử lý kết quả trước khi hoàn thành tất cả chúng.

1
những gì về áp dụng và áp dụng_async?
Harsh Daftary

10
@HarshDaftary applygửi một tác vụ duy nhất đến một quy trình worker, và sau đó chặn cho đến khi hoàn thành. apply_asyncgửi một tác vụ duy nhất đến một quy trình làm việc, và sau đó trả về ngay một AsyncResultđối tượng, có thể được sử dụng để chờ tác vụ hoàn thành và lấy kết quả. applyđược thực hiện bằng cách gọi đơn giảnapply_async(...).get()
dano

51
Đó là loại mô tả nên có trong Pooltài liệu chính thức chứ không phải là mô tả buồn tẻ hiện có .
phút

@dano Tôi muốn chạy một hàm trong nền nhưng tôi có một số hạn chế về tài nguyên và không thể chạy hàm nhiều lần mà tôi muốn và muốn xếp hàng các lần thực thi bổ sung của hàm. Bạn có biết tôi nên làm thế nào không? Tôi có câu hỏi của tôi ở đây . Bạn có thể vui lòng xem câu hỏi của tôi và xem liệu bạn có thể cho tôi một số gợi ý (hoặc thậm chí tốt hơn, một câu trả lời) về cách tôi nên làm điều đó không?
Amir

1
@BallpointBen Nó sẽ chuyển sang phần công việc tiếp theo ngay khi hoàn thành. Đặt hàng được xử lý trở lại trong quá trình cha mẹ.
dano
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.