From e360d9507a698290484f2d6b2ff7941db3d30045 Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Fri, 26 Jan 2001 10:00:39 +0000 Subject: The combo of getstate/setstate/jumpahead is very powerful, but needs examples to flesh it out for the uninitiated. Here they are. --- Lib/random.py | 51 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 6 deletions(-) (limited to 'Lib/random.py') diff --git a/Lib/random.py b/Lib/random.py index a22449cfe6..baebdf0474 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -25,12 +25,51 @@ Translated from anonymously contributed C/C++ source. -Multi-threading note: the random number generator used here is not -thread-safe; it is possible that two calls return the same random -value. But you can instantiate a different instance of Random() in -each thread to get generators that don't share state, then use -.setstate() and .jumpahead() to move the generators to disjoint -segments of the full period. +Multi-threading note: the random number generator used here is not thread- +safe; it is possible that two calls return the same random value. However, +you can instantiate a different instance of Random() in each thread to get +generators that don't share state, then use .setstate() and .jumpahead() to +move the generators to disjoint segments of the full period. For example, + +def create_generators(num, delta, firstseed=None): + ""\"Return list of num distinct generators. + Each generator has its own unique segment of delta elements from + Random.random()'s full period. + Seed the first generator with optional arg firstseed (default is + None, to seed from current time). + ""\" + + from random import Random + g = Random(firstseed) + result = [g] + for i in range(num - 1): + laststate = g.getstate() + g = Random() + g.setstate(laststate) + g.jumpahead(delta) + result.append(g) + return result + +gens = create_generators(10, 1000000) + +That creates 10 distinct generators, which can be passed out to 10 distinct +threads. The generators don't share state so can be called safely in +parallel. So long as no thread calls its g.random() more than a million +times (the second argument to create_generators), the sequences seen by +each thread will not overlap. + +The period of the underlying Wichmann-Hill generator is 6,953,607,871,644, +and that limits how far this technique can be pushed. + +Just for fun, note that since we know the period, .jumpahead() can also be +used to "move backward in time": + +>>> g = Random(42) # arbitrary +>>> g.random() +0.24855401895528142 +>>> g.jumpahead(6953607871644L - 1) # move *back* one +>>> g.random() +0.24855401895528142 """ # XXX The docstring sucks. -- cgit v1.2.1