SWDEV-541514 - Docs update 2025-09-15 (#993)
Co-authored-by: Julia Jiang <56359287+jujiang-del@users.noreply.github.com>
This commit is contained in:
@@ -411,11 +411,9 @@ warpSize
|
||||
================================================================================
|
||||
|
||||
The ``warpSize`` constant contains the number of threads per warp for the given
|
||||
target device. It can differ between different architectures, and on RDNA
|
||||
architectures it can even differ between kernel launches, depending on whether
|
||||
they run in CU or WGP mode. See the
|
||||
:doc:`hardware features <../reference/hardware_features>` for more
|
||||
information.
|
||||
target device. On AMD hardware, this is referred to as ``wavefront size``, which
|
||||
may vary depending on the architecture. For more details, see the
|
||||
:doc:`hardware features <../reference/hardware_features>`.
|
||||
|
||||
Since ``warpSize`` can differ between devices, it can not be assumed to be a
|
||||
compile-time constant on the host. It has to be queried using
|
||||
@@ -423,8 +421,8 @@ compile-time constant on the host. It has to be queried using
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
int val;
|
||||
hipDeviceGetAttribute(&val, hipDeviceAttributeWarpSize, deviceId);
|
||||
int warpSizeHost;
|
||||
hipDeviceGetAttribute(&warpSizeHost, hipDeviceAttributeWarpSize, deviceId);
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -435,6 +433,130 @@ compile-time constant on the host. It has to be queried using
|
||||
of 32 can run on devices with a ``warpSize`` of 64, it only utilizes half of
|
||||
the compute resources.
|
||||
|
||||
Prior to ROCm 7.0, the warpSize parameter was a compile-time constant. Starting
|
||||
with ROCm 7.0, it is early folded by the compiler, allowing it to be used in
|
||||
loop bounds and enabling loop unrolling in a manner similar to a compile-time
|
||||
constant warp size.
|
||||
|
||||
If compile time warp size is required, for example to select the correct mask
|
||||
type or code path at compile time, the recommended approach is to determine the
|
||||
warp size of the GPU on host side and setup the kernel accordingly, as shown in
|
||||
the following block reduce example.
|
||||
|
||||
The ``block_reduce`` kernel has a template parameter for warp size and performs
|
||||
a reduction operation in two main phases:
|
||||
|
||||
- Shared memory reduction: Reduction is performed iteratively, halving the
|
||||
number of active threads each step until only a warp remains
|
||||
(32 or 64 threads, depending on the device).
|
||||
|
||||
- Warp-level reduction: Once the shared memory reduction completes, the
|
||||
remaining threads use warp-level shuffling to sum the remaining values. This
|
||||
is done efficiently with the ``__shfl_down`` intrinsic, which allows threads within
|
||||
the warp to exchange values without explicit synchronization.
|
||||
|
||||
.. tab-set::
|
||||
|
||||
.. tab-item:: WarpSize template parameter
|
||||
:sync: template-warpsize
|
||||
|
||||
.. literalinclude:: ../tools/example_codes/template_warp_size_reduction.hip
|
||||
:start-after: // [Sphinx template warp size block reduction kernel start]
|
||||
:end-before: // [Sphinx template warp size block reduction kernel end]
|
||||
:language: cpp
|
||||
|
||||
|
||||
.. tab-item:: HIP warpSize
|
||||
:sync: hip-warpsize
|
||||
|
||||
.. literalinclude:: ../tools/example_codes/warp_size_reduction.hip
|
||||
:start-after: // [Sphinx HIP warp size block reduction kernel start]
|
||||
:end-before: // [Sphinx HIP warp size block reduction kernel end]
|
||||
:language: cpp
|
||||
|
||||
The host code with the main function:
|
||||
|
||||
- Retrieves the warp size of the GPU (``warpSizeHost``) to determine the optimal
|
||||
kernel configuration.
|
||||
|
||||
- Allocates device memory (``d_data`` for input, ``d_results`` for block-wise
|
||||
output) and initializes the input vector to 1.
|
||||
|
||||
- Generates the mask variables for every warp and copies them to the device.
|
||||
|
||||
.. tab-set::
|
||||
|
||||
.. tab-item:: WarpSize template parameter
|
||||
:sync: template-warpsize
|
||||
|
||||
.. literalinclude:: ../tools/example_codes/template_warp_size_reduction.hip
|
||||
:start-after: // [Sphinx template warp size mask generation start]
|
||||
:end-before: // [Sphinx template warp size mask generation end]
|
||||
:language: cpp
|
||||
|
||||
|
||||
.. tab-item:: HIP warpSize
|
||||
:sync: hip-warpsize
|
||||
|
||||
.. literalinclude:: ../tools/example_codes/warp_size_reduction.hip
|
||||
:start-after: // [Sphinx HIP warp size mask generation start]
|
||||
:end-before: // [Sphinx HIP warp size mask generation end]
|
||||
:language: cpp
|
||||
|
||||
- Selects the appropriate kernel specialization based on the warp
|
||||
size (either 32 or 64) and launches the kernel.
|
||||
|
||||
.. tab-set::
|
||||
|
||||
.. tab-item:: WarpSize template parameter
|
||||
:sync: template-warpsize
|
||||
|
||||
.. literalinclude:: ../tools/example_codes/template_warp_size_reduction.hip
|
||||
:start-after: // [Sphinx template warp size select kernel start]
|
||||
:end-before: // [Sphinx template warp size select kernel end]
|
||||
:language: cpp
|
||||
|
||||
|
||||
.. tab-item:: HIP warpSize
|
||||
:sync: hip-warpsize
|
||||
|
||||
.. literalinclude:: ../tools/example_codes/warp_size_reduction.hip
|
||||
:start-after: // [Sphinx HIP warp size select kernel start]
|
||||
:end-before: // [Sphinx HIP warp size select kernel end]
|
||||
:language: cpp
|
||||
|
||||
- Synchronizes the device and copies the results back to the host.
|
||||
|
||||
- Checks that each block's sum is equal with the expected mask bit count,
|
||||
verifying the reduction's correctness.
|
||||
|
||||
- Frees the device memory to prevent memory leaks.
|
||||
|
||||
.. note::
|
||||
|
||||
The ``warpSize`` runtime example code is also provided for comparison purposes
|
||||
and the full example codes are located in the `tools folder <https://github.com/ROCm/hip/tree/docs/develop/docs/tools/example_codes>`_.
|
||||
|
||||
The variable ``warpSize`` can be used for loop bounds and supports
|
||||
loop unrolling similarly to the template parameter ``WarpSize``.
|
||||
|
||||
For users who still require a compile-time constant warp size as a macro on the
|
||||
device side, it can be defined manually based on the target device architecture,
|
||||
as shown in the following example.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#if defined(__GFX8__) || defined(__GFX9__)
|
||||
#define WarpSize 64
|
||||
#else
|
||||
#define WarpSize 32
|
||||
#endif
|
||||
|
||||
.. note::
|
||||
|
||||
``mwavefrontsize64`` compiler option is not supported by HIP runtime, that's
|
||||
why the architecture based compile time selector is an acceptable approach.
|
||||
|
||||
********************************************************************************
|
||||
Vector types
|
||||
********************************************************************************
|
||||
@@ -855,7 +977,7 @@ The different shuffle functions behave as following:
|
||||
of range, the thread returns its own ``var``.
|
||||
|
||||
``__shfl_down``
|
||||
The thread reads ``var`` from lane ``laneIdx - delta``, thereby "shuffling"
|
||||
The thread reads ``var`` from lane ``laneIdx + delta``, thereby "shuffling"
|
||||
the values of the lanes of the warp "down". If the resulting source lane is
|
||||
out of range, the thread returns its own ``var``.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user