Context RcppZiggurat Accuracy Speed Summary RcppZiggurat: Faster Random Normal Draws Dr. Dirk Eddelbuettel [email protected] [email protected] @eddelbuettel useR! 2014 UCLA, 1 July 2014 Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary Overview Ziggurat Outline 1 Context Overview Ziggurat Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary Overview Ziggurat R and RNGs R has “batteries included”: Excellent support for random number generation Documentation isn’t all that easy to find: RNGkind There are four Normal RNGs in R (and six Uniforms) Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary Overview Ziggurat R Normal RNGs library(microbenchmark) res <- microbenchmark({RNGkind(,"Kinderman-Ramage"); rnorm(1e6)}, {RNGkind(,"Ahrens-Dieter"); rnorm(1e6)}, {RNGkind(,"Box-Muller"); rnorm(1e6)}, {RNGkind(,"Inversion"); rnorm(1e6)}, times=100) Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary Overview Ziggurat R Normal RNGs Time for 100 times 1e6 normal draws Time in msec 400 300 200 100 AH KR Dirk Eddelbuettel Inv RcppZiggurat BM Context RcppZiggurat Accuracy Speed Summary Overview Ziggurat Marsaglia and Tsang, JSS, 2000 Introduce a very small, very fast generator Just a few lines of C code (in MACROS) Plus two support functions But 32-bit only (which was ok at the time...) Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary Overview Ziggurat Marsaglia and Tsang, JSS, 2000 #include <math.h> static unsigned long jz,jsr=123456789; #define SHR3 (jz=jsr, jsr^=(jsr<<13), jsr^=(jsr>>17), \ jsr^=(jsr<<5),jz+jsr) #define UNI (.5 + (signed) SHR3*.2328306e-9) #define IUNI SHR3 static long hz; static unsigned long iz, kn[128], ke[256]; static float wn[128],fn[128], we[256],fe[256]; #define RNOR (hz=SHR3, iz=hz&127, \ (fabs(hz)<kn[iz])? hz*wn[iz] : nfix()) Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary Overview Ziggurat Leong, Zhang et al, JSS, 2005 Three page note extending Ziggurat Show a flaw in the underlying U(0,1) generator SHR3 Plugging in KISS, another Marsaglia U(0,1), as fix This correction is not always used (!!) And is still 32-bit only Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary Overview Ziggurat Widely used Open Source generators Lots of other scripting languages have Ziggurat It is sometimes their default GNU GSL has a widely used implementation by Voss GNU Gretl borrows from it, as does QuantLib Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary Base Derived Performance Outline 2 RcppZiggurat Base Derived Performance Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary Base Derived Performance Virtual Base Class #include <cmath> #include <stdint.h> // cstdint needs C++11 namespace Ziggurat { class Zigg { public: virtual ∼Zigg() {}; virtual void setSeed(const uint32_t s)=0; // no getSeed() as GSL has none virtual double norm() = 0; }; } Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary Base Derived Performance Our package provides several implementations Our default Ziggurat class implements LZLLV in 32 and 64 bit mode For comparison, we also have implementations ZigguratMT of Marsaglia and Tsang ZigguratLZLLV of Leong, Zhang et al (also the default) ZigguratGSL using the GNU GSL (by linking to GSL) ZigguratGl using the GNU Gretl generator (as an adapted copy) ZigguratQL using the QuantLib generator (as an adapted copy) Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary Base Derived Performance Ziggurat RNGs Time for 100 times 1e6 normal draws Time in msec 150 100 50 Zigg ZiggGSL Dirk Eddelbuettel ZiggQL ZiggGretl RcppZiggurat RInv Context RcppZiggurat Accuracy Speed Summary Standard Test Normal Test Chi-Square Test Outline 3 Accuracy Standard Test Normal Test Chi-Square Test Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary Standard Test Normal Test Chi-Square Test Use standard test for any Uniform generator Invert each Ziggurat draw from N(0,1) to U(0,1) n draws from a U(0, 1); compute sum of the n values. Repeat m times to create m sums of uniform RNGs. With n large, the m results converge towards p N(n/2, n/12) (Irwin-Hall distribution of sum of uniformly distributed values). Construct a p-value pi for each of m values using the inverse of the Normal using the known mean and standard dev. from the Irwin-Hall distribution. With m uniformly distributed values: standard tests such as Kolmogorov-Smirnow or Wilcoxon can be used to test for departures from uniform. Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary Standard Test Normal Test Chi-Square Test Standard test results MT 0.4 0.6 0.8 1.0 0.8 0.0 0.0 0.2 0.4 0.6 0.8 1.0 0.2 0.4 0.6 x x x QL Gretl 0.4 0.6 0.8 1.0 0.8 0.8 1.0 0.8 1.0 pKS: 0.2133 pWil.: 0.3365 0.0 0.4 Fn(x) 0.8 0.4 Fn(x) pKS: 0.0435 pWil.: 0.0335 0.0 0.0 0.2 0.0 GSL pKS: 0.6294 pWil.: 0.5647 0.0 pKS: 0.3597 pWil.: 0.3741 0.4 Fn(x) Fn(x) pKS: 0 pWil.: 0.7583 0.0 0.4 0.2 0.4 0.8 0.0 Fn(x) LZLLV 0.4 0.8 pKS: 0.3597 pWil.: 0.3741 0.0 Fn(x) 0.8 Ziggurat 0.0 0.2 0.4 0.6 0.8 1.0 0.0 0.2 Draws:5e+09 Repeats: 100 Seed: 123456789 Created at: 2014−06−18 18:59:41 Version: 0.1.2.2 x x Dirk Eddelbuettel RcppZiggurat 0.4 0.6 x Context RcppZiggurat Accuracy Speed Summary Standard Test Normal Test Chi-Square Test Suggested new test for N(0,1) generator n from a N(0, 1), then compute sum of the n values. Repeats m times to create m sums of N(0,1) draws. √ With n large, the m results converge to N(0, n). Construct a p-value pi for each of the m values using the inverse of the Normal distribution. With m uniformly distributed values: standard tests such as Kolmogorov-Smirnow or Wilcoxon can be used to test for departures from uniform. Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary Standard Test Normal Test Chi-Square Test Normal test results MT 0.4 0.6 0.8 1.0 0.8 0.0 0.0 0.2 0.4 0.6 0.8 1.0 0.2 0.4 0.6 x x x QL Gretl 0.4 0.6 0.8 1.0 0.8 0.8 1.0 0.8 1.0 pKS: 0.7187 pWil.: 0.5236 0.0 0.4 Fn(x) 0.8 0.4 Fn(x) pKS: 0.0378 pWil.: 0.0602 0.0 0.0 0.2 0.0 GSL pKS: 0.4003 pWil.: 0.3704 0.0 pKS: 0.4365 pWil.: 0.4301 0.4 Fn(x) Fn(x) pKS: 0 pWil.: 0.0399 0.0 0.4 0.2 0.4 0.8 0.0 Fn(x) LZLLV 0.4 0.8 pKS: 0.4365 pWil.: 0.4301 0.0 Fn(x) 0.8 Ziggurat 0.0 0.2 0.4 0.6 0.8 1.0 0.0 0.2 Draws:5e+09 Repeats: 100 Seed: 123456789 Created at: 2014−06−18 10:24:03 Version: 0.1.2.2 x x Dirk Eddelbuettel RcppZiggurat 0.4 0.6 x Context RcppZiggurat Accuracy Speed Summary Standard Test Normal Test Chi-Square Test Chi-square test by Leong et al Divide real line into B equally spaced bins such that no N(0, 1) draw should exceed furthest. Follow Leong et al: range from -7 to 7 with 200 bins. Large number of N(0, 1) drawn; for each of a counter in the bin corresponding to the draw is increased. After N draws, the empirical distribution is compared to the theoretical (provided by the corresponding value of the Normal density function) using a standard chi 2 test. Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary Standard Test Normal Test Chi-Square Test Chi−square test results 8e+09 0e+00 4e+09 8e+09 0e+00 4e+09 res[, 1] QL Gretl 8e+09 0 res[, i] res[, i] 0 4e+09 8e+09 200 400 600 res[, 1] GSL 200 400 600 res[, 1] 0 0e+00 200 400 600 0 res[, i] res[, i] 0 4e+09 200 400 600 0e+00 res[, i] LZLLV 200 400 600 200 400 600 MT 0 res[, i] Ziggurat 0e+00 4e+09 8e+09 0e+00 4e+09 Total draws:1e+10 Bins: 200 Seed: 123456789 Steps: 50 Created at: 2014−06−18 07:03:45 Version: 0.1.2.2 res[, 1] res[, 1] res[, 1] Dirk Eddelbuettel RcppZiggurat 8e+09 Context RcppZiggurat Accuracy Speed Summary Outline 4 Speed Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary Comparison to R, Boost and C++11 We posted an Rcpp Gallery article ’Timing normal RNGs’ comparing the Normal RNG generators of R (via Rcpp), Boost and C++. We can now include the (default) Ziggurat method: R> print(res[,1:4]) test replications elapsed relative 4 zrnorm(n) 500 1.397 1.000 3 cxx11Normals(n) 500 4.917 3.520 2 boostNormals(n) 500 5.114 3.661 1 rcppNormals(n) 500 6.166 4.414 R> Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary Outline 5 Summary Dirk Eddelbuettel RcppZiggurat Context RcppZiggurat Accuracy Speed Summary RcppZiggurat RcppZiggurat implements updated Ziggurat generators which now work for 32- and 64-bit OSs Simple use: Include a single header (per generator) Generator is fast, small, tested and has minimal state This makes it particularly useful for thread-local use in parallel simulations. Package has been on CRAN for a few months, will get update in the next few weeks. Dirk Eddelbuettel RcppZiggurat
© Copyright 2026 Paperzz