+7 (495) 229-0436   shopadmin@itshop.ru 119334, г. Москва, ул. Бардина, д. 4, корп. 3
 
 
Вход
 
 
Каталог
 
 
Подписка на новости
Новости ITShop
Windows 7 и Office: Новости и советы
Обучение и сертификация Microsoft
Вопросы и ответы по MSSQLServer
Delphi - проблемы и решения
Adobe Photoshop: алхимия дизайна
 
Ваш отзыв
Оцените качество магазина ITShop.ru на Яндекс.Маркете. Если вам нравится наш магазин - скажите об этом Google!
 
 
Способы оплаты
 
Курс расчета
 
 1 у.е. = 94.09 руб.
 
 Цены показывать:
 
 
 
 
  
Новости, статьи, акции
 

Краткий обзор Parallel Extensions для .NET Framework

12.01.2010 11:50

Сейчас никого не удивишь наличием нескольких ядер в процессоре, будь то рабочая станция, ноутбук, нетбук - неважно. Дальше - больше: "двухголовые" процессоры скоро обоснуются и в мобильных телефонах. Вот почему именно сейчас тема распараллеливания программ перестаёт быть академической и приобретает вполне практический интерес. Разумеется, при создании такого ПО есть ряд подводных камней. Кроме того, не всё и не всегда можно и нужно распараллеливать - но это тема отдельного разговора. Цель этой статьи - сделать экскурс в область инструментов от компании Microsoft для создания распараллеленных управляемых приложений.

Итак, Parallel Extensions, как можно догадаться по названию, это как раз и есть тот самый набор инструментов, призванный повысить эффективность применения новых аппаратных средств. Впервые в общем доступе библиотека появилась в ноябре 2007 года и имела статус CTP. В июне 2008 года появилась новая preview-версия. Обе они использовали .NET 3.5 для своей работы, и поставлялись в виде отдельной сборки. Однако осенью прошлого года с выходом Visual Studio 2010 CTP этот инструментарий переехал в сборку mscorlib и стал использовать .NET 4. С тех пор ничего не поменялось, и новых версий для .NET 3.5 не выпускалось. В течение всего этого времени менялся состав библиотеки, её API. Наиболее актуальная версия не так давно выпущена в составе .NET 4 beta 2. Вы можете скачать Visual Studio 2010 beta 2 и попробовать библиотеку своими руками.

Схематически состав Parallel Extensions можно изобразить следующим образом:

.NET 4 несёт весомое количество изменений. Они коснулись в том числе и принципа работы пула потоков. Его оптимизировали для управления большим числом рабочих потоков, и поменяли реализацию очереди задания для каждого из них. Теперь кроме глобальной очереди задач каждый поток имеет свою локальную очередь. Это позволяет более эффективно управлять задачами. Например, первый поток выполняет очередную задачу, а второй успел опустошить свою очередь. Тогда он может "украсть" задачу из очереди первого потока, тем самым распределив нагрузку. При этом не будет обращения к глобальной очереди задач, что уменьшит нагрузку на неё. Эти действия будут прозрачны для прикладного программиста.

Если внимательно присмотреться к предыдущему абзацу, можно заметить ключевое слово "задача". Оно знаменует один из подходов к упрощению распараллеливания программ. Библиотека Parallel Extensions предлагает сосредоточить внимание на реализуемом бизнес-сценарии. Слово "поток" относится к технической реализации. "Задача" же представляет собой некоторое атомарное действие, выполнение которого позволит получить результат. При этом не рассматривается, кем и где будет выполнена задача. Важнее то, как она реализуется и как соотносится с другими задачами. Такова концепция, положенная в основе Task Parallel Library (кратко TPL) - набора инструментов для создания, управления и выполнения задач. При этом TPL использует механизмы обновленного пула потоков для запуска и завершения задач. Фактически, задача представляет собой некую асинхронную операцию в контексте нашей программы. Конечно, в .NET 2.0 были QueueUserWorkItem(), BackgroundWorker и др. средства. С их помощью можно было достичь нужного функционала, что все мы с вами успешно делали. Но TPL предоставляет уже готовый, до некоторой степени универсальный подход. Это уменьшает затраты на распараллеливание, что в конечном счёте делает проект дешевле по экономическим и временным показателям.

