
# Reproducibility

## PRNG seeding

Liesel uses [JAX’ splittable Threefry counter-based
PRNG](https://jax.readthedocs.io/en/latest/notebooks/Common_Gotchas_in_JAX.html#random-numbers),
which does not have a global state, so you always need to seed it
explicitly, for example when initializing an
[`liesel.goose.EngineBuilder`](https://liesel-devs.github.io/liesel/liesel/goose.html#EngineBuilder).
However, even with the same seed, reproducible results cannot be
guaranteed across different systems or even for separate runs of the
same program on the same hardware.

## GPU non-determinism

Floating point operations on GPUs are generally not completely
deterministic, and even though JAX takes [some
precautions](https://github.com/google/jax/pull/4824#issuecomment-966514092)
against this surprising behavior, full reproducibility on GPUs should
not be assumed. See also [this (unmerged) page in the JAX
documentation](https://github.com/google/jax/blob/gpu-determinism-note/docs/gpu_determinism.rst).

## Non-reproducibility across systems

[In our
experience](https://github.com/blackjax-devs/blackjax/issues/181),
results from Liesel, BlackJAX and JAX may differ across systems, even if
the exact same code is run on the CPU. Following [the Stan
documentation](https://mc-stan.org/docs/reference-manual/reproducibility.html),
we expect reproducibility only on the CPU and only if all of the
following components are identical:

- the Liesel version,
- the Python version,
- the versions of all libraries Liesel depends on,
- the operating system version,
- the computer hardware including CPU, motherboard and memory,
- the compilers, including versions, flags and libraries, used to build
  Python and all libraries Liesel depends on,
- the program, including the seed, initialization and data.

## See also

- [The PyTorch docs on
  reproducibility](https://pytorch.org/docs/stable/notes/randomness.html)
- [The Stan docs on
  reproducibility](https://mc-stan.org/docs/reference-manual/reproducibility.html)
