Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Added the multivariate distributions, `permutation`, `shuffle`, `permuted`, `choice` and `bytes` to `dpnp.random.Generator` [#3160](https://github.com/IntelPython/dpnp/pull/3160)
* Added the `dpnp.random.PCG64DXSM` bit generator, which matches `numpy.random.PCG64DXSM` for raw values, `random`, `uniform` and `bytes` [#3161](https://github.com/IntelPython/dpnp/pull/3161)
* Added the `dpnp.random.MRG32k3a` bit generator [#3161](https://github.com/IntelPython/dpnp/pull/3161)
* Added `dpnp.random.get_state`, `dpnp.random.set_state`, `dpnp.random.get_bit_generator` and `dpnp.random.set_bit_generator`, and support for a bit generator as the seed of `dpnp.random.RandomState` [#3162](https://github.com/IntelPython/dpnp/pull/3162)

### Changed

Expand All @@ -24,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Merged the `ufunc` and `indexing` extensions into `dpnp.libtensor._tensor_elementwise_impl` and `dpnp.libtensor._tensor_impl`, while `statistics` and `window` extensions became part of libtensor [#3131](https://github.com/IntelPython/dpnp/pull/3131)
* Moved `blas`, `fft`, `lapack`, `sparse` and `vm` extensions into `dpnp/libtensor/extensions` [#3131](https://github.com/IntelPython/dpnp/pull/3131)
* Moved the libtensor headers shipped with dpnp from `dpnp/tensor/libtensor/include` to `dpnp/libtensor/include`, and changed `dpnp.get_include` to return that directory [#3131](https://github.com/IntelPython/dpnp/pull/3131)
* Reimplemented `dpnp.random.RandomState` and the `dpnp.random` functions on device kernels, giving the same values on every device. `device`, `usm_type` and `sycl_queue` are now keyword-only, `randint(dtype=int)` returns `int64` and `shuffle` requires a `dpnp.ndarray` [#3162](https://github.com/IntelPython/dpnp/pull/3162)

### Deprecated

Expand Down
53 changes: 32 additions & 21 deletions doc/reference/random.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ Random sampling (:mod:`dpnp.random`)
DPNP draws random numbers on the SYCL device, by default with the
counter-based Philox4x32x10 generator of the oneMKL device RNG API, or with
NumPy's PCG64DXSM generator or the MRG32k3a generator of the oneMKL device
RNG API. It provides the
:class:`Generator` API of NumPy, recommended for new code. The legacy
:class:`RandomState` API and the module-level functions still use the
host-side oneMKL RNG.
RNG API. It provides both NumPy random APIs: the :class:`Generator` API recommended for new code,
and the legacy :class:`RandomState` API with the module-level functions
built on it.

.. code-block:: python

Expand Down Expand Up @@ -41,8 +40,8 @@ Differences from NumPy
which defaults to the default floating-point type of the device. All
methods take a ``usm_type`` keyword.
* Parameters on the host (Python scalars, lists and NumPy arrays) are
checked as in NumPy. Parameters in :class:`dpnp.ndarray` are
not, since that would wait for the device.
checked as in NumPy. In :class:`Generator`, parameters in
:class:`dpnp.ndarray` are not, since that would wait for the device.
Invalid ones give undefined values, such as NaN or the smallest ``int64``,
but the kernels handle them safely: they never loop without end or access
memory out of bounds. Floating-point arrays given for integer parameters
Expand All @@ -58,9 +57,15 @@ Differences from NumPy
* ``zipf`` follows the Zipf distribution truncated to the largest ``int64``.
NumPy's rejection test rounds to accepting every sample above ``2**53``,
which makes its tail too heavy for ``a`` close to 1.
* ``hypergeometric`` requires ``ngood`` and ``nbad`` below ``10**9``.
* :meth:`Generator.shuffle` only accepts a :class:`dpnp.ndarray`, as in
CuPy.
* :meth:`RandomState.randint` and :func:`randint` return ``int64`` values by
default, as do :meth:`RandomState.random_integers`,
:func:`random_integers` and :meth:`RandomState.tomaxint`, whose values
reach the largest ``int64``. NumPy returns a C ``long`` instead, which is
``int32`` on Windows.
* ``hypergeometric`` requires ``ngood`` and ``nbad`` below ``10**9``, also in
:class:`RandomState`.
* :meth:`Generator.shuffle` and :func:`shuffle` only accept a
:class:`dpnp.ndarray`, as in CuPy.

Random Generator
----------------
Expand Down Expand Up @@ -157,6 +162,24 @@ Legacy random generation

.. hint:: `NumPy API Reference: Legacy random generation <https://numpy.org/doc/stable/reference/random/legacy.html>`_

:class:`RandomState` keeps the parameter checks of NumPy's legacy one, also
for parameters in :class:`dpnp.ndarray`, as CuPy's does, so that a call with
such parameters waits for the device to check them. The module-level
functions use one :class:`RandomState` per SYCL queue: the
queue given by the ``device`` or ``sycl_queue`` keyword, or else the queue of
a :class:`dpnp.ndarray` parameter, or else the default queue.

.. autosummary::
:toctree: generated/
:nosignatures:

RandomState
seed
get_state
set_state
get_bit_generator
set_bit_generator

Simple random data
^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -227,15 +250,3 @@ Distributions
wald
weibull
zipf

Random generator
^^^^^^^^^^^^^^^^

.. autosummary::
:toctree: generated/
:nosignatures:

RandomState
seed
get_random_state
set_random_state
4 changes: 2 additions & 2 deletions dpnp/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
- `dpnp_algo/dpnp_elementwise_common.py`: ufunc wrapper classes (`DPNPUnaryFunc`, `DPNPBinaryFunc`, two-output and specialised variants)
- `dpnp_utils/`: shared helpers (`get_usm_allocations`, `map_dtype_to_device`, reduction wrappers)
- `linalg/`, `fft/`, `random/`, `scipy/`, `lib/`: subpackages, each exporting through its own `__init__.py`
- `random/`: `_bit_generator.py` (`BitGenerator`, `Philox4x3210`, `PCG64DXSM`, `MRG32k3a`; `SeedSequence` is NumPy's) and `_generator.py` (`Generator`, which implements every distribution). The kernels are in `dpnp.libtensor._rng_impl`.
- `random/`: `_bit_generator.py` (`BitGenerator`, `Philox4x3210`, `PCG64DXSM`, `MRG32k3a`; `SeedSequence` is NumPy's), `_generator.py` (`Generator`, which implements every distribution), `dpnp_random_state.py` (`RandomState`, the same samplers with NumPy's legacy checks) and `dpnp_iface_random.py` (module functions, one `RandomState` per queue). The kernels are in `dpnp.libtensor._rng_impl`.
- Legacy, don't extend: the Cython `dpnp_algo` path and `dpnp_backend_c` (still used by `dpnp.partition` and `dpnp.random`), and the NumPy fallback `call_origin`. New kernels go into `dpnp/libtensor` (see `dpnp/libtensor/AGENTS.md`).

## Adding a Public Function
Expand All @@ -21,7 +21,7 @@
- Extension calls are ordered with `_manager = dpctl.utils.SequentialOrderManager[exec_q]`: pass `depends=_manager.submitted_events`, then `_manager.add_event_pair(ht_ev, ev)`. Don't add blocking waits.
- Use `dpnp.default_float_type(...)` or `map_dtype_to_device(...)` for the default float type.
- Deprecated ufuncs use `DPNPDeprecatedUnaryFunc(..., deprecated_msg=...)`.
- A `dpnp.random` distribution is a `Generator` method: it calls `self._check_queues(...)` on its array parameters (raises `ExecutionPlacementError`), checks host parameters as NumPy does, and draws through `_cont`, `_float_sample` or `_discrete_sample` into `BitGenerator._fill`. Parameters on the device are not checked, as the check waits for the device. Temporaries take the output's `usm_type`.
- A `dpnp.random` distribution is a `Generator` method: it calls `self._check_queues(...)` on its array parameters (raises `ExecutionPlacementError`), checks host parameters as NumPy does, and draws through `_cont`, `_float_sample` or `_discrete_sample` into `BitGenerator._fill`. `RandomState` and the module function delegate to it. Parameters on the device are checked only by `RandomState` (`_check_device`), as the check waits for the device. Temporaries take the output's `usm_type`.
- Unsupported NumPy keywords raise `NotImplementedError` (`dpnp.check_limitations`) and are listed under `Limitations` in the docstring.
- The Array API spec version is set in three places that change together: `__array_api_version__` in `dpnp/tensor/_array_api.py`, `ARRAY_API_TESTS_VERSION` in `.github/workflows/conda-package.yml` and `doc/reference/array_api.rst` (plus the version test in `dpnp/tests/test_ndarray.py`). Inspection utilities come from `__array_namespace_info__` in `dpnp_array_api_info.py`.
- `dpnp.tensor` replaces `dpctl.tensor`, which no longer exists here; `SyclQueue`, `SyclDevice`, `dpctl.memory` and `SequentialOrderManager` still come from `dpctl`.
Expand Down
8 changes: 8 additions & 0 deletions dpnp/random/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
f,
gamma,
geometric,
get_bit_generator,
get_state,
gumbel,
hypergeometric,
laplace,
Expand All @@ -71,6 +73,8 @@
rayleigh,
sample,
seed,
set_bit_generator,
set_state,
shuffle,
standard_cauchy,
standard_exponential,
Expand Down Expand Up @@ -104,6 +108,8 @@
"f",
"gamma",
"geometric",
"get_bit_generator",
"get_state",
"gumbel",
"hypergeometric",
"laplace",
Expand Down Expand Up @@ -131,6 +137,8 @@
"sample",
"shuffle",
"seed",
"set_bit_generator",
"set_state",
"standard_cauchy",
"standard_exponential",
"standard_gamma",
Expand Down
Loading
Loading