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}