patternjavaMinor
Better performance in calculating E
Viewed 0 times
calculatingperformancebetter
Problem
Can you give me some performance advice on how to optimize the time of execution of the following calculation of E?
The time of execution is about 3055588556 ns.
package calculatee;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
public class CalculateE {
static long start1 = System.nanoTime();
public static BigDecimal factorial(int x) {
BigDecimal prod = new BigDecimal("1");
for (int i = x; i > 1; i--) {
prod = prod.multiply(new BigDecimal(i));
}
return prod;
}
public static void main(String[] args) {
BigDecimal e = BigDecimal.ONE;
for (int i = 1; i < 1000; i++) {
e = e.add(BigDecimal.valueOf(Math.pow(3 * i, 2) + 1).divide(factorial(3 * i),new MathContext(10000, RoundingMode.HALF_UP)));
}
System.out.println("e = " + e);
long stop = System.nanoTime();
long diff = stop - start1;
System.out.println(diff + " ns");
}
}The time of execution is about 3055588556 ns.
Solution
you can split up the calculation in your
for loop into threads and sum up the results afterwards: here an example for 4 Threads: Use as many Threads as you have CPUs. It's important to add the result inside a synchronized block, otherwise you result could be corrupted by race conditions. I get a speed up of 50% with 4 threads compared to a single core execution.import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
public class CalculateE {
static long start1 = System.currentTimeMillis();
static BigDecimal result = BigDecimal.ONE;
public static BigDecimal factorial(int x) {
BigDecimal prod = new BigDecimal("1");
for (int i = x; i > 1; i--) {
prod = prod.multiply(new BigDecimal(i));
}
return prod;
}
public static Runnable getRunner(final int from, final int to) {
Runnable runner = new Runnable() {
@Override
public void run() {
BigDecimal e = BigDecimal.ZERO;
for (int i = from; i < to; i++) {
e = e.add(BigDecimal
.valueOf(Math.pow(3 * i, 2) + 1)
.divide(factorial(3 * i),
new MathContext(10000, RoundingMode.HALF_UP)));
}
addResult(e);
}
};
return runner;
}
public static synchronized void addResult(BigDecimal e){
result = result.add(e);
}
public static void main(String[] args) throws InterruptedException {
Runnable r1 = getRunner(1, 251);
Runnable r2 = getRunner(251, 501);
Runnable r3 = getRunner(501, 751);
Runnable r4 = getRunner(751, 1000);
Thread t1 = new Thread(r1);
t1.start();
Thread t2 = new Thread(r2);
t2.start();
Thread t3 = new Thread(r3);
t3.start();
Thread t4 = new Thread(r4);
t4.start();
t1.join();
t2.join();
t3.join();
t4.join();
System.out.println("e = " + result);
long stop = System.currentTimeMillis();
long diff = stop - start1;
System.out.println(diff + " ms");
}
}Code Snippets
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
public class CalculateE {
static long start1 = System.currentTimeMillis();
static BigDecimal result = BigDecimal.ONE;
public static BigDecimal factorial(int x) {
BigDecimal prod = new BigDecimal("1");
for (int i = x; i > 1; i--) {
prod = prod.multiply(new BigDecimal(i));
}
return prod;
}
public static Runnable getRunner(final int from, final int to) {
Runnable runner = new Runnable() {
@Override
public void run() {
BigDecimal e = BigDecimal.ZERO;
for (int i = from; i < to; i++) {
e = e.add(BigDecimal
.valueOf(Math.pow(3 * i, 2) + 1)
.divide(factorial(3 * i),
new MathContext(10000, RoundingMode.HALF_UP)));
}
addResult(e);
}
};
return runner;
}
public static synchronized void addResult(BigDecimal e){
result = result.add(e);
}
public static void main(String[] args) throws InterruptedException {
Runnable r1 = getRunner(1, 251);
Runnable r2 = getRunner(251, 501);
Runnable r3 = getRunner(501, 751);
Runnable r4 = getRunner(751, 1000);
Thread t1 = new Thread(r1);
t1.start();
Thread t2 = new Thread(r2);
t2.start();
Thread t3 = new Thread(r3);
t3.start();
Thread t4 = new Thread(r4);
t4.start();
t1.join();
t2.join();
t3.join();
t4.join();
System.out.println("e = " + result);
long stop = System.currentTimeMillis();
long diff = stop - start1;
System.out.println(diff + " ms");
}
}Context
StackExchange Code Review Q#49060, answer score: 3
Revisions (0)
No revisions yet.