Как ускорить вычисления с использованием нескольких потоков?

Я пытаюсь вычислить Pi, но на самом деле я хочу добиться эффективности при использовании более чем одного потока. Алгоритм прост: я произвольно генерирую точки в единичном квадрате и после этого подсчитываю, сколько из них находится в круге, вписанном в квадрат. (подробнее здесь: http://math.fullerton.edu/mathews/n2003/montecarlopimod.html ) Моя идея состоит в том, чтобы разделить квадрат по горизонтали и запустить отдельный поток для каждой его части. Но вместо того, чтобы ускориться, я получаю лишь задержку. Есть идеи, почему? Вот код:

public class TaskManager {

public static void main(String[] args) {

    int threadsCount = 3;
    int size = 10000000;
    boolean isQuiet = false;

    PiCalculator pi = new PiCalculator(size);   
    Thread tr[] = new Thread[threadsCount];

    long time = -System.currentTimeMillis();

    int i;
    double s = 1.0/threadsCount;
    int p = size/threadsCount;

    for(i = 0; i < threadsCount; i++) {
        PiRunnable r = new PiRunnable(pi, s*i, s*(1.0+i), p, isQuiet);
        tr[i] = new Thread(r);
    }

    for(i = 0; i < threadsCount; i++) {
        tr[i].start();
    }

    for(i = 0; i < threadsCount; i++) {
        try {
            tr[i].join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }       

    double myPi = 4.0*pi.getPointsInCircle()/pi.getPointsInSquare();
    System.out.println(myPi + " time = " + (System.currentTimeMillis()+time));
}
}

public class PiRunnable implements Runnable {

PiCalculator pi;
private double minX;
private double maxX;
private int pointsToSpread;

public PiRunnable(PiCalculator pi, double minX, double maxX, int pointsToSpread, boolean isQuiet) {
    super();
    this.pi = pi;
    this.minX = minX;
    this.maxX = maxX;
    this.pointsToSpread = pointsToSpread;
}


@Override
public void run() {
    int n = countPointsInAreaInCircle(minX, maxX, pointsToSpread);  
    pi.addToPointsInCircle(n);
}

public int countPointsInAreaInCircle (double minX, double maxX, int pointsCount) {
    double x;
    double y;

    int inCircle = 0;

    for (int i = 0; i < pointsCount; i++) { 
        x = Math.random() * (maxX - minX) + minX;
        y = Math.random();          

        if (x*x + y*y <= 1) {
            inCircle++;
        }
    }

    return inCircle;

}

}


public class PiCalculator {

private int pointsInSquare;
private int pointsInCircle;

public PiCalculator(int pointsInSquare) {
    super();
    this.pointsInSquare = pointsInSquare;
}

public synchronized void addToPointsInCircle (int pointsCount) {
    this.pointsInCircle += pointsCount;
}

public synchronized int getPointsInCircle () {
    return this.pointsInCircle;
}

public synchronized void setPointsInSquare (int pointsInSquare) {
    this.pointsInSquare = pointsInSquare;
}

public synchronized int getPointsInSquare () {
    return this.pointsInSquare;
}

}

Некоторые результаты: -для 3 потоков: «3.1424696 время = 2803» -для 1 потока: «3.1416192 time = 2337»

5
задан brain_damage 7 June 2011 в 19:27
поделиться