我不知道为什么,但是我用来计算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中执行。
答案 0 :(得分:4)
在您的代码中,您大量使用了随机数。请注意,java.util.Random
在这种情况下并不理想,因为它会在线程之间造成拥塞。这是一个已知的性能问题(来源documentation):
java.util.Random的实例是线程安全的。但是,跨线程并发使用同一java.util.Random实例可能会遇到争用并因此导致性能下降。考虑在多线程设计中改用ThreadLocalRandom。
我建议改用ThreadLocalRandom:
java.util.concurrent.ThreadLocalRandom.current().nextDouble()