Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
RunCommandLoop.h
Aller à la documentation de ce fichier.
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* RunCommandLoop.h (C) 2000-2024 */
9/* */
10/* Macros pour exécuter une boucle sur une commande. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_ACCELERATOR_RUNCOMMANDLOOP_H
13#define ARCANE_ACCELERATOR_RUNCOMMANDLOOP_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arcane/utils/ArcaneCxx20.h"
18
19#include "arcane/accelerator/RunCommand.h"
20#include "arcane/accelerator/RunQueueInternal.h"
21
22/*---------------------------------------------------------------------------*/
23/*---------------------------------------------------------------------------*/
24
25namespace Arcane::Accelerator::impl
26{
27
28/*---------------------------------------------------------------------------*/
29/*---------------------------------------------------------------------------*/
30/*!
31 * \brief Applique la lambda \a func sur une boucle \a bounds.
32 *
33 * \a N est la dimension de la boucle (actuellement 1, 2, 3 ou 4). La lambda
34 * \a func est appliqué à la commande \a command. Les arguments supplémentaires
35 * sont des fonctor supplémentaires (comme les réductions).
36 */
37template <int N, template <int T, typename> class LoopBoundType, typename Lambda, typename... RemainingArgs> void
38_applyGenericLoop(RunCommand& command, LoopBoundType<N, Int32> bounds,
39 const Lambda& func, const RemainingArgs&... other_args)
40{
41 Int64 vsize = bounds.nbElement();
42 if (vsize == 0)
43 return;
44 impl::RunCommandLaunchInfo launch_info(command, vsize);
45 const eExecutionPolicy exec_policy = launch_info.executionPolicy();
46 launch_info.beginExecute();
47 switch (exec_policy) {
49 _applyKernelCUDA(launch_info, ARCANE_KERNEL_CUDA_FUNC(impl::doDirectGPULambdaArrayBounds2) < LoopBoundType<N, Int32>, Lambda, RemainingArgs... >, func, bounds, other_args...);
50 break;
52 _applyKernelHIP(launch_info, ARCANE_KERNEL_HIP_FUNC(impl::doDirectGPULambdaArrayBounds2) < LoopBoundType<N, Int32>, Lambda, RemainingArgs... >, func, bounds, other_args...);
53 break;
55 _applyKernelSYCL(launch_info, ARCANE_KERNEL_SYCL_FUNC(impl::DoDirectSYCLLambdaArrayBounds) < LoopBoundType<N, Int32>, Lambda, RemainingArgs... > {}, func, bounds, other_args...);
56 break;
58 arcaneSequentialFor(bounds, func, other_args...);
59 break;
61 arcaneParallelFor(bounds, launch_info.computeParallelLoopOptions(), func, other_args...);
62 break;
63 default:
64 ARCANE_FATAL("Invalid execution policy '{0}'", exec_policy);
65 }
66 launch_info.endExecute();
67}
68
69/*---------------------------------------------------------------------------*/
70/*---------------------------------------------------------------------------*/
71
72template <typename LoopBoundType, typename... RemainingArgs>
74{
75 public:
76
77 ExtendedArrayBoundLoop(const LoopBoundType& bounds, RemainingArgs... args)
78 : m_bounds(bounds)
79 , m_remaining_args(args...)
80 {
81 }
82 LoopBoundType m_bounds;
83 std::tuple<RemainingArgs...> m_remaining_args;
84};
85
86template <typename ExtentType, typename... RemainingArgs> auto
87makeExtendedArrayBoundLoop(const ArrayBounds<ExtentType>& bounds, RemainingArgs... args)
89{
90 return ExtendedArrayBoundLoop<ArrayBounds<ExtentType>, RemainingArgs...>(bounds, args...);
91}
92
93/*---------------------------------------------------------------------------*/
94/*---------------------------------------------------------------------------*/
95
96} // namespace Arcane::Accelerator::impl
97
98namespace Arcane::Accelerator
99{
100
101/*---------------------------------------------------------------------------*/
102/*---------------------------------------------------------------------------*/
103
104//! Applique la lambda \a func sur l'intervalle d'itération donnée par \a bounds
105template <typename ExtentType, typename Lambda> void
106run(RunCommand& command, ArrayBounds<ExtentType> bounds, const Lambda& func)
107{
108 impl::_applyGenericLoop(command, SimpleForLoopRanges<ExtentType::rank()>(bounds), func);
109}
110
111/*---------------------------------------------------------------------------*/
112/*---------------------------------------------------------------------------*/
113
114//! Applique la lambda \a func sur l'intervalle d'itération donnée par \a bounds
115template <int N, typename Lambda> void
116run(RunCommand& command, SimpleForLoopRanges<N, Int32> bounds, const Lambda& func)
117{
118 impl::_applyGenericLoop(command, bounds, func);
119}
120
121/*---------------------------------------------------------------------------*/
122/*---------------------------------------------------------------------------*/
123
124//! Applique la lambda \a func sur l'intervalle d'itération donnée par \a bounds
125template <int N, typename Lambda> void
126run(RunCommand& command, ComplexForLoopRanges<N, Int32> bounds, const Lambda& func)
127{
128 impl::_applyGenericLoop(command, bounds, func);
129}
130
131//! Applique la lambda \a func sur l'intervalle d'itération donnée par \a bounds
132template <int N, template <int T, typename> class LoopBoundType, typename Lambda, typename... RemainingArgs> void
133runExtended(RunCommand& command, LoopBoundType<N, Int32> bounds,
134 const Lambda& func, const std::tuple<RemainingArgs...>& other_args)
135{
136 std::apply([&](auto... vs) { impl::_applyGenericLoop(command, bounds, func, vs...); }, other_args);
137}
138
139/*---------------------------------------------------------------------------*/
140/*---------------------------------------------------------------------------*/
141
142template <int N, typename LoopBoundType, typename... RemainingArgs>
144{
145 public:
146
147 ArrayBoundRunCommand(RunCommand& command, const LoopBoundType& bounds)
148 : m_command(command)
149 , m_bounds(bounds)
150 {
151 }
152 ArrayBoundRunCommand(RunCommand& command, const LoopBoundType& bounds, const std::tuple<RemainingArgs...>& args)
153 : m_command(command)
154 , m_bounds(bounds)
155 , m_remaining_args(args)
156 {
157 }
158 RunCommand& m_command;
159 LoopBoundType m_bounds;
160 std::tuple<RemainingArgs...> m_remaining_args;
161};
162
163template <typename ExtentType> auto
164operator<<(RunCommand& command, const ArrayBounds<ExtentType>& bounds)
165-> ArrayBoundRunCommand<ExtentType::rank(), SimpleForLoopRanges<ExtentType::rank(), Int32>>
166{
167 return { command, bounds };
168}
169
170template <typename ExtentType, typename... RemainingArgs> auto
171operator<<(RunCommand& command, const impl::ExtendedArrayBoundLoop<ExtentType, RemainingArgs...>& ex_loop)
172-> ArrayBoundRunCommand<1, SimpleForLoopRanges<1, Int32>, RemainingArgs...>
173{
174 return { command, ex_loop.m_bounds, ex_loop.m_remaining_args };
175}
176
177template <int N> ArrayBoundRunCommand<N, SimpleForLoopRanges<N>>
178operator<<(RunCommand& command, const SimpleForLoopRanges<N, Int32>& bounds)
179{
180 return { command, bounds };
181}
182
183template <int N> ArrayBoundRunCommand<N, ComplexForLoopRanges<N>>
184operator<<(RunCommand& command, const ComplexForLoopRanges<N, Int32>& bounds)
185{
186 return { command, bounds };
187}
188
189template <int N, template <int, typename> class ForLoopBoundType, typename Lambda, typename... RemainingArgs>
190void operator<<(ArrayBoundRunCommand<N, ForLoopBoundType<N, Int32>, RemainingArgs...>&& nr, const Lambda& f)
191{
192 if constexpr (sizeof...(RemainingArgs) > 0) {
193 runExtended(nr.m_command, nr.m_bounds, f, nr.m_remaining_args);
194 }
195 else {
196 run(nr.m_command, nr.m_bounds, f);
197 }
198}
199
200/*---------------------------------------------------------------------------*/
201/*---------------------------------------------------------------------------*/
202
203} // End namespace Arcane::Accelerator
204
205/*---------------------------------------------------------------------------*/
206/*---------------------------------------------------------------------------*/
207
208//! Boucle sur accélérateur
209#define RUNCOMMAND_LOOP(iter_name, bounds) \
210 A_FUNCINFO << bounds << [=] ARCCORE_HOST_DEVICE(typename decltype(bounds)::IndexType iter_name)
211
212//! Boucle sur accélérateur
213#define RUNCOMMAND_LOOPN(iter_name, N, ...) \
214 A_FUNCINFO << Arcane::ArrayBounds<typename Arcane::MDDimType<N>::DimType>(__VA_ARGS__) << [=] ARCCORE_HOST_DEVICE(Arcane::ArrayIndex<N> iter_name)
215
216//! Boucle sur accélérateur
217#define RUNCOMMAND_LOOP2(iter_name, x1, x2) \
218 A_FUNCINFO << Arcane::ArrayBounds<MDDim2>(x1, x2) << [=] ARCCORE_HOST_DEVICE(Arcane::MDIndex<2> iter_name)
219
220//! Boucle sur accélérateur
221#define RUNCOMMAND_LOOP3(iter_name, x1, x2, x3) \
222 A_FUNCINFO << Arcane::ArrayBounds<MDDim3>(x1, x2, x3) << [=] ARCCORE_HOST_DEVICE(Arcane::MDIndex<3> iter_name)
223
224//! Boucle sur accélérateur
225#define RUNCOMMAND_LOOP4(iter_name, x1, x2, x3, x4) \
226 A_FUNCINFO << Arcane::ArrayBounds<MDDim4>(x1, x2, x3, x4) << [=] ARCCORE_HOST_DEVICE(Arcane::MDIndex<4> iter_name)
227
228/*!
229 * \brief Boucle sur accélérateur avec arguments supplémentaires pour les réductions.
230 *
231 * Cette macro permet d'ajouter des arguments
232 * pour chaque valeur à réduire. Les arguments doivent être des instances des
233 * classes Arcane::Accelerator::ReducerSum2, Arcane::Accelerator::ReducerMax2 ou Arcane::Accelerator::ReducerMin2.
234 */
235#define RUNCOMMAND_LOOP1(iter_name, x1, ...) \
236 A_FUNCINFO << ::Arcane::Accelerator::impl::makeExtendedArrayBoundLoop(Arcane::ArrayBounds<MDDim1>(x1) __VA_OPT__(, __VA_ARGS__)) \
237 << [=] ARCCORE_HOST_DEVICE(Arcane::ArrayIndex<1> iter_name __VA_OPT__(ARCANE_RUNCOMMAND_REDUCER_FOR_EACH(__VA_ARGS__)))
238
239/*!
240 * \brief Boucle sur accélérateur pour exécution avec un seul thread.
241 */
242#define RUNCOMMAND_SINGLE(...) \
243 A_FUNCINFO << ::Arcane::Accelerator::impl::makeExtendedArrayBoundLoop(Arcane::ArrayBounds<MDDim1>(1) __VA_OPT__(, __VA_ARGS__)) \
244 << [=] ARCCORE_HOST_DEVICE(Arcane::ArrayIndex<1> __VA_OPT__(ARCANE_RUNCOMMAND_REDUCER_FOR_EACH(__VA_ARGS__)))
245
246/*!
247 * \brief Boucle sur accélérateur.
248 *
249 * \deprecated Utiliser RUNCOMMAND_LOOP1() à la place.
250 */
251#define RUNCOMMAND_LOOP1_EX(iter_name, x1, ...) \
252 RUNCOMMAND_LOOP1(iter_name, x1, __VA_ARGS__)
253
254/*---------------------------------------------------------------------------*/
255/*---------------------------------------------------------------------------*/
256
257/*---------------------------------------------------------------------------*/
258/*---------------------------------------------------------------------------*/
259
260#endif
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
void _applyGenericLoop(RunCommand &command, LoopBoundType< N, Int32 > bounds, const Lambda &func, const RemainingArgs &... other_args)
Applique la lambda func sur une boucle bounds.
Gestion d'une commande sur accélérateur.
void beginExecute()
Indique qu'on commence l'exécution de la commande.
ParallelLoopOptions computeParallelLoopOptions() const
Calcul les informations pour les boucles multi-thread.
void endExecute()
Signale la fin de l'exécution.
Interval d'itération simple.
void arcaneParallelFor(Integer i0, Integer size, InstanceType *itype, void(InstanceType::*lambda_function)(Integer i0, Integer size))
Applique en concurrence la fonction lambda lambda_function sur l'intervalle d'itération [i0,...
Espace de nom pour l'utilisation des accélérateurs.
void runExtended(RunCommand &command, LoopBoundType< N, Int32 > bounds, const Lambda &func, const std::tuple< RemainingArgs... > &other_args)
Applique la lambda func sur l'intervalle d'itération donnée par bounds.
std::ostream & operator<<(std::ostream &o, eExecutionPolicy exec_policy)
Affiche le nom de la politique d'exécution.
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.
void arcaneSequentialFor(LoopBoundType< 1, IndexType > bounds, const Lambda &func, ReducerArgs... reducer_args)
Applique le fonctor func sur une boucle 1D.
std::int64_t Int64
Type entier signé sur 64 bits.