You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
For what it's worth, we are using the latter approach in production here: https://github.com/glass-dev/glass/blob/main/glass/jax.py
But that was done because we were already using numpy Generators, not because the approach is better (which I don't believe).
NB: @NeilGirdhar, my invitation to this repo was expired, but if you could invite me again then I will move the above discussion here.
On topic: The stateful API is surely more attractive to a wider base of users who are accustomed to writing NumPy code, which is why we went for it. But there remains the fact that it cannot easily be moved to devices in jax, which I think has the potential to catch people out in the worst possible way. So there's a real decision to be made here.
But there remains the fact that it cannot easily be moved to devices in jax, which I think has the potential to catch people out in the worst possible way. So there's a real decision to be made here.
IIRC, the issue is that it can't cross jit/autograd boundaries? If I remember, the stateful class I went with is neither a pytree nor hashable, so they will get an error if they try to pass it across the boundary. You would have to really try to get it across the boundary.
I agree that the stateful approach is more intuitive to most people. But also, it's much easier to avoid the common error of key reuse. Also, it lets you write simpler code. (No premature splitting.)
These three advantages coupled with the fact that the main downside is hard to actually have happen to you makes the stateful approach more convincing to me. WDYT?
IIRC, the issue is that it can't cross jit/autograd boundaries? If I remember, the stateful class I went with is neither a pytree nor hashable, so they will get an error if they try to pass it across the boundary. You would have to really try to get it across the boundary.
That's right and I went down the same path. That being said, it is a rare but real pain point when you have to reorganise code around the constraint that "random number generation must be high level".
around the constraint that "random number generation must be high level".
I don't like reorganizing code in unintuitive ways, so I went with this pattern:
@jitdefg(keys: Mapping[str, KeyArray]):
streams=create_streams(keys)
# Now use streams in the usual stateful way:jax.random.uniform(streams["inference"].key())
jax.random.normal(streams["inference"].key())
# etc.deff(streams: Mapping[str, RngStream]):
keys=sample_streams(streams)
g(keys)
Activity
NeilGirdhar commentedon Jun 7, 2026
Done!
NeilGirdhar commentedon Jun 7, 2026
I also went with the stateful approach, which I adapted from flax.
NeilGirdhar commentedon Jun 7, 2026
Feel free to let me know if you need any additional permissions 😄
ntessore commentedon Jun 7, 2026
Thanks Neil! I don't think I need anything :)
On topic: The stateful API is surely more attractive to a wider base of users who are accustomed to writing NumPy code, which is why we went for it. But there remains the fact that it cannot easily be moved to devices in jax, which I think has the potential to catch people out in the worst possible way. So there's a real decision to be made here.
NeilGirdhar commentedon Jun 7, 2026
IIRC, the issue is that it can't cross jit/autograd boundaries? If I remember, the stateful class I went with is neither a pytree nor hashable, so they will get an error if they try to pass it across the boundary. You would have to really try to get it across the boundary.
I agree that the stateful approach is more intuitive to most people. But also, it's much easier to avoid the common error of key reuse. Also, it lets you write simpler code. (No premature splitting.)
These three advantages coupled with the fact that the main downside is hard to actually have happen to you makes the stateful approach more convincing to me. WDYT?
ntessore commentedon Jun 8, 2026
That's right and I went down the same path. That being said, it is a rare but real pain point when you have to reorganise code around the constraint that "random number generation must be high level".
NeilGirdhar commentedon Jun 8, 2026
I don't like reorganizing code in unintuitive ways, so I went with this pattern:
lucascolley commentedon Aug 12, 2026
might it be nice to draft adding one of your approaches to this repo, so we can compare it with alternative approaches inline?