Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How exactly does AsParallel work?

Tags:

c#

.net

plinq

It doesn't seem to do squat for the following test program. Is this because I'm testing with a small list?

static void Main(string[] args)
{
    List<int> list = 0.UpTo(4);

    Test(list.AsParallel());
    Test(list);
}

private static void Test(IEnumerable<int> input)
{
    var timer = new Stopwatch();
    timer.Start();
    var size = input.Count();
    if (input.Where(IsOdd).Count() != size / 2)
        throw new Exception("Failed to count the odds");

    timer.Stop();
    Console.WriteLine("Tested " + size + " numbers in " + timer.Elapsed.TotalSeconds + " seconds");
}

private static bool IsOdd(int n)
{
    Thread.Sleep(1000);
    return n%2 == 1;
}

Both versions take 4 seconds to run.

like image 649
ripper234 Avatar asked Nov 28 '09 14:11

ripper234


People also ask

What is AsParallel?

AsParallel(IEnumerable) Enables parallelization of a query. AsParallel<TSource>(Partitioner<TSource>) Enables parallelization of a query, as sourced by a custom partitioner that is responsible for splitting the input sequence into partitions.

Which extension method do you need to run a Parallel query in PLINQ?

If you specify Default as a parameter to the WithExecutionMode extension method, PLINQ will execute the query in parallel if an improvement in performance is evident in executing the query in parallel. If not, PLINQ would execute the query just like a LINQ query.


2 Answers

Task Parallel Library cares about the static type of the sequence. It should be IParallelEnumerable<T> for the operations to be handled by the TPL. You are casting the collection back to IEnumerable<T> when you call Test. Therefore, the compiler will resolve .Where call on the sequence to System.Linq.Enumerable.Where extension method instead of the parallel version provided by the TPL.

like image 169
mmx Avatar answered Oct 21 '22 14:10

mmx


(Updating for .NET4 since this question ranks pretty high in a Google search for AsParallel())

Just a few changes will allow your example to work as I imagine you expected.

Change List<int> list = 0.UpTo(4); to var list = Enumerable.Range(0, 4);

Your example would work if you added a function overload with a signature that takes a ParallelQuery...

    private static void Test(ParallelQuery<int> input)
    {
        var timer = new Stopwatch();
        timer.Start();

        int size = input.Count();
        if (input.Where(IsOdd).Count() != size / 2)
        {
            throw new Exception("Failed to count the odds");
        }
        timer.Stop();

        Console.WriteLine("Tested " + size + " numbers in " + timer.Elapsed.TotalSeconds + " seconds");
    }

Alternatively, you could use LINQ syntax....

    private static void Test(ParallelQuery<int> list)
    {
        var timer = Stopwatch.StartNew();

        if ((from n in list.AsParallel()
             where IsOdd(n)
             select n).Count() != (list.Count() / 2))
        {
            throw new Exception("Failed to count the odds");
        }

        Console.WriteLine("Tested " + list.Count() + " numbers in " + timer.Elapsed.TotalSeconds + " seconds");
    }

Hope this helps someone!

like image 34
AlfredBr Avatar answered Oct 21 '22 14:10

AlfredBr