2

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);
      }
  }
  }
3
  • Are you sure that your computation is correct; meaning: is your code working when you call it without any multi-threading on top of it? Commented Mar 27, 2015 at 10:04
  • public class quadCorePi extends Thread, it runs for an example that was given before. Commented Mar 27, 2015 at 10:15
  • For a start, use the java.util.concurrent packages instead of doing low level thread handling - it's a lot easier. Commented Mar 27, 2015 at 11:27

3 Answers 3

1

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);
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, yes my limits were wrong and thanks for the tip on class names.
0

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?

1 Comment

Not quite. The limits are divided into 4 ranges.
0

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;
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.