Должен ли я использовать ThreadPools или Task Parallel Library для операций ввода-вывода - PullRequest
76 голосов
/ 07 марта 2011

В одном из моих проектов, который является своего рода агрегатором, я анализирую фиды, подкасты и т. Д. Из Интернета.

Если я использую последовательный подход, учитывая большое количество ресурсов, это займет довольно много времени дляобрабатывать их все (из-за проблем с сетью и тому подобного);

foreach(feed in feeds)
{
   read_from_web(feed)
   parse(feed)
}

Поэтому я хочу реализовать параллелизм и не могу решить, должен ли я в основном использовать ThreadPools для обработки с рабочими потоками или просто полагаться на TPLчтобы разобраться в этом.

ThreadPools наверняка справится со мной с помощью рабочих потоков, и я получу то, что ожидаю (и в средах с многоядерными процессорами также будут использоваться и другие ядра).

concurrency

Но я все еще хочу рассмотреть TPL, так как это рекомендуемый метод, но я немного обеспокоен этим.Прежде всего я знаю, что TPL использует ThreadPools, но добавляет дополнительный уровень принятия решений.Меня больше всего беспокоит состояние, когда присутствует одноядерная среда.Если я не ошибаюсь, TPL начинается с количества рабочих потоков, равного количеству доступных процессорных ядер в самом начале.Я боюсь, что TPL даст результаты, аналогичные последовательному подходу для моего случая, связанного с IO.

Так что для операций, связанных с IO (в моем случае чтение ресурсов из Интернета), лучше всего использовать ThreadPools и контролировать вещиили лучше просто положиться на TPL?Может ли TPL также использоваться в сценариях, связанных с вводом-выводом?

Обновление : Моя главная проблема заключается в том, что - в одноядерном процессоре среда будет работать так же, как TPLпоследовательный подход или он все еще будет предлагать параллелизм?Я уже читаю Параллельное программирование с Microsoft .NET и, таким образом, book , но не смог найти точный ответ для этого.

Примечание: это повтор-фразировка моего предыдущего вопроса [ Возможно ли использовать параллелизм потоков и параллелизм вместе? ], что было совершенно неправильно сформулировано.

Ответы [ 6 ]

105 голосов
/ 07 марта 2011

Поэтому я решил написать для этого тесты и посмотреть их на практических данных.

Тестовая легенда

  • Itr: итерация
  • Seq: последовательный подход.
  • PrlEx: параллельные расширения - Parallel.ForEach
  • TPL: библиотека параллельных задач
  • TPool: ThreadPool

Результаты теста

Одноядерный CPU [Win7-32] - работает под управлением VMWare -

Test Environment: 1 physical cpus, 1 cores, 1 logical cpus.
Will be parsing a total of 10 feeds.
________________________________________________________________________________

Itr.    Seq.    PrlEx   TPL     TPool
________________________________________________________________________________

#1      10.82s  04.05s  02.69s  02.60s
#2      07.48s  03.18s  03.17s  02.91s
#3      07.66s  03.21s  01.90s  01.68s
#4      07.43s  01.65s  01.70s  01.76s
#5      07.81s  02.20s  01.75s  01.71s
#6      07.67s  03.25s  01.97s  01.63s
#7      08.14s  01.77s  01.72s  02.66s
#8      08.04s  03.01s  02.03s  01.75s
#9      08.80s  01.71s  01.67s  01.75s
#10     10.19s  02.23s  01.62s  01.74s
________________________________________________________________________________

Avg.    08.40s  02.63s  02.02s  02.02s
________________________________________________________________________________

Одноядерный CPU [WinXP] -работает под управлением VMWare -

Test Environment: 1 physical cpus, NotSupported cores, NotSupported logical cpus.
Will be parsing a total of 10 feeds.
________________________________________________________________________________

Itr.    Seq.    PrlEx   TPL     TPool
________________________________________________________________________________

#1      10.79s  04.05s  02.75s  02.13s
#2      07.53s  02.84s  02.08s  02.07s
#3      07.79s  03.74s  02.04s  02.07s
#4      08.28s  02.88s  02.73s  03.43s
#5      07.55s  02.59s  03.99s  03.19s
#6      07.50s  02.90s  02.83s  02.29s
#7      07.80s  04.32s  02.78s  02.67s
#8      07.65s  03.10s  02.07s  02.53s
#9      10.70s  02.61s  02.04s  02.10s
#10     08.98s  02.88s  02.09s  02.16s
________________________________________________________________________________

Avg.    08.46s  03.19s  02.54s  02.46s
________________________________________________________________________________

Двухъядерный процессор [Win7-64]

Test Environment: 1 physical cpus, 2 cores, 2 logical cpus.
Will be parsing a total of 10 feeds.
________________________________________________________________________________

Itr.    Seq.    PrlEx   TPL     TPool
________________________________________________________________________________

#1      07.09s  02.28s  02.64s  01.79s
#2      06.04s  02.53s  01.96s  01.94s
#3      05.84s  02.18s  02.08s  02.34s
#4      06.00s  01.43s  01.69s  01.43s
#5      05.74s  01.61s  01.36s  01.49s
#6      05.92s  01.59s  01.73s  01.50s
#7      06.09s  01.44s  02.14s  02.37s
#8      06.37s  01.34s  01.46s  01.36s
#9      06.57s  01.30s  01.58s  01.67s
#10     06.06s  01.95s  02.88s  01.62s
________________________________________________________________________________

