Reputation: 35
I am taking an online course on java programming and came across this problem, I am looking at parallel programming using threads.
I am to make a "quad-core" version of a program that calculates pi by dividing the range of the sum into four equal parts, and uses four threads.
I have tried to split it up into 4 different threads and to start and join each thread.
public class quadCorePi extends Thread {
public static void main(String[] args) throws Exception {
long startTime = System.currentTimeMillis();
quadCorePi thread1 = new quadCorePi();
thread1.begin = 0 ;
thread1.end = numSteps / 4 ;
quadCorePi thread2 = new quadCorePi();
thread2.begin = 1 ;
thread2.end = numSteps / 4 ;
quadCorePi thread3 = new quadCorePi();
thread3.begin = 2 ;
thread3.end = numSteps / 4 ;
quadCorePi thread4 = new quadCorePi();
thread4.begin = numSteps / 4 ;
thread4.end = numSteps ;
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread1.join();
thread2.join();
thread3.join();
thread4.join();
long endTime = System.currentTimeMillis();
double pi = step * (thread1.sum + thread2.sum + thread3.sum + thread4.sum);
System.out.println("Value of pi: " + pi);
System.out.println("Calculated in " +
(endTime - startTime) + " milliseconds");
}
But it gives me the wrong value for pi, an explanation would be really helpful to how to split the work up for threads.
This was the example code given:
public class ParallelPi extends Thread {
public static void main(String[] args) throws Exception {
long startTime = System.currentTimeMillis();
ParallelPi thread1 = new ParallelPi();
thread1.begin = 0 ;
thread1.end = numSteps / 2 ;
ParallelPi thread2 = new ParallelPi();
thread2.begin = numSteps / 2 ;
thread2.end = numSteps ;
thread1.start();
thread2.start();
thread1.join();
thread2.join();
long endTime = System.currentTimeMillis();
double pi = step * (thread1.sum + thread2.sum) ;
System.out.println("Value of pi: " + pi);
System.out.println("Calculated in " +
(endTime - startTime) + " milliseconds");
}
static int numSteps = 10000000;
static double step = 1.0 / (double) numSteps;
double sum ;
int begin, end ;
public void run() {
sum = 0.0 ;
for(int i = begin ; i < end ; i++){
double x = (i + 0.5) * step ;
sum += 4.0 / (1.0 + x * x);
}
}
}
Upvotes: 2
Views: 539
Reputation: 3819
An improvement would be to use the proper Java concurrent libraries - here is how the code would look in that case:
public class ParallelPi implements Callable<Double> {
private static final ExecutorService executorService =
Executors.newFixedThreadPool(4);
private static final int numSteps = 10000000;
private static final double step = 1.0 / (double) numSteps;
private final int begin, end;
public ParallelPi(int begin, int end) {
this.begin = begin;
this.end = end;
}
public static void main(String[] args) throws Exception {
long startTime = System.currentTimeMillis();
List<Future<Double>> results = executorService.invokeAll(Arrays.asList(
new ParallelPi(0, numSteps / 4),
new ParallelPi(numSteps / 4, numSteps / 2),
new ParallelPi(numSteps / 2, 3 * numSteps / 4),
new ParallelPi(3 * numSteps / 4, numSteps)));
double pi = 0;
for(Future<Double> result: results) {
pi += result.get();
}
pi *= step;
long endTime = System.currentTimeMillis();
System.out.println("Value of pi: " + pi);
System.out.println("Calculated in " +
(endTime - startTime) + " milliseconds");
}
@Override
public Double call() throws Exception {
double sum = 0.0;
for (int i = begin; i < end; i++) {
double x = (i + 0.5) * step;
sum += 4.0 / (1.0 + x * x);
}
return sum;
}
}
Upvotes: 0
Reputation:
Your limits are incorrect. Here is the corrected code:
public class QuadCorePi extends Thread {
public static void main(String[] args) throws Exception {
long startTime = System.currentTimeMillis();
QuadCorePi thread1 = new QuadCorePi();
thread1.begin = 0 ;
thread1.end = numSteps / 4 ;
QuadCorePi thread2 = new QuadCorePi();
thread2.begin = numSteps / 4 ;
thread2.end = numSteps / 2 ;
QuadCorePi thread3 = new QuadCorePi();
thread3.begin = numSteps / 2 ;
thread3.end = 3 * numSteps / 4 ;
QuadCorePi thread4 = new QuadCorePi();
thread4.begin = 3 * numSteps / 4 ;
thread4.end = numSteps ;
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread1.join();
thread2.join();
thread3.join();
thread4.join();
long endTime = System.currentTimeMillis();
double pi = step * (thread1.sum + thread2.sum + thread3.sum + thread4.sum) ;
System.out.println("Value of pi: " + pi);
System.out.println("Calculated in " +
(endTime - startTime) + " milliseconds");
}
static int numSteps = 10000000;
static double step = 1.0 / (double) numSteps;
double sum ;
int begin, end ;
public void run() {
sum = 0.0 ;
for(int i = begin ; i < end ; i++){
double x = (i + 0.5) * step ;
sum += 4.0 / (1.0 + x * x);
}
}
}
Upvotes: 1
Reputation: 3081
Are you sure that the limits for the calculators are ok? Shouldn't it be:
thread2.begin = numSteps / 4 + 1 ;
thread2.end = numSteps / 2;
and so on for 3 and 4?
Upvotes: 0