Arcane  v3.16.0.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
RunCommandEnumerate.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/* RunCommandEnumerate.h (C) 2000-2024 */
9/* */
10/* Macros pour exécuter une boucle sur une liste d'entités. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_ACCELERATOR_RUNCOMMANDENUMERATE_H
13#define ARCANE_ACCELERATOR_RUNCOMMANDENUMERATE_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arcane/accelerator/RunCommand.h"
18#include "arcane/accelerator/KernelLauncher.h"
19
20#include "arcane/utils/ArcaneCxx20.h"
21
23#include "arcane/core/ItemGroup.h"
25
26#include <concepts>
27
28/*---------------------------------------------------------------------------*/
29/*---------------------------------------------------------------------------*/
30
31namespace Arcane
32{
33
35{
36};
37/*!
38 * \brief Classe de base pour un itérateur permettant de conserver l'index
39 * de l'itération.
40 */
41template <typename T>
42class IteratorWithIndex
44{
45 public:
46
47 constexpr ARCCORE_HOST_DEVICE IteratorWithIndex(Int32 i, T v)
48 : m_index(i)
49 , m_value(v)
50 {}
51
52 public:
53
54 constexpr ARCCORE_HOST_DEVICE Int32 index() const { return m_index; }
55 constexpr ARCCORE_HOST_DEVICE T value() const { return m_value; }
56
57 private:
58
59 Int32 m_index;
60 T m_value;
61};
62
63} // namespace Arcane
64
65/*---------------------------------------------------------------------------*/
66/*---------------------------------------------------------------------------*/
67
68namespace Arcane::impl
69{
70
71template <typename T>
73{
74 public:
75
76 using ValueType = T;
77
78 public:
79
80 constexpr ARCCORE_HOST_DEVICE static IteratorWithIndex<T> create(Int32 index, T value)
81 {
82 return IteratorWithIndex<T>(index, value);
83 }
84};
85
86template <typename T>
88{
89 public:
90
91 using ValueType = T;
92
93 public:
94
95 constexpr ARCCORE_HOST_DEVICE static T create(Int32, T value)
96 {
97 return value;
98 }
99};
100
101} // namespace Arcane::impl
102
103/*---------------------------------------------------------------------------*/
104/*---------------------------------------------------------------------------*/
105
106namespace Arcane::Accelerator::impl
107{
108
109/*---------------------------------------------------------------------------*/
110/*---------------------------------------------------------------------------*/
111/*!
112 * \brief Concept pour contraintre les valeurs dans RUNCOMMAND_ENUMERATE.
113 *
114 * Le type doit être un type d'entité (Cell, Node, ...) ou un
115 * type de numéro local (CellLocalId, NodeLocalId, ...)
116 */
117template <typename T>
118concept RunCommandEnumerateIteratorConcept = std::derived_from<T, Item>
119 || std::derived_from<T, ItemLocalId>
120 || std::derived_from<T, IteratorWithIndexBase>;
121
122//! Template pour connaitre le type d'entité associé à T
123template <typename T>
125{
126 public:
127
128 using ItemType = T;
129 using ValueType = ItemTraitsT<ItemType>::LocalIdType;
131};
132
133//! Spécialisation pour ItemLocalIdT.
134template <typename T>
136{
137 public:
138
139 using ItemType = typename ItemLocalIdT<T>::ItemType;
140 using ValueType = ItemLocalIdT<T>;
142};
143
144//! Spécialisation pour IteratorWithIndex<T>
145template <typename T>
146requires std::derived_from<T, ItemLocalId> class RunCommandItemEnumeratorSubTraitsT<IteratorWithIndex<T>>
147{
148 public:
149
150 using ItemType = typename T::ItemType;
151 using ValueType = IteratorWithIndex<T>;
152 using BuilderType = Arcane::impl::IterBuilderWithIndex<T>;
153};
154
155/*---------------------------------------------------------------------------*/
156/*---------------------------------------------------------------------------*/
157/*!
158 * \brief Conteneur pour RunCommandEnumerate.
159 *
160 * Le conteneur peut être soit un ItemVectorView, soit un ItemGroup.
161 *
162 * Le but de ce conteneur est d'éviter de faire le padding SIMD pour un
163 * ItemGroup s'il est utilisé sur accélérateur. Comme le padding est
164 * fait sur le CPU, cela induirait des transferts mémoire lorsqu'on utilise
165 * la mémoire unifiée (ce qui est le cas par défaut).
166 */
167template <typename ItemType>
168class RunCommandItemContainer
169{
170 public:
171
172 explicit RunCommandItemContainer(const ItemGroupT<ItemType>& group)
173 : m_item_group(group)
174 , m_unpadded_vector_view(group._unpaddedView())
175 {}
176 explicit RunCommandItemContainer(const ItemVectorViewT<ItemType>& item_vector_view)
177 : m_item_vector_view(item_vector_view)
178 , m_unpadded_vector_view(item_vector_view)
179 {
180 }
181
182 public:
183
184 Int32 size() const { return m_unpadded_vector_view.size(); }
185 SmallSpan<const Int32> localIds() const { return m_unpadded_vector_view.localIds(); }
186 ItemVectorView paddedView() const
187 {
188 if (!m_item_group.null())
189 return m_item_group._paddedView();
190 return m_item_vector_view;
191 }
192
193 private:
194
195 ItemVectorViewT<ItemType> m_item_vector_view;
196 ItemGroupT<ItemType> m_item_group;
197 ItemVectorViewT<ItemType> m_unpadded_vector_view;
198};
199
200/*---------------------------------------------------------------------------*/
201/*---------------------------------------------------------------------------*/
202/*!
203 * \brief Caractéristiques d'un énumérateur d'une commande sur les entités.
204 *
205 * Cette classe doit être spécialisée et définir un type \a ValueType
206 * qui correspond au type de retour de 'operator*' de l'énumérateur.
207 *
208 * \a IteratorValueType_ doit être un type d'entité (Cell, Node, ...) ou un
209 * type de numéro local (CellLocalId, NodeLocalId, ...)
210 */
211template <RunCommandEnumerateIteratorConcept IteratorValueType_>
212class RunCommandItemEnumeratorTraitsT
213{
214 public:
215
217 using ItemType = typename SubTraitsType::ItemType;
218 using LocalIdType = ItemTraitsT<ItemType>::LocalIdType;
219 using ValueType = typename SubTraitsType::ValueType;
220 using ContainerType = RunCommandItemContainer<ItemType>;
221 using BuilderType = SubTraitsType::BuilderType;
222
223 public:
224
225 explicit RunCommandItemEnumeratorTraitsT(const ItemGroupT<ItemType>& group)
226 : m_item_container(group)
227 {}
228 explicit RunCommandItemEnumeratorTraitsT(const ItemVectorViewT<ItemType>& vector_view)
229 : m_item_container(vector_view)
230 {
231 }
232
233 public:
234
235 RunCommandItemContainer<ItemType> m_item_container;
236};
237
238/*---------------------------------------------------------------------------*/
239/*---------------------------------------------------------------------------*/
240
241template <typename TraitsType, typename ContainerType, typename Lambda, typename... ReducerArgs>
242void _doItemsLambda(Int32 base_index, ContainerType sub_items, const Lambda& func, ReducerArgs... reducer_args)
243{
244 using ItemType = TraitsType::ItemType;
245 using BuilderType = TraitsType::BuilderType;
246 using LocalIdType = BuilderType::ValueType;
247 auto privatizer = privatize(func);
248 auto& body = privatizer.privateCopy();
249
250 ENUMERATE_NO_TRACE_ (ItemType, iitem, sub_items) {
251 body(BuilderType::create(iitem.index() + base_index, LocalIdType(iitem.itemLocalId())), reducer_args...);
252 }
254}
255
256/*---------------------------------------------------------------------------*/
257/*---------------------------------------------------------------------------*/
258/*!
259 * \brief Applique l'enumération \a func sur la liste d'entité \a items.
260 */
261template <typename TraitsType, typename Lambda, typename... ReducerArgs> void
262_applyItems(RunCommand& command, typename TraitsType::ContainerType items,
263 const Lambda& func, const ReducerArgs&... reducer_args)
264{
265 // TODO: fusionner la partie commune avec 'applyLoop'
266 Integer vsize = items.size();
267 if (vsize == 0)
268 return;
269 using ItemType = TraitsType::ItemType;
270 impl::RunCommandLaunchInfo launch_info(command, vsize);
271 const eExecutionPolicy exec_policy = launch_info.executionPolicy();
272 launch_info.beginExecute();
273 SmallSpan<const Int32> ids = items.localIds();
274 switch (exec_policy) {
276 _applyKernelCUDA(launch_info, ARCANE_KERNEL_CUDA_FUNC(doIndirectGPULambda2) < TraitsType, Lambda, ReducerArgs... >, func, ids, reducer_args...);
277 break;
279 _applyKernelHIP(launch_info, ARCANE_KERNEL_HIP_FUNC(doIndirectGPULambda2) < TraitsType, Lambda, ReducerArgs... >, func, ids, reducer_args...);
280 break;
282 _applyKernelSYCL(launch_info, ARCANE_KERNEL_SYCL_FUNC(impl::DoIndirectSYCLLambda) < TraitsType, Lambda, ReducerArgs... > {}, func, ids, reducer_args...);
283 break;
285 impl::_doItemsLambda<TraitsType>(0, items.paddedView(), func, reducer_args...);
286 break;
288 arcaneParallelForeach(items.paddedView(), launch_info.loopRunInfo(),
289 [&](ItemVectorViewT<ItemType> sub_items, Int32 base_index) {
290 impl::_doItemsLambda<TraitsType>(base_index, sub_items, func, reducer_args...);
291 });
292 break;
293 default:
294 ARCANE_FATAL("Invalid execution policy '{0}'", exec_policy);
295 }
296 launch_info.endExecute();
297}
298
299/*---------------------------------------------------------------------------*/
300/*---------------------------------------------------------------------------*/
301
302template <typename TraitsType, typename... ReducerArgs>
303class ItemRunCommandArgs
304{
305 public:
306
307 ItemRunCommandArgs(const TraitsType& traits, const ReducerArgs&... reducer_args)
308 : m_traits(traits)
309 , m_reducer_args(reducer_args...)
310 {
311 }
312
313 public:
314
315 TraitsType m_traits;
316 std::tuple<ReducerArgs...> m_reducer_args;
317};
318
319/*---------------------------------------------------------------------------*/
320/*---------------------------------------------------------------------------*/
321
322} // namespace Arcane::Accelerator::impl
323
324namespace Arcane::Accelerator
325{
326
327/*---------------------------------------------------------------------------*/
328/*---------------------------------------------------------------------------*/
329
330template <typename TraitsType, typename Lambda> void
331run(RunCommand& command, const TraitsType& traits, const Lambda& func)
332{
333 impl::_applyItems<TraitsType>(command, traits.m_item_container, func);
334}
335
336/*---------------------------------------------------------------------------*/
337/*---------------------------------------------------------------------------*/
338
339template <typename TraitsType, typename... ReducerArgs>
340class ItemRunCommand
341{
342 public:
343
344 ItemRunCommand(RunCommand& command, const TraitsType& traits)
345 : m_command(command)
346 , m_traits(traits)
347 {
348 }
349
350 ItemRunCommand(RunCommand& command, const TraitsType& traits, const std::tuple<ReducerArgs...>& reducer_args)
351 : m_command(command)
352 , m_traits(traits)
353 , m_reducer_args(reducer_args)
354 {
355 }
356
357 public:
358
359 RunCommand& m_command;
360 TraitsType m_traits;
361 std::tuple<ReducerArgs...> m_reducer_args;
362};
363
364/*---------------------------------------------------------------------------*/
365/*---------------------------------------------------------------------------*/
366
367template <typename ItemType> auto
369{
371 return ItemRunCommand<TraitsType>(command, traits);
372}
373
374/*---------------------------------------------------------------------------*/
375/*---------------------------------------------------------------------------*/
376// Cette méthode est conservée pour compatibilité avec l'existant.
377// A rendre obsolète mi-2024
378template <typename ItemType> auto
379operator<<(RunCommand& command, const ItemVectorViewT<ItemType>& items)
380{
381 using TraitsType = impl::RunCommandItemEnumeratorTraitsT<ItemType>;
382 return ItemRunCommand<TraitsType>(command, TraitsType(items));
383}
384
385// Cette méthode est conservée pour compatibilité avec l'existant.
386// A rendre obsolète mi-2024
387template <typename ItemType> auto
388operator<<(RunCommand& command, const ItemGroupT<ItemType>& items)
389{
390 using TraitsType = impl::RunCommandItemEnumeratorTraitsT<ItemType>;
391 return ItemRunCommand<TraitsType>(command, TraitsType(items));
392}
393
394template <typename TraitsType, typename Lambda>
395void operator<<(ItemRunCommand<TraitsType>& nr, const Lambda& f)
396{
397 run(nr.m_command, nr.m_traits, f);
398}
399
400template <typename TraitsType, typename... ReducerArgs> auto
402{
403 return ItemRunCommand<TraitsType, ReducerArgs...>(command, args.m_traits, args.m_reducer_args);
404}
405
406template <typename TraitsType, typename Lambda, typename... ReducerArgs>
408{
409 if constexpr (sizeof...(ReducerArgs) > 0) {
410 std::apply([&](auto... vs) { impl::_applyItems<TraitsType>(nr.m_command, nr.m_traits.m_item_container, f, vs...); }, nr.m_reducer_args);
411 }
412 else
413 run(nr.m_command, nr.m_traits, f);
414}
415
416/*---------------------------------------------------------------------------*/
417/*---------------------------------------------------------------------------*/
418
419} // namespace Arcane::Accelerator
420
421namespace Arcane::Accelerator::impl
422{
423
424/*---------------------------------------------------------------------------*/
425/*---------------------------------------------------------------------------*/
426
427template <typename ItemTypeName, typename ItemContainerType, typename... ReducerArgs> auto
428makeExtendedItemEnumeratorLoop(const ItemContainerType& container_type,
429 const ReducerArgs&... reducer_args)
430{
432 return ItemRunCommandArgs<TraitsType, ReducerArgs...>(TraitsType(container_type), reducer_args...);
433}
434
435/*---------------------------------------------------------------------------*/
436/*---------------------------------------------------------------------------*/
437
438} // namespace Arcane::Accelerator::impl
439
440/*---------------------------------------------------------------------------*/
441/*---------------------------------------------------------------------------*/
442/*!
443 * \brief Macro pour itérer sur accélérateur sur un groupe d'entités.
444 *
445 * Conceptuellement, cela est équivalent à la boucle suivante:
446 *
447 * \code
448 * for( ItemTypeName iter_name : item_group ){
449 * ...
450 * }
451 * \endcode
452 *
453 * \a ItemTypeName doit être un type de numéro local (CellLocalId, NodeLocalId).
454 * L'utilisation du nom du type de l'entité (Cell, Node, ...) est possible mais est
455 * obsolète et il est équivalent à utiliser le type du numéro local (par exemple
456 * il faut remplacer \a Cell par \a CellLocalId).
457 * \a iter_name est le nom de la variable contenant la valeur courante de l'itérateur.
458 * \a item_group est le nom du ItemGroup ou ItemVectorView associé
459 * Les arguments supplémentaires servent à spécifier les réductions éventuelles
460 */
461#define RUNCOMMAND_ENUMERATE(ItemTypeName, iter_name, item_group, ...) \
462 A_FUNCINFO << ::Arcane::Accelerator::impl::makeExtendedItemEnumeratorLoop<ItemTypeName>(item_group __VA_OPT__(, __VA_ARGS__)) \
463 << [=] ARCCORE_HOST_DEVICE(::Arcane::Accelerator::impl::RunCommandItemEnumeratorTraitsT<ItemTypeName>::ValueType iter_name \
464 __VA_OPT__(ARCANE_RUNCOMMAND_REDUCER_FOR_EACH(__VA_ARGS__)))
465
466/*---------------------------------------------------------------------------*/
467/*---------------------------------------------------------------------------*/
468
469#endif
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Classes, Types et macros pour gérer la concurrence.
#define ENUMERATE_NO_TRACE_(type, name, group)
Enumérateur générique d'un groupe d'entité
Déclarations de types sur les entités.
void _applyItems(RunCommand &command, typename TraitsType::ContainerType items, const Lambda &func, const ReducerArgs &... reducer_args)
Applique l'enumération func sur la liste d'entité items.
Gestion d'une commande sur accélérateur.
Template pour connaitre le type d'entité associé à T.
Caractéristiques d'un énumérateur d'une commande sur les entités.
void beginExecute()
Indique qu'on commence l'exécution de la commande.
void endExecute()
Signale la fin de l'exécution.
const ForLoopRunInfo & loopRunInfo() const
Informations d'exécution de la boucle.
Référence à un groupe d'un genre donné.
Definition ItemGroup.h:398
ItemVectorView _unpaddedView() const
Vue sur les entités du groupe sans padding pour la vectorisation.
Definition ItemGroup.cc:600
Index d'une entité ItemType dans une variable.
Definition ItemLocalId.h:90
Vue sur un tableau typé d'entités.
Vue sur un vecteur d'entités.
Classe de base pour un itérateur permettant de conserver l'index de l'itération.
Vue d'un tableau d'éléments de type T.
Definition Span.h:673
static void applyReducerArgs(ReducerArgs &... reducer_args)
Applique les fonctors des arguments additionnels.
Concept pour contraintre les valeurs dans RUNCOMMAND_ENUMERATE.
void arcaneParallelForeach(const ItemVectorView &items_view, const ForLoopRunInfo &run_info, InstanceType *instance, void(InstanceType::*function)(ItemVectorViewT< ItemType > items))
Applique en concurrence la méthode function de l'instance instance sur la vue items_view avec les opt...
Definition Concurrency.h:54
Espace de nom pour l'utilisation des accélérateurs.
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.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Int32 Integer
Type représentant un entier.
std::int32_t Int32
Type entier signé sur 32 bits.