Skip to content

Fallback rand(Float32/64) discards more entropy than necessary #44887

@danielwe

Description

@danielwe

I just noticed that the current default Xoshiro RNG generates uniform floats with more entropy than other RNGs. The reason appears to be that it has it's own 24/53-bit implementation of the conversion from random bits to uniform floats at

rand(r::Union{TaskLocalRNG, Xoshiro}, ::SamplerTrivial{CloseOpen01{Float32}}) =
Float32(rand(r, UInt32) >>> 8) * Float32(0x1.0p-24)
rand(r::Union{TaskLocalRNG, Xoshiro}, ::SamplerTrivial{CloseOpen01_64}) =
Float64(rand(r, UInt64) >>> 11) * 0x1.0p-53

while the generic conversion uses a bit twiddling 23/52-bit implementation at
rand(r::AbstractRNG, ::SamplerTrivial{CloseOpen01{Float32}}) =
reinterpret(Float32, rand(r, UInt23()) | 0x3f800000) - 1
rand(r::AbstractRNG, ::SamplerTrivial{CloseOpen12_64}) =
reinterpret(Float64, 0x3ff0000000000000 | rand(r, UInt52()))
rand(r::AbstractRNG, ::SamplerTrivial{CloseOpen01_64}) = rand(r, CloseOpen12()) - 1.0

The explanation for this is here:

We still use the 52-bit version for our older RNGs so that they give the same values as before, but for the new xoshiro generator we're using shift-by-11-and-multiply currently.

Originally posted by @JeffBezanson in #33222 (comment)

However, one consequence is that the 23/52-bit conversions are also used by packages that implement their own RNG and provide only the minimal bit sampling interface, relying on generic fallbacks to produce floats. This includes, e.g., the native RNGs in CUDA.jl and StableRNGs.jl, but also any RNG library developed in the future.

Not sure if this is intended or unintended? I suppose it's desirable in the case of StableRNGs, but not so much in the case of future implementations. Wouldn't it be better to have the 24/53-bit conversion be the generic fallback, and rather specialize to the 23/52-bit conversion for legacy RNGs? StableRNGs could implement its own conversion if it wants to promise cross-version stability of float sequences.

Noticed this while investigating JuliaGPU/CUDA.jl#1464

Metadata

Metadata

Assignees

No one assigned

    Labels

    randomnessRandom number generation and the Random stdlib

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions