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,
Int32 block_size);
54 constexpr IndexType
nbElement()
const {
return m_total_size; }
64 return ((i + 1) != m_nb_block) ? m_block_size : m_last_block_size;
69 IndexType m_total_size = 0;
71 Int32 m_block_size = 0;
72 Int32 m_last_block_size = 0;
78template <
typename WorkGroupLoopRangeType_>
79class HostLaunchLoopRange
80:
public HostLaunchLoopRangeBase<typename WorkGroupLoopRangeType_::IndexType>
84 using WorkGroupLoopRangeType = WorkGroupLoopRangeType_;
85 using IndexType =
typename WorkGroupLoopRangeType_::IndexType;
86 using BaseClass = HostLaunchLoopRangeBase<typename WorkGroupLoopRangeType_::IndexType>;
90 explicit HostLaunchLoopRange(
const WorkGroupLoopRangeType& bounds)
91 : BaseClass(bounds.nbElement(), bounds.nbBlock(), bounds.blockSize())
103#if defined(ARCCORE_COMPILING_CUDA_OR_HIP)
119#if defined(ARCCORE_COMPILING_SYCL)
135#if defined(ARCCORE_COMPILING_SYCL)
139template <
typename IndexType_>
141:
public std::true_type
146template <
typename IndexType_>
148:
public std::true_type
166 template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
static void
168 const Lambda& func, RemainingArgs... remaining_args)
170 using LoopIndexType = LoopBoundType::LoopIndexType;
173 Int32 loop_index = begin_index * group_size;
174 for (
Int32 i = begin_index; i < (begin_index + nb_loop); ++i) {
179 func(LoopIndexType(loop_index, i, group_size, nb_active, bounds.
nbElement()), remaining_args...);
180 loop_index += group_size;
190#if defined(ARCCORE_COMPILING_CUDA_OR_HIP)
193template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs> __global__
static void
194doHierarchicalLaunchCudaHip(LoopBoundType bounds, Lambda func, RemainingArgs... remaining_args)
202 Int32 i = blockDim.x * blockIdx.x + threadIdx.x;
206 if (i < bounds.nbOriginalElement()) {
207 func(WorkGroupLoopContextBuilder::build(bounds.originalLoop()), remaining_args...);
214#if defined(ARCCORE_COMPILING_SYCL)
216template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
217class doHierarchicalLaunchSycl
221 void operator()(sycl::nd_item<1> x, SmallSpan<std::byte> shared_memory,
222 LoopBoundType bounds, Lambda func,
223 RemainingArgs... remaining_args)
const
225 Int32 i =
static_cast<Int32
>(x.get_global_id(0));
226 SyclKernelRemainingArgsHelper::applyAtBegin(x, shared_memory, remaining_args...);
228 if (i < bounds.nbOriginalElement()) {
229 func(WorkGroupLoopContextBuilder::build(bounds.originalLoop(), x), remaining_args...);
231 SyclKernelRemainingArgsHelper::applyAtEnd(x, shared_memory, remaining_args...);
252template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
253_doHierarchicalLaunch(RunCommand& command, LoopBoundType bounds,
254 const Lambda& func,
const RemainingArgs&... other_args)
256 Int64 nb_orig_element = bounds.nbElement();
257 if (nb_orig_element == 0)
262 if ((bounds.blockSize() == 0) || bounds.isCooperativeLaunch())
263 bounds.setBlockSize(command);
265 TrueLoopBoundType bounds2(bounds);
267 command.addNbThreadPerBlock(bounds.blockSize());
268 bounds2.setNbStride(command.nbStride());
273 Impl::RunCommandLaunchInfo launch_info(command, bounds2.strideValue(), bounds.isCooperativeLaunch());
274 launch_info.beginExecute();
275 switch (exec_policy) {
277 ARCCORE_KERNEL_CUDA_FUNC((Impl::doHierarchicalLaunchCudaHip<TrueLoopBoundType, Lambda, RemainingArgs...>),
278 launch_info, func, bounds2, other_args...);
281 ARCCORE_KERNEL_HIP_FUNC((Impl::doHierarchicalLaunchCudaHip<TrueLoopBoundType, Lambda, RemainingArgs...>),
282 launch_info, func, bounds2, other_args...);
285 ARCCORE_KERNEL_SYCL_FUNC((Impl::doHierarchicalLaunchSycl<TrueLoopBoundType, Lambda, RemainingArgs...>{}),
286 launch_info, func, bounds2, other_args...);
289 HostLoopBoundType host_bounds(bounds);
290 arccoreSequentialFor(host_bounds, func, other_args...);
293 HostLoopBoundType host_bounds(bounds);
294 arccoreParallelFor(host_bounds, launch_info.loopRunInfo(), func, other_args...);
297 ARCCORE_FATAL(
"Invalid execution policy '{0}'", exec_policy);
299 launch_info.endExecute();
307template <
typename LoopBoundType,
typename... RemainingArgs>
308class ExtendedLaunchRunCommand
312 ExtendedLaunchRunCommand(
RunCommand& command,
const LoopBoundType& bounds)
317 ExtendedLaunchRunCommand(
RunCommand& command,
const LoopBoundType& bounds,
const std::tuple<RemainingArgs...>& args)
320 , m_remaining_args(args)
324 LoopBoundType m_bounds;
325 std::tuple<RemainingArgs...> m_remaining_args;
333template <
typename LoopBoundType,
typename... RemainingArgs>
334class ExtendedLaunchLoop
338 ExtendedLaunchLoop(
const LoopBoundType& bounds, RemainingArgs... args)
340 , m_remaining_args(args...)
343 LoopBoundType m_bounds;
344 std::tuple<RemainingArgs...> m_remaining_args;
350template <
typename LoopBoundType,
typename... RemainingArgs>
auto
351makeLaunch(
const LoopBoundType& bounds, RemainingArgs... args)
360template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
361operator<<(ExtendedLaunchRunCommand<LoopBoundType, RemainingArgs...>&& nr,
const Lambda& f)
363 if constexpr (
sizeof...(RemainingArgs) > 0) {
364 std::apply([&](
auto... vs) { _doHierarchicalLaunch(nr.m_command, nr.m_bounds, f, vs...); }, nr.m_remaining_args);
367 _doHierarchicalLaunch(nr.m_command, nr.m_bounds, f);
377template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
389template <
typename LoopBoundType,
typename Lambda,
typename... RemainingArgs>
void
390arccoreParallelFor(Impl::HostLaunchLoopRange<LoopBoundType> bounds, ForLoopRunInfo run_info,
391 const Lambda& func,
const RemainingArgs&... remaining_args)
393 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 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.