Arcane  v4.1.5.0
Documentation développeur
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-2026 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-2026 */
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 "arccore/common/accelerator/RunCommand.h"
18#include "arcane/accelerator/KernelLauncher.h"
19
21#include "arcane/core/ItemGroup.h"
23
24#include "arccore/common/HostKernelRemainingArgsHelper.h"
25
26#include <concepts>
27
28#if defined(ARCCORE_EXPERIMENTAL_GRID_STRIDE)
29#include "arccore/common/StridedLoopRanges.h"
30#endif
31
32/*---------------------------------------------------------------------------*/
33/*---------------------------------------------------------------------------*/
34
35namespace Arcane::Accelerator::Impl
36{
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
43template <typename TraitsType_>
44class ItemLocalIdsLoopRanges
45{
46 public:
47
48 using TraitsType = TraitsType_;
49 using BuilderType = TraitsType::BuilderType;
50
51 public:
52
53 explicit ItemLocalIdsLoopRanges(SmallSpan<const Int32> ids) : m_ids(ids){}
54 constexpr SmallSpan<const Int32> ids() const { return m_ids; }
55 constexpr Int64 nbElement() const { return m_ids.size(); }
56
57 public:
58
60};
61
62/*---------------------------------------------------------------------------*/
63/*---------------------------------------------------------------------------*/
64
65#if defined(ARCCORE_COMPILING_CUDA_OR_HIP)
66
67template <typename LoopBoundsType, typename Lambda, typename... RemainingArgs> __global__ void
68doIndirectGPULambda2(LoopBoundsType bounds, Lambda func, RemainingArgs... remaining_args)
69{
70 // TODO: a supprimer quand il n'y aura plus les anciennes réductions
71 auto privatizer = privatize(func);
72 auto& body = privatizer.privateCopy();
73
74 Int32 i = blockDim.x * blockIdx.x + threadIdx.x;
75
77
78 if constexpr (requires { bounds.nbStride(); }) {
79 // Test expérimental pour utiliser un pas de la taille
80 // de la grille. Le nombre de pas est donné par bounds.nbStride().
81 using BuilderType = LoopBoundsType::LoopBoundType::BuilderType;
82 using LocalIdType = BuilderType::ValueType;
83 Int32 nb_grid_stride = bounds.nbStride();
84 Int32 offset = blockDim.x * gridDim.x;
85 Int64 nb_item = bounds.nbOriginalElement();
86 SmallSpan<const Int32> ids = bounds.originalLoop().ids();
87#pragma unroll 4
88 for (Int32 k = 0; k < nb_grid_stride; ++k) {
89 Int32 true_i = i + (offset * k);
90 if (true_i < nb_item) {
91 LocalIdType lid(ids[true_i]);
92 body(BuilderType::create(true_i, lid), remaining_args...);
93 }
94 }
95 }
96 else {
97 using BuilderType = LoopBoundsType::BuilderType;
98 using LocalIdType = BuilderType::ValueType;
99
100 SmallSpan<const Int32> ids = bounds.ids();
101 if (i < ids.size()) {
102 LocalIdType lid(ids[i]);
103 body(BuilderType::create(i, lid), remaining_args...);
104 }
105 }
106
108}
109
110/*---------------------------------------------------------------------------*/
111/*---------------------------------------------------------------------------*/
112
113#endif // ARCCORE_COMPILING_CUDA_OR_HIP
114
115/*---------------------------------------------------------------------------*/
116/*---------------------------------------------------------------------------*/
117
118#if defined(ARCCORE_COMPILING_SYCL)
119
121template <typename TraitsType, typename Lambda, typename... RemainingArgs>
122class DoIndirectSYCLLambda
123{
124 public:
125
126 void operator()(sycl::nd_item<1> x, SmallSpan<std::byte> shared_memory,
127 SmallSpan<const Int32> ids, Lambda func,
128 RemainingArgs... remaining_args) const
129 {
130 using BuilderType = TraitsType::BuilderType;
131 using LocalIdType = BuilderType::ValueType;
132 auto privatizer = privatize(func);
133 auto& body = privatizer.privateCopy();
134
135 Int32 i = static_cast<Int32>(x.get_global_id(0));
136 SyclKernelRemainingArgsHelper::applyAtBegin(x, shared_memory, remaining_args...);
137 if (i < ids.size()) {
138 LocalIdType lid(ids[i]);
139 body(BuilderType::create(i, lid), remaining_args...);
140 }
141 SyclKernelRemainingArgsHelper::applyAtEnd(x, shared_memory, remaining_args...);
142 }
143 void operator()(sycl::id<1> x, SmallSpan<const Int32> ids, Lambda func) const
144 {
145 using BuilderType = TraitsType::BuilderType;
146 using LocalIdType = BuilderType::ValueType;
147 auto privatizer = privatize(func);
148 auto& body = privatizer.privateCopy();
149
150 Int32 i = static_cast<Int32>(x);
151 if (i < ids.size()) {
152 LocalIdType lid(ids[i]);
153 body(BuilderType::create(i, lid));
154 }
155 }
156};
157
158#endif
159
160} // namespace Arcane::Accelerator::Impl
161
162/*---------------------------------------------------------------------------*/
163/*---------------------------------------------------------------------------*/
164
165namespace Arcane
166{
167
168/*---------------------------------------------------------------------------*/
169/*---------------------------------------------------------------------------*/
170
172{
173};
174
175/*---------------------------------------------------------------------------*/
176/*---------------------------------------------------------------------------*/
181template <typename T>
182class IteratorWithIndex
184{
185 public:
186
187 constexpr ARCCORE_HOST_DEVICE IteratorWithIndex(Int32 i, T v)
188 : m_index(i)
189 , m_value(v)
190 {}
191
192 public:
193
194 constexpr ARCCORE_HOST_DEVICE Int32 index() const { return m_index; }
195 constexpr ARCCORE_HOST_DEVICE T value() const { return m_value; }
196
197 private:
198
199 Int32 m_index;
200 T m_value;
201};
202
203} // namespace Arcane
204
205/*---------------------------------------------------------------------------*/
206/*---------------------------------------------------------------------------*/
207
208namespace Arcane::impl
209{
210
211template <typename T>
213{
214 public:
215
216 using ValueType = T;
217
218 public:
219
220 constexpr ARCCORE_HOST_DEVICE static IteratorWithIndex<T> create(Int32 index, T value)
221 {
222 return IteratorWithIndex<T>(index, value);
223 }
224};
225
226template <typename T>
228{
229 public:
230
231 using ValueType = T;
232
233 public:
234
235 constexpr ARCCORE_HOST_DEVICE static T create(Int32, T value)
236 {
237 return value;
238 }
239};
240
241} // namespace Arcane::impl
242
243/*---------------------------------------------------------------------------*/
244/*---------------------------------------------------------------------------*/
245
246namespace Arcane::Accelerator::impl
247{
248
249/*---------------------------------------------------------------------------*/
250/*---------------------------------------------------------------------------*/
257template <typename T>
258concept RunCommandEnumerateIteratorConcept = std::derived_from<T, Item>
259 || std::derived_from<T, ItemLocalId>
260 || std::derived_from<T, IteratorWithIndexBase>;
261
263template <typename T>
265{
266 public:
267
268 using ItemType = T;
269 using ValueType = typename ItemTraitsT<ItemType>::LocalIdType;
271};
272
274template <typename T>
276{
277 public:
278
279 using ItemType = typename ItemLocalIdT<T>::ItemType;
280 using ValueType = ItemLocalIdT<T>;
282};
283
285template <typename T>
286requires std::derived_from<T, ItemLocalId> class RunCommandItemEnumeratorSubTraitsT<IteratorWithIndex<T>>
287{
288 public:
289
290 using ItemType = typename T::ItemType;
291 using ValueType = IteratorWithIndex<T>;
292 using BuilderType = Arcane::impl::IterBuilderWithIndex<T>;
293};
294
295/*---------------------------------------------------------------------------*/
296/*---------------------------------------------------------------------------*/
307template <typename ItemType>
308class RunCommandItemContainer
309{
310 public:
311
312 explicit RunCommandItemContainer(const ItemGroupT<ItemType>& group)
313 : m_item_group(group)
314 , m_unpadded_vector_view(group._unpaddedView())
315 {}
316 explicit RunCommandItemContainer(const ItemVectorViewT<ItemType>& item_vector_view)
317 : m_item_vector_view(item_vector_view)
318 , m_unpadded_vector_view(item_vector_view)
319 {
320 }
321
322 public:
323
324 Int32 size() const { return m_unpadded_vector_view.size(); }
325 SmallSpan<const Int32> localIds() const { return m_unpadded_vector_view.localIds(); }
326 ItemVectorView paddedView() const
327 {
328 if (!m_item_group.null())
329 return m_item_group._paddedView();
330 return m_item_vector_view;
331 }
332
333 private:
334
335 ItemVectorViewT<ItemType> m_item_vector_view;
336 ItemGroupT<ItemType> m_item_group;
337 ItemVectorViewT<ItemType> m_unpadded_vector_view;
338};
339
340/*---------------------------------------------------------------------------*/
341/*---------------------------------------------------------------------------*/
351template <RunCommandEnumerateIteratorConcept IteratorValueType_>
352class RunCommandItemEnumeratorTraitsT
353{
354 public:
355
357 using ItemType = typename SubTraitsType::ItemType;
358 using LocalIdType = typename ItemTraitsT<ItemType>::LocalIdType;
359 using ValueType = typename SubTraitsType::ValueType;
360 using ContainerType = RunCommandItemContainer<ItemType>;
361 using BuilderType = typename SubTraitsType::BuilderType;
362
363 public:
364
365 explicit RunCommandItemEnumeratorTraitsT(const ItemGroupT<ItemType>& group)
366 : m_item_container(group)
367 {}
368 explicit RunCommandItemEnumeratorTraitsT(const ItemVectorViewT<ItemType>& vector_view)
369 : m_item_container(vector_view)
370 {
371 }
372
373 public:
374
375 RunCommandItemContainer<ItemType> m_item_container;
376};
377
378/*---------------------------------------------------------------------------*/
379/*---------------------------------------------------------------------------*/
380
381template <typename TraitsType, typename ContainerType, typename Lambda, typename... RemainingArgs>
382void _doItemsLambda(Int32 base_index, ContainerType sub_items, const Lambda& func, RemainingArgs... remaining_args)
383{
384 using ItemType = TraitsType::ItemType;
385 using BuilderType = TraitsType::BuilderType;
386 using LocalIdType = BuilderType::ValueType;
387 auto privatizer = Impl::privatize(func);
388 auto& body = privatizer.privateCopy();
389
391 ENUMERATE_NO_TRACE_ (ItemType, iitem, sub_items) {
392 body(BuilderType::create(iitem.index() + base_index, LocalIdType(iitem.itemLocalId())), remaining_args...);
393 }
395}
396
397/*---------------------------------------------------------------------------*/
398/*---------------------------------------------------------------------------*/
402template <typename TraitsType, typename Lambda, typename... RemainingArgs> void
403_applyItems(RunCommand& command, typename TraitsType::ContainerType items,
404 const Lambda& func, const RemainingArgs&... remaining_args)
405{
406 // TODO: fusionner la partie commune avec 'applyLoop'
407 Integer vsize = items.size();
408 if (vsize == 0)
409 return;
410 using ItemType = typename TraitsType::ItemType;
411 using LoopBoundType = Impl::ItemLocalIdsLoopRanges<TraitsType>;
412 [[maybe_unused]] SmallSpan<const Int32> ids = items.localIds();
413 [[maybe_unused]] LoopBoundType bounds(ids);
414
415#if defined(ARCCORE_EXPERIMENTAL_GRID_STRIDE) && defined(ARCCORE_COMPILING_CUDA_OR_HIP)
416 using TrueLoopBoundType = Impl::StridedLoopRanges<LoopBoundType>;
417 TrueLoopBoundType bounds2(command.nbStride(), bounds);
418 Impl::RunCommandLaunchInfo launch_info(command, bounds2.strideValue());
419#else
420 using TrueLoopBoundType = LoopBoundType;
421 [[maybe_unused]] const TrueLoopBoundType& bounds2 = bounds;
422 Impl::RunCommandLaunchInfo launch_info(command, vsize);
423#endif
424
425 const eExecutionPolicy exec_policy = launch_info.executionPolicy();
426
427 launch_info.beginExecute();
428 switch (exec_policy) {
430 ARCCORE_KERNEL_CUDA_FUNC((Impl::doIndirectGPULambda2<TrueLoopBoundType, Lambda, RemainingArgs...>),
431 launch_info, func, bounds2, remaining_args...);
432 break;
434 ARCCORE_KERNEL_HIP_FUNC((Impl::doIndirectGPULambda2<TrueLoopBoundType, Lambda, RemainingArgs...>),
435 launch_info, func, bounds2, remaining_args...);
436 break;
438 ARCCORE_KERNEL_SYCL_FUNC((Impl::DoIndirectSYCLLambda<TraitsType, Lambda, RemainingArgs...>{}),
439 launch_info, func, ids, remaining_args...);
440 break;
442 impl::_doItemsLambda<TraitsType>(0, items.paddedView(), func, remaining_args...);
443 break;
445 arcaneParallelForeach(items.paddedView(), launch_info.loopRunInfo(),
446 [&](ItemVectorViewT<ItemType> sub_items, Int32 base_index) {
447 impl::_doItemsLambda<TraitsType>(base_index, sub_items, func, remaining_args...);
448 });
449 break;
450 default:
451 ARCCORE_FATAL("Invalid execution policy '{0}'", exec_policy);
452 }
453 launch_info.endExecute();
454}
455
456/*---------------------------------------------------------------------------*/
457/*---------------------------------------------------------------------------*/
458
459template <typename TraitsType, typename... RemainingArgs>
460class ItemRunCommandArgs
461{
462 public:
463
464 ItemRunCommandArgs(const TraitsType& traits, const RemainingArgs&... remaining_args)
465 : m_traits(traits)
466 , m_remaining_args(remaining_args...)
467 {
468 }
469
470 public:
471
472 TraitsType m_traits;
473 std::tuple<RemainingArgs...> m_remaining_args;
474};
475
476/*---------------------------------------------------------------------------*/
477/*---------------------------------------------------------------------------*/
478
479} // namespace Arcane::Accelerator::impl
480
481namespace Arcane::Accelerator
482{
483
484/*---------------------------------------------------------------------------*/
485/*---------------------------------------------------------------------------*/
486
487template <typename TraitsType, typename Lambda> void
488run(RunCommand& command, const TraitsType& traits, const Lambda& func)
489{
490 impl::_applyItems<TraitsType>(command, traits.m_item_container, func);
491}
492
493/*---------------------------------------------------------------------------*/
494/*---------------------------------------------------------------------------*/
495
496template <typename TraitsType, typename... RemainingArgs>
497class ItemRunCommand
498{
499 public:
500
501 ItemRunCommand(RunCommand& command, const TraitsType& traits)
502 : m_command(command)
503 , m_traits(traits)
504 {
505 }
506
507 ItemRunCommand(RunCommand& command, const TraitsType& traits, const std::tuple<RemainingArgs...>& remaining_args)
508 : m_command(command)
509 , m_traits(traits)
510 , m_remaining_args(remaining_args)
511 {
512 }
513
514 public:
515
516 RunCommand& m_command;
517 TraitsType m_traits;
518 std::tuple<RemainingArgs...> m_remaining_args;
519};
520
521/*---------------------------------------------------------------------------*/
522/*---------------------------------------------------------------------------*/
523
524template <typename ItemType> auto
525operator<<(RunCommand& command, const impl::RunCommandItemEnumeratorTraitsT<ItemType>& traits)
526{
528 return ItemRunCommand<TraitsType>(command, traits);
529}
530
531/*---------------------------------------------------------------------------*/
532/*---------------------------------------------------------------------------*/
533// Cette méthode est conservée pour compatibilité avec l'existant.
534// A rendre obsolète mi-2024
535template <typename ItemType> auto
536operator<<(RunCommand& command, const ItemVectorViewT<ItemType>& items)
537{
538 using TraitsType = impl::RunCommandItemEnumeratorTraitsT<ItemType>;
539 return ItemRunCommand<TraitsType>(command, TraitsType(items));
540}
541
542// Cette méthode est conservée pour compatibilité avec l'existant.
543// A rendre obsolète mi-2024
544template <typename ItemType> auto
545operator<<(RunCommand& command, const ItemGroupT<ItemType>& items)
546{
547 using TraitsType = impl::RunCommandItemEnumeratorTraitsT<ItemType>;
548 return ItemRunCommand<TraitsType>(command, TraitsType(items));
549}
550
551template <typename TraitsType, typename Lambda>
552void operator<<(ItemRunCommand<TraitsType>& nr, const Lambda& f)
553{
554 run(nr.m_command, nr.m_traits, f);
555}
556
557template <typename TraitsType, typename... RemainingArgs> auto
559{
560 return ItemRunCommand<TraitsType, RemainingArgs...>(command, args.m_traits, args.m_remaining_args);
561}
562
563template <typename TraitsType, typename Lambda, typename... RemainingArgs>
564void operator<<(ItemRunCommand<TraitsType, RemainingArgs...>&& nr, const Lambda& f)
565{
566 if constexpr (sizeof...(RemainingArgs) > 0) {
567 std::apply([&](auto... vs) { impl::_applyItems<TraitsType>(nr.m_command, nr.m_traits.m_item_container, f, vs...); }, nr.m_remaining_args);
568 }
569 else
570 run(nr.m_command, nr.m_traits, f);
571}
572
573/*---------------------------------------------------------------------------*/
574/*---------------------------------------------------------------------------*/
575
576} // namespace Arcane::Accelerator
577
578namespace Arcane::Accelerator::impl
579{
580
581/*---------------------------------------------------------------------------*/
582/*---------------------------------------------------------------------------*/
583
584template <typename ItemTypeName, typename ItemContainerType, typename... RemainingArgs> auto
585makeExtendedItemEnumeratorLoop(const ItemContainerType& container_type,
586 const RemainingArgs&... remaining_args)
587{
589 return ItemRunCommandArgs<TraitsType, RemainingArgs...>(TraitsType(container_type), remaining_args...);
590}
591
592/*---------------------------------------------------------------------------*/
593/*---------------------------------------------------------------------------*/
594
595} // namespace Arcane::Accelerator::impl
596
597/*---------------------------------------------------------------------------*/
598/*---------------------------------------------------------------------------*/
618#define RUNCOMMAND_ENUMERATE(ItemTypeName, iter_name, item_group, ...) \
619 A_FUNCINFO << ::Arcane::Accelerator::impl::makeExtendedItemEnumeratorLoop<ItemTypeName>(item_group __VA_OPT__(, __VA_ARGS__)) \
620 << [=] ARCCORE_HOST_DEVICE(::Arcane::Accelerator::impl::RunCommandItemEnumeratorTraitsT<ItemTypeName>::ValueType iter_name \
621 __VA_OPT__(ARCCORE_RUNCOMMAND_REMAINING_FOR_EACH(__VA_ARGS__)))
622
623/*---------------------------------------------------------------------------*/
624/*---------------------------------------------------------------------------*/
625
626#endif
#define ARCCORE_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 RemainingArgs &... remaining_args)
Applique l'enumération func sur la liste d'entité items.
static ARCCORE_DEVICE void applyAtEnd(Int32 index, RemainingArgs &... remaining_args)
Applique les fonctors des arguments additionnels en fin de kernel.
static ARCCORE_DEVICE void applyAtBegin(Int32 index, RemainingArgs &... remaining_args)
Applique les fonctors des arguments additionnels en début de kernel.
Informations pour la boucle accélérateur sur les entités.
Object temporaire pour conserver les informations d'exécution d'une commande et regrouper les tests.
void beginExecute()
Indique qu'on commence l'exécution de la commande.
void endExecute()
Signale la fin de l'exécution.
Classe pour gérer la décomposition d'une boucle en plusieurs parties.
Int32 nbStride() const
Nombre de pas de décomposition de la boucle.
Template pour connaitre le type d'entité associé à T.
Caractéristiques d'un énumérateur d'une commande sur les entités.
static void applyAtEnd(RemainingArgs &... remaining_args)
Applique les functors des arguments additionnels à la fin de l'itération.
static void applyAtBegin(RemainingArgs &... remaining_args)
Applique les functors des arguments additionnels au début de l'itération.
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
Espace de nom pour l'utilisation des accélérateurs.
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 -*-
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
Int32 LocalIdType
Type des entiers utilisés pour stocker les identifiants locaux des entités.
std::int32_t Int32
Type entier signé sur 32 bits.