Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upChange in runif() behavior in Rcpp 0.12.16 #836
Comments
|
This definitely has something to do with the RNG state. I suspect I broke this somehow with this commit: The following example provides the expected results: #include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector sim_crossovers_orig(const double L)
{
int n_xo;
GetRNGstate();
n_xo = R::rpois(L/100.0);
PutRNGstate();
GetRNGstate();
NumericVector tmp = runif(n_xo, 0.0, L);
PutRNGstate();
return tmp.sort();
}
/*** R
set.seed(20180318)
z <- replicate(10000, sim_crossovers_orig(100))
table(sapply(z, length))
## 0 1 2 3 4 5 6
## 3661 3681 1837 631 151 35 4
*/ |
|
Argh. Let's understand where this issue is coming from. The call to Rcpp/inst/include/Rcpp/stats/random/random.h Lines 307 to 309 in 9c1c356 We use the 'fill' constructor of Rcpp/inst/include/Rcpp/stats/random/runif.h Lines 45 to 55 in 9c1c356 It inherits from something called 'Generator'. What is that? Well, it lives here: Rcpp/inst/include/Rcpp/stats/random/random.h Lines 27 to 31 in 9c1c356 In other words, all our generator objects inherit from RNGScope. Which means every time a generator is constructed, and then destructed, it's now (indiscriminately) getting and setting the RNG state. Before, this didn't happen because these RNGScope calls were effectively screened by a global counter. But now, all of the Rcpp sugar random functions are getting and setting the RNG state -- potentially before other calls to R's C APIs for random number generation have had a chance to synchronize the R-level seed with the C-level seed. It also doesn't help that apparently these generator objects get copied around a bit, which imply a few spurious calls to tl;dr: I broke it. Sorry for the trouble :-/ The issue can be fixed by making sure our generators don't inherit from RNGScope, and can be worked around on your side (in the interim) by surrounding any calls of the 'random' functions in the |
|
Nice analysis. The only other breakage we had seen was in ECctmc where I liased with the maintainer. So I guess the breakage was a little wider that we thought :-/ |
|
thanks, @kevinushey! |
|
@kbroman For completeness, were you able to check that the now-merged PR fixes your test failures? |
|
@eddelbuettel Yes, the PR fixed my test failures; thanks! |
|
Thanks for confirming, and sorry for the breakage. We usually manage to do better, but the shiny folks wanted a change so ... it happened. |
|
@eddelbuettel Absolutely no problem; only praise from me for Rcpp! And reducing my mess to a reasonably concise reproducible example was an interesting puzzle. |
With Rcpp 0.12.16, my simcross package started throwing errors in the tests. I don't fully understand what's going on, but it seems related to me calling
runif(n,0,L)withn==0.Consider the following code (also available as a gist). This simulates a Poisson process on the interval (0,L) by drawing a Poisson number of points and then drawing their positions from a uniform distribution. There are two versions of the function; in the first, I don't try to trap the
n==0cases; in the latter I callrunif()only withn>0.With Rcpp ver 0.12.15, these two functions give the same results.
But with Rcpp ver 0.12.16, the former gives a ton of 0-length vectors, while the latter works fine, though it gives somewhat different results from ver 0.12.15. (The tables being printed should be 10,000 draws from a Poisson distribution with mean 1.)
I've tried this in both Linux and MacOS (High Sierra), and with R 3.4.3 and 3.4.4, with the same results in all cases. (Just the version of Rcpp matters.)
Here's my session info in the Rcpp 0.12.16 case on my Mac: