Как Reactive Framework, PLINQ, TPL и Parallel Extensions связаны друг с другом? - PullRequest
63 голосов
/ 26 января 2010

По крайней мере, с момента выпуска .NET 4.0 Microsoft, похоже, приложила немало усилий для поддержки параллельного и асинхронного программирования, и, похоже, появилось много API и библиотек для этого. Особенно следующие модные имена постоянно упоминаются везде в последнее время:

  • Reactive Framework,
  • PLINQ (Parallel LINQ),
  • TPL (библиотека параллельных задач) и
  • Параллельные расширения.

Теперь все они кажутся продуктами Microsoft, и, похоже, все они нацелены на сценарии асинхронного или параллельного программирования для .NET. Но не совсем ясно, что каждый из них на самом деле и как они связаны друг с другом. Некоторые из них могут быть одним и тем же.

В двух словах, кто-нибудь может поставить точку в том, что к чему?

Ответы [ 2 ]

94 голосов
/ 30 января 2010

PLINQ (Parallel Linq) - это просто новый способ написания обычных запросов Linq, чтобы они выполнялись параллельно - другими словами, Framework автоматически позаботится о выполнении вашего запроса в нескольких потоках, чтобы они заканчиваются быстрее (то есть с использованием нескольких процессорных ядер).

Например, допустим, у вас есть куча строк, и вы хотите получить все те, которые начинаются с буквы «А». Вы можете написать свой запрос так:

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

И это прекрасно работает. Однако если у вас есть 50 000 слов для поиска, вы можете воспользоваться тем фактом, что каждый тест является независимым, и разделить его на несколько ядер:

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

Это все, что вам нужно сделать, чтобы превратить обычный запрос в параллельный, который выполняется на нескольких ядрах. Довольно аккуратно.


TPL (библиотека параллельных задач) является своего рода дополнением к PLINQ, и вместе они составляют параллельные расширения. В то время как PLINQ в значительной степени основан на стиле функционального программирования с побочными эффектами no , побочные эффекты - это как раз то, для чего предназначен TPL. Если вы хотите на самом деле работать параллельно, а не просто искать / выбирать вещи параллельно, используйте TPL.

TPL - это, по существу, класс Parallel, который предоставляет перегрузки For, Foreach и Invoke. Invoke немного похож на постановку в очередь задач в ThreadPool, но немного проще в использовании. ИМО, более интересные биты это For и Foreach. Например, предположим, у вас есть целая куча файлов, которые вы хотите сжать. Вы можете написать обычную последовательную версию:

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);
}

Опять же, каждая итерация этого сжатия полностью независима от любой другой. Мы можем ускорить это, выполнив несколько из них одновременно:

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

И снова, это все, что нужно для распараллеливания этой операции. Теперь, когда мы запустим наш метод CompressFiles (или как мы его назовем), он будет использовать несколько ядер ЦП и, вероятно, закончится в два раза или в 1/4 раза.

Преимущество этого по сравнению с простым бросанием всего этого в ThreadPool состоит в том, что на самом деле работает синхронно . Если бы вы использовали ThreadPool вместо (или просто Thread экземпляров), вам нужно было бы найти способ узнать, когда все задачи завершены, и хотя это не ужасно сложно, это то, что многие люди, как правило, портят или, по крайней мере, имеют проблемы. Когда вы используете класс Parallel, вам не нужно об этом думать; многопоточность скрыта от вас, все это обрабатывается за кулисами.


Реактивные расширения (Rx) - это совсем другое животное. Это другой способ думать об обработке событий. Об этом действительно много материала, но, если коротко, вместо того, чтобы подключать обработчики событий к событиям, Rx позволяет вам обрабатывать последовательности событий как ... ну, последовательности (IEnumerable<T>). Вы получаете возможность обрабатывать события итеративным способом, а не запускать их асинхронно в случайные моменты времени, когда вам необходимо постоянно сохранять состояние, чтобы обнаружить серию событий, происходящих в определенном порядке.

Один из самых крутых примеров, которые я нашел для Rx, это здесь . Перейдите к разделу «Linq to IObservable», где он реализует обработчик перетаскивания, который обычно является проблемой в WPF, всего за 4 строки кода. Rx дает вам состав событий, чего у вас нет на самом деле с обычными обработчиками событий, и фрагменты кода, подобные этим, также просты для рефакторинга в классы поведения, которые вы можете использовать в любом месте.


И это все. Вот некоторые из функций кулера, которые доступны в .NET 4.0. Конечно, есть еще несколько, но о них вы спрашивали!

29 голосов
/ 03 февраля 2010

Мне нравится ответ Аарона, но я бы сказал, что Rx и TPL решают разные проблемы. Часть того, что добавила команда TPL, - это потоковые примитивы и значительные улучшения для строительных блоков среды выполнения, таких как ThreadPool. И все, что вы перечисляете, построено на основе этих примитивов и функций времени выполнения.

Но TPL и Rx решают две разные проблемы. TPL работает лучше всего, когда программа или алгоритм «вытягивают и ставят в очередь». Rx превосходит, когда программе или алгоритму нужно «реагировать» на данные из потока (например, ввод с помощью мыши или при получении потока связанных сообщений от конечной точки, такой как WCF).

Вам понадобится концепция «единицы работы» из TPL, чтобы работать как файловая система, перебирать коллекцию или проходить иерархию, например, организационную диаграмму. В каждом из этих случаев программист может рассуждать об общем объеме работы, работа может быть разбита на куски определенного размера (Задачи), а в случае выполнения вычислений по иерархии задачи могут быть «объединены» в цепочку. , Таким образом, определенные виды работ поддаются модели TPL «Иерархия задач» и получают выгоду от таких улучшений, как отмена (см. Видео 9-го канала на CancellationTokenSource). TPL также имеет множество ручек для специализированных доменов, таких как обработка данных практически в реальном времени.

Rx будет тем, что большинство разработчиков должно использовать в конечном итоге. Это то, как приложения WPF могут «реагировать» на внешние сообщения, такие как внешние данные (поток сообщений IM для клиента IM) или внешний ввод (как пример перетаскивания мышью, связанный с Aaronaught). Под покровами Rx используются потоковые примитивы из TPL / BCL, потоковые коллекции из TPL / BCL и объекты времени выполнения, такие как ThreadPool. На мой взгляд, Rx - это «высший уровень» программирования для выражения ваших намерений.

Может ли среднестатистический разработчик сосредоточиться на наборе намерений, которые вы можете выразить с помощью Rx, еще неизвестно. :)

Но я думаю, что в ближайшие пару лет TPL vs. Rx станут следующими дебатами, такими как LINQ-to-SQL против Entity Framework. Существует два варианта API в одном и том же домене, и они специализируются для разных сценариев, но во многом пересекаются. Но в случае TPL & Rx они фактически знают друг о друге, и есть встроенные адаптеры для создания приложений и совместного использования обеих платформ (например, передача результатов из цикла PLINQ в поток IObservable Rx). Для тех, кто не занимался параллельным программированием, есть тонна обучения, чтобы набрать скорость.

Обновление: я использую и TPL, и RxNet в своей обычной работе в течение последних 6 месяцев (из 18 месяцев с момента моего первоначального ответа). Мои мысли о выборе TPL и / или RxNet в сервисе WCF среднего уровня (сервис корпоративного объекта): http://yzorgsoft.blogspot.com/2011/09/middle-tier-tpl-andor-rxnet.html

...