PLinq по своей природе быстрее, чем System.Threading.Tasks.Parallel.ForEach - PullRequest
7 голосов
/ 04 марта 2011

Сводка : я изменил структуру System.Threading.Tasks.Parallel.ForEach и Concurrent Data на простой запрос plinq (Parallel Linq). Скорость была удивительно .

Так что, по сути, plinq быстрее, чем Parallel.ForEach? Или это специфично для задачи.

// Original Code
// concurrent dictionary to store results
var resultDict = new ConcurrentDictionary<string, MyResultType>();

Parallel.ForEach(items, item =>
        {
            resultDict.TryAdd(item.Name, PerformWork(source));
        });


// new code

var results =
            items
            .AsParallel()
            .Select(item => new { item.Name, queryResult = PerformWork(item) })
            .ToDictionary(kv => kv.SourceName, kv => kv.queryResult);

Примечания : Каждая задача (PerformWork) теперь выполняется от 0 до 200 мс. Раньше это занимало больше времени, чем я оптимизировал его Вот почему я использовал библиотеку Tasks.Parallel в первую очередь. Таким образом, я перешел от общего времени 2 секунды к общему времени ~ 100-200 мс, выполняя примерно одну и ту же работу, только разными методами. (Ух ты, Линк и Плинк классные!)

Вопросы

  1. Ускорено ли использование plinq vs Parallel.ForEach?
  2. Является ли это просто удалением параллельной структуры данных (ConcurrentDictionary)? (Потому что не нужно синхронизировать потоки).
  3. На основании ответа на этот связанный вопрос

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

Могу ли я предположить, что, поскольку мой шаблон в основном функционален (предоставление входов приводит к новым выходам без мутации), эта технология plinq является правильной для использования?

Я ищу подтверждение того, что мои предположения верны, или указание на то, что я что-то упустил.

Ответы [ 2 ]

4 голосов
/ 04 марта 2011

Невозможно использовать эти 2 примера кода для окончательного сравнения Parallel.ForEach и PLINQ.Примеры кода просто слишком разные.

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

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

На основании ограниченной информации, которую вы предоставили в своем примере (я попросил более подробную информацию в комментарии к OP), я уверен, что вы видите различия из-за используемого алгоритма разделения. Вы должны прочитать о Разделение на чанки и Разделение по диапазонам в этом сообщении в блоге, где он обсуждает, как они различаются и для каких типов работы они могут лучше всего подходить. Настоятельно рекомендуем вам прочитать эту статью в блоге, а также эту , в которой более подробно рассматриваются эти два типа, а также два других типа разбиения, которые можно использовать, хотя и неприменимо к вашему образцу. как предоставление наглядных пособий для лучшего понимания разбиения. Наконец, вот еще одно сообщение в блоге , в котором обсуждается разделение работы и его влияние на вас, когда алгоритм разделения по умолчанию не имеет смысла для вашей конкретной рабочей нагрузки. Этот пост на самом деле относится к замечательной программе, которая помогает вам визуализировать разделители на работе, которые являются частью набора параллельных сэмплов от команды PFX .

...