Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[oneDPL][RNG][Spec] Added the extensions sections #492

Merged
Merged
Changes from 5 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
103 changes: 100 additions & 3 deletions source/elements/oneDPL/source/sycl_kernels_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ CPU-based platform.

.. _`C++ Standard`: https://isocpp.org/std/the-standard


Random Number Generation
++++++++++++++++++++++++

oneDPL provides a subset of the standard C++ pseudo-random number generation functionality
suitable to use within SYCL kernels. The APIs are defined in the :code:`<oneapi/dpl/random>` header.
suitable to use within SYCL kernels. The APIs are defined in the :code:`<oneapi/dpl/random>` header.

Supported functionality:
------------------------

- Engine class templates:
- ``linear_congruential_engine``
- ``subtract_with_carry_engine``
Expand All @@ -46,17 +48,112 @@ Supported functionality:
- ``cauchy_distribution``
- ``extreme_value_distribution``

Additionally, ``sycl::vec<>`` can be used as the result type for engines, engine adaptors, and distributions.
``linear_congruential_engine`` and ``subtract_with_carry_engine`` satisfy the uniform random bit generator requirements.

Limitations:
------------

The following deviations from the `C++ Standard`_ may apply:

- ``random_device`` and ``seed_seq`` classes and related APIs in other classes are not required;
- ``operator>>()``, ``operator<<()``, ``operator==()`` are not required;
- specifying the size of a random number engine's state is not required;
- distributions are only required to operate with floating point types applicable to supported SYCL devices.

Extensions:
-----------

As an extension to the `C++ Standard`_, ``sycl::vec<Type, N>`` can be used as the data type template parameter for
engines, engine adaptors, and distributions, where ``Type`` is one of data types supported by the corresponding
class template in the standard. For such template instantiations, the ``result_type`` is also defined to
``sycl::vec<Type, N>``.

Engines, engine adaptors, and distributions additionally define ``scalar_type``, equivalent to the following:

- ``using scalar_type = typename result_type::element_type;`` if ``result_type`` is ``sycl::vec<Type, N>``,
- otherwise, ``using scalar_type = result_type;``

The ``scalar_type`` is used instead of ``result_type`` in all contexts where a scalar data type is expected, including

- the type of configuration parameters and properties,
- the seed value type,
- the input parameters of constructors,
- the return value type of ``min()`` and ``max()`` methods, etc.

Since ``scalar_type`` is the same as ``result_type`` except for template instantiations with ``sycl::vec``,
class templates still meet the applicable requirements of the `C++ Standard`_.

When instantiated with ``sycl::vec<Type,N>``, ``linear_congruential_engine`` and ``subtract_with_carry_engine`` may not
formally satisfy the uniform random bit generator requirements defined by the `C++ Standard`_. Instead, the following
akukanov marked this conversation as resolved.
Show resolved Hide resolved
alternative requirements apply: for an engine object ``g`` of type ``G``,

- ``G::scalar_type`` is an unsigned integral type same as ``sycl::vec<Type,N>::element_type``,
Comment on lines +88 to +90
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
alternative requirements apply: for an engine object ``g`` of type ``G``,
- ``G::scalar_type`` is an unsigned integral type same as ``sycl::vec<Type,N>::element_type``,
alternative requirements apply.
For an engine object ``g`` of type ``G``:
- ``G::scalar_type`` is an unsigned integral type same as ``sycl::vec<Type,N>::element_type``,

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am afraid, in this way it's not quite clear what the alternative requirements are. Let's try improving it later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Postpone the change

- ``G::min()`` and ``G::max()`` return a value of ``G::scalar_type``,
- for each index ``i`` in the range [0, ``N``), ``G::min() <= g()[i]`` and ``g()[i] <= G::max()``.
akukanov marked this conversation as resolved.
Show resolved Hide resolved

Effectively, these engines satisfy the standard uniform random bit generator requirements for each element
of a ``sycl::vec`` returned by their ``operator()``.

Similarly, for a distribution ``d`` of a type ``D`` that is a template instantiated with ``sycl::vec<Type,N>``,
akukanov marked this conversation as resolved.
Show resolved Hide resolved

- ``D::scalar_type`` is the same as ``sycl::vec<Type,N>::element_type``,
- ``D::min()`` and ``D::max()`` return a value of ``D::scalar_type``, and ``D::min() <= D::max()``,
- ``operator()`` of a distribution returns a ``sycl::vec<Type,N>`` filled with random values
in the closed interval ``[D::min(), D::max()]``;

The following engines and engine adaptors with predefined parameters are defined:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The following engines and engine adaptors with predefined parameters are defined:
The following template aliases for engines and engine adaptors are defined:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wording "with predefined parameters" is aligned with C++ std. Should we change it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I think we should keep it. From the RNG standpoint, it's exactly engines with predefined parameters.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kept it as it is now

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree, because in the standard they don't have template aliases to the best of my knowledge. But I don't want to argue.

Copy link
Contributor

@akukanov akukanov Sep 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://eel.is/c++draft/rand.predef

using minstd_rand0 =
      linear_congruential_engine<uint_fast32_t, 16'807, 0, 2'147'483'647>;

and so on. OK, not template, just aliases.


.. code:: cpp

template <int N>
using minstd_rand0_vec = linear_congruential_engine<sycl::vec<::std::uint_fast32_t, N>, 16807, 0, 2147483647>;

template <int N>
using minstd_rand_vec = linear_congruential_engine<sycl::vec<uint_fast32_t, N>, 48271, 0, 2147483647>;

template <int N>
using ranlux24_base_vec = subtract_with_carry_engine<sycl::vec<uint_fast32_t, N>, 24, 10, 24>;

template <int N>
using ranlux48_base_vec = subtract_with_carry_engine<sycl::vec<uint_fast64_t, N>, 48, 5, 12>;

template <int N>
using ranlux24_vec = discard_block_engine<ranlux24_base_vec<N>, 223, 23>;

template <int N>
using ranlux48_vec = discard_block_engine<ranlux48_base_vec<N>, 389, 11>;

Except for producing a ``sycl::vec`` of random values per invocation, the behavior of these engines is equivalent to
the corresponding scalar engines, as described in the following table.
akukanov marked this conversation as resolved.
Show resolved Hide resolved

.. container:: tablenoborder

.. list-table::
:header-rows: 1

* - Engines and engine adaptors based on ``sycl::vec<>``
- C++ standard analogue
- The 10000th scalar random value consecutively produced by a default-constructed object
* - ``minstd_rand0_vec``
- ``minstd_rand0``
- 1043618065
* - ``minstd_rand_vec``
- ``minstd_rand``
- 399268537
* - ``ranlux24_base_vec``
- ``ranlux24_base``
- 7937952
* - ``ranlux48_base_vec``
- ``ranlux48_base``
- 61839128582725
* - ``ranlux24_vec``
- ``ranlux24``
- 9901578
* - ``ranlux48_vec``
- ``ranlux48``
- 1112339016


Function Objects
++++++++++++++++

Expand All @@ -75,5 +172,5 @@ The oneDPL function objects are defined in the :code:`<oneapi/dpl/functional>` h
}
}

The :code:`oneapi::dpl::identity` class implements an identity operation. Its function operator
The :code:`oneapi::dpl::identity` class implements an identity operation. Its function operator
receives an instance of a type and returns the argument unchanged.