# CUDA.jl random number generation

**URL:** <https://discourse.julialang.org/t/cuda-jl-random-number-generation/137209>\
**Category:** GPU\
**Created:** [May 20, 2026, 8:05am UTC](https://discourse.julialang.org/t/cuda-jl-random-number-generation/137209 "2026-05-20T08:05:31Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![shiroghost](https://avatars.discourse-cdn.com/v4/letter/s/b9e5f3/32.png) [@shiroghost](https://discourse.julialang.org/u/shiroghost)\
**Post date:** [May 20, 2026, 8:05am UTC](https://discourse.julialang.org/t/cuda-jl-random-number-generation/137209/1 "2026-05-20T08:05:31Z")

</div>

Hi all,

I am trying to understand Random Numbers generated in CUDA. In particular which RNG is used in each version/case. If I understood this correctly:

```julia
using CUDA

v = randn(Float64, N)

```

will use CUDA.jl interface, and in particular will make use of `Philox` RNG.

On the other hand, the code:

```julia
using CUDA

v = CuArray{Float64}(undef, N);
randn!(v)

```

will make use of the cuRAND library, and by default will use `XORWOW`.

Is this correct?

What is the canonical way to seed these generators?

Has this changed in different CUDA versions? If yes, is there a document where I can check the RNG used in each version?

Is there a canonical way to use a (good) RNG across CUDA versions?

Many thanks!

---

<div class="post-metadata">

**Author:** ![maleadt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maleadt/32/10097_2.png) [@maleadt](https://discourse.julialang.org/u/maleadt)\
**Post date:** [May 20, 2026, 10:29am UTC](https://discourse.julialang.org/t/cuda-jl-random-number-generation/137209/2 "2026-05-20T10:29:20Z")

</div>

> [@shiroghost](#):
>
> If I understood this correctly:
> 
> ```julia-auto
> using CUDA
> 
> v = randn(Float64, N)
> 
> ```
> 
> will use [CUDA.jl](https://juliaregistries.github.io/General/packages/redirect_to_repo/CUDA) interface, and in particular will make use of `Philox` RNG.

That simply generates a CPU array using the Random.jl stdlib. Maybe you’re confusing with doing that _within_ a kernel, which will use a Philox-based RNG.

From the host, there’s multiple RNG choices. The main two ones are:

- `cuRAND.LibraryRNG`: the cuRAND one
- `GPUArrays.RNG{CuArray}` (also exposed as `CUDA.RNG`): a fallback for elements cuRAND can’t handle

CUDA.jl will automatically route towards one of those depending on the kind of array you’re working with (when calling `CUDA.randn`), or the element type you’re requesting (when calling `CUDA.rand`). But for explicit use you can always instantiate those RNGs directly and use them as the first argument to the Random.jl APIs. Seeding then also becomes very explicit; when doing `CUDA.seed!` we will automatically seed all RNGs that may be used.

---

<div class="post-metadata">

**Author:** ![shiroghost](https://avatars.discourse-cdn.com/v4/letter/s/b9e5f3/32.png) [@shiroghost](https://discourse.julialang.org/u/shiroghost)\
**Post date:** [May 20, 2026, 11:11am UTC](https://discourse.julialang.org/t/cuda-jl-random-number-generation/137209/3 "2026-05-20T11:11:29Z")

</div>

Of course you are right… Sorry for the noise. I meant that:

```julia
v = randn(CUDA.default_rng(), Float64, N)

```

Will use CUDA.jl and the Philox RNG, while `randn!` calls fills the array using `cuRAND`.

Thanks!
