C.W.K.
Stream
Lesson 02 of 06 · published

PRNG Keys and Splitting

~8 min · random, jax, tutorial

Level 0Curious
0 XP0/73 lessons0/17 achievements
0/100 XP to next level100 XP to go0% complete

A PRNG key (Pseudo-Random Number Generator key) is a small array that encodes the random state. You create your first key from an integer seed, then produce new keys by splitting.

import jax
import jax.numpy as jnp

# Create a starting key from a seed
key = jax.random.key(0)
print(key)  # a special key array

# WRONG: reusing the same key gives the same numbers
print(jax.random.normal(key))  # 0.18784384
print(jax.random.normal(key))  # 0.18784384 — identical!

# RIGHT: split the key to get new, independent keys
key, subkey = jax.random.split(key)
print(jax.random.normal(subkey))  # -1.2515389

key, subkey = jax.random.split(key)
print(jax.random.normal(subkey))  # -0.5841975 — different!

jax.random.split(key) consumes one key and produces two new, independent keys. The standard pattern is to keep one for future splitting and use the other ("subkey") immediately. You can also split into more than two keys:

# Split into many keys at once
key = jax.random.key(42)
keys = jax.random.split(key, num=5)
print(keys.shape)  # (5,) — five independent keys

# Use each key for a different purpose
samples = jax.vmap(jax.random.normal)(keys)
print(samples)  # 5 independent random numbers

The key hierarchy forms a tree: you start with one key, split it into children, split those into grandchildren, and so on. Every path through the tree produces statistically independent random streams. This is mathematically guaranteed by the Threefry hash function that JAX uses under the hood.

💡 Why This Matters

Splitting gives you fine-grained control over reproducibility. You can reproduce any part of your computation by saving the key that was used. Need to debug the random initialization of layer 3? Just save and replay its key — you don't need to re-run the entire program in the same order like you would with NumPy.

A note on jax.random.key vs jax.random.PRNGKey: The modern API is jax.random.key(seed), which returns a typed key array. The older jax.random.PRNGKey(seed) still works but returns a raw uint32 array. Use key() for new code.

# Modern API (recommended)
key = jax.random.key(0)

# Legacy API (still works)
key_legacy = jax.random.PRNGKey(0)

# Both produce valid keys for all jax.random functions

Code

import jax
import jax.numpy as jnp

# Create a starting key from a seed
key = jax.random.key(0)
print(key)  # a special key array

# WRONG: reusing the same key gives the same numbers
print(jax.random.normal(key))  # 0.18784384
print(jax.random.normal(key))  # 0.18784384 — identical!

# RIGHT: split the key to get new, independent keys
key, subkey = jax.random.split(key)
print(jax.random.normal(subkey))  # -1.2515389

key, subkey = jax.random.split(key)
print(jax.random.normal(subkey))  # -0.5841975 — different!
# Split into many keys at once
key = jax.random.key(42)
keys = jax.random.split(key, num=5)
print(keys.shape)  # (5,) — five independent keys

# Use each key for a different purpose
samples = jax.vmap(jax.random.normal)(keys)
print(samples)  # 5 independent random numbers
# Modern API (recommended)
key = jax.random.key(0)

# Legacy API (still works)
key_legacy = jax.random.PRNGKey(0)

# Both produce valid keys for all jax.random functions

External links

Exercise

Build a key tree: start with PRNGKey(0), split into 4, split each of those into 4 more. Use them to sample 16 independent normals. Verify pairwise correlations are close to zero. The branching key model is what makes JAX randomness composable.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.