1

I'm running a Simulation for thin films in very low temperatures. I tried using ExecutorService to properly multithread my code and hopefully reduce runtime. But I found out the hard way that this is easier said than done. I fiddled with many parameters, but wasn't able to increase any efficiency. What I found weird was that running the code with single, double or triple thread ExecutorService takes almost the same time.

The bottomline is that although more iteration of the for loop are running parallel at the same time, the amount of time taken to run a single iteration is increased. The overall total runtime comes out to be almost same no matter how many processors are being utilized.

I'm confused. What am I doing wrong?

public abstract class IsingRun {
public static void main(String[] args)  {   
    long starta = System.currentTimeMillis(); //time for single thread
    for (double t=temp[1];t<=temp[0] ;t+=temp[2] ) {
        long start = System.currentTimeMillis();
        //do stuff
        start = System.currentTimeMillis()-start;
        print(t,output,start); //start is the time taken for single iteration
    }
    starta = System.currentTimeMillis()-starta;
    System.out.println("Total Runtime (Single): "+ starta); //single thread total time

/*end of single threaded process */

    long startb = System.currentTimeMillis();
    ExecutorService e = Executors.newFixedThreadPool(2);
    for (double t=temp[1];t<=temp[0] ;t+=temp[2] ) {
        simulate s = new simulate(t);
        e.execute(s);

    }
    e.shutdown();
    startb = System.currentTimeMillis()-startb;
    System.out.println("Total Runtime (Double): "+ startb);

    /*end of double threaded process */

    long startc = System.currentTimeMillis();
    e = Executors.newFixedThreadPool(3);
    for (double t=temp[1];t<=temp[0] ;t+=temp[2] ) {
        simulate s = new simulate(t);
        e.execute(s);

    }
    e.shutdown();
    startc = System.currentTimeMillis()-startc;
    System.out.println("Total Runtime (Triple): "+ startc);
     /*end of triple threaded process */

}
}
class simulate implements Runnable{
simulate(double T){this.t=T;};

public void run() {
 long start = System.currentTimeMillis();
   //do stuff     
 start = System.currentTimeMillis()-start;
 print(t,output,start); //start is the time taken for single iteration
}
}

I got the following results

Temp - Output - Runtime for single iteration
2.10 - 0.85410 - 632288
2.20 - 0.83974 - 646527
2.30 - 0.81956 - 655128
2.40 - 0.80318 - 645012
2.50 - 0.79169 - 649863
2.60 - 0.77140 - 662429
Total Runtime (Single): 3891257
2.10 - 0.85585 - 1291943
2.20 - 0.83733 - 1299240
2.40 - 0.80284 - 1313495
2.30 - 0.82294 - 1334043
2.50 - 0.79098 - 1315072
2.60 - 0.77341 - 1338203
Total Runtime (Double): 3964290
2.10 - 0.85001 - 1954315
2.20 - 0.84137 - 1971372
2.30 - 0.82196 - 1996214
2.40 - 0.80684 - 1966009
2.50 - 0.78995 - 1970542
2.60 - 0.77437 - 1966503
Total Runtime (Triple): 3962763

What am I doing wrong? Task manager show all processors are being used, but is it?

1 Answers1

1

A couple of things:

1) If you take a look at the ExecutorService Javadoc, the shutdown() method does not wait for threads to complete execution. In you code you are not waiting for the task to actually complete. The javadoc also contains some sample code which demonstrates how to properly wait for ExecutorService to finish.

2) Benchmarking programs is not really a straight forward thing. I may/may not trust the numbers here. Also take a look at this SO post regarding measuring execution time in Java. Also, I would test your different type of execution methods separately and not all in one go.

3) If your task is really CPU intensive. I would create a ExecutorService with the number of threads matching the number of cores/processors in your machine. If your tasks are short lived then the additional overhead of threading/context switching may not be worth it and single threaded might be the way to go.