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