Skip to content

Random.randbelow speed up by using larger variates #154656

Description

@isaacl

Feature or enhancement

Proposal:

_randbelow is implemented as a loop polling r = self.getrandbits(k) # 0 <= r < 2**k until r < n. For small n, such as when used in shuffle, this can force re-rolls.

But if poll with a larger random, we minimize re-rolls. The cPython intrinsic can return of 32 random bits at a time for the same cost as a smaller number of bits. So essentially, if we assume we can get multiples of 32 random bits for free:

bits = (n.bit_length() + 31) & ~31  # round up to next multiple of 32
max_rand = 1 << bits  # max value from getrandbits
limit = max_rand - (max_rand % n)   # reject anything above limit
while (r := self.getrandbits(bits)) >= limit:
  pass
return r % n

See also OpenJDK

Has this already been discussed elsewhere?

This is a minor feature, which does not need previous discussion elsewhere

Links to previous discussion of this feature:

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirpendingThe issue will be closed if no feedback is providedperformancePerformance or resource usagetype-featureA feature request or enhancement

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions