1 /** 2 * Simple speed shootout benchmark between the generators 3 * implemented in this package and the default phobos 4 * random number generator. 5 * 6 * Usage: 7 * ------ 8 * dxorshift_benchmark [-n N] [--seed S] 9 * 10 * -n specify number of calls to the RNG 11 * in the benchmark; if not specified, 12 * 10 ^^ 9 will be used by default 13 * 14 * --seed, -s specify the seed to provide to the 15 * benchmarked RNGS; if not specified, 16 * an unpredictable seed will be used. 17 * ------ 18 * 19 * Authors: 20 * $(LINK2 http://braingam.es/, Joseph Rushton Wakeling) 21 * 22 * Copyright: 23 * Written in 2016 by Joseph Rushton Wakeling. 24 * 25 * License: 26 * $(LINK2 https://creativecommons.org/publicdomain/zero/1.0/legalcode, Creative Commons CC0) 27 * (public domain) 28 */ 29 module benchmark.app; 30 31 void main(string[] args) 32 { 33 import std.conv : to; 34 import std.datetime : benchmark, Duration; 35 import std.getopt : getopt; 36 import std.random : Random, unpredictableSeed; 37 import std.stdio : writeln, writefln; 38 39 import dxorshift.splitmix64; 40 import dxorshift.xoroshiro128plus; 41 import dxorshift.xorshift1024star; 42 43 uint repeats; 44 45 uint seed; 46 47 getopt(args, 48 "|n", &repeats, 49 "seed|s", &seed); 50 51 if (!repeats) 52 { 53 repeats = 1_000_000_000u; 54 writefln("Number of variates not specified: defaulting to %s", repeats); 55 } 56 57 if (!seed) 58 { 59 seed = unpredictableSeed; 60 } 61 62 writefln("Seeding generators with %s", seed); 63 64 auto genX128 = Xoroshiro128plus(seed); 65 66 auto genX1024 = Xorshift1024star(seed); 67 68 auto genSM64 = SplitMix64(seed); 69 70 auto genDefault = Random(seed); 71 72 // summing over all generated variates adds 73 // a little overhead, but prevents spurious 74 // optimizations of generator `popFront()` 75 // calls: e.g. since `SplitMix64.popFront()` 76 // is just an addition, any arbitrary number 77 // of calls can be optimized away at compile 78 // time unless `.front` values are actually 79 // used for something 80 ulong variateSum; 81 82 void variateX128() 83 { 84 variateSum += genX128.front; 85 genX128.popFront(); 86 } 87 88 void variateX1024() 89 { 90 variateSum += genX1024.front; 91 genX1024.popFront(); 92 } 93 94 void variateSM64() 95 { 96 variateSum += genSM64.front; 97 genSM64.popFront(); 98 } 99 100 void variateDefault() 101 { 102 variateSum += genDefault.front; 103 genDefault.popFront(); 104 } 105 106 107 auto bench = benchmark!(variateX128, variateX1024, variateSM64, variateDefault)(repeats); 108 auto benchX128 = to!Duration(bench[0]); 109 auto benchX1024 = to!Duration(bench[1]); 110 auto benchSM64 = to!Duration(bench[2]); 111 auto benchDefault = to!Duration(bench[3]); 112 113 writefln("xoroshiro128+ benchmark for %s variates: %s", repeats, benchX128); 114 writefln("last variate: %s", genX128.front); 115 writeln(); 116 117 writefln("xorshift1024* benchmark for %s variates: %s", repeats, benchX1024); 118 writefln("last variate: %s", genX1024.front); 119 writeln(); 120 121 writefln("splitmix64 benchmark for %s variates: %s", repeats, benchSM64); 122 writefln("last variate: %s", genSM64.front); 123 writeln(); 124 125 writefln("Default phobos RNG benchmark for %s variates: %s", repeats, benchDefault); 126 writefln("last variate: %s", genDefault.front); 127 }