На основе Task Parallel Library и концепции "задач" работают прикладные средства по распараллеливанию. Среди них - PLINQ, т.е. Parallel LINQ. Эта часть библиотеки Parallel Extensions, позволяющая выполнять LINQ запросы одновременно в нескольких потоках. Изюминка её заключается в очень простом способе интеграции с уже имеющимся кодом. Не придется снова переписывать кучу запросов на новый лад. Можно просто вызвать метод-расширение AsParallel(), и теперь LINQ запрос будет выполнен параллельно:

Последовательная версия  Параллельная версия 
from i in collection from i in collection.AsParallel()
where IsValid(i) where IsValid(i)
select i; select i;

Разумеется, возникает много интересных моментов - например, в нашем примере никто не знает, в каком порядке элементы будут обработаны при параллельном исполнении. Есть свои особенности, связанные с обработкой исключений. Опять же, не всякий LINQ-запрос есть смысл распараллеливать. Как всегда, нужно правильно оценивать ситуацию и действовать по обстоятельствам. Но наличие такой легкой возможности распараллелить процесс выполнения, безусловно, радует. Ещё одним преимуществом PLINQ является масштабируемость. Поясню: запрос будет выполнен настолько быстро, насколько это можно в данной конкретной среде. Наша программа без перекомпиляции и без внесения каких-либо изменений будет работать с эффективностью 1х на одноядерной машине, 1,8х-1,9х на двухядерной, 3,7х-3,8х на четырехядерной и т.д. (числа приведены приблизительные, для сравнения; реальная разница, конечно, зависит от задачи и способа её реализации). Т.е. чем более мощное оборудование будет использовано, тем быстрее выполнится запрос. PLINQ физически является набором методов-расширений, работающих с System.Linq.ParallelQuery<T>.

Кроме того, Parallel Extensions содержит несколько конструкций, облегчающих создание распараллеленных циклов и запуск множества делегатов одновременно. Это набор статических методов класса Parallel. Их много, но большинство являются перегруженными версиями следующих трёх:

  • Parallel.For() - метод позволяет выполнить делегат параллельно в несколько потоков заданное количество итераций;
  • Parallel.ForEach() - параллельно выполняет делегат над элементами коллекции IEnumerable<TSource>;
  • Parallel.Invoke() - принимает набор делегатов Action и обеспечивает их одновременное выполнение

Разные версии этих методов содержат дополнительные параметры, с помощью которых можно указать, например, степень параллелизма, маркер отмены и т.д. Давайте рассмотрим несколько простых примеров. Предположим, есть следующий цикл foreach:

Код:
IEnumerable<string> collection =
    new[] { "The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"};

foreach (var word in collection)
{
    ProcessString(word);
}

Чтобы перевести этот цикл на "параллельные рельсы", достаточно заменить его вызовом:

Код:
Parallel.ForEach(collection, (word) => { ProcessString(word); });

Теперь обработка слов будет выполнена параллельно. Каждый вызов Parallel.For() и Parallel.ForEach() генерирует определённое количество задач, в зависимости от текущего окружения, после чего передаёт их для выполнения рабочим потокам. Т.о., цикл будет выполнен настолько быстро, насколько это возможно.

А вот так можно ограничить степень параллелизма:

Код:
ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = 4;

Parallel.For(0, 100, options, (i) => { ProcessItem(i); });

Как видите, используется перегруженная версия Parallel.For(), принимающая настройки (ParallelOptions). 

В довесок пример обхода дерева следующего вида:

Код:
class Tree<T>
{
    public T Data;
    public Tree<T> Left, Right;
   // ...
}

Последовательно это можно сделать следующим образом:

Код:
static void WalkTree<T>(Tree<T> tree, Action<T> func)
{
    if (tree == null) return;
    WalkTree(tree.Left, func);
    WalkTree(tree.Right, func);
    func(tree.Data);
}

Однако, если вычисления не зависят от порядка обработки узлов, то можно легко распараллелить процесс:

