62

Ít nhất kể từ khi phát hành .NET 4.0, Microsoft dường như đã đặt rất nhiều nỗ lực hỗ trợ cho lập trình song song và không đồng bộ và có vẻ như rất nhiều API và thư viện xung quanh điều này đã xuất hiện. Đặc biệt là những cái tên ưa thích sau đây thường xuyên đề cập ở khắp mọi nơi thời gian gần đây:Làm cách nào để khung phản ứng, PLINQ, TPL và các phần mở rộng song song liên quan đến nhau?

  • Khung Reactive,
  • PLINQ (Parallel LINQ),
  • TPL (Parallel Library Task) và
  • Extensions song song.

Bây giờ tất cả chúng dường như là các sản phẩm của Microsoft và tất cả đều dường như nhắm mục tiêu các kịch bản lập trình không đồng bộ hoặc song song cho .NET. Nhưng nó không phải là khá rõ ràng những gì từng người trong số họ thực sự là và làm thế nào họ có liên quan với nhau. Một số thực sự có thể giống nhau.

Trong một vài từ, bất kỳ ai cũng có thể đặt bản ghi trực tiếp về những gì là gì?

+0

Tôi đã chỉnh sửa câu hỏi này để làm rõ nó một chút và bỏ phiếu để mở lại. Điều đó nói rằng, tôi không phải là một chuyên gia .NET, vì vậy tôi có thể đã thực hiện một mess của nó; cảm thấy tự do để chỉnh sửa nó hơn nữa (hoặc thậm chí hoàn nguyên các thay đổi của tôi hoàn toàn) nếu bạn nghĩ rằng tôi đã phạm sai lầm ở đâu đó. Ngoài ra, thẳng thắn, tôi vẫn nghĩ rằng câu hỏi này * cảm thấy * quá rộng và không rõ ràng để phù hợp tốt trên Stack Overflow; nói rằng, vì nó có một câu trả lời rất được tán thành và được chấp nhận, tôi sẵn sàng chấp nhận rằng nó có thể là một ngoại lệ. –

+0

Tôi cho rằng ** tất cả mọi người ** biết 4 điều trên (có thể là tất cả những người có khả năng trả lời câu hỏi này) sẽ biết ** ngay lập tức ** câu hỏi này là gì. Các upvotes và câu trả lời chứng minh điều đó. Dù sao tôi có chỉnh sửa câu hỏi để nó càng rõ ràng càng tốt. – bitbonk

Trả lời

93

PLINQ (song song LINQ) chỉ đơn giản là một cách mới để viết các truy vấn LINQ thông thường để chúng chạy song song - nói cách khác, Khung sẽ tự động quản lý truy vấn của bạn trên nhiều chuỗi sao cho chúng hoàn thành nhanh hơn (tức là sử dụng nhiều lõi CPU).

Ví dụ: giả sử bạn có một chuỗi các chuỗi và bạn muốn có tất cả các chuỗi bắt đầu bằng chữ "A". Bạn có thể viết truy vấn của mình như thế này:

var words = new[] { "Apple", "Banana", "Coconut", "Anvil" }; 
var myWords = words.Select(s => s.StartsWith("A")); 

Và điều này hoạt động tốt. Nếu bạn đã có 50.000 từ để tìm kiếm, tuy nhiên, bạn có thể muốn tận dụng lợi thế của một thực tế rằng mỗi bài kiểm tra là độc lập, và chia này trên nhiều lõi:

var myWords = words.AsParallel().Select(s => s.StartsWith("A")); 

Đó là tất cả các bạn phải làm gì để biến một truy vấn thường xuyên thành một song song chạy trên nhiều lõi. Khá gọn gàng.


Các TPL (Parallel Library Task) là hai yếu tố bổ sung cho PLINQ, và họ cùng nhau tạo nên Extensions song song. Trong khi PLINQ chủ yếu dựa trên chức năng kiểu lập trình với không có các tác dụng phụ, tác dụng phụ chính xác là những gì TPL dành cho. Nếu bạn muốn thực sự làm việc song song như trái ngược với chỉ tìm kiếm/lựa chọn những thứ song song, bạn sử dụng TPL.

TPL thực chất là lớp Parallel cho thấy tình trạng quá tải của For, ForeachInvoke. Invoke hơi giống như xếp hàng các nhiệm vụ trong ThreadPool, nhưng đơn giản hơn một chút để sử dụng. IMO, các bit thú vị hơn là ForForeach. Vì vậy, ví dụ: giả sử bạn có toàn bộ các tệp bạn muốn nén. Bạn có thể viết phiên bản tuần tự thường xuyên:

