This is an automated email from the ASF dual-hosted git repository. aherbert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-rng.git
commit 80c94a5916041fef587796abcafe646387c461c0 Author: aherbert <aherb...@apache.org> AuthorDate: Tue Mar 5 12:25:14 2019 +0000 RNG-79: Modify benchmark to use uniform random generator. --- .../rng/examples/jmh/NextDoublePerformance.java | 102 +++++++++++---------- 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/NextDoublePerformance.java b/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/NextDoublePerformance.java index f182955..70620f3 100644 --- a/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/NextDoublePerformance.java +++ b/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/NextDoublePerformance.java @@ -41,112 +41,122 @@ import java.util.concurrent.TimeUnit; @State(Scope.Benchmark) @Fork(value = 1, jvmArgs = { "-server", "-Xms128M", "-Xmx128M" }) public class NextDoublePerformance { - // Mimic the generation of the SplitMix64 algorithm - // and a SplitMix32 algorithm to get a spread of input numbers. - - /** - * The 64-bit golden ratio number. - */ - private static final long GOLDEN_64 = 0x9e3779b97f4a7c15L; - /** - * The 32-bit golden ratio number. - */ - private static final long GOLDEN_32 = 0x9e3779b9; - - /** The long state. */ - private long longState = ThreadLocalRandom.current().nextLong(); - /** The int state. */ - private int intState = ThreadLocalRandom.current().nextInt(); - /** - * Get the next long in the sequence. + * Mimic the generation of the SplitMix64 algorithm. * - * @return the long - */ - private long nextLong() { - return longState += GOLDEN_64; - } - - /** - * Get the next int in the sequence. - * - * @return the int + * <p>The final mixing step must be included otherwise the output numbers are sequential + * and the test may run with a lack of numbers with higher order bits. */ - private int nextInt() { - return intState += GOLDEN_32; + @State(Scope.Benchmark) + public static class LongSource { + /** The state. */ + private long state = ThreadLocalRandom.current().nextLong(); + + /** + * Get the next long. + * + * @return the long + */ + public final long nextLong() { + long z = state += 0x9e3779b97f4a7c15L; + z = (z ^ (z >>> 30)) * 0xbf58476d1ce4e5b9L; + z = (z ^ (z >>> 27)) * 0x94d049bb133111ebL; + return z ^ (z >>> 31); + } + + /** + * Get the next int. + * + * <p>Returns the 32 high bits of Stafford variant 4 mix64 function as int. + * + * @return the int + */ + public final int nextInt() { + long z = state += 0x9e3779b97f4a7c15L; + z = (z ^ (z >>> 33)) * 0x62a9d9ed799705f5L; + return (int)(((z ^ (z >>> 28)) * 0xcb24d0a5c88c35b3L) >>> 32); + } } // Benchmark methods /** + * @param source the source * @return the long */ @Benchmark - public long nextDoubleBaseline() { - return nextLong(); + public long nextDoubleBaseline(LongSource source) { + return source.nextLong(); } /** + * @param source the source * @return the double */ @Benchmark - public double nextDoubleUsingBitsToDouble() { + public double nextDoubleUsingBitsToDouble(LongSource source) { // Combine 11 bit unsigned exponent with value 1023 (768 + 255) with 52 bit mantissa // 0x300L = 256 + 512 = 768 // 0x0ff = 255 // This makes a number in the range 1.0 to 2.0 so subtract 1.0 - return Double.longBitsToDouble(0x3ffL << 52 | nextLong() >>> 12) - 1.0; + return Double.longBitsToDouble(0x3ffL << 52 | source.nextLong() >>> 12) - 1.0; } /** + * @param source the source * @return the double */ @Benchmark - public double nextDoubleUsingMultiply52bits() { - return (nextLong() >>> 12) * 0x1.0p-52d; // 1.0 / (1L << 52) + public double nextDoubleUsingMultiply52bits(LongSource source) { + return (source.nextLong() >>> 12) * 0x1.0p-52d; // 1.0 / (1L << 52) } /** + * @param source the source * @return the double */ @Benchmark - public double nextDoubleUsingMultiply53bits() { - return (nextLong() >>> 11) * 0x1.0p-53d; // 1.0 / (1L << 53) + public double nextDoubleUsingMultiply53bits(LongSource source) { + return (source.nextLong() >>> 11) * 0x1.0p-53d; // 1.0 / (1L << 53) } /** + * @param source the source * @return the int */ @Benchmark - public int nextFloatBaseline() { - return nextInt(); + public int nextFloatBaseline(LongSource source) { + return source.nextInt(); } /** + * @param source the source * @return the float */ @Benchmark - public float nextFloatUsingBitsToFloat() { + public float nextFloatUsingBitsToFloat(LongSource source) { // Combine 8 bit unsigned exponent with value 127 (112 + 15) with 23 bit mantissa // 0x70 = 64 + 32 + 16 = 112 // 0x0f = 15 // This makes a number in the range 1.0f to 2.0f so subtract 1.0f - return Float.intBitsToFloat(0x7f << 23 | nextInt() >>> 9) - 1.0f; + return Float.intBitsToFloat(0x7f << 23 | source.nextInt() >>> 9) - 1.0f; } /** + * @param source the source * @return the float */ @Benchmark - public float nextFloatUsingMultiply23bits() { - return (nextInt() >>> 9) * 0x1.0p-23f; // 1.0f / (1 << 23) + public float nextFloatUsingMultiply23bits(LongSource source) { + return (source.nextInt() >>> 9) * 0x1.0p-23f; // 1.0f / (1 << 23) } /** + * @param source the source * @return the float */ @Benchmark - public float nextFloatUsingMultiply24bits() { - return (nextInt() >>> 8) * 0x1.0p-24f; // 1.0f / (1 << 24) + public float nextFloatUsingMultiply24bits(LongSource source) { + return (source.nextInt() >>> 8) * 0x1.0p-24f; // 1.0f / (1 << 24) } }