1

I am writing a program that shows the mandelbrot set depending on some conditions provided by the user. As the calculation takes long (more than 500 ms), I have decided to use more than one thread. Without any previous experience, I have managed to do it by using the System.Threading.Tasks class, which works just fine. The only thing that I don't like is that every time that the mandelbrot is generated, the threads are created and then destroyed.

This is an example of how it works. It creates the threads (Tasks) every time that the method is called.

for (int i = 0; i < maxThreads; i++) {
    int a = i;
    tasks[a] = Task.Factory.StartNew(() => generateSector(a));
}

I don't know really how that affects performance, but it looks like creating and destroying threads is time expensive, and that it would be more efficient to have the threads ready and waiting for a trigger message, and when they are done go back to that waiting state. May be the following example code is useful to understand this idea.

for (int i = 0; i < maxThreads; i++)
    tasks[i].sendMessage("Start"); // Tells the running thread to begin its work

So each thread would execute an infinite loop in which it waits until they are required to do calculations. Then, it would continue with waiting. Something like this:

// Into the method that a thread executes
while(true) {
    Wait(); // Waits for the start signal
    calculate(); // Do some calculations
}   // Go back to waiting

Would that be more efficient? Is there any way to do that?

aochagavia
  • 5,887
  • 5
  • 34
  • 53

3 Answers3

4

Leave your code as it is.

1) Tasks use ThreadPool threads, so there is no problem

2) "I don't know really how that affects performance" - this is where you should start. Never optimize before measuring. Do you have performance issues? Is your code running slow? I guess no, so you should not be bothered.

Pavel Tupitsyn
  • 8,393
  • 3
  • 22
  • 44
  • An alternate view is, "It is OK to design for run time efficiency." – pamphlet Sep 24 '13 at 14:02
  • It takes an average of 200ms to calculate the mandelbrot set each time, and I have to show it to the user, so the idea is that it works so fast as possible. However, from your answer it looks like my actual solution is good enough. – aochagavia Sep 24 '13 at 14:09
  • @pamphlet, of course it is, but you need to be sure what is efficient and what is not. Like HashSet.Contains vs List.Contains: this is quite obvious when you have many items. But when you are not certain, the only way is to measure and find out. – Pavel Tupitsyn Sep 24 '13 at 14:37
  • @Wofo: I understand your idea. Why do guesswork? Just run a profiler and find your true bottleneck. – Pavel Tupitsyn Sep 24 '13 at 14:40
1

When you use Task.Factory.StartNew(...), you are not necessarily creating and destroying threads. The task library uses a ThreadPool to do this, so you don't need to manage it yourself, like you would if you created new Thread()s yourself.

Community
  • 1
  • 1
Tim S.
  • 55,448
  • 7
  • 96
  • 122
0

It sounds like you're trying to use a set of of threads and setting up a system for scheduling work to run on those threads. This is a great idea but in fact, it's so great of an idea that it's built into the .NET framework and you don't need to build it yourself. This is actually exactly what Tasks are made for.

Tasks are a relatively lightweight abstraction over the Thread Pool which is managed by the .NET Runtime. Threads are an operating-system construct that are relatively heavy and it's somewhat expensive to start, stop, and context-switch between threads. When you create a Task, it schedules that task to execute on a the next available thread in the pool and the .NET runtime will automatically increase and decrease the size of the pool based on whether there's work getting queued up and waiting for a thread to execute. You can customize the minimum and maximum thread counts if you need to but usually this is not nessecary.

So by simply creating short-lived Tasks that exist for the lifetime of the single unit of work, they're already going to have your work be run on a managed collection of actual threads.

Eric Damtoft
  • 1,353
  • 7
  • 13