string[] fileNames = (...); 
foreach (string fileName in fileNames) 
{ 
    byte[] data = File.ReadAllBytes(fileName); 
    byte[] compressedData = Compress(data); 
    string outputFileName = Path.ChangeExtension(fileName, ".zip"); 
    File.WriteAllBytes(outputFileName, compressedData); 
} 

Một lần nữa, mỗi lần lặp của nén này hoàn toàn độc lập với bất kỳ loại nào khác.Chúng ta có thể tăng tốc độ này lên bằng cách thực hiện một vài trong số họ cùng một lúc:

Parallel.ForEach(fileNames, fileName => 
{ 
    byte[] data = File.ReadAllBytes(fileName); 
    byte[] compressedData = Compress(data); 
    string outputFileName = Path.ChangeExtension(fileName, ".zip"); 
    File.WriteAllBytes(outputFileName, compressedData); 
}); 

Và một lần nữa, đó là tất cả nó cần để parallelize hoạt động này. Bây giờ khi chúng ta chạy phương thức CompressFiles (hoặc bất kỳ phương thức nào chúng ta quyết định gọi nó), nó sẽ sử dụng nhiều lõi CPU và có thể kết thúc bằng một nửa hoặc 1/4 thời gian.

Lợi thế của việc này chỉ là nhét tất cả trong số ThreadPool là điều này thực sự chạy đồng bộ. Nếu bạn đã sử dụng số ThreadPool thay vì (hoặc chỉ đơn giản là Thread trường hợp), bạn phải tìm ra cách tìm ra khi tất cả các tác vụ được hoàn thành và trong khi đây không phải là terribly phức tạp, đó là điều mà rất nhiều người có xu hướng vặn lên hoặc ít nhất cũng gặp rắc rối với. Khi bạn sử dụng lớp học Parallel, bạn không thực sự phải suy nghĩ về nó; khía cạnh đa luồng được ẩn khỏi bạn, tất cả được xử lý đằng sau hậu trường.


Extensions Reactive (Rx) là thực sự là một con thú khác nhau hoàn toàn. Đó là một cách suy nghĩ khác về xử lý sự kiện. Có rất nhiều tài liệu để đề cập đến điều này, nhưng để tạo ra một câu chuyện dài ngắn, thay vì kết nối các bộ xử lý sự kiện cho các sự kiện, Rx cho phép bạn xử lý chuỗi các sự kiện là ... tốt, trình tự (IEnumerable<T>). Bạn có thể xử lý các sự kiện theo kiểu lặp đi lặp lại thay vì cho chúng bắn không đồng bộ vào các thời điểm ngẫu nhiên, nơi bạn phải luôn luôn lưu trạng thái để phát hiện một loạt các sự kiện xảy ra theo một thứ tự cụ thể.

Một trong những ví dụ tuyệt vời nhất mà tôi đã tìm thấy của Rx là here. Bỏ qua phần "LINQ to IObservable", nơi anh ta thực hiện một trình xử lý kéo và thả, thường là một nỗi đau trong WPF, chỉ trong 4 dòng mã. Rx cung cấp cho bạn thành phần sự kiện, thứ mà bạn không thực sự có với trình xử lý sự kiện thông thường và đoạn mã như vậy cũng đơn giản để cấu trúc lại thành các lớp hành vi mà bạn có thể đưa vào bất kỳ đâu.


Và đó là nó. Đây là một số tính năng thú vị có trong .NET 4.0. Có nhiều thứ nữa, tất nhiên, nhưng đây là những thứ bạn hỏi về!

+0

Có bất kỳ cái nào trong số này có sẵn trong .net 3.5 trở xuống không? – Myster

+1

@Myster: RX có sẵn (http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx). PLINQ đã có một thời gian dài trước đây như là một CTP nhưng không còn được cung cấp nữa - bạn phải nâng cấp cho điều đó. – Aaronaught

+2

Thư viện dữ liệu TPL (TDF) xuất hiện với C# async CTP trông thực sự tốt. Nó sẽ làm cho nó dễ dàng hơn nhiều cho các phần mềm trung gian. NET để ở trong 'hiệu suất điểm ngọt' của xử lý song song. Để có được hiệu suất tốt nhất (xem xét thông lượng và độ trễ), bạn đặt giới hạn. Vì vậy, mỗi 'khối' xử lý có thể có 'nắp bộ đệm' của riêng nó và có thể có một mũ song song. Bạn cũng có thể yêu cầu mỗi khối xử lý các lô thay vì các thư riêng lẻ. Điều này có vẻ tuyệt vời. – yzorg

28

