0

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));
            }
  • 3
    What are you trying to do with that `tasks` array? Is this your actual set of tasks, just writing to the console 4 times? As for just 4 iterations, you'll probably suffer more from the overhead of starting new threads than gain from the work done in parallel. – Mattias Buelens Feb 05 '13 at 13:40
  • Just FYI, Parallel.For has a lot of overhead, so unless you've actually measured it and found it to be faster, or need its built in throttling, I suggest you just loop yourself and spin off work using Task.Run like you're doing, – Andrew Arnott Feb 08 '13 at 14:34

3 Answers3

1

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?

Colin Mackay
  • 18,736
  • 7
  • 61
  • 88
  • Yes I have TaskWaitAll, but I did not post all the code. Thank you code line! – user2023152 Feb 05 '13 at 13:49
  • It did not work. It compiled fine but too many errors during the run. – user2023152 Feb 05 '13 at 13:54
  • Unhandled Exception: System.AggregateException: One or more erroros occured. System.ArgumentExcpetion: The tasks array inclue at least one null element paraemeter name: Tasks – user2023152 Feb 05 '13 at 14:08
  • What were the InnerExceptions of that AggregateException? – Colin Mackay Feb 05 '13 at 14:09
  • 1
    I'm confused about what errors you could be getting. The docs for Console.WriteLine only indicate a possible IOException, yet it also says that access to the streams is synchronised (so should be thread safe). Are you doing more that just writing to the console? – Colin Mackay Feb 05 '13 at 14:18
  • No, just writing to the console, but I have another outside loop that runs the Parallel.For for X number of iterations, the reason for it, I am trying to do performance testing, and I am trying it get the time it takes (AVERAGE - that is reason for outside loop). – user2023152 Feb 05 '13 at 14:25
  • Can you show us the outside loop with the timing code so we can see what you are doing there? – Alex Moore Feb 05 '13 at 20:22
0

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#.

Community
  • 1
  • 1
Alex Moore
  • 3,415
  • 1
  • 23
  • 39
  • Thank you. That is a good example, but the tasks are needed for another performance reason. Is there a way to contact by email so I can send you two cpu utilization graphs with hope you can explain what is happening? – user2023152 Feb 05 '13 at 22:29
  • 2
    It is better to update your question and upload the graphs so that everyone can benefit. StackOverflow also has an open chat facility (which is public) so that everyone can benefit - That is the point of this site. – Colin Mackay Feb 06 '13 at 09:22
0

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);
Jean Hominal
  • 16,518
  • 5
  • 56
  • 90