Why is PLINQ slower than LINQ for this code?

Firstly, I am running this on a 2.66GHz dual core processor. I'm not sure if I have a .AsParallel () call in the correct place. I also tried it directly on the range variable and it was even slower. I do not understand why...

Here are my results:

Non-parallel process 1000 took 146 milliseconds

Parallel 1000 process took 156 milliseconds

Non-parallel process 5000 took 5187 milliseconds

Parallel 5000 process took 5300 milliseconds

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


source to share


2 answers


It's a little slower because PLINQ has a certain overhead (threads, scheduling, etc.), so you need to carefully choose what you will be parallelizing. This particular code you are comparing is not worth parallelizing, you must parallelize heavy-load tasks or the overhead will weigh more than the benefits of parallelizing.



+4


source


Most of your runtime here will probably actually be created in a list using a method ToList()

. This will have to do multiple memory allocations, list resizing, etc. You also don't get much benefit from parallelization here, because the final operation must be synchronized (you create a single list in the output).

Try to do something significantly more complicated / expensive in the parallel segment, such as primary factorization and increasing the number of iterations to hundreds of thousands (5000 is a very small number to use when profiling). You should start to see the difference.



Also make sure you are profiling in release mode; all too often I see profiling attempts in debug mode and the results are not accurate.

0


source







All Articles