Многопоточность или параллельная библиотека задач - PullRequest
8 голосов
/ 26 марта 2010

У меня есть приложение, которое выполняет 30 независимых задач одновременно, используя многопоточность, каждая задача извлекает данные через http, выполняет вычисления и возвращает результат в поток пользовательского интерфейса.

Могу ли я использовать TPL для выполнения тех же задач?

Создает ли TPL 30 новых потоков и распределяет их по всем доступным ядрам, или он просто разделяет задачи по доступным ядрам и использует один поток на ядро?

Будет ли в этом случае повышение производительности при использовании TPL по сравнению с многопоточностью?

Ответы [ 4 ]

10 голосов
/ 26 марта 2010

Как правило, ничто не мешает TPL использовать больше (или меньше) потоков, чем ядра.

Для некоторого управления ситуацией с использованием TPL мой первый подход был бы следующим: убедитесь, что для параметра максимальное количество потоков установлено не менее 30, затем распараллелите задачу с максимальным уровнем параллелизма из 30. В рамках задачи вы можете использовать семафор, прежде чем начинать вычисления с привязкой к ЦП, чтобы ограничить параллелизм количеством ядер. Если вы не используете IIS или SQL-сервер, вы можете и, возможно, захотите установить минимальное / максимальное количество потоков пула потоков равным 30, чтобы избежать слишком большого количества эвристических операций пула потоков с количеством потоков. (Разумеется, при условии, что TPL и пул потоков не будут использоваться для других целей в течение этого времени в вашем приложении.)

Оптимальное количество потоков зависит от ситуации. Рассмотрим, например, ваш сценарий: ваши задачи не связаны с процессором, когда они получают данные - они связаны с сетью. Когда вы начнете выполнять задачи, было бы разумно увеличить параллелизм, чтобы загрузки выполнялись одновременно. Однако ваши вычисления могут быть связаны с процессором. В этом случае уменьшение количества потоков, так что на каждое ядро ​​может работать только один поток, может повысить производительность.

TPL теперь основан на новом пуле потоков CLR .
Пул потоков использует эвристику для определения количества потоков.
Существует Channel9 видео о новом пуле потоков с некоторой проницательностью.
Эвристику старого пула потоков и некоторые сведения о новом можно найти здесь (последний абзац "Что нас ждет в будущем?") .

Алгоритм и числа были изменены в разных версиях CLR.
Это может произойти и в будущем.

Есть много постов об уровне параллелизма, один из которых я наткнулся на здесь .

9 голосов
/ 26 марта 2010

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

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

С точки зрения эффективности, ваше приложение на самом деле связано с процессором? Похоже, вам нужно получить максимально подходящий уровень параллелизма на стороне сети - это то, на чем стоит сконцентрироваться, если только вычисления не являются действительно тяжелыми.


ОБНОВЛЕНИЯ - НЕ ОТ ОРИГИНАЛЬНОГО АВТОРА

Ответ выше, как всегда, великолепен, но может вводить в заблуждение, поскольку в нем нет важных изменений в .NET 4.0 CLR.

Как говорит Андрас, текущая реализация TPL использует пул потоков, следовательно, будет использовать столько потоков, сколько требуется ( количество ядер не имеет значения ):

Task Parallel Library (TPL) - это коллекция новых классов специально разработанный, чтобы сделать его проще и эффективнее выполнять очень мелкозернистые параллельные рабочие нагрузки на современном оборудовании. TPL был доступен отдельно в виде ОСАГО в течение некоторого времени и был включен в Visual Studio 2010 CTP, но в тех версиях он был построен на его собственный выделенный рабочий планировщик . Для бета-версии 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

2 голосов
/ 16 мая 2010

У меня есть приложение, которое выполняет 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

Это решение никогда не блокирует поток, поэтому оно полностью параллельное.

0 голосов
/ 26 марта 2010

Вы порождаете 30 потоков? Вы используете пул потоков? Я верю, что вы будете гораздо более оптимизированы. Нерестовые нити - довольно дорогая операция. Я согласен с Джоном, что tpl обычно использует один поток на ядро. О какой .NET-версии мы говорим здесь b.t.w.

...