2015-05-21 12 views
10

Tôi đang chạy đoạn mã sau trên một máy i3 dựa trên Intel có 4 lõi ảo (2 hyperthreads/lõi vật lý, 64bit) và Ubuntu 14.04 cài đặt:Python 2.7 concurrent.futures.ThreadPoolExecutor không parallelize

n = multiprocessing.cpu_count() 
executor = ThreadPoolExecutor(n) 
tuple_mapper = lambda i: (i, func(i)) 
results = dict(executor.map(tuple_mapper, range(10))) 

Mã này dường như không được thực thi theo kiểu song song, vì CPU chỉ được sử dụng 25% liên tục. Trên biểu đồ sử dụng, chỉ một trong 4 lõi ảo được sử dụng 100% tại một thời điểm. Các lõi được sử dụng được luân phiên sau mỗi 10 giây hoặc lâu hơn.

Nhưng việc song song hoạt động tốt trên máy chủ có cùng cài đặt phần mềm. Tôi không biết chính xác số lõi và loại bộ xử lý chính xác, nhưng tôi biết chắc chắn rằng nó có nhiều lõi và mức sử dụng là 100% và các phép tính có tốc độ nhanh (nhanh gấp 10 lần sau khi sử dụng song song) một số thí nghiệm với nó).

Tôi mong đợi, sự song song đó cũng sẽ hoạt động trên máy của tôi, không chỉ trên máy chủ.

Tại sao nó không hoạt động? Nó có liên quan gì đến cài đặt hệ điều hành của tôi không? Tôi có phải thay đổi chúng không?

Cảm ơn trước!

Cập nhật: Để biết thông tin cơ bản, hãy xem câu trả lời chính xác bên dưới. Vì lợi ích của sự hoàn chỉnh, tôi muốn đưa ra một số mẫu mã mà giải quyết vấn đề:

tuple_mapper = lambda i: (i, func(i)) 
n = multiprocessing.cpu_count() 
with concurrent.futures.ProcessPoolExecutor(n) as executor: 
    results = dict(executor.map(tuple_mapper, range(10))) 

Trước khi bạn sử dụng lại này chăm sóc mà tất cả các chức năng bạn đang sử dụng được quy định tại các cấp cao nhất của một module như mô tả ở đây : Python multiprocessing pickling error

+2

Hãy dùng thử bằng 'ProcessPoolExecutor'. Có thể là [GIL] (https://wiki.python.org/moin/GlobalInterpreterLock). – kichik

+0

Thú vị, nhưng sau đó tôi vẫn còn bị kích thích bởi thực tế là máy chủ cho thấy 100% sử dụng với và ít hơn mà không cần song song, vì nó có cùng một cài đặt phần mềm phần mềm. Tôi sẽ thử lời khuyên của bạn. –

Trả lời

13

Có vẻ như bạn đang thấy kết quả của Python Global Interpreter Lock (aka GIL).

Trong CPython, khóa thông dịch toàn cầu, hoặc GIL, là một mutex rằng ngăn chặn nhiều luồng bản địa từ thực bytecode Python tại một lần.

Vì tất cả các chủ đề của bạn đang chạy mã Python thuần túy, chỉ một trong số chúng có thể chạy song song. Điều đó sẽ chỉ khiến một CPU hoạt động và khớp với mô tả của bạn về vấn đề.

Bạn có thể sử dụng nhiều quy trình với ProcessPoolExecutor từ cùng một mô-đun. Các giải pháp khác bao gồm chuyển đổi sang Jython hoặc IronPython không có GIL.

Lớp ProcessPoolExecutor là lớp con Executor sử dụng hồ bơi của các quá trình thực hiện cuộc gọi không đồng bộ. ProcessPoolExecutor sử dụng mô-đun đa xử lý, cho phép nó bước sang bên cạnh Khóa thông dịch toàn cầu nhưng cũng có nghĩa là chỉ các đối tượng có thể chọn có thể là được thực hiện và trả lại.

+2

Cảm ơn, bây giờ tôi đang sử dụng CPU 100%! Trên con đường của tôi giải quyết điều này tôi cũng đã phải giải quyết các lỗi sau đây trước khi nó hoạt động: http://stackoverflow.com/questions/8804830/python-multiprocessing-pickling-error –

+0

Tại sao không pypy? Tôi tin pypy cũng miễn phí từ GIL. – 0xc0de

+0

@ 0xc0de PyPy vẫn có GIL theo [FAQ] (http://doc.pypy.org/en/latest/faq.html#does-pypy-have-a-gil-why) – kichik