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
38template <
typename IndexType_>
39class HostLaunchLoopRangeBase
43 using IndexType = IndexType_;
47 ARCCORE_ACCELERATOR_EXPORT
48 HostLaunchLoopRangeBase(IndexType total_size,
Int32 nb_group, IndexType block_size);
53 constexpr IndexType
nbElement()
const {
return m_total_size; }
55 constexpr IndexType
blockSize()
const {
return m_block_size; }
63 return ((i + 1) != m_nb_block) ? m_block_size : m_last_block_size;
79 IndexType m_total_size = 0;
80 IndexType m_block_size = 0;
81 IndexType m_last_block_size = 0;
88template <
typename WorkGroupLoopRangeType_>
89class HostLaunchLoopRange
90:
public HostLaunchLoopRangeBase<typename WorkGroupLoopRangeType_::IndexType>
94 using WorkGroupLoopRangeType = WorkGroupLoopRangeType_;
95 using IndexType =
typename WorkGroupLoopRangeType_::IndexType;
96 using BaseClass = HostLaunchLoopRangeBase<typename WorkGroupLoopRangeType_::IndexType>;
100 explicit HostLaunchLoopRange(
const WorkGroupLoopRangeType& bounds)
101 : BaseClass(bounds.nbElement(), bounds.nbBlock(), bounds.blockSize())
113#if defined(ARCCORE_COMPILING_CUDA_OR_HIP)
129#if defined(ARCCORE_COMPILING_SYCL)
145#if defined(ARCCORE_COMPILING_SYCL)
149template <
typename IndexType_>
151:
public std::true_type
156template <
typename IndexType_>
158:
public std::true_type
176 template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
static void
178 const Lambda& func, RemainingArgs... remaining_args)
180 using LoopIndexType = LoopBoundType::LoopIndexType;
183 Int32 loop_index = begin_index * group_size;
184 for (
Int32 i = begin_index; i < (begin_index + nb_loop); ++i) {
190 func(li, remaining_args...);
191 loop_index += group_size;
201#if defined(ARCCORE_COMPILING_CUDA_OR_HIP)
204template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs> __global__
static void
205doHierarchicalLaunchCudaHip(LoopBoundType bounds, Lambda func, RemainingArgs... remaining_args)
207 Int32 i = blockDim.x * blockIdx.x + threadIdx.x;
211 if (i < bounds.nbOriginalElement()) {
212 func(WorkGroupLoopContextBuilder::build(bounds.originalLoop()), remaining_args...);
219#if defined(ARCCORE_COMPILING_SYCL)
221template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
222class doHierarchicalLaunchSycl
226 void operator()(sycl::nd_item<1> x, SmallSpan<std::byte> shared_memory,
227 LoopBoundType bounds, Lambda func,
228 RemainingArgs... remaining_args)
const
230 Int32 i =
static_cast<Int32
>(x.get_global_id(0));
231 SyclKernelRemainingArgsHelper::applyAtBegin(x, shared_memory, remaining_args...);
233 if (i < bounds.nbOriginalElement()) {
234 func(WorkGroupLoopContextBuilder::build(bounds.originalLoop(), x), remaining_args...);
236 SyclKernelRemainingArgsHelper::applyAtEnd(x, shared_memory, remaining_args...);
257template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
258_doHierarchicalLaunch(RunCommand& command, LoopBoundType bounds,
259 const Lambda& func,
const RemainingArgs&... other_args)
261 Int64 nb_orig_element = bounds.nbElement();
262 if (nb_orig_element == 0)
268 if ((bounds.blockSize() == 0) || bounds.isCooperativeLaunch())
269 bounds.setBlockSize(command);
271 TrueLoopBoundType bounds2(bounds);
273 command.addNbThreadPerBlock(bounds.blockSize());
274 bounds2.setNbStride(command.nbStride());
279 Impl::RunCommandLaunchInfo launch_info(command, bounds2.strideValue(), bounds.isCooperativeLaunch());
280 launch_info.beginExecute();
281 switch (exec_policy) {
283 ARCCORE_KERNEL_CUDA_FUNC((Impl::doHierarchicalLaunchCudaHip<TrueLoopBoundType, Lambda, RemainingArgs...>),
284 launch_info, func, bounds2, other_args...);
287 ARCCORE_KERNEL_HIP_FUNC((Impl::doHierarchicalLaunchCudaHip<TrueLoopBoundType, Lambda, RemainingArgs...>),
288 launch_info, func, bounds2, other_args...);
291 ARCCORE_KERNEL_SYCL_FUNC((Impl::doHierarchicalLaunchSycl<TrueLoopBoundType, Lambda, RemainingArgs...>{}),
292 launch_info, func, bounds2, other_args...);
295 HostLoopBoundType host_bounds(bounds);
296 arccoreSequentialFor(host_bounds, func, other_args...);
299 HostLoopBoundType host_bounds(bounds);
300 arccoreParallelFor(host_bounds, launch_info.loopRunInfo(), func, other_args...);
303 ARCCORE_FATAL(
"Invalid execution policy '{0}'", exec_policy);
305 launch_info.endExecute();
313template <
typename LoopBoundType,
typename... RemainingArgs>
314class ExtendedLaunchRunCommand
318 ExtendedLaunchRunCommand(
RunCommand& command,
const LoopBoundType& bounds)
323 ExtendedLaunchRunCommand(
RunCommand& command,
const LoopBoundType& bounds,
const std::tuple<RemainingArgs...>& args)
326 , m_remaining_args(args)
330 LoopBoundType m_bounds;
331 std::tuple<RemainingArgs...> m_remaining_args;
339template <
typename LoopBoundType,
typename... RemainingArgs>
340class ExtendedLaunchLoop
344 ExtendedLaunchLoop(
const LoopBoundType& bounds, RemainingArgs... args)
346 , m_remaining_args(args...)
349 LoopBoundType m_bounds;
350 std::tuple<RemainingArgs...> m_remaining_args;
356template <
typename LoopBoundType,
typename... RemainingArgs>
auto
357makeLaunch(
const LoopBoundType& bounds, RemainingArgs... args)
366template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
367operator<<(ExtendedLaunchRunCommand<LoopBoundType, RemainingArgs...>&& nr,
const Lambda& f)
369 if constexpr (
sizeof...(RemainingArgs) > 0) {
370 std::apply([&](
auto... vs) { _doHierarchicalLaunch(nr.m_command, nr.m_bounds, f, vs...); }, nr.m_remaining_args);
373 _doHierarchicalLaunch(nr.m_command, nr.m_bounds, f);
383template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
395template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
397 const Lambda& func,
const RemainingArgs&... remaining_args)
399 Int32 nb_thread = run_info.options().value().maxThread();
401 bounds.setThreadGridSynchronizer(&grid_sync);
402 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.
void arccoreParallelFor(const ComplexForLoopRanges< RankValue, IndexType_ > &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::int64_t Int64
Type entier signé sur 64 bits.
std::int32_t Int32
Type entier signé sur 32 bits.