001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.rng.examples.jmh.sampling.distribution;
019
020import org.apache.commons.rng.UniformRandomProvider;
021import org.apache.commons.rng.examples.jmh.RandomSources;
022import org.apache.commons.rng.sampling.distribution.AhrensDieterExponentialSampler;
023import org.apache.commons.rng.sampling.distribution.AhrensDieterMarsagliaTsangGammaSampler;
024import org.apache.commons.rng.sampling.distribution.BoxMullerNormalizedGaussianSampler;
025import org.apache.commons.rng.sampling.distribution.ChengBetaSampler;
026import org.apache.commons.rng.sampling.distribution.ContinuousSampler;
027import org.apache.commons.rng.sampling.distribution.ContinuousUniformSampler;
028import org.apache.commons.rng.sampling.distribution.InverseTransformParetoSampler;
029import org.apache.commons.rng.sampling.distribution.LevySampler;
030import org.apache.commons.rng.sampling.distribution.LogNormalSampler;
031import org.apache.commons.rng.sampling.distribution.MarsagliaNormalizedGaussianSampler;
032import org.apache.commons.rng.sampling.distribution.StableSampler;
033import org.apache.commons.rng.sampling.distribution.TSampler;
034import org.apache.commons.rng.sampling.distribution.ZigguratSampler;
035import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler;
036
037import org.openjdk.jmh.annotations.Benchmark;
038import org.openjdk.jmh.annotations.BenchmarkMode;
039import org.openjdk.jmh.annotations.Fork;
040import org.openjdk.jmh.annotations.Measurement;
041import org.openjdk.jmh.annotations.Mode;
042import org.openjdk.jmh.annotations.OutputTimeUnit;
043import org.openjdk.jmh.annotations.Param;
044import org.openjdk.jmh.annotations.Scope;
045import org.openjdk.jmh.annotations.Setup;
046import org.openjdk.jmh.annotations.State;
047import org.openjdk.jmh.annotations.Warmup;
048
049import java.util.concurrent.TimeUnit;
050
051/**
052 * Executes benchmark to compare the speed of generation of random numbers
053 * from the various source providers for different types of {@link ContinuousSampler}.
054 */
055@BenchmarkMode(Mode.AverageTime)
056@OutputTimeUnit(TimeUnit.NANOSECONDS)
057@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
058@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
059@State(Scope.Benchmark)
060@Fork(value = 1, jvmArgs = {"-server", "-Xms128M", "-Xmx128M"})
061public class ContinuousSamplersPerformance {
062    /**
063     * The value.
064     *
065     * <p>This must NOT be final!</p>
066     */
067    private double value;
068
069    /**
070     * The {@link ContinuousSampler} samplers to use for testing. Creates the sampler for each
071     * {@link org.apache.commons.rng.simple.RandomSource RandomSource} in the default
072     * {@link RandomSources}.
073     */
074    @State(Scope.Benchmark)
075    public static class Sources extends RandomSources {
076        /**
077         * The sampler type.
078         */
079        @Param({"BoxMullerNormalizedGaussianSampler",
080                "MarsagliaNormalizedGaussianSampler",
081                "ZigguratNormalizedGaussianSampler",
082                "ZigguratSampler.NormalizedGaussian",
083                "AhrensDieterExponentialSampler",
084                "ZigguratSampler.Exponential",
085                "AhrensDieterGammaSampler",
086                "MarsagliaTsangGammaSampler",
087                "LevySampler",
088                "LogNormalBoxMullerNormalizedGaussianSampler",
089                "LogNormalMarsagliaNormalizedGaussianSampler",
090                "LogNormalZigguratNormalizedGaussianSampler",
091                "LogNormalSampler.ZigguratSampler.NormalizedGaussian",
092                "ChengBetaSampler",
093                "ContinuousUniformSampler",
094                "InverseTransformParetoSampler",
095                "StableSampler",
096                "TSampler"})
097        private String samplerType;
098
099        /** The sampler. */
100        private ContinuousSampler sampler;
101
102        /**
103         * @return the sampler.
104         */
105        public ContinuousSampler getSampler() {
106            return sampler;
107        }
108
109        /** Instantiates sampler. */
110        @Override
111        @Setup
112        public void setup() {
113            super.setup();
114            final UniformRandomProvider rng = getGenerator();
115            if ("BoxMullerNormalizedGaussianSampler".equals(samplerType)) {
116                sampler = BoxMullerNormalizedGaussianSampler.of(rng);
117            } else if ("MarsagliaNormalizedGaussianSampler".equals(samplerType)) {
118                sampler = MarsagliaNormalizedGaussianSampler.of(rng);
119            } else if ("ZigguratNormalizedGaussianSampler".equals(samplerType)) {
120                sampler = ZigguratNormalizedGaussianSampler.of(rng);
121            } else if ("ZigguratSampler.NormalizedGaussian".equals(samplerType)) {
122                sampler = ZigguratSampler.NormalizedGaussian.of(rng);
123            } else if ("AhrensDieterExponentialSampler".equals(samplerType)) {
124                sampler = AhrensDieterExponentialSampler.of(rng, 4.56);
125            } else if ("ZigguratSampler.Exponential".equals(samplerType)) {
126                sampler = ZigguratSampler.Exponential.of(rng, 4.56);
127            } else if ("AhrensDieterGammaSampler".equals(samplerType)) {
128                // This tests the Ahrens-Dieter algorithm since alpha < 1
129                sampler = AhrensDieterMarsagliaTsangGammaSampler.of(rng, 0.76, 9.8);
130            } else if ("MarsagliaTsangGammaSampler".equals(samplerType)) {
131                // This tests the Marsaglia-Tsang algorithm since alpha > 1
132                sampler = AhrensDieterMarsagliaTsangGammaSampler.of(rng, 12.34, 9.8);
133            } else if ("LevySampler".equals(samplerType)) {
134                sampler = LevySampler.of(rng, 1.23, 4.56);
135            } else if ("LogNormalBoxMullerNormalizedGaussianSampler".equals(samplerType)) {
136                sampler = LogNormalSampler.of(BoxMullerNormalizedGaussianSampler.of(rng), 12.3, 4.6);
137            } else if ("LogNormalMarsagliaNormalizedGaussianSampler".equals(samplerType)) {
138                sampler = LogNormalSampler.of(MarsagliaNormalizedGaussianSampler.of(rng), 12.3, 4.6);
139            } else if ("LogNormalZigguratNormalizedGaussianSampler".equals(samplerType)) {
140                sampler = LogNormalSampler.of(ZigguratNormalizedGaussianSampler.of(rng), 12.3, 4.6);
141            } else if ("LogNormalSampler.ZigguratSampler.NormalizedGaussian".equals(samplerType)) {
142                sampler = LogNormalSampler.of(ZigguratSampler.NormalizedGaussian.of(rng), 12.3, 4.6);
143            } else if ("ChengBetaSampler".equals(samplerType)) {
144                sampler = ChengBetaSampler.of(rng, 0.45, 6.7);
145            } else if ("ContinuousUniformSampler".equals(samplerType)) {
146                sampler = ContinuousUniformSampler.of(rng, 123.4, 5678.9);
147            } else if ("InverseTransformParetoSampler".equals(samplerType)) {
148                sampler = InverseTransformParetoSampler.of(rng, 23.45, 0.1234);
149            } else if ("StableSampler".equals(samplerType)) {
150                sampler = StableSampler.of(rng, 1.3, 0.2);
151            } else if ("TSampler".equals(samplerType)) {
152                sampler = TSampler.of(rng, 1.23);
153            }
154        }
155    }
156
157    // Benchmarks methods below.
158
159    /**
160     * Baseline for the JMH timing overhead for production of an {@code double} value.
161     *
162     * @return the {@code double} value
163     */
164    @Benchmark
165    public double baseline() {
166        return value;
167    }
168
169    /**
170     * Run the sampler.
171     *
172     * @param sources Source of randomness.
173     * @return the sample value
174     */
175    @Benchmark
176    public double sample(Sources sources) {
177        return sources.getSampler().sample();
178    }
179}