views:

600

answers:

4

Hi, everybody I have a some computation program. Now, this program is a single-thread, I need to enhance it to do it multi-thread. In general, program computes, dynamic evolution of thermal circuit (Some configured types of different involved elements (Tube, Pump, Active zone, and its connection), for each of it for every time step program calculates diffusion equations (http://en.wikipedia.org/wiki/Diffusion%5Fequation)) Problem is, on every time steps each involved element could be handled separately, but on every new time steps all elements should synchronize each other. I've decided to do it by starting on each time step one Thread per element, to solve it.

     private void SolveElementDynamic(object element)
    {
        if (element is PJunction)
        {
            ((PJunction)element).SolveDynamic();
        }
        else
            if (element is PElementData)
            {
                ((PElementData)element).SolveDynamic();
            }
    }

   public void SolveDynamic()
    {
         ParameterizedThreadStart threadStart = new ParameterizedThreadStart(SolveElementDynamic);

        for (int i = 0; i < _elementDataCollection.Count; i++)
        {
            _threadArray.Add(new Thread(threadStart));
        } 

        int j = 0;
        foreach (object element in _elementDataCollection)
            {
                ((Thread)_threadArray[j]).Start(element);
                j++;    
            }

    }

But it seems that creating new Thread is too expensive in comparison with calculating one element per step. I've tried to create Thread array, only one time at the start of the computation. But unfortunately It is seems that Thread object can't be started more than one times?

  // Thread's array created before
 public void SolveDynamic()
    {
           int j = 0;
        foreach (object element in _elementDataCollection)
            {
                ((Thread)_threadArray[j]).Start(element);
                j++;    
            }
    }

Is there any way to do it? Or is there any way to do it better?)

PS I've never encountered with Threading in .Net, and I have a small practice in threading programming

+6  A: 

try this How to: Use a Thread Pool (C# Programming Guide).

lsalamon
Unbelievable. An MSDN link that was actually useful!
Pierreten
the trick is to find the right information
lsalamon
+1  A: 

First, why your solution does NOT work:

A .NET thread is associated with an OS object (the os thread) - and a windows (and unix as well for that matter) contains its own execution stack. Now, if you where to have multiple execution units use the same stack, it would result in absolutely unpredictable behaviour. Therefor: One thread object can only ever be running or not running - not something like running 10 times.

Using a thread array is possible - but you need to create a new thread element for each index.

The problem with using a new thread for each step of a computation is that the creation of a thread itself is rather costly - it needs to do a system call, create a stack, a kernel object and so forth.

There are effectively two things you might wish to do:

First, assign a lot more than a single step to each thread. A more effective version of this is to have a central (synchronized) work queue where each thread can get more work. You then only create a single thread per available CPU and still usually assign more than a single step of work at once (otherwise your bottleneck will be the work distribution).

Second, reuse your existing threads. Whether by using the .NET thread pool, or by simply not recreating your threads, does not matter in this context - a synchronization of existing threads is a lot cheaper than complete recreation. Also, if you use slim locks, you can completely avoid the os call.

dionadar
>Second, reuse your existing threads. or by simply not recreating your threads, does not matter in this context - a synchronization of existing threads is a lot cheaper than complete recreation. Also, if you use slim locks, you can completely avoid the os call.That is exactly what I tried to do, but when program tries to reuse one Thread second time exception is occured: Unhandled exception "System.Threading.ThreadStateException" in mscorlib.dllAdditional info: thread is now running or already interrupted; it can't be started second time.
IOException
Either use a thread start function that does not need to be restarted, but instead waits on a synchronization object, or stop the thread once it has done its piece of work. since you need to wait on all threads in any case, the first solution is preferable.
dionadar
+1  A: 

Why do you need your program to be multithreaded? It's going to make your program much more complex, so what's the benefit you are hoping for? Do you want to utilize more cores to increase speed?

Assuming that you want to utilize more cores, you might want to look at .NET 4 and Parallel Programming.

It's still in Beta right now but it looks pretty stable, and it will likely be released for production soon.

Mark Byers
Yes, I need to utilize more cores and increase speed of the program
IOException
+1  A: 

Due to limited experience with paralellism in C#, I would recommend looking into PLINQ and the Task Parallel Library that it is built on. This framework is currently part of a seperate 'add-on' library for .Net 3.0, but will be built in to the .Net 4.0 framework.

You could do what you're currently trying to do using the Task constructs, or the parallel For extension methods:

foreach (var element in var _elementDataCollection)
{
    var task = new Task(element.SolveDynamic);
    task.Wait();
}

or

Parallel.ForEach(_elementDataCollection, x => {
    x.SolveDynamic();
});

Example Post Using the TPL

JD Courtoy
Thanx :), It is very interesting, and seems suitable for me. I'm studing it tomorrow.
IOException