# Counting number of times a RNG is called

**URL:** <https://discourse.julialang.org/t/counting-number-of-times-a-rng-is-called/24903>\
**Category:** General Usage\
**Created:** [June 4, 2019, 1:40am UTC](https://discourse.julialang.org/t/counting-number-of-times-a-rng-is-called/24903 "2019-06-04T01:40:36Z")\
**Posts on this page:** 3\
**Page:** 2

<div class="post-metadata">

**Author:** ![rfourquet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rfourquet/32/3610_2.png) [@rfourquet](https://discourse.julialang.org/u/rfourquet)\
**Post date:** [June 8, 2019, 4:07pm UTC](https://discourse.julialang.org/t/counting-number-of-times-a-rng-is-called/24903/21 "2019-06-08T16:07:29Z")

</div>

> [@MFairley](#):
>
> it seems like I need to redefine all the `Sampler` and `rand` methods to work with CountingRNG

Yes, but the example I gave does just that, with a catch-all method. The problem is that you will get ambiguities in some cases, it would be great to figure a way to have less of those in `Random`.

> [@MFairley](#):
>
> Is this approach robust in that if I forget to define a method then the call will produce an error and I won’t end up silently not counting some random number generation?

In the example I gave yes, at least when wrapping `MersenneTwister` (and most likely for all currently existing generators, unless they specialize generation of `UInt52`). You can’t predict how a function will use an RNG. In the case of `randn`, only by looking at the source code can you see that it uses `rand(UInt52())` and decide to count that the same as if it was generating a `Float64`. Another routine could generate an `Int` and treat it as a `Float64`. Ultimately, an `RNG` just produces random bits which are put together into a value of a certain type. Another way to solve the problem is to count the number of generated bits, at the lower level of the generator. But then you don’t discriminate between e.g. integers and floats.

---

<div class="post-metadata">

**Author:** ![MFairley](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mfairley/32/8599_2.png) [@MFairley](https://discourse.julialang.org/u/MFairley)\
**Post date:** [June 9, 2019, 12:29am UTC](https://discourse.julialang.org/t/counting-number-of-times-a-rng-is-called/24903/23 "2019-06-09T00:29:18Z")

</div>

> [@rfourquet](#):
>
> Another way to solve the problem is to count the number of generated bits, at the lower level of the generator. But then you don’t discriminate between e.g. integers and floats.

Thanks. How would I count the number of generated bits as an alternative to defining all these rand methods? I think this approach would actually suit my use case better because I am generating different types of random numbers across different estimators. E.g. some estimators require a random integer. If generating different types uses different numbers of bits then it would be better to measure the number of generated bits to have a standardized measurement across estimators.

As for the original approach, I hit another ambiguous method error when using `sample(rng, 1:N, m, replace=false)` from StatsBase.jl.

MethodError: Random.Sampler(::Type{EVSI.CountingRNG{MersenneTwister}}, ::UnitRange{Int64}, ::Val{1}) is ambiguous. Candidates:  
(::Type{Random.Sampler})(::Type{EVSI.CountingRNG{T}}, X, n::Union{Val{1}, Val{Inf}}) where T in EVSI at /Users/michaelfairley/Git-Projects/EVSI/src/counting\_rng.jl:9  
(::Type{Random.Sampler})(::Type{#s623} where #s623\<:AbstractRNG, r::AbstractUnitRange{T}, ::Union{Val{1}, Val{Inf}}) where T\<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} in Random at /Users/julia/buildbot/worker/package\_macos64/build/usr/share/julia/stdlib/v1.1/Random/src/generation.jl:278  
Possible fix, define  
Random.Sampler(::Type{EVSI.CountingRNG{T}}, ::AbstractUnitRange{T\<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}}, ::Union{Val{1}, Val{Inf}})

I tried defining the following but it didn’t fix the error.

```julia
Sampler(::Type{CountingRNG{T}}, ::Type{X}, n::Repetition) where {T,X<:AbstractUnitRange{Integer}} = Sampler(T, X, n)

```

---

<div class="post-metadata">

**Author:** ![rfourquet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rfourquet/32/3610_2.png) [@rfourquet](https://discourse.julialang.org/u/rfourquet)\
**Post date:** [June 9, 2019, 8:11am UTC](https://discourse.julialang.org/t/counting-number-of-times-a-rng-is-called/24903/24 "2019-06-09T08:11:32Z")

</div>

Counting the number of bits is again tricky: at the lowest level you can use the following ugly solution. It will count the total number of bits generated from the dSFMT library. But `MersenneTwister` “wastes” some bits, so the count will be overestimated. I think for your pupose, your best bet is to write a `countingRNG` wrapper like discussed above but without a catch-all method (i.e. you write the `rand` methods for everything that you want to count).  
For your new ambiguous method, you didn’t implement exactly the one suggested by the error message, by using `Integer` instead of the `Union` of specific integers.

```julia
# counting all the bits generated from dSFMT
const count = Ref(0)

function Random.fill_array!(s::Random.DSFMT_state, A::Ptr{Float64}, n::Int, ::Random.CloseOpen01_64)
    count[] += n
    Random.dsfmt_fill_array_close_open!(s, A, n)
end

function Random.fill_array!(s::Random.DSFMT_state, A::Ptr{Float64}, n::Int, ::Random.CloseOpen12_64)
    count[] += n
    Random.dsfmt_fill_array_close1_open2!(s, A, n)
end

function Random.gen_rand(r::MersenneTwister)
    GC.@preserve r Random.fill_array!(r.state, pointer(r.vals), length(r.vals), Random.CloseOpen12())
    Random.mt_setfull!(r)
end

getcount(r::MersenneTwister) = 52*(count[] - Random.MT_CACHE_F + r.idxF) - 8*r.idxI

```

I have a PR which add counters to `MersenneTwister`, so this may become easier in the fututre.

[Previous page](https://discourse.julialang.org/t/counting-number-of-times-a-rng-is-called/24903.md?page=1)
