[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