[Mono-dev] Multi-threading problem in mono
Maximino Aldana
max at fis.unam.mx
Fri May 7 19:04:33 EDT 2010
Dear mono developers.
I'm writing a C# multi-threading program in which the threads do not
share any information, so no thread synchronization is needed. Each
thread has its own internal variables, none of which is static, and all
the threads perform exactly the same task but with different values of
the parameters. I'm running this program in a multi-core processor
computer (Intel Quad-core), and therefore I expect the program to run
faster when the job is divided among several threads than when the
entire job is carried out only by a single thread.
However, it happens exactly the opposite. Namely, when the job is
performed by several threads the execution time is considerably longer
than when only one thread performs the entire job.
To be more specific, look at the example listed below (at the end of
this e-mail), in which I have encapsulated the thread in a MyThread
class. The MyThread class performs a very simple task: it just generates
a bunch of random numbers and computes their square root. This is a
simplified version of the thread I was working with in my original
project. However, even such a simple object exhibits the pathology I
would like you to ask how to solve. It is important to stress the fact
that each MyThread object creates its own internal variables, including
the random number generator, and (apparently) no sharing of the instance
variables occurs at any time.
I have run the program listed below in two cases:
Case 1: The three threads run sequentially. This is done by starting a
thread and calling on its Join() method before the next thread starts
(in the program listed below, the three lines calling the Join() method
are uncommented). In this case, the SystemMonitor shows only one core
working at any time, and the execution of the three threads running
sequentially takes 25.894 seconds.
Case 2: The three threads run in parallel (no calling on the Join()
method occurs here because the three lines that call the Join() method
are commented). In this case the SystemMonitor shows several cores
working simultaneously, as expected. However, what is not expected is
that the execution of the three threads running in parallel takes 42.307
seconds!!!
In summary, the three threads running in parallel and with many cores
working simultaneously, run about 1.6 times SLOWER than the three
threads running sequentially with only one core working at a time. How
can this be possible?
It is important to mention that I run exactly the same program and in
the same machine, but in Windows 7 using the C# Express .NET environment
2010, and the performance was consistent with what I expected from the
very beginning. Namely, the three threads running in parallel did the
job in one third of the time than the three threads running
sequentially. The same consistency happened when I implemented the
program in Java 6, both in Windows 7 and in Ubuntu Linux 10.04.
So, the problem, as I have encountered it, occurs only with the
implementation of this program in mono. (I did the mono experiments in
Linux. I have not tried running mono in Windows).
I suspect the problem resides in the implementation of the Random class
(probably some static variables in there??), but I'm not sure and my
programming skills do not allow me to dig that far.
I thank you in advance for your help. Below is the code.
Maximino Aldana.
*********************************
using System;
using System.Threading;
namespace Pruebas
{
public class MyThread
{
Thread t;
Random rnd;
int i_max;
int t_num;
public MyThread (int tn, int im)
{
this.rnd = new Random();
this.t = new Thread(new ThreadStart(MyMethod));
this.t_num = tn;
this.i_max = im;
}
private void MyMethod(){
double x, y;
Console.WriteLine("Method in thread {0} started",t_num);
for(int n = 0; n < 10000; ++n){
for(int i = 0; i < i_max; ++i){
x = rnd.NextDouble();
y = Math.Sqrt(x);
}
}
Console.WriteLine("Method in thread {0} ended",t_num);
}
public void StartMyThread(){
t.Start();
}
public void JoinMyThread(){
t.Join();
}
}
}
// ******* Now the entry point **************
using System;
namespace Pruebas
{
class MainClass
{
public static void Main(string[] args)
{
MyThread t1 = new MyThread(1, 50000);
MyThread t2 = new MyThread(2, 50000);
MyThread t3 = new MyThread(3, 50000);
t1.StartMyThread();
// t1.JoinMyThread();
t2.StartMyThread();
// t2.JoinMyThread();
t3.StartMyThread();
// t3.JoinMyThread();
/* Comment or uncomment the calls to the JoinMyThread()
* method to make the threads run in parallel or sequentially.
*/
}
}
}
*******************************
More information about the Mono-devel-list
mailing list