我正在尝试计算e=∑(3−4k^2/(2k+1)!); k=0..10000
但是我被卡住了,无法使用多线程获得所需的性能提升。
给定多个线程,我尝试将整个总和分成k / numberOfThreads
块并为每个部分总和提交期货。我认为不好的部分可能是阶乘计算或粒度。我尝试了一个较小的步骤,但没有得到很大的改进。也许需要一种不同的方法。
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
List<Future<BigDecimal>> futures = new ArrayList<>(numberOfThreads);
int step = k / numberOfThreads ;
BigDecimal result = BigDecimal.ZERO;
for (int j = 0; j <= k; j += step) {
Future<BigDecimal> future = executor.submit(new EulerCalculator(j, j + step));
futures.add(future);
}
for (Future<BigDecimal> future : futures) {
result = result.add(future.get());
}
public class EulerCalculator implements Callable<BigDecimal> {
private int start;
private int end;
public BigDecimal call() {
long numerator = 3 - 4 * start * start;
BigDecimal denominator = factorial(2 * start + 1);
BigDecimal partialSum = BigDecimal.valueOf(numerator)
.divide(denominator, 1000, RoundingMode.HALF_EVEN);
for (int i = start + 1 ; i < end; i++) {
numerator = 3 - 4 * i * i;
denominator = denominator.multiply(BigDecimal.valueOf(2 * i * (2*i + 1)));
partialSum = partialSum.add(BigDecimal.valueOf(numerator)
.divide(fact, 1000, RoundingMode.HALF_EVEN));
}
return partialSum;
}
private BigDecimal factorial(int cur) {
BigDecimal fact = BigDecimal.ONE;
for (int i = 2; i <= cur; i++) {
fact = fact.multiply(BigDecimal.valueOf(i));
}
return fact;
}
}
在四核上运行几次的最佳结果:
k = 10000
线程 = 1:345 毫秒
线程 = 2:216 毫秒
线程 = 4:184 毫秒
线程 = 8:225 毫秒