Arcane  v3.14.10.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/RunQueueInternal.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.computeLoopRunInfo();
273 launch_info.beginExecute();
274 SmallSpan<const Int32> ids = items.localIds();
275 switch (exec_policy) {
277 _applyKernelCUDA(launch_info, ARCANE_KERNEL_CUDA_FUNC(doIndirectGPULambda2) < TraitsType, Lambda, ReducerArgs... >, func, ids, reducer_args...);
278 break;
280 _applyKernelHIP(launch_info, ARCANE_KERNEL_HIP_FUNC(doIndirectGPULambda2) < TraitsType, Lambda, ReducerArgs... >, func, ids, reducer_args...);
281 break;
283 _applyKernelSYCL(launch_info, ARCANE_KERNEL_SYCL_FUNC(impl::DoIndirectSYCLLambda) < TraitsType, Lambda, ReducerArgs... > {}, func, ids, reducer_args...);
284 break;
286 impl::_doItemsLambda<TraitsType>(0, items.paddedView(), func, reducer_args...);
287 break;
289 arcaneParallelForeach(items.paddedView(), launch_info.loopRunInfo(),
290 [&](ItemVectorViewT<ItemType> sub_items, Int32 base_index) {
291 impl::_doItemsLambda<TraitsType>(base_index, sub_items, func, reducer_args...);
292 });
293 break;
294 default:
295 ARCANE_FATAL("Invalid execution policy '{0}'", exec_policy);
296 }
297 launch_info.endExecute();
298}
299
300/*---------------------------------------------------------------------------*/
301/*---------------------------------------------------------------------------*/
302
303template <typename TraitsType, typename... ReducerArgs>
305{
306 public:
307
308 ItemRunCommandArgs(const TraitsType& traits, const ReducerArgs&... reducer_args)
309 : m_traits(traits)
310 , m_reducer_args(reducer_args...)
311 {
312 }
313
314 public:
315
316 TraitsType m_traits;
317 std::tuple<ReducerArgs...> m_reducer_args;
318};
319
320/*---------------------------------------------------------------------------*/
321/*---------------------------------------------------------------------------*/
322
323} // namespace Arcane::Accelerator::impl
324
325namespace Arcane::Accelerator
326{
327
328/*---------------------------------------------------------------------------*/
329/*---------------------------------------------------------------------------*/
330
331template <typename TraitsType, typename Lambda> void
332run(RunCommand& command, const TraitsType& traits, const Lambda& func)
333{
334 impl::_applyItems<TraitsType>(command, traits.m_item_container, func);
335}
336
337/*---------------------------------------------------------------------------*/
338/*---------------------------------------------------------------------------*/
339
340template <typename TraitsType, typename... ReducerArgs>
342{
343 public:
344
345 ItemRunCommand(RunCommand& command, const TraitsType& traits)
346 : m_command(command)
347 , m_traits(traits)
348 {
349 }
350
351 ItemRunCommand(RunCommand& command, const TraitsType& traits, const std::tuple<ReducerArgs...>& reducer_args)
352 : m_command(command)
353 , m_traits(traits)
354 , m_reducer_args(reducer_args)
355 {
356 }
357
358 public:
359
360 RunCommand& m_command;
361 TraitsType m_traits;
362 std::tuple<ReducerArgs...> m_reducer_args;
363};
364
365/*---------------------------------------------------------------------------*/
366/*---------------------------------------------------------------------------*/
367
368template <typename ItemType> auto
370{
372 return ItemRunCommand<TraitsType>(command, traits);
373}
374
375/*---------------------------------------------------------------------------*/
376/*---------------------------------------------------------------------------*/
377// Cette méthode est conservée pour compatibilité avec l'existant.
378// A rendre obsolète mi-2024
379template <typename ItemType> auto
380operator<<(RunCommand& command, const ItemVectorViewT<ItemType>& items)
381{
382 using TraitsType = impl::RunCommandItemEnumeratorTraitsT<ItemType>;
383 return ItemRunCommand<TraitsType>(command, TraitsType(items));
384}
385
386// Cette méthode est conservée pour compatibilité avec l'existant.
387// A rendre obsolète mi-2024
388template <typename ItemType> auto
389operator<<(RunCommand& command, const ItemGroupT<ItemType>& items)
390{
391 using TraitsType = impl::RunCommandItemEnumeratorTraitsT<ItemType>;
392 return ItemRunCommand<TraitsType>(command, TraitsType(items));
393}
394
395template <typename TraitsType, typename Lambda>
396void operator<<(ItemRunCommand<TraitsType>& nr, const Lambda& f)
397{
398 run(nr.m_command, nr.m_traits, f);
399}
400
401template <typename TraitsType, typename... ReducerArgs> auto
402operator<<(RunCommand& command, const impl::ItemRunCommandArgs<TraitsType, ReducerArgs...>& args)
403{
404 return ItemRunCommand<TraitsType, ReducerArgs...>(command, args.m_traits, args.m_reducer_args);
405}
406
407template <typename TraitsType, typename Lambda, typename... ReducerArgs>
408void operator<<(ItemRunCommand<TraitsType, ReducerArgs...>&& nr, const Lambda& f)
409{
410 if constexpr (sizeof...(ReducerArgs) > 0) {
411 std::apply([&](auto... vs) { impl::_applyItems<TraitsType>(nr.m_command, nr.m_traits.m_item_container, f, vs...); }, nr.m_reducer_args);
412 }
413 else
414 run(nr.m_command, nr.m_traits, f);
415}
416
417/*---------------------------------------------------------------------------*/
418/*---------------------------------------------------------------------------*/
419
420} // namespace Arcane::Accelerator
421
422namespace Arcane::Accelerator::impl
423{
424
425/*---------------------------------------------------------------------------*/
426/*---------------------------------------------------------------------------*/
427
428template <typename ItemTypeName, typename ItemContainerType, typename... ReducerArgs> auto
429makeExtendedItemEnumeratorLoop(const ItemContainerType& container_type,
430 const ReducerArgs&... reducer_args)
431{
432 using TraitsType = RunCommandItemEnumeratorTraitsT<ItemTypeName>;
433 return ItemRunCommandArgs<TraitsType, ReducerArgs...>(TraitsType(container_type), reducer_args...);
434}
435
436/*---------------------------------------------------------------------------*/
437/*---------------------------------------------------------------------------*/
438
439} // namespace Arcane::Accelerator::impl
440
441/*---------------------------------------------------------------------------*/
442/*---------------------------------------------------------------------------*/
443/*!
444 * \brief Macro pour itérer sur accélérateur sur un groupe d'entités.
445 *
446 * Conceptuellement, cela est équivalent à la boucle suivante:
447 *
448 * \code
449 * for( ItemTypeName iter_name : item_group ){
450 * ...
451 * }
452 * \endcode
453 *
454 * \a ItemTypeName doit être un type de numéro local (CellLocalId, NodeLocalId).
455 * L'utilisation du nom du type de l'entité (Cell, Node, ...) est possible mais est
456 * obsolète et il est équivalent à utiliser le type du numéro local (par exemple
457 * il faut remplacer \a Cell par \a CellLocalId).
458 * \a iter_name est le nom de la variable contenant la valeur courante de l'itérateur.
459 * \a item_group est le nom du ItemGroup ou ItemVectorView associé
460 * Les arguments supplémentaires servent à spécifier les réductions éventuelles
461 */
462#define RUNCOMMAND_ENUMERATE(ItemTypeName, iter_name, item_group, ...) \
463 A_FUNCINFO << ::Arcane::Accelerator::impl::makeExtendedItemEnumeratorLoop<ItemTypeName>(item_group __VA_OPT__(, __VA_ARGS__)) \
464 << [=] ARCCORE_HOST_DEVICE(::Arcane::Accelerator::impl::RunCommandItemEnumeratorTraitsT<ItemTypeName>::ValueType iter_name \
465 __VA_OPT__(ARCANE_RUNCOMMAND_REDUCER_FOR_EACH(__VA_ARGS__)))
466
467/*!
468 * \deprecated Utiliser RUNCOMMAN_ENUMERATE à la place.
469 */
470#define RUNCOMMAND_ENUMERATE_EX(ItemTypeName, iter_name, item_group, ...) \
471 RUNCOMMAND_ENUMERATE (ItemTypeName, iter_name, item_group, __VA_ARGS__)
472
473/*---------------------------------------------------------------------------*/
474/*---------------------------------------------------------------------------*/
475
476#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.
void computeLoopRunInfo()
Calcule la valeur de loopRunInfo()
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.