2009-08-04 52 views
32

Tôi có một ứng dụng python lấy một tập hợp dữ liệu và cho từng phần dữ liệu trong bộ sưu tập đó, nó thực hiện một tác vụ. Nhiệm vụ mất một thời gian để hoàn thành vì có sự chậm trễ liên quan. Vì sự chậm trễ này, tôi không muốn mỗi phần dữ liệu thực hiện nhiệm vụ sau đó, tôi muốn tất cả chúng xảy ra song song. Tôi có nên sử dụng đa xử lý không? hoặc luồng cho hoạt động này?đa xử lý hoặc luồng trong python?

Tôi đã cố gắng sử dụng luồng nhưng gặp sự cố, thường một số tác vụ sẽ không bao giờ thực sự kích hoạt.

+0

"Bộ sưu tập dữ liệu" của bạn lớn đến mức nào. Nếu nó là rất lớn, bạn có thể không muốn bắt đầu chủ đề hoặc quy trình cho mỗi một. –

+0

thường là 1, 2 hoặc 3 phần dữ liệu. – Ryan

+0

@ S.Lott - bạn sẽ giới hạn số lượng luồng/quy trình với một số nhỏ hơn nhiều so với kích thước của dữ liệu như thế nào? –

Trả lời

0

Sử dụng mô hình luồng của CPython sẽ không cung cấp cho bạn bất kỳ cải thiện hiệu suất nào, vì các luồng không thực sự được thực thi song song, do cách xử lý thu gom rác. Multiprocess sẽ cho phép thực thi song song. Rõ ràng trong trường hợp này, bạn phải có nhiều lõi có sẵn để trang trại các công việc song song của bạn.

Có nhiều thông tin hơn có sẵn trong this related question.

+4

Điều này không đúng. Nó sẽ không cung cấp cho bạn cải thiện hiệu suất AS MUCH như trong C, C++, nhưng một số sự tương tranh xảy ra. Đặc biệt nếu bạn là I/O bị ràng buộc làm chủ đề giúp đỡ. – Christopher

+0

Tôi đã không nhận ra điều đó - cảm ơn thông tin. Dưới đây là một giới thiệu bên ngoài: http://mail.python.org/pipermail/python-dev/2008-May/079461.html. Trong tiêu chuẩn này, bạn có thể thấy sự cải thiện cho các vấn đề I/O-ràng buộc mà bạn mô tả. Tuy nhiên, nó là giá trị chỉ ra rằng vấn đề CPU ràng buộc thực sự chạy ** chậm hơn ** với 2 chủ đề Python hơn với 1! Có vẻ như hồ sơ cho ứng dụng của bạn là rất cần thiết. –

7

Đối với các tập hợp dữ liệu nhỏ, chỉ cần tạo các quy trình con với subprocess.Popen.

Mỗi quy trình con có thể lấy dữ liệu từ stdin hoặc từ đối số dòng lệnh, thực hiện xử lý và chỉ cần ghi kết quả vào tệp đầu ra.

Khi các quy trình con đã hoàn tất (hoặc hết giờ), bạn chỉ cần hợp nhất các tệp đầu ra.

Rất đơn giản.

+3

Đây là một giải pháp thực sự nặng. Bạn không chỉ phải sắp xếp để cung cấp dữ liệu cho một quy trình bên ngoài, mà bạn còn có chi phí lớn. – Christopher

+1

@Christopher. Vấn đề là sự đơn giản. Thế giới Unix đã sử dụng kỹ thuật này trong 40 năm. Nó hoạt động tốt bởi vì nó đơn giản. Ngoài ra, chi phí trên không thực sự "lớn" vì bạn đang chạy nhiều phiên bản của cùng một hình ảnh nhị phân. Điều này được tối ưu hóa tốt bởi GNU/Linux. –

+8

@ S.Lott: Chỉ vì nó đã được sử dụng trong một thời gian dài, không có nghĩa là nó là một giải pháp tốt. Nó đặc biệt không phải là một giải pháp tốt cho các vấn đề về tính toán. Chi phí là "lớn" bởi vì bạn có phí trên bộ nhớ của tất cả các cấu trúc trên mỗi quá trình, cũng như độ trễ của nhiều lần chuyển đổi hạt nhân. Mô đun đa xử lý python không thực sự tạo ra một "tiến trình" mới như tiến trình con. Nó tạo ra một bối cảnh thông dịch mới, nhẹ hơn nhiều so với việc tạo ra một quy trình cấp hệ điều hành mới. – Christopher

7