Avg.    06.17s  01.76s  01.95s  01.75s
________________________________________________________________________________

Четырехъядерный процессор [Win7-64] - Поддерживается HyprerThreading -

Test Environment: 1 physical cpus, 4 cores, 8 logical cpus.
Will be parsing a total of 10 feeds.
________________________________________________________________________________

Itr.    Seq.    PrlEx   TPL     TPool
________________________________________________________________________________

#1      10.56s  02.03s  01.71s  01.69s
#2      07.42s  01.63s  01.71s  01.69s
#3      11.66s  01.69s  01.73s  01.61s
#4      07.52s  01.77s  01.63s  01.65s
#5      07.69s  02.32s  01.67s  01.62s
#6      07.31s  01.64s  01.53s  02.17s
#7      07.44s  02.56s  02.35s  02.31s
#8      08.36s  01.93s  01.73s  01.66s
#9      07.92s  02.15s  01.72s  01.65s
#10     07.60s  02.14s  01.68s  01.68s
________________________________________________________________________________

Avg.    08.35s  01.99s  01.75s  01.77s
________________________________________________________________________________

Суммирование

  • Работаете ли вы в одноядерной среде или на несколькихосновной, Parallel Extensions, TPL и ThreadPool ведет себя одинаково и дает приблизительные результаты .
  • Тем не менее TPL имеет преимущества как легкий обработка исключений, поддержка отмены и возможность легко возвращать результаты Задачи .Хотя Parallel Extensions также является другой жизнеспособной альтернативой.

Запуск тестов самостоятельно

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

Обновление: исправлена ​​ссылка на источник.

15 голосов
/ 08 марта 2011

Если вы пытаетесь максимизировать пропускную способность для задач, связанных с вводом-выводом, вы абсолютно должны объединить традиционные API модели асинхронной обработки (APM) с работой на основе TPL.API APM - единственный способ разблокировать поток ЦП, пока асинхронный обратный вызов ввода-вывода еще не завершен.TPL предоставляет TaskFactory::FromAsync вспомогательный метод для помощи в комбинировании кода APM и TPL.

Ознакомьтесь с этим разделом .NET SDK для MSDN под названием TPL и традиционный .NET.Асинхронное программирование для получения дополнительной информации о том, как объединить эти две модели программирования для достижения асинхронной нирваны.

2 голосов
/ 07 марта 2011

Вы правы в том, что TPL удаляет некоторые элементы управления, которые есть у вас, когда вы создаете свой собственный пул потоков. Но это только правильно, если вы не хотите копать глубже. TPL позволяет вам создавать долгосрочные Задачи, которые не являются частью пула потоков TPL и могут хорошо служить вашей цели. Опубликованная книга, которая является бесплатным для чтения Параллельное программирование с Microsoft .NET , даст вам гораздо больше понимания того, как TPL должен использоваться. У вас всегда есть возможность указать Parallels. Задачи явные Параметры, сколько потоков должно быть выделено. Кроме того, вы можете заменить планировщик TPL своим собственным, если хотите получить полный контроль.

1 голос
/ 07 марта 2011

Вы можете назначить свой собственный планировщик задач для задачи TPL.По умолчанию работа ворует один довольно умный, хотя.

0 голосов
/ 06 декабря 2016

Если вы распараллелите свои обращения к URL-адресам, я думаю, что это улучшит ваше приложение, даже если у вас будет только одно ядро.Посмотрите на этот код:

var client = new HttpClient();
var urls = new[]{"a", "url", "to", "find"};

// due to the EAP pattern, this will run in parallel.
var tasks = urls.Select(c=> client.GetAsync(c));

var result = Tasks.WhenAll(task).ContinueWith(a=> AnalyzeThisWords(a.Result));
result.Wait(); // don't know if this is needed or it's correct to call wait

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

При использовании EAP количество задач не связанос количеством потоков.

Поскольку вы полагаетесь на задачу GetAsync, http-клиент использует сетевой поток (сокет, tcp-клиент или любой другой) и сигнализирует его, чтобы вызвать событие, когда BeginRead / EndRead выполнен,Таким образом, в этот момент не участвуют никакие потоки.

После вызова завершения может быть создан новый поток, но это до TaskScheduler (используется при вызове GetAsync / ContinueWith) для создания нового потока, используйтесуществующий поток или встроенное задание для использования вызывающего потока.

Если AnalyzeThisWords блокируется слишком много времени, вы начинаете получать узкие места, поскольку «обратный вызов» в ContinueWith выполняется из пула потоковработник.

0 голосов
/ 07 марта 2011

Я боюсь, что TPL даст результаты, аналогичные последовательному подходу для моего случая, связанного с IO.

Я думаю, что так и будет. Что является узким местом? Это анализ или загрузка? Многопоточность не сильно поможет при загрузке из Интернета.

Я бы использовал Task Parallel Library для обрезки, применения маски или эффектов для загруженных изображений, вырезания некоторых образцов из подкаста и т. Д. Это более масштабируемо.

Но это не будет на порядок быстрее. Потратьте свои ресурсы на реализацию некоторых функций, тестирование.

PS. "Ух ты, моя функция работает за 0,7 с вместо 0,9";)

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