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"
32namespace Arcane::Accelerator::Impl
41template <
typename IndexType_>
42class HostLaunchLoopRangeBase
46 using IndexType = IndexType_;
50 ARCCORE_ACCELERATOR_EXPORT
51 HostLaunchLoopRangeBase(IndexType total_size,
Int32 nb_group,
Int32 block_size);
56 constexpr IndexType
nbElement()
const {
return m_total_size; }
66 return ((i + 1) != m_nb_block) ? m_block_size : m_last_block_size;
70 m_thread_grid_synchronizer = v;
72 ThreadGridSynchronizer* threadGridSynchronizer()
const
74 return m_thread_grid_synchronizer;
79 IndexType m_total_size = 0;
81 Int32 m_block_size = 0;
82 Int32 m_last_block_size = 0;
84 ThreadGridSynchronizer* m_thread_grid_synchronizer =
nullptr;
90template <
typename WorkGroupLoopRangeType_>
91class HostLaunchLoopRange
92:
public HostLaunchLoopRangeBase<typename WorkGroupLoopRangeType_::IndexType>
96 using WorkGroupLoopRangeType = WorkGroupLoopRangeType_;
97 using IndexType =
typename WorkGroupLoopRangeType_::IndexType;
98 using BaseClass = HostLaunchLoopRangeBase<typename WorkGroupLoopRangeType_::IndexType>;
102 explicit HostLaunchLoopRange(
const WorkGroupLoopRangeType& bounds)
103 : BaseClass(bounds.nbElement(), bounds.nbBlock(), bounds.blockSize())
115#if defined(ARCCORE_COMPILING_CUDA_OR_HIP)
131#if defined(ARCCORE_COMPILING_SYCL)
147#if defined(ARCCORE_COMPILING_SYCL)
151template <
typename IndexType_>
153:
public std::true_type
158template <
typename IndexType_>
160:
public std::true_type
178 template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
static void
180 const Lambda& func, RemainingArgs... remaining_args)
182 using LoopIndexType = LoopBoundType::LoopIndexType;
185 Int32 loop_index = begin_index * group_size;
186 for (
Int32 i = begin_index; i < (begin_index + nb_loop); ++i) {
191 LoopIndexType li(loop_index, i, group_size, nb_active, bounds.
nbElement(), bounds.
nbBlock(), bounds.threadGridSynchronizer());
192 func(li, remaining_args...);
193 loop_index += group_size;
203#if defined(ARCCORE_COMPILING_CUDA_OR_HIP)
206template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs> __global__
static void
207doHierarchicalLaunchCudaHip(LoopBoundType bounds, Lambda func, RemainingArgs... remaining_args)
209 Int32 i = blockDim.x * blockIdx.x + threadIdx.x;
213 if (i < bounds.nbOriginalElement()) {
214 func(WorkGroupLoopContextBuilder::build(bounds.originalLoop()), remaining_args...);
221#if defined(ARCCORE_COMPILING_SYCL)
223template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
224class doHierarchicalLaunchSycl
228 void operator()(sycl::nd_item<1> x, SmallSpan<std::byte> shared_memory,
229 LoopBoundType bounds, Lambda func,
230 RemainingArgs... remaining_args)
const
232 Int32 i =
static_cast<Int32
>(x.get_global_id(0));
233 SyclKernelRemainingArgsHelper::applyAtBegin(x, shared_memory, remaining_args...);
235 if (i < bounds.nbOriginalElement()) {
236 func(WorkGroupLoopContextBuilder::build(bounds.originalLoop(), x), remaining_args...);
238 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();
315template <
typename LoopBoundType,
typename... RemainingArgs>
316class ExtendedLaunchRunCommand
320 ExtendedLaunchRunCommand(
RunCommand& command,
const LoopBoundType& bounds)
325 ExtendedLaunchRunCommand(
RunCommand& command,
const LoopBoundType& bounds,
const std::tuple<RemainingArgs...>& args)
328 , m_remaining_args(args)
332 LoopBoundType m_bounds;
333 std::tuple<RemainingArgs...> m_remaining_args;
341template <
typename LoopBoundType,
typename... RemainingArgs>
342class ExtendedLaunchLoop
346 ExtendedLaunchLoop(
const LoopBoundType& bounds, RemainingArgs... args)
348 , m_remaining_args(args...)
351 LoopBoundType m_bounds;
352 std::tuple<RemainingArgs...> m_remaining_args;
358template <
typename LoopBoundType,
typename... RemainingArgs>
auto
359makeLaunch(
const LoopBoundType& bounds, RemainingArgs... args)
368template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
369operator<<(ExtendedLaunchRunCommand<LoopBoundType, RemainingArgs...>&& nr,
const Lambda& f)
371 if constexpr (
sizeof...(RemainingArgs) > 0) {
372 std::apply([&](
auto... vs) { _doHierarchicalLaunch(nr.m_command, nr.m_bounds, f, vs...); }, nr.m_remaining_args);
375 _doHierarchicalLaunch(nr.m_command, nr.m_bounds, f);
385template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
397template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
399 const Lambda& func,
const RemainingArgs&... remaining_args)
401 Int32 nb_thread = run_info.options().value().maxThread();
403 bounds.setThreadGridSynchronizer(&grid_sync);
404 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.
constexpr Int32 blockSize() const
Taille d'un bloc.
constexpr Int32 lastBlockSize() const
Nombre d'éléments du dernier groupe.
constexpr Int32 nbActiveItem(Int32 i) const
Nombre d'éléments actifs pour le i-ème groupe.
constexpr IndexType nbElement() const
Nombre d'éléments à traiter.
constexpr Int32 nbBlock() const
Nombre de groupes.
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;.
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.