12#ifndef ARCCORE_ACCELERATOR_RUNCOMMANDLAUNCHIMPL_H
13#define ARCCORE_ACCELERATOR_RUNCOMMANDLAUNCHIMPL_H
17#include "arccore/common/SequentialFor.h"
18#include "arccore/common/StridedLoopRanges.h"
19#include "arccore/common/accelerator/RunCommand.h"
20#include "arccore/concurrency/ParallelFor.h"
22#include "arccore/accelerator/WorkGroupLoopRange.h"
23#include "arccore/accelerator/CooperativeWorkGroupLoopRange.h"
24#include "arccore/accelerator/KernelLauncher.h"
29namespace Arcane::Accelerator::Impl
39template <
typename IndexType_>
40class HostLaunchLoopRangeBase
44 using IndexType = IndexType_;
48 ARCCORE_ACCELERATOR_EXPORT
49 HostLaunchLoopRangeBase(IndexType total_size,
Int32 nb_group, IndexType block_size);
54 constexpr IndexType
nbElement()
const {
return m_total_size; }
56 constexpr IndexType
blockSize()
const {
return m_block_size; }
64 return ((i + 1) != m_nb_block) ? m_block_size : m_last_block_size;
69 return m_thread_grid_synchronizer;
73 m_thread_grid_synchronizer = v;
79 ThreadGridSynchronizer* m_thread_grid_synchronizer =
nullptr;
80 IndexType m_total_size = 0;
81 IndexType m_block_size = 0;
82 IndexType m_last_block_size = 0;
89template <
typename WorkGroupLoopRangeType_>
90class HostLaunchLoopRange
91:
public HostLaunchLoopRangeBase<typename WorkGroupLoopRangeType_::IndexType>
95 using WorkGroupLoopRangeType = WorkGroupLoopRangeType_;
96 using IndexType =
typename WorkGroupLoopRangeType_::IndexType;
97 using BaseClass = HostLaunchLoopRangeBase<typename WorkGroupLoopRangeType_::IndexType>;
101 explicit HostLaunchLoopRange(
const WorkGroupLoopRangeType& bounds)
102 : BaseClass(bounds.nbElement(), bounds.nbBlock(), bounds.blockSize())
114#if defined(ARCCORE_COMPILING_CUDA_OR_HIP)
130#if defined(ARCCORE_COMPILING_SYCL)
146#if defined(ARCCORE_COMPILING_SYCL)
150template <
typename IndexType_>
152:
public std::true_type
157template <
typename IndexType_>
159:
public std::true_type
177 template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
static void
179 const Lambda& func, RemainingArgs... remaining_args)
181 using LoopIndexType = LoopBoundType::LoopIndexType;
184 Int32 loop_index = begin_index * group_size;
185 for (
Int32 i = begin_index; i < (begin_index + nb_loop); ++i) {
191 func(li, remaining_args...);
192 loop_index += group_size;
202#if defined(ARCCORE_COMPILING_CUDA_OR_HIP)
205template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs> __global__
static void
206doHierarchicalLaunchCudaHip(LoopBoundType bounds, Lambda func, RemainingArgs... remaining_args)
208 Int32 i = blockDim.x * blockIdx.x + threadIdx.x;
212 if (i < bounds.nbOriginalElement()) {
213 func(WorkGroupLoopContextBuilder::build(bounds.originalLoop()), remaining_args...);
220#if defined(ARCCORE_COMPILING_SYCL)
222template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
223class doHierarchicalLaunchSycl
227 void operator()(sycl::nd_item<1> x, SmallSpan<std::byte> shared_memory,
228 LoopBoundType bounds, Lambda func,
229 RemainingArgs... remaining_args)
const
231 Int32 i =
static_cast<Int32
>(x.get_global_id(0));
232 SyclKernelRemainingArgsHelper::applyAtBegin(x, shared_memory, remaining_args...);
234 if (i < bounds.nbOriginalElement()) {
235 func(WorkGroupLoopContextBuilder::build(bounds.originalLoop(), x), remaining_args...);
237 SyclKernelRemainingArgsHelper::applyAtEnd(x, shared_memory, remaining_args...);
259template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
260_doHierarchicalLaunch(RunCommand& command, LoopBoundType bounds,
261 const Lambda& func,
const RemainingArgs&... other_args)
263 Int64 nb_orig_element = bounds.nbElement();
264 if (nb_orig_element == 0)
270 if ((bounds.blockSize() == 0) || bounds.isCooperativeLaunch())
271 bounds.setBlockSize(command);
273 TrueLoopBoundType bounds2(bounds);
275 command.addNbThreadPerBlock(bounds.blockSize());
276 bounds2.setNbStride(command.nbStride());
281 Impl::RunCommandLaunchInfo launch_info(command, bounds2.strideValue(), bounds.isCooperativeLaunch());
282 launch_info.beginExecute();
283 switch (exec_policy) {
285 ARCCORE_KERNEL_CUDA_FUNC((Impl::doHierarchicalLaunchCudaHip<TrueLoopBoundType, Lambda, RemainingArgs...>),
286 launch_info, func, bounds2, other_args...);
289 ARCCORE_KERNEL_HIP_FUNC((Impl::doHierarchicalLaunchCudaHip<TrueLoopBoundType, Lambda, RemainingArgs...>),
290 launch_info, func, bounds2, other_args...);
293 ARCCORE_KERNEL_SYCL_FUNC((Impl::doHierarchicalLaunchSycl<TrueLoopBoundType, Lambda, RemainingArgs...>{}),
294 launch_info, func, bounds2, other_args...);
297 HostLoopBoundType host_bounds(bounds);
298 arccoreSequentialFor(host_bounds, func, other_args...);
301 HostLoopBoundType host_bounds(bounds);
302 arccoreParallelFor(host_bounds, launch_info.loopRunInfo(), func, other_args...);
305 ARCCORE_FATAL(
"Invalid execution policy '{0}'", exec_policy);
307 launch_info.endExecute();
316template <
typename LoopBoundType,
typename... RemainingArgs>
317class ExtendedLaunchRunCommand
321 ExtendedLaunchRunCommand(
RunCommand& command,
const LoopBoundType& bounds)
326 ExtendedLaunchRunCommand(
RunCommand& command,
const LoopBoundType& bounds,
const std::tuple<RemainingArgs...>& args)
329 , m_remaining_args(args)
333 LoopBoundType m_bounds;
334 std::tuple<RemainingArgs...> m_remaining_args;
343template <
typename LoopBoundType,
typename... RemainingArgs>
344class ExtendedLaunchLoop
348 ExtendedLaunchLoop(
const LoopBoundType& bounds, RemainingArgs... args)
350 , m_remaining_args(args...)
353 LoopBoundType m_bounds;
354 std::tuple<RemainingArgs...> m_remaining_args;
360template <
typename LoopBoundType,
typename... RemainingArgs>
auto
361makeLaunch(
const LoopBoundType& bounds, RemainingArgs... args)
370template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
371operator<<(ExtendedLaunchRunCommand<LoopBoundType, RemainingArgs...>&& nr,
const Lambda& f)
373 if constexpr (
sizeof...(RemainingArgs) > 0) {
374 std::apply([&](
auto... vs) { _doHierarchicalLaunch(nr.m_command, nr.m_bounds, f, vs...); }, nr.m_remaining_args);
377 _doHierarchicalLaunch(nr.m_command, nr.m_bounds, f);
388template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
401template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
403 const Lambda& func,
const RemainingArgs&... remaining_args)
405 Int32 nb_thread = run_info.options().value().maxThread();
407 bounds.setThreadGridSynchronizer(&grid_sync);
408 auto sub_func = [=](
Int32 begin_index,
Int32 nb_loop) {
#define ARCCORE_FATAL(...)
Macro throwing a FatalErrorException.
Execution context for a command on a set of blocks.
Iteration range of a loop using cooperative hierarchical parallelism.
static ARCCORE_DEVICE void applyAtEnd(Int32 index, RemainingArgs &... remaining_args)
Applies the functors of additional arguments at the end of the kernel.
static ARCCORE_DEVICE void applyAtBegin(Int32 index, RemainingArgs &... remaining_args)
Applies the functors of additional arguments at the beginning of the kernel.
Class to manage the launch of a hierarchical compute kernel.
constexpr IndexType nbActiveItem(Int32 i) const
Number of active items for the i-th block.
ThreadGridSynchronizer * threadGridSynchronizer() const
Grid synchronizer (non-null only in cooperative multi-threading).
constexpr IndexType nbElement() const
Number of elements to process.
constexpr IndexType lastBlockSize() const
Number of elements in the last block.
constexpr IndexType blockSize() const
Block size.
constexpr Int32 nbBlock() const
Number of blocks.
Template to determine if a type used as a loop in kernels always requires sycl::nb_item as an argumen...
Class to manage the decomposition of a loop into multiple parts.
Class to manage grid synchronization in multi-thread;.
static void apply(Int32 begin_index, Int32 nb_loop, HostLaunchLoopRange< LoopBoundType > bounds, const Lambda &func, RemainingArgs... remaining_args)
Applies the functor func on a sequential loop.
Management of an accelerator command.
Execution context of a command on a set of blocks.
constexpr IndexType nbElement() const
Number of elements to process.
Iteration range of a loop using hierarchical parallelism.
static void applyAtEnd(RemainingArgs &... remaining_args)
Applies the functors of additional arguments at the end of the iteration.
static void applyAtBegin(RemainingArgs &... remaining_args)
Applies the functors of additional arguments at the beginning of the iteration.
eExecutionPolicy
Execution policy for a Runner.
@ SYCL
Execution policy using the SYCL environment.
@ HIP
Execution policy using the HIP environment.
@ CUDA
Execution policy using the CUDA environment.
@ Sequential
Sequential execution policy.
@ Thread
Multi-threaded execution policy.
bool isAcceleratorPolicy(eExecutionPolicy exec_policy)
Indicates if exec_policy corresponds to an accelerator.
void arccoreParallelFor(const ComplexForLoopRanges< RankValue, IndexType_ > &loop_ranges, const ForLoopRunInfo &run_info, const LambdaType &lambda_function, const ReducerArgs &... reducer_args)
Applies the lambda function lambda_function concurrently over the iteration interval given by loop_ra...
std::int64_t Int64
Signed integer type of 64 bits.
std::int32_t Int32
Signed integer type of 32 bits.