2011-06-17 49 views
24

Tôi mới sử dụng loại lập trình này và cần quan điểm của bạn.Đa luồng và đa xử lý

Tôi phải xây dựng một ứng dụng nhưng tôi không thể làm cho nó tính toán đủ nhanh. Tôi đã thử dùng TBB của Intel, và nó rất dễ sử dụng, nhưng tôi chưa bao giờ sử dụng các thư viện khác.

Trong lập trình đa xử lý, tôi đang đọc về OpenMP và Boost cho đa luồng, nhưng tôi không biết ưu và nhược điểm của chúng.

Trong C++, khi nào lập trình đa luồng thuận lợi so với lập trình đa xử lý và ngược lại, điều nào phù hợp nhất với tính toán nặng hoặc khởi chạy nhiều tác vụ ...? Ưu và khuyết điểm của họ khi chúng ta xây dựng một ứng dụng được thiết kế với chúng là gì? Và cuối cùng, thư viện nào là tốt nhất để làm việc cùng?

+1

Trong máy đa xử lý sử dụng thư viện chuỗi như tăng cường sẽ tận dụng lợi thế của các lõi khả dụng. Bạn cũng có thể có nhiều luồng trên một bộ xử lý có thể xen kẽ với các công nghệ như siêu phân luồng trong Pentium 4. Ý của bạn có nghĩa là đa tiến trình và hệ thống phân tán hay đa luồng? Bạn có thể làm cả hai trên thực tế nhưng bản chất của các chủ đề là nhận được song song bất kể bộ vi xử lý. Tăng FYI dựa trên các chủ đề posix theo như tôi biết và tôi thấy nó khá dễ sử dụng. Ngoài ra tiêu chuẩn C++ 0x mới sẽ bao gồm hỗ trợ luồng gốc cho ngôn ngữ. – AJG85

+0

Bạn nghĩ gì về Boost và Intel TBB? Nó nhanh hơn TBB của Intel? Hoặc tôi nên đi cho Intel nếu tôi có một bộ xử lý intel? – Nazka

+0

Intel TBB có lợi thế ở một số lĩnh vực mà nó cung cấp các phần tử song song được tối ưu hóa song song như các vòng lặp song song, v.v., trợ giúp trong việc tạo ra các thuật toán kiểu thu thập phân tán song song trên bộ vi xử lý của Intel, cũng như các tính toán song song khác. Chủ đề Boost chủ yếu là một gói phần mềm đa nền tảng sẽ chạy trên nhiều loại nền tảng phần cứng và hệ điều hành. Bạn nếu bạn cần một số nguyên thủy tính toán song song mặc dù, chủ đề Boost không trực tiếp cung cấp, bạn sẽ phải tự mình mã hóa chúng. Vì vậy, bạn có thể xem TBB như đang ở mức trừu tượng cao hơn Boost. – Jason

Trả lời

50

Đa luồng có nghĩa là chính xác, chạy nhiều luồng. Điều này có thể được thực hiện trên một hệ thống uni-processor, hoặc trên một hệ thống đa xử lý. Trên một hệ thống xử lý đơn, khi chạy nhiều luồng, quan sát thực tế của máy tính làm nhiều việc cùng một lúc (nghĩa là đa tác vụ) là một ảo ảnh, bởi vì điều thực sự xảy ra dưới mui xe là ở đó là một bộ lập lịch trình phần mềm thực hiện cắt thời gian trên CPU đơn. Vì vậy, chỉ có một nhiệm vụ duy nhất đang diễn ra tại bất kỳ thời điểm nào, nhưng bộ lập lịch đang chuyển đổi giữa các tác vụ đủ nhanh để bạn không bao giờ nhận thấy rằng có nhiều quy trình, luồng, v.v., cạnh tranh cho cùng một tài nguyên CPU.

