7

I have been using numpy's random functionality for a while, by calling methods such as np.random.choice() or np.random.randint() etc. I just now found about the ability to create a default_rng object, or other Generator objects:

from numpy.random import default_rng
gen = default_rng()
random_number = gen.integers(10)

So far I would have always used

np.random.randint(10)

instead, and I am wondering what the difference between both ways is.

The only benefit I can think of would be keeping track of multiple seeds, or wanting to use specific PRNGs, but maybe there are also differences for a more generic use-case?

johannesack
  • 660
  • 3
  • 19
  • 1
    `randint` and other functions of `np.random` are now deprecated in favor of generators. The ability to use multiple independent streams of random numbers is one of their benefits, but generators also allow you to choose between different [bit generator algorithms](https://docs.scipy.org/doc/numpy/reference/random/bit_generators/index.html), or even implement your own, so it is more flexible and may make reproducibility easier too. – jdehesa Mar 09 '20 at 11:06
  • The reproducibilty and flexibility arguments do make sense, although I guess writing your own bit generator is mostly limited to cryptographic application? – johannesack Mar 09 '20 at 11:16
  • 1
    Yes, I'd say that is limited to very specific applications, research/study or particular cases where you are trying to match exactly the behavior of some other piece of software. – jdehesa Mar 09 '20 at 11:23
  • Does this answer your question? [How to use numpy.random to generate random numbers from a certain distribution?](https://stackoverflow.com/questions/59728162/how-to-use-numpy-random-to-generate-random-numbers-from-a-certain-distribution) – Peter O. Mar 09 '20 at 15:32
  • @PeterO. Not exactly, I do understand the usage, I was wondering if there were some underlying differences that I should be aware off. Or if there were any non-obvious benefits to switching to the new interface, etc. – johannesack Mar 09 '20 at 19:07

1 Answers1

10

numpy.random.* functions (including numpy.random.binomial) make use of a global pseudorandom number generator (PRNG) object which is shared across the application. On the other hand, default_rng() is a self-contained Generator object that doesn't rely on global state.

If you don't care about reproducible "randomness" in your application, these two approaches are equivalent for the time being. Although NumPy's new RNG policy discourages the use of global state in general, it did not deprecate any numpy.random.* functions in version 1.17, although a future version of NumPy might.

Note also that because numpy.random.* functions rely on a global PRNG object that isn't thread-safe, these functions can cause race conditions if your application uses multiple threads. (Generator objects are not thread-safe, either, but there are ways to generate pseudorandom numbers via multithreading, without the need to share PRNG objects across threads.)

Peter O.
  • 32,158
  • 14
  • 82
  • 96