Skip to content

Instantly share code, notes, and snippets.

@amalic
Created February 19, 2019 15:33
Show Gist options
  • Save amalic/cb9d159cf4ce38d54511fbb00e22eccd to your computer and use it in GitHub Desktop.
Save amalic/cb9d159cf4ce38d54511fbb00e22eccd to your computer and use it in GitHub Desktop.
package test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.IntStream;
public class Log2vsApproxLog2 {
public static void main(String[] args) {
final int TOTAL_REPETITIONS = 1000;
final int RUNS = 10;
final int REPEATS_PER_RUN = 100000;
final int WARMUPS = 5;
final int ARRAY_SIZE = 100000000;
Map<String, List<Long>> totalStats = new HashMap<>();
for(int mode=0; mode<2; mode++) {
String key = mode%2 == 0 ? "log2" : "approxLog2";
totalStats.put(key, new ArrayList<Long>());
}
IntStream.range(0, TOTAL_REPETITIONS + WARMUPS).sequential().forEach(repetition -> {
Random r = new Random(System.currentTimeMillis());
Timer timer = new Timer();
double[] randoms = new double[ARRAY_SIZE];
for(int i=0; i<randoms.length; i++)
randoms[i] = r.nextDouble();
System.out.println(String.format("\ngenerating %d random double values took %d ms", randoms.length, timer.durationAsMilliS()));
Map<String, List<Long>> runStats = new HashMap<>();
Timer nt;
for(int mode=0; mode<2; mode++) {
String key = (mode + repetition) %2 == 0 ? "log2" : "approxLog2";
if(!runStats.containsKey(key))
runStats.put(key, new ArrayList<Long>());
for(int run = 0; run < RUNS + WARMUPS; run++) {
if(key.equals("log2")) {
nt = new Timer();
for(int i=0; i<REPEATS_PER_RUN; i++)
for(double d: randoms)
log2(d);
long time = nt.durationAsNanoS();
if(run >= WARMUPS)
runStats.get(key).add(time);
} else {
nt = new Timer();
for(int i=0; i<REPEATS_PER_RUN; i++)
for(double d: randoms)
approxLog2(d);
long time = nt.durationAsNanoS();
if(run >= WARMUPS)
runStats.get(key).add(time);
}
}
}
if(repetition >= WARMUPS) {
System.out.println("Stats: " + runStats);
for(String key: runStats.keySet()) {
long average = (long)runStats.get(key).stream().mapToLong((x) -> x).summaryStatistics().getAverage();
totalStats.get(key).add(average);
System.out.println("Average time for " + key + " -> " + average + " ns");
}
} else {
System.out.println("warmup round");
}
});
System.out.println("\n\nFINAL RESULTS FOR " + TOTAL_REPETITIONS + " REPETITIONS");
for(String key: totalStats.keySet())
System.out.println(String.format("Total Stats time for %s -> %s", key, totalStats.get(key).stream().mapToLong((x) -> x).summaryStatistics()));
}
static final double lg2 = Math.log(2);
public static double log2(double n) {
return (Math.log(n) / lg2);
}
public static double approxLog2(double value) {
final long valueBits = Double.doubleToRawLongBits(value);
final long exponent = ((valueBits & 0x7ff0_0000_0000_0000L) >>> 52) - 1024;
final double m = Double.longBitsToDouble((valueBits & 0x800fffffffffffffL) | 0x3ff0000000000000L);
return (m * (2 - (1.0 / 3) * m) + exponent - (2.0 / 3.0));
}
static class Timer {
final static long KILO = 1000L;
private long start;
public Timer() {
start = System.nanoTime();
}
public long durationAsNanoS() {
return System.nanoTime() - start;
}
public long durationAsMicroS() {
return durationAsNanoS()/KILO;
}
public long durationAsMilliS() {
return durationAsMicroS()/KILO;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment