Class ZigguratSamplerPerformance


  • public class ZigguratSamplerPerformance
    extends Object
    Executes a benchmark to compare the speed of generation of random numbers using variations of the ziggurat method.
    • Method Detail

      • baseline

        public double baseline()
        Baseline for the JMH timing overhead for production of an double value.
        Returns:
        the double value
      • getIndex

        public int getIndex​(ZigguratSamplerPerformance.IndexSources sources)
        Benchmark methods for obtaining an index from the lower bits of a long.

        Note: This is disabled as there is no measurable difference between methods.

        Parameters:
        sources - Source of randomness.
        Returns:
        the sample value
      • compareIndex

        public int compareIndex​(ZigguratSamplerPerformance.IndexCompareSources sources)
        Benchmark methods for obtaining an index from the lower bits of a long and comparing them to a limit then returning the index as an int.

        Note: This is disabled as there is no measurable difference between methods.

        Parameters:
        sources - Source of randomness.
        Returns:
        the sample value
      • getUnsignedLong

        public long getUnsignedLong​(ZigguratSamplerPerformance.LongSources sources)
        Benchmark methods for obtaining an unsigned long.

        Note: This is disabled. Either there is no measurable difference between methods or the bit shift method is marginally faster depending on JDK and platform.

        Parameters:
        sources - Source of randomness.
        Returns:
        the sample value
      • interpolate

        public double interpolate​(ZigguratSamplerPerformance.InterpolationSources sources)
        Benchmark methods for obtaining an interpolated value from an unsigned long.

        Note: This is disabled. The speed is typically: U1, 1minusU2, U_1minusU.

        Parameters:
        sources - Source of randomness.
        Returns:
        the sample value
      • signBit

        public double signBit​(ZigguratSamplerPerformance.SignBitSources sources)
        Benchmark methods for obtaining a sign value from a long.

        Note: This is disabled. The branchless versions using a subtraction of 2 - 1 or 0 - 1 are faster.

        Parameters:
        sources - Source of randomness.
        Returns:
        the sample value
      • diff

        public long[] diff​(ZigguratSamplerPerformance.DiffSources sources)
        Benchmark methods for obtaining 2 random longs in ascending order.

        Note: This is disabled. The branchless versions using a ternary conditional assignment are faster. This may not manifest as a performance improvement when used in the ziggurat sampler as it is not on the hot path (i.e. sampling inside the ziggurat).

        Parameters:
        sources - Source of randomness.
        Returns:
        the sample value
      • exp

        public double exp​(ZigguratSamplerPerformance.ExpSources sources)
        Benchmark methods for obtaining exp(z) when -8 <= z <= 0.

        Note: This is disabled. On JDK 8 FastMath is faster. On JDK 11 Math.exp is a hotspot intrinsic and may be faster based on the platform architecture. Example results:

                             JDK 8                     JDK 11
                             i7-6820HQ     E5-1680     i7-6820HQ     E5-1680     3960X
         noop                    4.523       3.871         4.351       4.206     3.936
         Math.exp               61.350      48.519        22.552      19.195    12.568
         FastMath.exp           33.858      24.469        31.396      24.568    11.159
         

        The ziggurat sampler avoids calls to Math.exp in the majority of cases when using McFarland's fast method for overhangs which exploit the known maximum difference between pdf(x) and the triangle hypotenuse. Example data of the frequency that Math.exp is called per sample from the base implementations (using n=2^31):

                    Calls            FastOverhangs     SimpleOverhangs
         Exp        exp(-x)          0.00271           0.0307
         Normal     exp(-0.5*x*x)    0.00359           0.0197*
        
         * Increases to 0.0198 if the tail exponential sampler uses simple overhangs
         

        Note that the maximum difference between pdf(x) and the triangle hypotenuse is smaller for the exponential distribution; thus the fast method can avoid using Math.exp more often. In the case of simple overhangs the normal distribution has more region covered by the ziggurat thus has a lower frequency of overhang sampling.

        A significant speed-up of the exp function may improve run-time of the simple overhangs method. Any effect on the fast method is less likely to be noticed. This is observed in benchmark times which show an improvement of the simple overhangs method for the exponential relative to other methods on JDK 11 vs 8. However the simple overhangs is still slower as the exponential distribution is always concave and upper-right triangle samples are avoided by the fast overhang method.

        Parameters:
        sources - Source of randomness.
        Returns:
        the sample value