Tôi đang cố gắng hiểu một chút về những gì đang diễn ra đằng sau hậu trường khi sử dụng phương thức apply_sync của một nhóm đa xử lý.Ai chạy cuộc gọi lại khi sử dụng phương thức apply_async của một nhóm đa xử lý?
Ai chạy phương thức gọi lại? Đây có phải là quá trình chính được gọi là apply_async không?
Giả sử tôi gửi toàn bộ các lệnh apply_async có gọi lại và sau đó tiếp tục với chương trình của tôi. Chương trình của tôi vẫn đang hoạt động khi bắt đầu kết thúc áp dụng. Làm thế nào để gọi lại có được chạy của tôi "quá trình chính" trong khi quá trình chính vẫn còn bận rộn với kịch bản?
Đây là một ví dụ.
import multiprocessing
import time
def callback(x):
print '{} running callback with arg {}'.format(multiprocessing.current_process().name, x)
def func(x):
print '{} running func with arg {}'.format(multiprocessing.current_process().name, x)
return x
pool = multiprocessing.Pool()
args = range(20)
for a in args:
pool.apply_async(func, (a,), callback=callback)
print '{} going to sleep for a minute'.format(multiprocessing.current_process().name)
t0 = time.time()
while time.time() - t0 < 60:
pass
print 'Finished with the script'
Đầu ra là một cái gì đó giống như
PoolWorker-1 chạy func với arg 0
PoolWorker-2 chạy func với arg 1
PoolWorker-3 chạy func với arg 2
MainProcess sẽ ngủ trong một phút < - quá trình chính là bận rộn
PoolWorker-4 chạy func với arg 3
PoolWorker-1 chạy func với arg 4
PoolWorker-2 chạy func với arg 5
PoolWorker-3 chạy func với arg 6
PoolWorker-4 chạy func với arg 7
MainProcess running callback w ith arg 0 < - quá trình chính chạy gọi lại trong khi nó vẫn còn trong vòng lặp while !!
MainProcess chạy callback với arg 1
MainProcess chạy callback với arg 2
MainProcess chạy callback với arg 3
MainProcess chạy callback với arg 4
PoolWorker-1 chạy func với arg 8
...
Đã kết thúc với kịch bản
như thế nào MainProcess chạy callback khi nó ở giữa trong khi vòng lặp ??
Có tuyên bố này về cuộc gọi lại trong tài liệu cho multiprocessing.Pool có vẻ như gợi ý nhưng tôi không hiểu.
apply_async (func [, args [, kwds [, gọi lại]]])
Một biến thể của phương pháp được áp dụng() trả về một đối tượng kết quả.
Nếu gọi lại được chỉ định thì nó phải là một cuộc gọi có thể chấp nhận một đối số duy nhất. Khi kết quả trở thành sẵn sàng gọi lại được áp dụng cho nó (trừ khi cuộc gọi không thành công). gọi lại sẽ hoàn thành ngay lập tức vì nếu không thì luồng xử lý kết quả sẽ bị chặn.
Cảm ơn Dano vì đã dành thời gian viết câu trả lời chi tiết như vậy! Nếu tôi hiểu chính xác, hồ bơi sẽ tạo một chuỗi * đơn * mới (result_handler) mà công việc của nó là chờ đợi xung quanh để apply_async hoàn thành và sau đó gọi lại callback trong chuỗi của result_handler (là một phần của MainProcess). Các cuộc gọi lại (đối với một đối tượng đơn lẻ) có được gọi tuần tự không? I E. Một loạt các apply_async có thể kết thúc với nhau nhưng các callbacks sẽ được chạy từng cái một trong serial bởi result_handler? – Alex
Một câu hỏi khác. Điều gì sẽ xảy ra nếu chức năng gọi lại và tập lệnh chính cả hai lẫn lộn với cùng một đối tượng (trong MainProcess)? Có thể có hành vi không thể đoán trước? I E. nếu gọi lại và một cái gì đó sau này trong kịch bản chính cả hai cố gắng ghi vào cùng một tập tin hoặc sửa đổi cùng một mảng. Khi gọi lại thực sự được chạy những người biết những gì kịch bản chính sẽ được làm tại thời điểm đó. – Alex
@Alex Có, các cuộc gọi lại sẽ được thực hiện một cách bình thường.Chuỗi '_result_handler' kéo một tác vụ đã hoàn thành ra khỏi hàng đợi, gọi' _set' (chạy lệnh gọi lại), sau đó chuyển sang bước tiếp theo. Đây là lý do tại sao tài liệu nói để đảm bảo cuộc gọi lại hoàn tất ngay lập tức; thực thi các cuộc gọi lại chặn các kết quả khác không được xử lý. – dano