Tôi thích câu trả lời của Aaronaught, nhưng tôi sẽ nói Rx và TPL giải quyết các vấn đề khác nhau. Một phần của những gì mà nhóm TPL thêm vào là các nguyên thủy luồng và các cải tiến đáng kể cho các khối xây dựng của thời gian chạy như ThreadPool. Và mọi thứ bạn liệt kê đều được xây dựng dựa trên các tính năng cơ bản và thời gian chạy.

Nhưng TPL và Rx giải quyết hai vấn đề khác nhau. TPL hoạt động tốt nhất khi chương trình hoặc thuật toán được 'kéo & xếp hàng'. Rx trội khi chương trình hoặc thuật toán cần phải 'phản ứng' với dữ liệu từ một luồng (như đầu vào chuột hoặc khi nhận được một luồng các tin nhắn liên quan từ một điểm cuối như WCF).

Bạn cần khái niệm 'đơn vị công việc' từ TPL để làm việc như hệ thống tệp, lặp qua bộ sưu tập hoặc đi bộ một hệ thống phân cấp như biểu đồ tổ chức. Trong mỗi trường hợp, lập trình viên có thể lý giải về tổng số công việc, công việc có thể được chia thành các phần của một kích thước nhất định (Nhiệm vụ), và trong trường hợp tính toán trên một hệ thống phân cấp, các nhiệm vụ có thể được 'xích' lại với nhau . Vì vậy, một số loại công việc cho bản thân họ tham gia vào mô hình Phân cấp nhiệm vụ của TPL, và được hưởng lợi từ việc cải tiến hệ thống ống nước như hủy bỏ (xem Video trên kênh 9 trên CancellationTokenSource). TPL cũng có nhiều nút bấm cho các miền chuyên biệt như xử lý dữ liệu gần thời gian thực.

Rx sẽ là những gì hầu hết các nhà phát triển nên sử dụng. Đó là cách các ứng dụng WPF có thể 'phản ứng' với các tin nhắn bên ngoài như dữ liệu bên ngoài (luồng tin nhắn IM tới ứng dụng khách IM) hoặc đầu vào bên ngoài (ví dụ như ví dụ kéo chuột được liên kết từ Aaronaught). Dưới sự bao gồm Rx sử dụng luồng nguyên thủy từ TPL/BCL, các bộ sưu tập luồng chủ đề từ TPL/BCL và các đối tượng thời gian chạy như ThreadPool. Trong tâm trí của tôi, Rx là "lập trình cao nhất" để thể hiện ý định của bạn.

Cho dù nhà phát triển trung bình có thể lấy đầu của họ được bao quanh tập hợp các ý định bạn có thể thể hiện với Rx chưa được nhìn thấy. :)

Nhưng tôi nghĩ rằng vài năm tới TPL và Rx sẽ là cuộc tranh luận tiếp theo như LINQ-to-SQL vs. Entity Framework. Có hai hương vị của API trong cùng một miền và chuyên biệt cho các kịch bản khác nhau nhưng chồng chéo theo nhiều cách. Nhưng trong trường hợp của TPL & Rx, chúng thực sự nhận biết lẫn nhau và có sẵn các adapter để tạo các ứng dụng và sử dụng cả hai khung công tác (như kết quả cho ăn từ một vòng PLINQ vào luồng RBS IObservable). Đối với những người không thực hiện bất kỳ chương trình song song nào thì có rất nhiều việc học để đạt được tốc độ.

Cập nhật: Tôi đã sử dụng cả TPL và RxNet trong công việc thường xuyên của mình trong 6 tháng qua (trong 18 tháng kể từ câu trả lời gốc). Suy nghĩ của tôi về sự lựa chọn của TPL và/hoặc RxNet trong một dịch vụ WCF bậc trung (dịch vụ LOB doanh nghiệp): http://yzorgsoft.blogspot.com/2011/09/middle-tier-tpl-andor-rxnet.html

+1

Một điều cần lưu ý là TPL và TPL Dataflow bắt đầu với giả sử bạn muốn xử lý song song. Rx theo mặc định bắt đầu là 'sự kiện phong phú', vì vậy nó làm cho bạn nhảy qua hoops để thực hiện xử lý song song (như tăng số lượng các mục đồng thời được xử lý song song). Xem ["nghĩ về IObservable như thread safe"] (http://stackoverflow.com/a/13524931/195755) và ["cách xử lý Queue không đồng bộ bằng Rx"] (http://stackoverflow.com/a/6552193/195755). Nó cũng _way quá easy_ theo ý kiến ​​của tôi để [vô tình sử dụng các hoạt động chặn trong Rx] (http://stackoverflow.com/a/2394305/195755). – yzorg