user2023152
user2023152

Reputation: 29

TPL and Parallel.for

Someone on the net said the following C# code cannot be converted to some Parallel.for (for multi-core system) is that correct? If yes, is there a better way to optimize it further. thanks

            for (int i = 0; i < 4; i++)
            {
                var tmp = i;
                tasks[i] = Task.Factory.StartNew(() => Console.WriteLine(tmp));
            }

Upvotes: 0

Views: 332

Answers (3)

Jean Hominal
Jean Hominal

Reputation: 16796

First, about the error you reported:

Unhandled Exception: System.AggregateException: One or more erroros occured. System.ArgumentExcpetion: The tasks array inclue at least one null element paraemeter name: Tasks

The error is pretty clear, it is raised by your Task.WaitAll call - it says that one of the task slots in your tasks array is null.

Second, measuring performance on Console.WriteLine is bad for two reasons:

  1. The workload is too light: I am guessing that the setup overhead will dwarf the actual work;
  2. Console.WriteLine is synchronized - meaning that all the tasks will begin and then immediately synchronize - it is the case for which using a map reduce API is absolutely inappropriate. Just design a real computing workload instead (e.g. calculating prime numbers);

Upvotes: 0

Alex Moore
Alex Moore

Reputation: 3455

Since we don't have the outer loop code I am taking a stab in the dark here. If you are just measuring overall average runtime you don't need to store the tasks, you could use something like this to measure serial and parallel versions:

var iterations = 100;
var stopwatch = new Stopwatch();

// Run Serial version
stopwatch.Start();    
for(int i = 0; i < iterations; i++)
{
    for (int i = 0; i < 4; i++)
    {
        Console.WriteLine(tmp);
    }
}

stopwatch.Stop();
var serialTime = stopwatch.ElapsedMilliseconds;
stopwatch.Reset();

// Run parallel version
stopwatch.Start();

for(int i = 0; i < iterations; i++)
{
    Parallel.For(0,4, (i) => Console.WriteLine(i));    
}

stopwatch.Stop();

var parallelTime = stopwatch.ElapsedMilliseconds;

Console.WriteLine("Serial took  : {0}ms", serialTime / (double)iterations);
Console.WriteLine("Parallel took: {0}ms", parallelTime / (double)iterations);

This may not be a great test for measuring speedup since the workload is so light. You could try calling a function with more overhead or something like Thread.Sleep to imitate more work. Also see my answer at This StackOverflow Question for how to measure Amdahl's Law speedup in C#.

Upvotes: 0

Colin Mackay
Colin Mackay

Reputation: 19175

Well, you don't have a Tast.WaitAll(tasks) at the end, which Parallel.For would do for you, so you are not quite doing what Parallel.For is doing (unless you have not put that code in your question. If so then the next line is what your code would look like as a Parallel.For loop)

Parallel.For(0,4, (i) => Console.WriteLine(i));

Other than that, I don't see why you can't convert it to Parallel.For. What reason did the person give for not being able to convert it?

Upvotes: 1

Related Questions