Bạn có thể xem xét xem xét Stackless Python. Nếu bạn có quyền kiểm soát chức năng mất một thời gian dài, bạn có thể chỉ cần ném một số stackless.schedule() s trong đó (nói năng suất cho coroutine tiếp theo), nếu không bạn có thể set Stackless to preemptive multitasking.

Trong Stackless, bạn không có chủ đề, nhưng tasklets hoặc greenlets chủ yếu là các chuỗi rất nhẹ. Nó hoạt động tuyệt vời theo nghĩa là có một khung công tác khá tốt với rất ít thiết lập để có được đa nhiệm.

Tuy nhiên, Stackless cản trở tính di động vì bạn phải thay thế một vài thư viện Python chuẩn - Stackless loại bỏ sự phụ thuộc vào ngăn xếp C. Nó rất di động nếu người dùng tiếp theo cũng có Stackless được cài đặt, nhưng điều đó hiếm khi xảy ra.

29

Nếu bạn đang thực sự tính ràng buộc, sử dụng multiprocessing module có lẽ là giải pháp trọng lượng nhẹ nhất (cả về tiêu thụ bộ nhớ và khó thực hiện.)

Nếu bạn là I/O bị ràng buộc, bằng cách sử dụng các threading module thường sẽ cung cấp cho bạn có kết quả tốt. Đảm bảo rằng bạn sử dụng lưu trữ an toàn luồng (như Hàng đợi) để chuyển dữ liệu đến chuỗi của bạn. Hoặc đưa cho họ một mẩu dữ liệu duy nhất cho họ khi chúng được sinh ra.

PyPy được tập trung vào hiệu suất. Nó có một số tính năng có thể giúp xử lý tính toán. Họ cũng có hỗ trợ cho bộ nhớ giao dịch phần mềm, mặc dù đó chưa phải là chất lượng sản xuất. Lời hứa là bạn có thể sử dụng các cơ chế song song hoặc đồng thời đơn giản hơn đa xử lý (có một số yêu cầu khó xử.)

Stackless Python cũng là một ý tưởng hay. Stackless có các vấn đề về tính di động như được chỉ ra ở trên. Unladen Swallow hứa hẹn nhưng hiện không còn tồn tại.Pyston là một (chưa hoàn thành) Python thực hiện tập trung vào tốc độ. Đó là cách tiếp cận khác với PyPy, có thể mang lại tốc độ nhanh hơn (hoặc chỉ khác).

0

Nếu bạn có thể dễ dàng phân vùng và tách dữ liệu bạn có, có vẻ như bạn chỉ nên thực hiện phân vùng đó ra bên ngoài và cho chúng vào một số quy trình của chương trình. (ví dụ: một số quy trình thay vì chủ đề)

0

IronPython có đa luồng thực, không giống như CPython và GIL. Vì vậy, tùy thuộc vào những gì bạn đang làm, nó có thể đáng xem. Nhưng có vẻ như trường hợp sử dụng của bạn phù hợp hơn với mô-đun đa xử lý.

Đối với người đề xuất python stackless, tôi không phải là chuyên gia về nó, nhưng có vẻ như tôi đang nói về phần mềm "đa luồng", mà thực sự không song song chút nào (vẫn chạy trong một chuỗi vật lý) vì vậy không thể mở rộng thành nhiều lõi.) Nó chỉ đơn thuần là một cách thay thế để cấu trúc ứng dụng không đồng bộ (nhưng vẫn đơn luồng, không song song).

9

Tác vụ chạy như tuần tự nhưng bạn có ảo tưởng chạy song song. Nhiệm vụ là tốt khi bạn sử dụng cho tập tin hoặc kết nối I/O và bởi vì là lightweights.

Đa xử lý với hồ bơi có thể là giải pháp phù hợp với bạn vì các quy trình chạy song song nên rất tốt với tính toán chuyên sâu vì mỗi quá trình chạy trong một CPU (hoặc lõi).

cài đặt đa tiến có thể rất dễ dàng:

from multiprocessing import Pool 

def worker(input_item): 
    output = do_some_work() 
    return output 

pool = Pool() # it make one process for each CPU (or core) of your PC. Use "Pool(4)" to force to use 4 processes, for example. 
list_of_results = pool.map(worker, input_list) # Launch all automatically 
+0

có nghĩa là tất cả các lõi hoạt động trên cùng một dữ liệu? có thể tách input_list và chuyển từng đoạn vào các lõi khác nhau không? – Moj

0

Bạn có thể muốn nhìn vào Twisted. Nó được thiết kế cho các nhiệm vụ mạng không đồng bộ.

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