12#ifndef ARCCORE_ACCELERATOR_RUNCOMMANDLAUNCHIMPL_H
13#define ARCCORE_ACCELERATOR_RUNCOMMANDLAUNCHIMPL_H
17#include "AcceleratorGlobal.h"
18#include "arccore/common/SequentialFor.h"
19#include "arccore/common/StridedLoopRanges.h"
20#include "arccore/common/accelerator/RunCommand.h"
21#include "arccore/concurrency/ParallelFor.h"
23#include "arccore/accelerator/WorkGroupLoopRange.h"
24#include "arccore/accelerator/CooperativeWorkGroupLoopRange.h"
25#include "arccore/accelerator/KernelLauncher.h"
30namespace 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;
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...);
258template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
259_doHierarchicalLaunch(RunCommand& command, LoopBoundType bounds,
260 const Lambda& func,
const RemainingArgs&... other_args)
262 Int64 nb_orig_element = bounds.nbElement();
263 if (nb_orig_element == 0)
269 if ((bounds.blockSize() == 0) || bounds.isCooperativeLaunch())
270 bounds.setBlockSize(command);
272 TrueLoopBoundType bounds2(bounds);
274 command.addNbThreadPerBlock(bounds.blockSize());
275 bounds2.setNbStride(command.nbStride());
280 Impl::RunCommandLaunchInfo launch_info(command, bounds2.strideValue(), bounds.isCooperativeLaunch());
281 launch_info.beginExecute();
282 switch (exec_policy) {
284 ARCCORE_KERNEL_CUDA_FUNC((Impl::doHierarchicalLaunchCudaHip<TrueLoopBoundType, Lambda, RemainingArgs...>),
285 launch_info, func, bounds2, other_args...);
288 ARCCORE_KERNEL_HIP_FUNC((Impl::doHierarchicalLaunchCudaHip<TrueLoopBoundType, Lambda, RemainingArgs...>),
289 launch_info, func, bounds2, other_args...);
292 ARCCORE_KERNEL_SYCL_FUNC((Impl::doHierarchicalLaunchSycl<TrueLoopBoundType, Lambda, RemainingArgs...>{}),
293 launch_info, func, bounds2, other_args...);
296 HostLoopBoundType host_bounds(bounds);
297 arccoreSequentialFor(host_bounds, func, other_args...);
300 HostLoopBoundType host_bounds(bounds);
301 arccoreParallelFor(host_bounds, launch_info.loopRunInfo(), func, other_args...);
304 ARCCORE_FATAL(
"Invalid execution policy '{0}'", exec_policy);
306 launch_info.endExecute();
314template <
typename LoopBoundType,
typename... RemainingArgs>
315class ExtendedLaunchRunCommand
319 ExtendedLaunchRunCommand(
RunCommand& command,
const LoopBoundType& bounds)
324 ExtendedLaunchRunCommand(
RunCommand& command,
const LoopBoundType& bounds,
const std::tuple<RemainingArgs...>& args)
327 , m_remaining_args(args)
331 LoopBoundType m_bounds;
332 std::tuple<RemainingArgs...> m_remaining_args;
340template <
typename LoopBoundType,
typename... RemainingArgs>
341class ExtendedLaunchLoop
345 ExtendedLaunchLoop(
const LoopBoundType& bounds, RemainingArgs... args)
347 , m_remaining_args(args...)
350 LoopBoundType m_bounds;
351 std::tuple<RemainingArgs...> m_remaining_args;
357template <
typename LoopBoundType,
typename... RemainingArgs>
auto
358makeLaunch(
const LoopBoundType& bounds, RemainingArgs... args)
367template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
368operator<<(ExtendedLaunchRunCommand<LoopBoundType, RemainingArgs...>&& nr,
const Lambda& f)
370 if constexpr (
sizeof...(RemainingArgs) > 0) {
371 std::apply([&](
auto... vs) { _doHierarchicalLaunch(nr.m_command, nr.m_bounds, f, vs...); }, nr.m_remaining_args);
374 _doHierarchicalLaunch(nr.m_command, nr.m_bounds, f);
384template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
396template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
398 const Lambda& func,
const RemainingArgs&... remaining_args)
400 Int32 nb_thread = run_info.options().value().maxThread();
402 bounds.setThreadGridSynchronizer(&grid_sync);
403 auto sub_func = [=](
Int32 begin_index,
Int32 nb_loop) {
#define ARCCORE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Contexte d'exécution d'une commande sur un ensemble de blocs.
Intervalle d'itération d'une boucle utilisant le parallélisme hiérarchique collaboratif.
static ARCCORE_DEVICE void applyAtEnd(Int32 index, RemainingArgs &... remaining_args)
Applique les fonctors des arguments additionnels en fin de kernel.
static ARCCORE_DEVICE void applyAtBegin(Int32 index, RemainingArgs &... remaining_args)
Applique les fonctors des arguments additionnels en début de kernel.
Classe pour gérer le lancement d'un noyau de calcul hiérarchique.
ThreadGridSynchronizer * m_thread_grid_synchronizer
constexpr IndexType nbActiveItem(Int32 i) const
Nombre d'éléments actifs pour le i-ème bloc.
ThreadGridSynchronizer * threadGridSynchronizer() const
Synchronizer de la grille (non nul uniquement en multi-thread coopératif)
constexpr IndexType nbElement() const
Nombre d'éléments à traiter.
constexpr IndexType lastBlockSize() const
Nombre d'éléments du dernier bloc.
constexpr IndexType blockSize() const
Taille d'un bloc.
constexpr Int32 nbBlock() const
Nombre de blocs.
Template pour savoir si un type utilisé comme boucle dans les kernels nécessite toujours sycl::nb_ite...
Classe pour gérer la décomposition d'une boucle en plusieurs parties.
Classe pour gérer la synchronisation de grille en multi-thread;.
Classe pour exécuter en séquentiel sur l'hôte une partie de la boucle.
static void apply(Int32 begin_index, Int32 nb_loop, HostLaunchLoopRange< LoopBoundType > bounds, const Lambda &func, RemainingArgs... remaining_args)
Applique le fonctor func sur une boucle séqentielle.
Gestion d'une commande sur accélérateur.
Contexte d'exécution d'une commande sur un ensemble de blocs.
constexpr IndexType nbElement() const
Nombre d'éléments à traiter.
Intervalle d'itération d'une boucle utilisant le parallélisme hiérarchique.
static void applyAtEnd(RemainingArgs &... remaining_args)
Applique les functors des arguments additionnels à la fin de l'itération.
static void applyAtBegin(RemainingArgs &... remaining_args)
Applique les functors des arguments additionnels au début de l'itération.
eExecutionPolicy
Politique d'exécution pour un Runner.
@ SYCL
Politique d'exécution utilisant l'environnement SYCL.
@ HIP
Politique d'exécution utilisant l'environnement HIP.
@ CUDA
Politique d'exécution utilisant l'environnement CUDA.
@ Sequential
Politique d'exécution séquentielle.
@ Thread
Politique d'exécution multi-thread.
bool isAcceleratorPolicy(eExecutionPolicy exec_policy)
Indique si exec_policy correspond à un accélérateur.
std::int64_t Int64
Type entier signé sur 64 bits.
void arccoreParallelFor(const ComplexForLoopRanges< RankValue > &loop_ranges, const ForLoopRunInfo &run_info, const LambdaType &lambda_function, const ReducerArgs &... reducer_args)
Applique en concurrence la fonction lambda lambda_function sur l'intervalle d'itération donné par loo...
std::int32_t Int32
Type entier signé sur 32 bits.