Trên hệ thống đa bộ xử lý, cần giảm thời gian cắt. Hiệu ứng cắt thời gian vẫn còn đó, bởi vì một hệ điều hành hiện đại có thể có hàng trăm chủ đề cạnh tranh cho hai hoặc nhiều bộ vi xử lý, và thường không bao giờ có mối quan hệ 1-1 với số lượng lõi xử lý sẵn có. Vì vậy, tại một số điểm, một thread sẽ phải dừng lại và thread khác bắt đầu trên một CPU mà hai luồng đang chia sẻ. Điều này một lần nữa được xử lý bởi bộ lập lịch của hệ điều hành. Điều đó đang được nói, với một hệ thống đa xử lý, bạn có thể có hai điều xảy ra cùng một lúc, không giống như với hệ thống uni-processor. Cuối cùng, hai mô hình thực sự phần trực giao theo nghĩa là bạn sẽ cần đa luồng bất cứ khi nào bạn muốn có hai hoặc nhiều tác vụ chạy không đồng bộ, nhưng do cắt thời gian, bạn không nhất thiết cần một đa hệ thống xử lý để thực hiện điều đó. Nếu bạn đang cố gắng chạy nhiều luồng và đang thực hiện một tác vụ song song cao (tức là, cố giải quyết tích phân), thì có, bạn càng có thể ném nhiều lõi hơn vào một vấn đề, thì càng tốt. Bạn sẽ không nhất thiết cần một mối quan hệ 1-1 giữa các chủ đề và xử lý lõi, nhưng đồng thời, bạn không muốn vắt bỏ quá nhiều luồng mà bạn kết thúc bằng tấn luồng không hoạt động vì chúng phải đợi đến được lên lịch trên một trong các lõi CPU có sẵn. Mặt khác, nếu các tác vụ song song của bạn yêu cầu một số thành phần tuần tự, nghĩa là một luồng sẽ chờ kết quả từ một chuỗi khác trước khi nó có thể tiếp tục, thì bạn có thể chạy nhiều luồng hơn với một số loại hàng rào hoặc phương thức đồng bộ hóa rằng các chủ đề cần phải được nhàn rỗi không quay đi bằng cách sử dụng thời gian CPU, và chỉ có các chủ đề cần chạy là tranh tài nguyên CPU.

+2

Dang bạn gõ nhanh! Tôi sẽ chỉ thêm hai xu của tôi làm bình luận. – AJG85

+0

Tất cả các bình luận là tuyệt vời cho tôi :) @ Jason, do đó, thread được thiết kế để chương trình nhiều phần lớn của ứng dụng và làm công việc của họ không? – Nazka

+0

Một chủ đề có thể được sử dụng cho một nhiệm vụ ... nhiệm vụ đó có thể là bất cứ điều gì. Nó có thể là một cái gì đó chạy toàn bộ thời gian của chương trình của bạn, chẳng hạn như một daemon mạng sẽ "lắng nghe" cho các kết nối trên một ổ cắm và sau đó quay ra nhiều chủ đề để quản lý các kết nối đó. Một chủ đề cũng có thể được sử dụng cho một nhiệm vụ nhỏ như giải quyết một sự lặp lại của một tích phân mà là một nhiệm vụ rất song song. – Jason

2

Để trả lời câu hỏi đầu tiên: Cách tiếp cận tốt nhất là chỉ sử dụng các kỹ thuật đa luồng trong mã của bạn cho đến khi bạn đạt đến điểm mà ngay cả điều đó không mang lại cho bạn đủ lợi ích. Giả sử hệ điều hành sẽ xử lý ủy quyền cho nhiều bộ xử lý nếu chúng có sẵn.

Nếu bạn thực sự đang xử lý sự cố đa luồng không đủ, ngay cả với nhiều bộ xử lý (hoặc nếu bạn đang chạy trên hệ điều hành không sử dụng nhiều bộ xử lý) thì bạn có thể lo lắng về việc khám phá cách để có thêm sức mạnh. Điều này có nghĩa là các quá trình sinh sản trên mạng đến các máy khác.

Tôi chưa sử dụng TBB, nhưng tôi đã sử dụng IPP và thấy rằng IPP có hiệu quả và được thiết kế tốt. Boost là xách tay.

20

Có một vài điểm quan trọng mà tôi tin rằng nên được thêm vào câu trả lời tuyệt vời của @ Jason.