Код:
static void WalkTree<T>(Tree<T> tree, Action<T> func)
{
    if (tree == null) return;
    Parallel.Invoke(
        () => WalkTree(tree.Left, func),
        () => WalkTree(tree.Right, func),
        () => func(tree.Data));
}

Указываем набор делегатов, а именно проход по левому и правому потомкам текущего узла, и обработку текущего в качестве параметров Parallel.Invoke() и радуемся возросшей производительности. Надо отметить, что Parallel.Invoke() также поддерживает указание ParallelOptions, для этого есть соответствующий перегруженный метод.

В довесок к этому Parallel Extensions предоставляет весьма удобные хранилища данных с возможностью конкурентного доступа и набор примитивов синхронизации. Это выглядит совершенно логично: выполняя действия в нескольких потоках, неплохо было бы иметь где-либо результат работы. У меня есть 2 большие статьи, в которых проводится обзор этих структур данных, предлагаю всем заинтересовавшимся их прочитать:

часть 1

и

часть 2

. Здесь я не стану подробно на них останавливаться.

Итак, подведем итог. То, что компания Microsoft уделила большое внимание вопросам параллельного выполнения кода, весьма радует. Инструментарий, на мой взгляд, получился достаточно удобным в использовании и довольно простым. Вообще, малый входной порог - один из козырей Parallel Extensions. Концепция и API прозрачны и понятны. Мы получили (я говорю именно "получили", поскольку уже сейчас вышла GoLive лицензия на VS 2010 beta 2, позволяющая строить коммерческие приложения на её основе) удобную библиотеку, которая позволит минимизировать расходы на распараллеливание.

Ссылки по теме

  
Помощь
Задать вопрос
 программы
 обучение
 экзамены
 компьютеры
Бесплатный звонок
ICQ-консультанты
Skype-консультанты

Общая справка
Как оформить заказ
Тарифы доставки
Способы оплаты
Прайс-лист
Карта сайта
 
Бестселлеры
Курсы обучения "Atlassian JIRA - система управления проектами и задачами на предприятии"
Microsoft Windows 10 Профессиональная 32-bit/64-bit. Все языки. Электронный ключ
Microsoft Office для Дома и Учебы 2019. Все языки. Электронный ключ
Курс "Oracle. Программирование на SQL и PL/SQL"
Курс "Основы TOGAF® 9"
Microsoft Office 365 Персональный 32-bit/x64. 1 ПК/MAC + 1 Планшет + 1 Телефон. Все языки. Подписка на 1 год. Электронный ключ
Курс "Нотация BPMN 2.0. Ее использование для моделирования бизнес-процессов и их регламентации"
 

О нас
Интернет-магазин ITShop.ru предлагает широкий спектр услуг информационных технологий и ПО.

На протяжении многих лет интернет-магазин предлагает товары и услуги, ориентированные на бизнес-пользователей и специалистов по информационным технологиям.

Хорошие отзывы постоянных клиентов и высокий уровень специалистов позволяет получить наивысший результат при совместной работе.

В нашем магазине вы можете приобрести лицензионное ПО выбрав необходимое из широкого спектра и ассортимента по самым доступным ценам. Наши менеджеры любезно помогут определиться с выбором ПО, которое необходимо именно вам. Также мы проводим учебные курсы. Мы приглашаем к сотрудничеству учебные центры, организаторов семинаров и бизнес-тренингов, преподавателей. Сфера сотрудничества - продвижение бизнес-тренингов и курсов обучения по информационным технологиям.



 

О нас

 
Главная
Каталог
Новинки
Акции
Вакансии
 

Помощь

 
Общая справка
Как оформить заказ
Тарифы доставки
Способы оплаты
Прайс-лист
Карта сайта
 

Способы оплаты

 

Проекты Interface Ltd.

 
Interface.ru   ITShop.ru   Interface.ru/training   Olap.ru   ITnews.ru  
 

119334, г. Москва, ул. Бардина, д. 4, корп. 3
+7 (495) 229-0436   shopadmin@itshop.ru
Проверить аттестат
© ООО "Interface Ltd."
Продаем программное обеспечение с 1990 года