# Random number iterator?

**URL:** <https://discourse.julialang.org/t/random-number-iterator/76330>\
**Category:** Performance\
**Tags:** iterators, random\
**Created:** [February 13, 2022, 6:58am UTC](https://discourse.julialang.org/t/random-number-iterator/76330 "2022-02-13T06:58:55Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [February 13, 2022, 6:58am UTC](https://discourse.julialang.org/t/random-number-iterator/76330/1 "2022-02-13T06:58:55Z")

</div>

Is it possible to get a random number iterator that doesn’t allocate? I was hoping I could do something like this:

```julia
julia> using Random

julia> sum(Iterators.take(MersenneTwister(0), 4))
ERROR: MethodError: no method matching iterate(::MersenneTwister)

```

Of course I could write a generator,

```julia
sum(rand() for _ in 1:4)

```

but `n` calls to `rand()` is usually slower than `rand(n)`:

```julia
julia> @btime sum(rand() for _ in 1:100_000);
  146.216 μs (0 allocations: 0 bytes)

julia> @btime sum(rand(100_000));
  105.032 μs (2 allocations: 781.30 KiB)

```

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [February 13, 2022, 7:58am UTC](https://discourse.julialang.org/t/random-number-iterator/76330/2 "2022-02-13T07:58:12Z")

</div>

> [@CameronBieganek](#):
>
> but `n` calls to `rand()` is usually slower than `rand(n)` :

That’s just how it works right?.. Trading space for speed. The iterator will necessarily call rand() to minimize allocation… You can’t not allocate but also want batch rand(1000)…

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [February 13, 2022, 9:41am UTC](https://discourse.julialang.org/t/random-number-iterator/76330/3 "2022-02-13T09:41:30Z")

</div>

Maybe I misunderstand, but why not

```julia
julia> using BenchmarkTools, Random

julia> a = zeros(1_000);

julia> @btime rand!($a);
  1.667 μs (0 allocations: 0 bytes)

```

---

<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:** [February 13, 2022, 10:02am UTC](https://discourse.julialang.org/t/random-number-iterator/76330/4 "2022-02-13T10:02:17Z")

</div>

> [@CameronBieganek](#):
>
> but `n` calls to `rand()` is usually slower than `rand(n)` :
> 
> ```julia
> 
> ```

The extent of this would depend on which version you are in. In Julia 1.6, the dicrepancy would mostly be fixed by passing an explicit rng to `rand` in the generator version. But you your timings make me guess you are on 1.7. There I don’t think you can easily beat the array version, because it uses simd, unlike the scalar version. An idea I would want to explore in a package is wrapping `Xoshiro` in a way that even the scalar version of `rand` uses simd, by having an internal cache (like what `MersenneTwister` does).

EDIT: but to your question about having a rand iterator, you can check out `Rand()` from the RandomExtensions package. It won’t help performance in this instance, but as it hanldes the `Sampler` thing in the same way as in arrays, it can occasionally help speed-up things where a “pre-computation” can be shared between multiple calls of `rand`.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [February 13, 2022, 3:16pm UTC](https://discourse.julialang.org/t/random-number-iterator/76330/5 "2022-02-13T15:16:17Z")

</div>

I think we could make a really fast operator version that generates 32 at a time and feeds them to you.

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [February 13, 2022, 4:48pm UTC](https://discourse.julialang.org/t/random-number-iterator/76330/7 "2022-02-13T16:48:34Z")

</div>

Thanks! `Rand()` from `RandomExtensions` is indeed the kind of thing I was looking for. Here it is in action:

```julia
julia> using Random, RandomExtensions, Base.Iterators, BenchmarkTools

julia> rng = MersenneTwister(0);

julia> itr = Rand(rng)
Rand{MersenneTwister, Random.SamplerTrivial{Random.CloseOpen01{Float64}, Float64}}(MersenneTwister(0), Random.SamplerTrivial{Random.CloseOpen01{Float64}, Float64}(Random.CloseOpen01{Float64}()))

julia> @btime sum(take($itr, 100_000));
  169.361 μs (0 allocations: 0 bytes)

julia> @btime sum(rand() for _ in 1:100_000);
  146.219 μs (0 allocations: 0 bytes)

julia> @btime sum(rand(100_000));
  105.492 μs (2 allocations: 781.30 KiB)

```

I see that `RandomExtensions` is experimental, but it looks cool. I don’t know anything about pseudo-random number generation algorithms, so I wasn’t sure if there was some conceptual reason why one couldn’t make a random number iterator. Whether that iterator can take advantage of SIMD is a separate question, I suppose.
