2017-09-05 29 views
5

Sự khác biệt giữa ThreadPoolPool trong mô hình multiprocessing là gì. Khi tôi cố gắng mã của tôi ra, đây là sự khác biệt chính tôi thấy:Sự khác biệt giữa ThreadPool vs Pool trong mô-đun đa xử lý Python

from multiprocessing import Pool 
import os, time 

print("hi outside of main()") 

def hello(x): 
    print("inside hello()") 
    print("Proccess id: ", os.getpid()) 
    time.sleep(3) 
    return x*x 

if __name__ == "__main__": 
    p = Pool(5) 
    pool_output = p.map(hello, range(3)) 

    print(pool_output) 

tôi nhìn thấy đầu ra sau đây:

hi outside of main() 
hi outside of main() 
hi outside of main() 
hi outside of main() 
hi outside of main() 
hi outside of main() 
inside hello() 
Proccess id: 13268 
inside hello() 
Proccess id: 11104 
inside hello() 
Proccess id: 13064 
[0, 1, 4] 

Với "ThreadPool":

from multiprocessing.pool import ThreadPool 
import os, time 

print("hi outside of main()") 

def hello(x): 
    print("inside hello()") 
    print("Proccess id: ", os.getpid()) 
    time.sleep(3) 
    return x*x 

if __name__ == "__main__": 
    p = ThreadPool(5) 
    pool_output = p.map(hello, range(3)) 

    print(pool_output) 

tôi thấy sản lượng sau:

hi outside of main() 
inside hello() 
inside hello() 
Proccess id: 15204 
Proccess id: 15204 
inside hello() 
Proccess id: 15204 
[0, 1, 4] 

Ques của tôi tions là:

  • tại sao "bên ngoài __main __()" chạy mỗi lần trong Pool?

  • multiprocessing.pool.ThreadPool không sinh ra các quy trình mới? Nó chỉ tạo ra các chủ đề mới?

  • Nếu có sự khác biệt nào giữa việc sử dụng multiprocessing.pool.ThreadPool thay vì chỉ mô-đun threading?

Tôi không thấy bất kỳ tài liệu chính thức nào cho ThreadPool ở bất kỳ đâu, ai đó có thể giúp tôi tìm nơi tôi có thể tìm thấy?

+0

Như tôi biết, vì GIL trong Python, sự đa luồng của Python trông giống như đa luồng nhưng nó không thực. Nếu bạn muốn tận dụng lợi thế của đa lõi của bạn với python, bạn cần phải sử dụng đa xử lý. Trong máy tính hiện đại, việc tạo ra một quy trình và tạo ra một luồng có cùng mức chi phí. – Yves

+0

Tạo chuỗi có thể có chi phí tương tự để tạo quy trình, nhưng việc liên lạc giữa các luồng có chi phí rất khác nhau để giao tiếp giữa các quy trình (trừ khi có thể bạn đã sử dụng bộ nhớ dùng chung). Ngoài ra, nhận xét của bạn về GIL chỉ là một phần đúng: nó được phát hành trong các hoạt động I/O và bởi một số thư viện (ví dụ: numpy) ngay cả trong các hoạt động liên kết CPU. Tuy nhiên, GIL cuối cùng là lý do để sử dụng các quy trình riêng biệt trong Python. –

Trả lời

5

multiprocessing.pool.ThreadPool hoạt động giống như multiprocessing.Pool với sự khác biệt duy nhất sử dụng chuỗi thay vì các quy trình để chạy logic công nhân.

Lý do bạn thấy

hi outside of main() 

được in nhiều lần với multiprocessing.Pool là do thực tế rằng hồ bơi sẽ spawn 5 quá trình độc lập. Mỗi quá trình sẽ khởi tạo trình thông dịch Python của riêng nó và tải mô-đun dẫn đến mức cao nhất print đang được thực hiện lại.

Lưu ý rằng điều này chỉ xảy ra nếu phương pháp tạo quy trình spawn được sử dụng (chỉ có phương pháp có sẵn trên Windows). Nếu bạn sử dụng fork một (Unix), bạn sẽ thấy thông báo được in chỉ một lần như cho các chủ đề.

multiprocessing.pool.ThreadPool không được ghi lại vì triển khai của nó chưa bao giờ được hoàn thành. Nó thiếu kiểm tra và tài liệu. Bạn có thể xem triển khai của nó trong source code.

Tôi tin rằng câu hỏi tự nhiên tiếp theo là: khi nào nên sử dụng nhóm dựa trên luồng và khi nào nên sử dụng một quy trình dựa trên hồ sơ?

Nguyên tắc hàng đầu là:

  • IO việc ràng buộc ->multiprocessing.pool.ThreadPool
  • CPU bị ràng buộc công việc ->multiprocessing.Pool
  • việc Hybrid -> phụ thuộc vào khối lượng công việc, tôi thường thích multiprocessing.Pool do quá trình cách ly lợi thế mang lại

Trên Python 3 bạn có thể muốn xem xét triển khai hồ bơi concurrent.future.Executor .

+0

Cảm ơn câu trả lời. Tôi chỉ muốn hiểu tuyên bố này: Lưu ý rằng điều này chỉ xảy ra nếu phương pháp tạo phương thức sinh sản được sử dụng (chỉ có phương thức có sẵn trên Windows). Nếu bạn sử dụng một ngã ba (Unix), bạn sẽ thấy thông báo được in chỉ một lần như cho các chủ đề. Giả sử, "đẻ trứng" và "ngã ba" là ngầm khi tôi gọi là "map()" hoặc "Pool()"? Hay đây là thứ tôi có thể kiểm soát? – ozn

+0

Giải thích là trong liên kết tôi đã cung cấp cho bạn ở trên khi đề cập đến phương pháp bắt đầu [đẻ trứng] (https://docs.python.org/3.6/library/multiprocessing.html#contexts-and-start-methods). Bạn có thể kiểm soát nó, nhưng các phương pháp bắt đầu có sẵn phụ thuộc vào nền tảng hệ điều hành. Tôi cho rằng bạn đang sử dụng Windows làm chiến lược khởi động mặc định là chiến dịch "đẻ trứng". Nếu vậy, có rất ít việc phải làm vì Windows chỉ hỗ trợ 'spawn'. – noxdafox

Các vấn đề liên quan