Java-计算PI-单线程与多线程

时间:2019-06-19 22:32:12

标签: java

我不知道为什么,但是我用来计算PI的单线程代码比多线程要快得多。我正在使用5亿点和用于多线程16核。使用单CPU可以很好地使用多线程,所有16个核都是100%,但是速度较慢...

任何线索?

    public static double monteCarloMethodSequencialMethod(long points) {
    long inCircle = 0;

    for (long i = 0; i < points; i++) {

        double x = Math.random();
        double y = Math.random();

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

    return 4.0 * inCircle / points;
}
  蒙特卡洛序列估计PI值:3.1141562496。在13432.927304 ms中执行。

多线程

    public double calculatePI() throws InterruptedException, ExecutionException {

    double sum = 0;

    List<Future<Double>> tasks = new ArrayList<>();

    ExecutorService executor = Executors.newFixedThreadPool(nProcessors);

    for (long i = 0; i < points; i += points / nProcessors) {
        Future<Double> task = executor.submit(() -> {
            long inCircle = 0;
            double val = 0;

            for(long k = 0; k < points / nProcessors; k++) {
                double x = Math.random();
                double y = Math.random();

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

            return val;
        });

        tasks.add(task);
    }

    long pending = nProcessors;
    while(pending != 0) {
        for(Future<Double> future : tasks) {
            if(future.isDone()) {
                sum += future.get();
                pending--;
                System.out.println(pending + " task are still pending");
            }
        }
    }       

    executor.shutdown();

    return sum / points;
}
  

并行蒙特卡洛估计PI值:3.141666048。在116236.812471 ms中执行。

1 个答案:

答案 0 :(得分:4)

在您的代码中,您大量使用了随机数。请注意,java.util.Random在这种情况下并不理想,因为它会在线程之间造成拥塞。这是一个已知的性能问题(来源documentation):

  

java.util.Random的实例是线程安全的。但是,跨线程并发使用同一java.util.Random实例可能会遇到争用并因此导致性能下降。考虑在多线程设计中改用ThreadLocalRandom。

我建议改用ThreadLocalRandom

java.util.concurrent.ThreadLocalRandom.current().nextDouble()