Reputation: 31
i wrote a code which do a sum function in single and multi-threading way as bellow:
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ParallelFor
{
class Program
{
static void Main()
{
Console.WriteLine("Program started");
var step_time = Stopwatch.StartNew();
step_time.Start();
double R1 = 0.0;
double R2 = 0.0;
double R3 = 0.0;
var t1 = new Thread(() => TestCounter(2000, ref R1, 1));
var t2 = new Thread(() => TestCounter(2000, ref R2, 2));
var t3 = new Thread(() => TestCounter(2000, ref R3, 3));
t1.Start();
t2.Start();
t3.Start();
do
{
} while (t1.IsAlive == true || t2.IsAlive == true || t3.IsAlive == true);
Console.WriteLine("inside R1: {0}", R1);
Console.WriteLine("inside R2: {0}", R2);
Console.WriteLine("inside R3: {0}", R3);
Console.WriteLine("Program finished");
step_time.Stop();
Console.WriteLine("multi-thread last {0} (MilSec)\n", step_time.ElapsedMilliseconds);
step_time.Reset();
step_time.Start();
R1 = 0.0;
R2 = 0.0;
R3 = 0.0;
TestCounter(2000, ref R1, 1);
TestCounter(2000, ref R2, 2);
TestCounter(2000, ref R3, 3);
Console.WriteLine("inside R1: {0}", R1);
Console.WriteLine("inside R2: {0}", R2);
Console.WriteLine("inside R3: {0}", R3);
step_time.Stop();
Console.WriteLine("single thread last {0} (MilSec)\n", step_time.ElapsedMilliseconds);
Console.ReadLine();
}
static void TestCounter(int counter, ref double result, int No)
{
for (int i = 0; i < counter + 1; i++)
for (int j = 0; j < counter; j++)
for (int k = 0; k < counter; k++)
result += (double)i;
}
}
}
i found that the single thread part, last shorter ! (i ran the code with counter=10000, the result is the same !) why the single thread pars proceed faster ?!?!
Upvotes: 0
Views: 488
Reputation: 79
I think the overhead of setting up the threads and waiting for the threads to complete is higher than the gain of running your code over multiple threads. Also, if you start more threads than the number of available cores, your code will slow down because of the many context switches.
One optimization you could try is to get rid of the manual synchronization using the Monitor.Wait()
call. You could manually create Thread
objects (as many as you have CPU cores), start them all and then wait for the threads to complete by calling Thread.Join()
. That way you don't need any synchronization code in your threads:
Thread[] threads = new Thread[NumCores];
for (int i = 0; i < NumCores; i++)
{
threads[i] = new Thread(MyThread);
threads[i].Start(threadData);
}
for (int i = 0; i < NumCores; i++){
threads[i].Join();
}
Upvotes: 4
Reputation: 1281
The problem is most likely Cache Thrashing. I changed the TestCounter method to the following:
static void TestCounter(int counter, ref double result, int No)
{
double internalResult = 0;
for (int i = 0; i < counter + 1; i++)
for (int j = 0; j < counter; j++)
for (int k = 0; k < counter; k++)
internalResult += (double)i;
result += internalResult;
}
Here, the value is first accumulated into a local variable and just in the end written to the passed result variable. Hence, the thread works most of the time on its local stack and not on a memory location (respectively the cache line) that is also accessed by the other threads.
With this change, I almost get a speedup of the expected factor 3.
Upvotes: 3