Đầu tiên, đa luồng không phải lúc nào cũng là ảo ảnh ngay cả trên một bộ xử lý đơn lẻ - có các thao tác không liên quan đến bộ xử lý. Đây là chủ yếu I/O - đĩa, mạng, thiết bị đầu cuối, vv Các hình thức cơ bản cho các hoạt động như vậy là chặn hoặc đồng bộ, ví dụ: chương trình của bạn chờ đợi cho đến khi hoạt động được hoàn thành và sau đó tiến hành. Trong khi chờ đợi, CPU được chuyển sang một tiến trình/luồng khác.

nếu bạn có bất cứ điều gì bạn có thể làm trong thời gian đó (ví dụ như tính toán nền trong khi chờ đợi cho người dùng nhập vào, phục vụ yêu cầu khác vv), bạn có về cơ bản hai lựa chọn:

  • sử dụng không đồng bộ I/O : bạn gọi số không chặn I/O cung cấp chức năng gọi lại , cho biết "gọi chức năng này khi bạn hoàn tất". Cuộc gọi trả về ngay lập tức và thao tác I/O tiếp tục ở chế độ nền. Bạn tiếp tục với những thứ khác.

  • sử dụng đa luồng: bạn có một chuỗi chuyên dụng cho từng loại tác vụ. Trong khi một người chờ cuộc gọi I/O chặn, người kia tiếp tục.

Cả hai phương pháp tiếp cận đều là mô hình lập trình khó, mỗi phương pháp đều có ưu và nhược điểm riêng.

  • với async I/O logic của logic của chương trình ít rõ ràng và khó theo dõi và gỡ lỗi. Tuy nhiên, bạn tránh sự cố an toàn chủ đề.
  • với chủ đề, challange là viết thread-safe chương trình. Lỗi an toàn chủ đề là những lỗi khó chịu gây ra khá khó khăn. Việc sử dụng quá mức khóa thực sự có thể dẫn đến sự xuống cấp thay vì cải thiện hiệu suất.

(đến đa xử lý)

Multithreading được phổ biến trên Windows vì thao túng quá trình khá nặng trên Windows (tạo ra một quá trình, bối cảnh chuyển đổi vv) như trái ngược với chủ đề mà được nhiều hơn nữa nhẹ (ít nhất đây là trường hợp khi tôi làm việc trên Win2K).

Trên Linux/Unix, các quy trình có trọng lượng nhẹ hơn nhiều. Ngoài ra (AFAIK) chủ đề trên Linux được thực hiện thực sự như là một loại quy trình nội bộ, do đó, không có được trong bối cảnh chuyển đổi của chủ đề so với quá trình. Tuy nhiên, bạn cần sử dụng một số hình thức IPC (liên lạc quy trình), như bộ nhớ chia sẻ, đường ống, hàng đợi tin nhắn, v.v.

Ghi chú: "Chủ đề là xấu"!:)

+2

Ngoài ra còn có một tùy chọn thứ ba, ghép kênh I/O thông qua select()/poll()/etc. Điều đó có thể an toàn hơn so với đa luồng và dễ hiểu hơn I/O không đồng bộ. –

0

Chỉ muốn đề cập rằng mô hình Dựa trên luồng (http://www.jpaulmorrison.com/fbp) là một phương pháp đa lập trình/đa xử lý tự nhiên để phát triển ứng dụng. Nó cung cấp một cái nhìn ứng dụng nhất quán từ cấp cao đến cấp thấp. Việc triển khai Java và C# tận dụng lợi thế của tất cả các bộ vi xử lý trên máy của bạn, nhưng việc thực thi C++ cũ hơn chỉ sử dụng một bộ xử lý. Tuy nhiên, nó có thể khá dễ dàng được mở rộng để sử dụng BOOST (hoặc pthreads, tôi giả định) bằng cách sử dụng khóa trên các kết nối. Tôi đã bắt đầu chuyển đổi nó để sử dụng sợi, nhưng tôi không chắc chắn nếu có bất kỳ điểm nào trong việc tiếp tục trên tuyến đường này. :-) Phản hồi sẽ được đánh giá cao. BTW Việc triển khai Java và C# thậm chí có thể giao tiếp bằng cách sử dụng các ổ cắm.

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