-
Notifications
You must be signed in to change notification settings - Fork 114
Launch_nd: Abstraction to switch between flat and nested loops #2021
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
base: develop
Are you sure you want to change the base?
Changes from all commits
8e84c53
7e6c77a
65706f2
0a86357
6349a4e
57870d4
fcdc683
0bbfaba
9329f4f
ccd5925
47e3c8d
fc7f8de
d719c1a
b6a1ab0
6ddb464
b46b288
f39d09e
ffcbd82
463429d
e4a32bc
f644bb9
17313a8
8c5b20d
36ad2b7
b9f872f
8829b2c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| .. ## | ||
| .. ## Copyright (c) Lawrence Livermore National Security, LLC and other | ||
| .. ## RAJA Project Developers. See top-level LICENSE and COPYRIGHT | ||
| .. ## files for dates and other details. No copyright assignment is required | ||
| .. ## to contribute to RAJA. | ||
| .. ## | ||
| .. ## SPDX-License-Identifier: (BSD-3-Clause) | ||
| .. ## | ||
|
|
||
| .. _cook-book-launch-nd-label: | ||
|
|
||
| ============================ | ||
| Cooking with RAJA::launch_nd | ||
| ============================ | ||
|
|
||
| ``RAJA::launch_nd`` runs a logical 2-D or 3-D loop body through selectable | ||
| launch-backed mappings. It is intended for kernels where the source code should | ||
| stay written in logical multi-dimensional indices, but the best GPU mapping is | ||
| not known from the source alone. | ||
|
|
||
| The interface supports two mapping policy families: | ||
|
|
||
| * ``RAJA::launch_nd_flattened_policy<ExecPolicy, LayoutTag>`` maps the product | ||
| of the logical dimensions to a 1-D launch. The ``ExecPolicy`` is a regular | ||
| forall-style policy such as ``RAJA::cuda_exec<256>`` or | ||
| ``RAJA::hip_exec<256>``. RAJA derives the launch parameters and performs the | ||
| linear-to-logical index reconstruction internally. | ||
| * ``RAJA::launch_nd_grid_policy<LaunchPolicy, LoopPolicies...>`` maps the | ||
| logical dimensions directly to a true 2-D or 3-D launch. The user supplies | ||
| the launch policy, one loop policy per segment, and the ``RAJA::LaunchParams``. | ||
|
|
||
| This makes it possible to put both mappings behind one abstraction and choose | ||
| the mapping policy from problem size, backend, or measurements while preserving | ||
| one logical loop body. | ||
|
|
||
| ---------------------------------- | ||
| Why Compare Flat and Grid Mappings | ||
| ---------------------------------- | ||
|
|
||
| Many application kernels are logically 2-D or 3-D but have historically run on | ||
| a 1-D iteration space, with division and modulo operations used to recover the | ||
| logical indices. That approach can expose more parallelism when one logical | ||
| dimension is small. | ||
|
|
||
| For example, a ``cells x components`` kernel with only a few components may not | ||
| fit a fixed ``16 x 16`` block well. A true 2-D grid can leave many component | ||
| threads inactive in each block. The flattened mapping instead launches over | ||
| ``cells * components`` as a 1-D space, which can produce fuller blocks. The | ||
| tradeoff is the extra index reconstruction arithmetic. The true grid mapping | ||
| can still win when the dimensions fit the block shape, when the body is very | ||
| small and index reconstruction dominates, or when direct multi-dimensional | ||
| mapping improves memory access or scheduling. | ||
|
|
||
| ---------------- | ||
| Mapping Policies | ||
| ---------------- | ||
|
|
||
| The example source defines backend-specific policy aliases. CUDA uses direct | ||
| global loop policies for the true grid mapping: | ||
|
Comment on lines
+58
to
+59
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is confusing to have direct and loop in close proximity here.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good call, I updated the example |
||
|
|
||
| .. literalinclude:: ../../../../examples/launch_nd.cpp | ||
| :start-after: // _launch_nd_policy_aliases_start | ||
| :end-before: // _launch_nd_policy_aliases_end | ||
| :language: C++ | ||
|
|
||
| The flattened policy uses a forall-style execution policy such as | ||
| ``RAJA::cuda_exec<block_size_1d>`` or ``RAJA::hip_exec<block_size_1d>``. The | ||
| grid policy uses ``RAJA::LaunchPolicy`` and direct global loop policies such as | ||
| ``RAJA::cuda_global_y_direct`` and ``RAJA::cuda_global_x_direct``. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you use
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If people want to do more complicated things like mixing direct and loop policies they could always use launch itself.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree actually, that would good but we would need to first update formalize support “multi-dim per-loop” policies. Something I've played around with but have not yet formalized |
||
|
|
||
| Both mappings call the same logical body through one ``RAJA::launch_nd`` call: | ||
|
|
||
| .. literalinclude:: ../../../../examples/launch_nd.cpp | ||
| :start-after: // _launch_nd_call_start | ||
| :end-before: // _launch_nd_call_end | ||
| :language: C++ | ||
|
|
||
| ---------------------- | ||
| Runtime Policy Choice | ||
| ---------------------- | ||
|
|
||
| The mapping can be selected at run time by choosing which policy object is | ||
| passed to the common implementation: | ||
|
|
||
| .. literalinclude:: ../../../../examples/launch_nd.cpp | ||
| :start-after: // _launch_nd_runtime_select_start | ||
| :end-before: // _launch_nd_runtime_select_end | ||
| :language: C++ | ||
|
|
||
| Run the example both ways and compare timing with the profiling tool normally | ||
| used for the target backend:: | ||
|
|
||
| ./launch_nd flat | ||
| ./launch_nd grid | ||
|
|
||
| The example uses ``num_cells = 257`` and ``num_comp = 5`` to show a case where | ||
| the ``16 x 16`` grid mapping has a small logical component dimension. Change | ||
| ``num_cells``, ``num_comp``, ``block_size_1d``, ``block_x``, and ``block_y`` in | ||
| ``RAJA/examples/launch_nd.cpp`` to explore when the flattened or true-grid | ||
| mapping is better for a kernel shape. | ||
|
|
||
| -------------------- | ||
| Current Capabilities | ||
| -------------------- | ||
|
|
||
| ``RAJA::launch_nd`` currently supports ``RAJA::TypedRangeSegment`` packs created | ||
| with ``RAJA::nd_segments``. The grid mapping supports 2-D and 3-D loops and | ||
| requires one loop policy per segment. The flattened mapping uses | ||
| ``RAJA::layout_right`` by default, or ``RAJA::layout_left`` when that layout tag | ||
| is supplied, to control which logical index is unit stride in the flattened | ||
| space. | ||
|
Comment on lines
+106
to
+111
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not just a tuple of segments?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In some sense it already is, Second question: For the grid policy: |
||
|
|
||
| Use direct ``RAJA::launch`` when the kernel needs explicit shared memory, team | ||
| synchronization, multiple cooperating loops in a single launch body, or other | ||
| hierarchical launch features that do not fit the single logical body accepted by | ||
| ``RAJA::launch_nd``. | ||
|
|
||
| When using overloads that take both a ``RAJA::resources::Resource`` and an | ||
| explicit ``RAJA::ExecPlace``, the place must match the resource platform (host | ||
| vs device); otherwise RAJA aborts or throws. | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The GPU is part of this, but wouldn't this also be useful for doing things like collapsed openmp loops, or reordered sequential loops?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Underneath we just map to regular nested loops in launch, I think we would have to leave that for when we do the expanded version of this. One thing to explore is transitioning between flat loops to nested loops using threads in a GPU setting. We also would have to figure out the backend on how that would look like for OpenMP
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose it could, I haven't thought about that yet though actually, I think that could be a neat expansion. I think that goes beyond the targeted scope of this PR though, but something to definitely revisit as we expand capabilities. I would be interested in testing it some kernels in RAJAPerf