2013-08-11 51 views
8

Tôi đang cố gắng tìm hiểu cách xử lý đa Python.Tài liệu đa xử lý Python Ví dụ

http://docs.python.org/2/library/multiprocessing.html từ ví dụ của "Để hiển thị các ID quá trình cá nhân có liên quan, đây là một ví dụ mở rộng:"

from multiprocessing import Process 
import os 

def info(title): 
    print title 
    print 'module name:', __name__ 
    if hasattr(os, 'getppid'): # only available on Unix 
     print 'parent process:', os.getppid() 
    print 'process id:', os.getpid() 

def f(name): 
    info('function f') 
    print 'hello', name 

if __name__ == '__main__': 
    info('main line') 
    p = Process(target=f, args=('bob',)) 
    p.start() 
    p.join() 

chính xác tôi đang tìm kiếm gì ở? Tôi thấy rằng def f (name): được gọi sau khi thông tin ('dòng chính') được hoàn thành, nhưng cuộc gọi đồng bộ này sẽ được mặc định anyways. Tôi thấy rằng các thông tin quá trình tương tự ('dòng chính') là PID cha của def f (tên): nhưng không chắc chắn những gì là 'đa xử lý' về điều đó.

Ngoài ra, với tham gia() "Chặn chuỗi gọi cho đến khi quá trình có phương thức join() được gọi là chấm dứt". Tôi không rõ ràng về những gì các chủ đề gọi điện thoại sẽ được. Trong ví dụ này, những gì sẽ tham gia() được chặn?

Trả lời

25

Làm thế nào multiprocessing công trình, trong một nutshell:

  • Process() spawn (fork hoặc tương tự trên các hệ thống Unix-like) một bản sao của chương trình gốc (trên Windows, mà thiếu một thực fork, đây là khó khăn và yêu cầu sự chăm sóc đặc biệt mà ghi chú tài liệu mô-đun).
  • Bản sao giao tiếp với bản gốc để tìm ra rằng (a) đó là bản sao và (b) nó sẽ tắt và gọi hàm target= (xem bên dưới).
  • Tại thời điểm này, bản gốc và bản sao giờ đây khác và độc lập và có thể chạy đồng thời.

Vì đây là các quy trình độc lập, giờ đây chúng có Khóa thông dịch toàn cầu độc lập (trong CPython) để cả hai có thể sử dụng tới 100% CPU trên hộp nhiều CPU, miễn là chúng không tranh các tài nguyên cấp thấp hơn (OS) khác. Đó là phần "đa xử lý". Tất nhiên, tại một thời điểm nào đó bạn phải gửi dữ liệu qua lại giữa các quy trình được cho là độc lập này, ví dụ: để gửi kết quả từ một (hoặc nhiều) quy trình công nhân trở lại quy trình "chính". (Có ngoại lệ thường xuyên, nơi mọi người hoàn toàn độc lập, nhưng nó rất hiếm ... cộng với toàn bộ chuỗi khởi động, được khởi động bởi p.start().) Vì vậy, mỗi trường được tạo Process dụ— p, trong ví dụ trên — có kênh liên lạc đối với người tạo bố mẹ và ngược lại (đó là kết nối đối xứng). Mô-đun multiprocessing sử dụng mô-đun pickle để chuyển dữ liệu thành chuỗi — các chuỗi giống nhau bạn có thể lưu trữ trong các tệp có số pickle.dump —và gửi dữ liệu qua kênh "xuống dưới" tới công nhân để gửi đối số và như vậy và "trở lên" từ công nhân đến gửi lại kết quả.

Cuối cùng, khi bạn đã hoàn thành xong việc nhận kết quả, nhân viên hoàn thành (bằng cách trở về từ hàm target=) và thông báo cho phụ huynh đã hoàn thành. Để đảm bảo mọi thứ được đóng và dọn dẹp, phụ huynh nên gọi số p.join() để đợi thông báo "Tôi đã hoàn tất" của nhân viên (thực tế là cấp hệ điều hành exit trên các hệ thống Unix-ish).

Ví dụ này hơi ngớ ngẩn vì hai thông báo được in về cơ bản không có thời gian chút nào, do đó, chạy chúng "cùng một lúc" không có mức tăng có thể đo lường được. Nhưng giả sử thay vì chỉ in hello, f là để tính 100.000 chữ số đầu tiên của π (3.14159 ...). Sau đó, bạn có thể sinh ra một số khác Process, p2 với một mục tiêu khác nhau g để tính 100.000 chữ số đầu tiên của e (2.71828 ...). Chúng sẽ chạy độc lập.Sau đó, cha mẹ có thể gọi p.join()p2.join() để chờ cho cả hai hoàn thành (hoặc đẻ trứng nhưng nhiều công nhân hơn để làm nhiều việc hơn và chiếm nhiều CPU hơn, hoặc thậm chí đi và làm công việc của mình một thời gian trước).