-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using std::normal_distribution
rather than inverse transform sampling?
#196
Comments
Hello Matt. Thanks for your interest!
I didn't know this. Can you provide a source (not that I don't believe you, but I'd like to read more)? I'd be more than happy to review a PR if you'd like to contribute? Also, out of paranoia, are there any cheeky differing factors of |
In looking for a reference for this I think I've instead found that it might have been an outdated belief on my part about the accuracy of numerical approximations to the inverse error function 😅. There is a discussion of the relative precision of the the inverse transform and Box-Muller methods for generating normal random variates in this blog post by Christian Robert which found that counter to his expectations the inverse transform method remained accurate in the tails and I've just a quick investigation with
I'd be happy to submit a PR though equally if you think in the context of above its not worthwhile that's also fine.
Good catch - there is indeed a missing factor of std::normal_distribution<double> normal_half_var(0, 1 / sqrt(2));
...
auto rvx = normal_half_var(rng_phasespace);
auto rvy = normal_half_var(rng_phasespace);
auto rvz = normal_half_var(rng_phasespace); to match current distribution. |
Great, thanks for this, and I'm happy to hear that I have unknowingly not fallen into a trap by avoiding the extra couple of lines required to write a Box-Muller transform. I think using a normal distribution is less surprising than the |
The lines
NESO/solvers/Electrostatic2D3V/ParticleSystems/charged_particles.hpp
Lines 255 to 257 in 9423bff
are I think sampling Cartesian components of a velocity vector from independent standard normal distributions, using an inverse transform sampling approach. While it probably has a negligible performance impact overall, for a standard normal distribution inverse transform sampling is generally a relatively inefficient way to generate random variates, and the implementation of random variate generation for
std::normal_distribution
is likely to be quicker (*). Probably more importantly, inverse transform sampling can also be less numerically stable than alternatives when sampling values in the tails of the distribution, depending on how accurate the inverse cumulative distribution function / (or here inverse error function) approximation is, and also I would say is less readable compared to something likeIs there some other reason for preferring the current inverse transform sampling approach that I'm missing though?
(*) Sampling with
std::normal_distribution
appears to be about 2× quicker than the current inverse transform sampling method in the example below on my laptop.Microbenchmark
Output
The text was updated successfully, but these errors were encountered: