Arcane  v3.15.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>
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>
72class IterBuilderWithIndex
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>
87class IterBuilderNoIndex
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;
130 using BuilderType = Arcane::impl::IterBuilderNoIndex<ValueType>;
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>;
141 using BuilderType = Arcane::impl::IterBuilderNoIndex<ValueType>;
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>
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_>
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
226 : m_item_container(group)
227 {}
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>
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>
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
401operator<<(RunCommand& command, const impl::ItemRunCommandArgs<TraitsType, ReducerArgs...>& args)
402{
403 return ItemRunCommand<TraitsType, ReducerArgs...>(command, args.m_traits, args.m_reducer_args);
404}
405
406template <typename TraitsType, typename Lambda, typename... ReducerArgs>
407void operator<<(ItemRunCommand<TraitsType, ReducerArgs...>&& nr, const Lambda& f)
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{
431 using TraitsType = RunCommandItemEnumeratorTraitsT<ItemTypeName>;
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 _paddedView() const
Vue sur les entités du groupe avec padding pour la vectorisation.
Definition ItemGroup.cc:591
ItemVectorView _unpaddedView() const
Vue sur les entités du groupe sans padding pour la vectorisation.
Definition ItemGroup.cc:600
bool null() const
true is le groupe est le groupe nul
Definition ItemGroup.h:70
Index d'une entité ItemType dans une variable.
Definition ItemLocalId.h:89
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.
static void applyReducerArgs(ReducerArgs &... reducer_args)
Applique les fonctors des arguments additionnels.
Vue d'un tableau d'éléments de type T.
Definition Span.h:670
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 LocalIdType
Type des entiers utilisés pour stocker les identifiants locaux des entités.
Int32 Integer
Type représentant un entier.
std::int32_t Int32
Type entier signé sur 32 bits.