views:

128

answers:

4

Why the performance of following code is degrading when I use threads ?

**1.Without threads

int[] arr =  new int[100000000]; //Array elements - [0][1][2][3]---[100000000-1]      
addWithOutThreading(arr); // Time required for this operation - 1.16 sec

Definition for addWithOutThreading

        public void addWithOutThreading(int[] arr)
        {
            UInt64 result = 0;
            for (int i = 0; i < 100000000; i++)
            {
                result = result + Convert.ToUInt64(arr[i]);
            }
            Console.WriteLine("Addition = " + result.ToString());
        }

**2.With threads

int[] arr =  new int[100000000];
int part = (100000000 / 4);
UInt64 res1 = 0, res2 = 0, res3 = 0, res4 = 0;

ThreadStart starter1 = delegate 
                       { addWithThreading(arr, 0, part, ref res1); };
ThreadStart starter2 = delegate 
                       { addWithThreading(arr, part, part * 2, ref res2); };
ThreadStart starter3 = delegate 
                       { addWithThreading(arr, part * 2, part * 3, ref res3); };
ThreadStart starter4 = delegate 
                       { addWithThreading(arr, part * 3, part * 4, ref res4); };

Thread t1 = new Thread(starter1);
Thread t2 = new Thread(starter2);
Thread t3 = new Thread(starter3);
Thread t4 = new Thread(starter4);

t1.Start();
t2.Start();
t3.Start();
t4.Start();
t1.Join();
t2.Join();
t3.Join();
t4.Join();

Console.WriteLine("Addition = "+(res1+res2+res3+res4).ToString());
// Time required for this operation - 1.30 sec

Definition for addWithThreading

public void addWithThreading(int[] arr,int startIndex, int endIndex,ref UInt64 result)
{            
    for (int i = startIndex; i < endIndex; i++)
    {
        result = result + Convert.ToUInt64(arr[i]);
    }            
}
A: 

Perhaps the overhead of your threads is larger than any performance savings. Try scaling this up (IE, making 100000000 larger) to see if there is still the same type of gap in performance.

Justin Ethier
+8  A: 

You are talking about an operation that is already fairly quick, there is performance overhead in the creation of threads and getting everything up and running. More than likely your thread creation, splitting of the array and the additional calculation needed are what make up the extra time.

Mitchel Sellers
You also have core contention and context switching.
Matthew Whited
And probably false sharing (cache-line ping-ponging).
Audrius
A: 

If you are doing something that is CPU-intensive, then having multiple threads is of limited use, if you go over the number of hardware threads (hence the question from Ivan about hyperthreading).

If you have threads writing to a file, or reading from a file, then you will see a difference.

If you have one cpu/core then everything gets runs as a single-thread anyway, as only one thread can do something at a time.

Why not try a test where you have a momentary sleep each time, to simulate waiting for some slower resource, then you can see the benefit of multiple threads.

James Black
+3  A: 

The most likely reason is that your problem simply is not large enough to overcome the inherent overhead of starting up the threads. And, as you indicate that you have only 2 cores, using 4 threads is overkill if you have no I/O. At most 2 threads can be running at any given time so with 4 you only ensure that you have some unnecessary context switching.

Also possible, for large problems, is that you may be running into issues of memory thrashing. That's not likely in this case, but you've split your work up so that each thread deals with a different block of memory. These can be located on different pages and, if memory is a bottleneck, it may swap out the page used by one thread to bring in the page needed by another. Every time you switch contexts, it may need to do this page swap. A better way to construct the problem would be to have each thread i start on the ith row, then step the rows by the number of threads. That way, assuming the threads proceed at roughly the same rate, the locality of reference for the threads is the same and they are all working on the same pages -- no thrashing.

tvanfosson