Почему PLINQ медленнее, чем LINQ для этого кода? - PullRequest
2 голосов
/ 11 апреля 2010

Во-первых, я использую это на двухъядерном процессоре с частотой 2,66 ГГц Я не уверен, что у меня есть вызов .AsParallel () в правильном месте. Я попробовал это прямо на переменной диапазона, и это было еще медленнее. Я не понимаю, почему ...

Вот мои результаты:

Непараллельный процесс 1000 занял 146 миллисекунд

Процесс параллельной 1000 занял 156 миллисекунд

Процесс, не параллельный 5000, занял 5187 миллисекунд

Процесс параллельного 5000 занял 5300 миллисекунд

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace DemoConsoleApp
{
  internal class Program
  {
    private static void Main()
    {
      ReportOnTimedProcess(
        () => GetIntegerCombinations(),
        "non-parallel 1000");

      ReportOnTimedProcess(
        () => GetIntegerCombinations(runAsParallel: true),
        "parallel 1000");

      ReportOnTimedProcess(
        () => GetIntegerCombinations(5000),
        "non-parallel 5000");

      ReportOnTimedProcess(
        () => GetIntegerCombinations(5000, true),
        "parallel 5000");

      Console.Read();
    }

    private static List<Tuple<int, int>> GetIntegerCombinations(
      int iterationCount = 1000, bool runAsParallel = false)
    {
      IEnumerable<int> range = Enumerable.Range(1, iterationCount);

      IEnumerable<Tuple<int, int>> integerCombinations =
        from x in range
        from y in range
        select new Tuple<int, int>(x, y);

      return runAsParallel
               ? integerCombinations.AsParallel().ToList()
               : integerCombinations.ToList();
    }

    private static void ReportOnTimedProcess(
      Action process, string processName)
    {
      var stopwatch = new Stopwatch();
      stopwatch.Start();
      process();
      stopwatch.Stop();

      Console.WriteLine("Process {0} took {1} milliseconds",
                        processName, stopwatch.ElapsedMilliseconds);
    }
  }
}

Ответы [ 2 ]

4 голосов
/ 11 апреля 2010

Это немного медленнее, потому что PLINQ имеет определенные накладные расходы (потоки, планирование и т. Д.), Поэтому вам нужно тщательно выбирать, что вы будете распараллеливать. Этот конкретный код, который вы тестируете, на самом деле не стоит распараллеливать, вы должны распараллеливаться над задачами со значительной нагрузкой, иначе издержки будут больше, чем преимущества распараллеливания.

0 голосов
/ 11 апреля 2010

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

Попробуйте сделать что-то значительно более сложное / дорогое в параллельном сегменте, например простую факторизацию, и увеличьте число итераций до сотен тысяч (5000 - это очень небольшое число, используемое при профилировании). Тогда вы должны начать видеть разницу.

Также убедитесь, что вы профилируете в режиме релиза; слишком часто я вижу попытки профилирования в режиме отладки, и результаты этого не будут точными.

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