У меня есть приложение, которое выполняет 30 независимых задач одновременно с помощью многопоточности, каждая задача получает данные по http, выполняет вычисление и возвращает результат потоку ui.
Я могу использовать TPL для выполнения тех же задач?
TPL создает 30 новых потоков и распространять их по всем доступным ядрам, или он просто разделяет задачи по доступным ядрам и использует один поток на ядро?
Будет повышение производительности с помощью TPL по многопоточности в этом случае?
Я считаю, что TPL обычно использует один поток на ядро, если вы специально не укажете ему использовать больше. Возможно возможно , что он обнаружит, когда этого недостаточно - например, в вашем случае, когда ваши задачи будут проводить большую часть времени в ожидании данных.
По какой-либо причине вы не можете использовать асинхронную веб-загрузку? Я подозреваю, что здесь нет необходимости иметь поток на задачу или даже поток на ядро. TPL упрощает различные аспекты асинхронного программирования с помощью таких вещей, как продолжения.
С точки зрения эффективности, ваше приложение действительно ограничено процессором? Похоже, вам нужно получить максимально подходящий уровень параллелизма на сетевой стороне - это то, на чем следует сосредоточиться, если только вычисления не являются действительно тяжелыми.
Приведенный выше ответ как всегда хорош, но может ввести в заблуждение, поскольку он не содержит некоторых важных изменений в .NET 4.0 CLR.
Как говорит Андрас, текущая реализация TPL использует пул потоков, следовательно, будет использовать столько потоков, сколько требуется ( количество ядер сейчас не имеет значения ):
Библиотека параллельных задач (TPL) - это коллекция новых классов , специально разработанных для упрощения и повышения эффективности выполнения очень мелких параллельных рабочих нагрузок на современном оборудовании. TPL уже некоторое время доступен отдельно как CTP и был включен в CTP Visual Studio 2010, но в этих выпусках он был построен на его {{ 1}} собственный выделенный планировщик работы . Для Beta 1 CLR 4.0 планировщиком по умолчанию для TPL будет пул потоков CLR , что позволяет рабочим нагрузкам в стиле TPL "хорошо играть" с существующими, QUWI. на основе кода и позволяет нам повторно использовать большую часть базовой технологии в пуле потоков - в частности, алгоритм внедрения потоков, который мы обсудим в будущем Почта.
Источник:
http://blogs.msdn.com/b/ericeil/archive/2009/04/23/clr-4-0-threadpool-improvements-part-1.aspx
Как правило, ничто не мешает TPL использовать больше (или меньше) потоков, чем ядра.
Чтобы немного контролировать ситуацию с помощью TPL, мой первый подход: убедиться, что параметр максимального количества потоков пула потоков составляет не менее 30, затем распараллелить задачу с максимальным уровнем параллелизма ] из 30. В задаче вы можете использовать семафор перед запуском вычислений с привязкой к ЦП, чтобы ограничить параллелизм числом ядер. Если вы не работаете под IIS или SQL-сервером, вы можете и, возможно, захотите установить минимальное / максимальное количество потоков пула потоков равным 30, чтобы предотвратить чрезмерное влияние эвристики пула потоков на количество потоков. (При условии, конечно, что TPL и пул потоков не используются для других целей в течение этого времени в вашем приложении.)
Оптимальное количество потоков зависит от ситуации. Рассмотрим, например, ваш сценарий: ваши задачи не привязаны к ЦП при извлечении данных - они привязаны к сети. При запуске задач было бы разумно увеличить параллелизм, чтобы загрузки выполнялись одновременно. Однако ваши расчеты могут быть связаны с процессором. В этом случае уменьшение количества потоков так, чтобы на каждом ядре выполнялся только один поток, может повысить производительность.
TPL теперь основан на новом пуле потоков CLR .
Пул потоков использует эвристику для определения количества потоков.
Есть видео Channel9 о новом пуле потоков с некоторой информацией.
Эвристику старого пула потоков и некоторые сведения о новом можно найти здесь (последний абзац «Что ждет в будущем?») .
Алгоритм и числа подвергались изменениям в разных версиях CLR.
Возможно, так будет и в будущем.
Есть много сообщений об уровне параллелизма, я наткнулся на здесь .
Вы порождаете 30 потоков? Используете ли вы пул потоков? Я полагаю, что tpl будет гораздо более оптимизированным. Порождение потоков - довольно дорогая операция. Я согласен с Джоном, что tpl обычно использует один поток на ядро. О какой версии .NET идет речь b.t.w.
У меня есть приложение, которое выполняет 30 независимых задач одновременно с использованием многопоточности, каждая задача извлекает данные через http, выполняет вычисления и возвращает результат в поток пользовательского интерфейса.
Это параллельная программа с привязкой к вводу-выводу.
Могу ли я использовать TPL для выполнения тех же задач?
Можно, но TPL разработан для параллельных программ с привязкой к ЦП, поэтому вы будете злоупотреблять им.
Создает ли TPL 30 новых потоков и распределяет их по всем доступным ядрам, или он просто разделяет задачи по доступным ядрам и использует один поток на каждое ядро?
Ни то, ни другое. TPL, по сути, использует очереди задач с перехватом работы без ожидания для каждого ядра для динамической балансировки нагрузки вычислений, интенсивно использующих ЦП, по мере их выполнения.
Будет ли в этом случае прирост производительности при использовании TPL по сравнению с многопоточностью?
Вы сэкономите 30 созданий потоков и дополнительную конкуренцию, вызванную вашими ненужными потоками.
Правильное решение вашей проблемы - написать асинхронную программу, которая не блокирует потоки. Это делается путем выражения оставшейся части ваших вычислений после завершения загрузки в виде продолжения, которое вызывается с данными после завершения загрузки.
Новый язык программирования Microsoft F # включает функции, специально разработанные для упрощения этой задачи. Например, ваша проблема может быть решена с помощью всего 5 строк кода на F #:
let fetchCalcAndPost uris calc post =
for uri in uris do
async { use client = new System.Net.WebClient()
let! data = client.AsyncDownloadString uri
do calc data |> post }
|> Async.Start
Это решение никогда не блокирует ни один поток, поэтому он полностью параллелен.