Arcane  v4.1.4.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 for (Int32 k = 0; k < nb_grid_stride; ++k) {
88 Int32 true_i = i + (offset * k);
89 if (true_i < nb_item) {
90 LocalIdType lid(ids[true_i]);
91 body(BuilderType::create(true_i, lid), remaining_args...);
92 }
93 }
94 }
95 else {
96 using BuilderType = LoopBoundsType::BuilderType;
97 using LocalIdType = BuilderType::ValueType;
98
99 SmallSpan<const Int32> ids = bounds.ids();
100 if (i < ids.size()) {
101 LocalIdType lid(ids[i]);
102 body(BuilderType::create(i, lid), remaining_args...);
103 }
104 }
105
107}
108
109/*---------------------------------------------------------------------------*/
110/*---------------------------------------------------------------------------*/
111
112#endif // ARCCORE_COMPILING_CUDA_OR_HIP
113
114/*---------------------------------------------------------------------------*/
115/*---------------------------------------------------------------------------*/
116
117#if defined(ARCCORE_COMPILING_SYCL)
118
120template <typename TraitsType, typename Lambda, typename... RemainingArgs>
121class DoIndirectSYCLLambda
122{
123 public:
124
125 void operator()(sycl::nd_item<1> x, SmallSpan<std::byte> shared_memory,
126 SmallSpan<const Int32> ids, Lambda func,
127 RemainingArgs... remaining_args) const
128 {
129 using BuilderType = TraitsType::BuilderType;
130 using LocalIdType = BuilderType::ValueType;
131 auto privatizer = privatize(func);
132 auto& body = privatizer.privateCopy();
133
134 Int32 i = static_cast<Int32>(x.get_global_id(0));
135 SyclKernelRemainingArgsHelper::applyAtBegin(x, shared_memory, remaining_args...);
136 if (i < ids.size()) {
137 LocalIdType lid(ids[i]);
138 body(BuilderType::create(i, lid), remaining_args...);
139 }
140 SyclKernelRemainingArgsHelper::applyAtEnd(x, shared_memory, remaining_args...);
141 }
142 void operator()(sycl::id<1> x, SmallSpan<const Int32> ids, Lambda func) const
143 {
144 using BuilderType = TraitsType::BuilderType;
145 using LocalIdType = BuilderType::ValueType;
146 auto privatizer = privatize(func);
147 auto& body = privatizer.privateCopy();
148
149 Int32 i = static_cast<Int32>(x);
150 if (i < ids.size()) {
151 LocalIdType lid(ids[i]);
152 body(BuilderType::create(i, lid));
153 }
154 }
155};
156
157#endif
158
159} // namespace Arcane::Accelerator::Impl
160
161/*---------------------------------------------------------------------------*/
162/*---------------------------------------------------------------------------*/
163
164namespace Arcane
165{
166
167/*---------------------------------------------------------------------------*/
168/*---------------------------------------------------------------------------*/
169
171{
172};
173
174/*---------------------------------------------------------------------------*/
175/*---------------------------------------------------------------------------*/
180template <typename T>
181class IteratorWithIndex
183{
184 public:
185
186 constexpr ARCCORE_HOST_DEVICE IteratorWithIndex(Int32 i, T v)
187 : m_index(i)
188 , m_value(v)
189 {}
190
191 public:
192
193 constexpr ARCCORE_HOST_DEVICE Int32 index() const { return m_index; }
194 constexpr ARCCORE_HOST_DEVICE T value() const { return m_value; }
195
196 private:
197
198 Int32 m_index;
199 T m_value;
200};
201
202} // namespace Arcane
203
204/*---------------------------------------------------------------------------*/
205/*---------------------------------------------------------------------------*/
206
207namespace Arcane::impl
208{
209
210template <typename T>
212{
213 public:
214
215 using ValueType = T;
216
217 public:
218
219 constexpr ARCCORE_HOST_DEVICE static IteratorWithIndex<T> create(Int32 index, T value)
220 {
221 return IteratorWithIndex<T>(index, value);
222 }
223};
224
225template <typename T>
227{
228 public:
229
230 using ValueType = T;
231
232 public:
233
234 constexpr ARCCORE_HOST_DEVICE static T create(Int32, T value)
235 {
236 return value;
237 }
238};
239
240} // namespace Arcane::impl
241
242/*---------------------------------------------------------------------------*/
243/*---------------------------------------------------------------------------*/
244
245namespace Arcane::Accelerator::impl
246{
247
248/*---------------------------------------------------------------------------*/
249/*---------------------------------------------------------------------------*/
256template <typename T>
257concept RunCommandEnumerateIteratorConcept = std::derived_from<T, Item>
258 || std::derived_from<T, ItemLocalId>
259 || std::derived_from<T, IteratorWithIndexBase>;
260
262template <typename T>
264{
265 public:
266
267 using ItemType = T;
268 using ValueType = typename ItemTraitsT<ItemType>::LocalIdType;
270};
271
273template <typename T>
275{
276 public:
277
278 using ItemType = typename ItemLocalIdT<T>::ItemType;
279 using ValueType = ItemLocalIdT<T>;
281};
282
284template <typename T>
285requires std::derived_from<T, ItemLocalId> class RunCommandItemEnumeratorSubTraitsT<IteratorWithIndex<T>>
286{
287 public:
288
289 using ItemType = typename T::ItemType;
290 using ValueType = IteratorWithIndex<T>;
291 using BuilderType = Arcane::impl::IterBuilderWithIndex<T>;
292};
293
294/*---------------------------------------------------------------------------*/
295/*---------------------------------------------------------------------------*/
306template <typename ItemType>
307class RunCommandItemContainer
308{
309 public:
310
311 explicit RunCommandItemContainer(const ItemGroupT<ItemType>& group)
312 : m_item_group(group)
313 , m_unpadded_vector_view(group._unpaddedView())
314 {}
315 explicit RunCommandItemContainer(const ItemVectorViewT<ItemType>& item_vector_view)
316 : m_item_vector_view(item_vector_view)
317 , m_unpadded_vector_view(item_vector_view)
318 {
319 }
320
321 public:
322
323 Int32 size() const { return m_unpadded_vector_view.size(); }
324 SmallSpan<const Int32> localIds() const { return m_unpadded_vector_view.localIds(); }
325 ItemVectorView paddedView() const
326 {
327 if (!m_item_group.null())
328 return m_item_group._paddedView();
329 return m_item_vector_view;
330 }
331
332 private:
333
334 ItemVectorViewT<ItemType> m_item_vector_view;
335 ItemGroupT<ItemType> m_item_group;
336 ItemVectorViewT<ItemType> m_unpadded_vector_view;
337};
338
339/*---------------------------------------------------------------------------*/
340/*---------------------------------------------------------------------------*/
350template <RunCommandEnumerateIteratorConcept IteratorValueType_>
351class RunCommandItemEnumeratorTraitsT
352{
353 public:
354
356 using ItemType = typename SubTraitsType::ItemType;
357 using LocalIdType = typename ItemTraitsT<ItemType>::LocalIdType;
358 using ValueType = typename SubTraitsType::ValueType;
359 using ContainerType = RunCommandItemContainer<ItemType>;
360 using BuilderType = typename SubTraitsType::BuilderType;
361
362 public:
363
364 explicit RunCommandItemEnumeratorTraitsT(const ItemGroupT<ItemType>& group)
365 : m_item_container(group)
366 {}
367 explicit RunCommandItemEnumeratorTraitsT(const ItemVectorViewT<ItemType>& vector_view)
368 : m_item_container(vector_view)
369 {
370 }
371
372 public:
373
374 RunCommandItemContainer<ItemType> m_item_container;
375};
376
377/*---------------------------------------------------------------------------*/
378/*---------------------------------------------------------------------------*/
379
380template <typename TraitsType, typename ContainerType, typename Lambda, typename... RemainingArgs>
381void _doItemsLambda(Int32 base_index, ContainerType sub_items, const Lambda& func, RemainingArgs... remaining_args)
382{
383 using ItemType = TraitsType::ItemType;
384 using BuilderType = TraitsType::BuilderType;
385 using LocalIdType = BuilderType::ValueType;
386 auto privatizer = Impl::privatize(func);
387 auto& body = privatizer.privateCopy();
388
390 ENUMERATE_NO_TRACE_ (ItemType, iitem, sub_items) {
391 body(BuilderType::create(iitem.index() + base_index, LocalIdType(iitem.itemLocalId())), remaining_args...);
392 }
394}
395
396/*---------------------------------------------------------------------------*/
397/*---------------------------------------------------------------------------*/
401template <typename TraitsType, typename Lambda, typename... RemainingArgs> void
402_applyItems(RunCommand& command, typename TraitsType::ContainerType items,
403 const Lambda& func, const RemainingArgs&... remaining_args)
404{
405 // TODO: fusionner la partie commune avec 'applyLoop'
406 Integer vsize = items.size();
407 if (vsize == 0)
408 return;
409 using ItemType = typename TraitsType::ItemType;
410 using LoopBoundType = Impl::ItemLocalIdsLoopRanges<TraitsType>;
411 [[maybe_unused]] SmallSpan<const Int32> ids = items.localIds();
412 [[maybe_unused]] LoopBoundType bounds(ids);
413
414#if defined(ARCCORE_EXPERIMENTAL_GRID_STRIDE) && defined(ARCCORE_COMPILING_CUDA_OR_HIP)
415 using TrueLoopBoundType = Impl::StridedLoopRanges<LoopBoundType>;
416 TrueLoopBoundType bounds2(command.nbStride(), bounds);
417 Impl::RunCommandLaunchInfo launch_info(command, bounds2.strideValue());
418#else
419 using TrueLoopBoundType = LoopBoundType;
420 [[maybe_unused]] const TrueLoopBoundType& bounds2 = bounds;
421 Impl::RunCommandLaunchInfo launch_info(command, vsize);
422#endif
423
424 const eExecutionPolicy exec_policy = launch_info.executionPolicy();
425
426 launch_info.beginExecute();
427 switch (exec_policy) {
429 ARCCORE_KERNEL_CUDA_FUNC((Impl::doIndirectGPULambda2<TrueLoopBoundType, Lambda, RemainingArgs...>),
430 launch_info, func, bounds2, remaining_args...);
431 break;
433 ARCCORE_KERNEL_HIP_FUNC((Impl::doIndirectGPULambda2<TrueLoopBoundType, Lambda, RemainingArgs...>),
434 launch_info, func, bounds2, remaining_args...);
435 break;
437 ARCCORE_KERNEL_SYCL_FUNC((Impl::DoIndirectSYCLLambda<TraitsType, Lambda, RemainingArgs...>{}),
438 launch_info, func, ids, remaining_args...);
439 break;
441 impl::_doItemsLambda<TraitsType>(0, items.paddedView(), func, remaining_args...);
442 break;
444 arcaneParallelForeach(items.paddedView(), launch_info.loopRunInfo(),
445 [&](ItemVectorViewT<ItemType> sub_items, Int32 base_index) {
446 impl::_doItemsLambda<TraitsType>(base_index, sub_items, func, remaining_args...);
447 });
448 break;
449 default:
450 ARCCORE_FATAL("Invalid execution policy '{0}'", exec_policy);
451 }
452 launch_info.endExecute();
453}
454
455/*---------------------------------------------------------------------------*/
456/*---------------------------------------------------------------------------*/
457
458template <typename TraitsType, typename... RemainingArgs>
459class ItemRunCommandArgs
460{
461 public:
462
463 ItemRunCommandArgs(const TraitsType& traits, const RemainingArgs&... remaining_args)
464 : m_traits(traits)
465 , m_remaining_args(remaining_args...)
466 {
467 }
468
469 public:
470
471 TraitsType m_traits;
472 std::tuple<RemainingArgs...> m_remaining_args;
473};
474
475/*---------------------------------------------------------------------------*/
476/*---------------------------------------------------------------------------*/
477
478} // namespace Arcane::Accelerator::impl
479
480namespace Arcane::Accelerator
481{
482
483/*---------------------------------------------------------------------------*/
484/*---------------------------------------------------------------------------*/
485
486template <typename TraitsType, typename Lambda> void
487run(RunCommand& command, const TraitsType& traits, const Lambda& func)
488{
489 impl::_applyItems<TraitsType>(command, traits.m_item_container, func);
490}
491
492/*---------------------------------------------------------------------------*/
493/*---------------------------------------------------------------------------*/
494
495template <typename TraitsType, typename... RemainingArgs>
496class ItemRunCommand
497{
498 public:
499
500 ItemRunCommand(RunCommand& command, const TraitsType& traits)
501 : m_command(command)
502 , m_traits(traits)
503 {
504 }
505
506 ItemRunCommand(RunCommand& command, const TraitsType& traits, const std::tuple<RemainingArgs...>& remaining_args)
507 : m_command(command)
508 , m_traits(traits)
509 , m_remaining_args(remaining_args)
510 {
511 }
512
513 public:
514
515 RunCommand& m_command;
516 TraitsType m_traits;
517 std::tuple<RemainingArgs...> m_remaining_args;
518};
519
520/*---------------------------------------------------------------------------*/
521/*---------------------------------------------------------------------------*/
522
523template <typename ItemType> auto
524operator<<(RunCommand& command, const impl::RunCommandItemEnumeratorTraitsT<ItemType>& traits)
525{
527 return ItemRunCommand<TraitsType>(command, traits);
528}
529
530/*---------------------------------------------------------------------------*/
531/*---------------------------------------------------------------------------*/
532// Cette méthode est conservée pour compatibilité avec l'existant.
533// A rendre obsolète mi-2024
534template <typename ItemType> auto
535operator<<(RunCommand& command, const ItemVectorViewT<ItemType>& items)
536{
537 using TraitsType = impl::RunCommandItemEnumeratorTraitsT<ItemType>;
538 return ItemRunCommand<TraitsType>(command, TraitsType(items));
539}
540
541// Cette méthode est conservée pour compatibilité avec l'existant.
542// A rendre obsolète mi-2024
543template <typename ItemType> auto
544operator<<(RunCommand& command, const ItemGroupT<ItemType>& items)
545{
546 using TraitsType = impl::RunCommandItemEnumeratorTraitsT<ItemType>;
547 return ItemRunCommand<TraitsType>(command, TraitsType(items));
548}
549
550template <typename TraitsType, typename Lambda>
551void operator<<(ItemRunCommand<TraitsType>& nr, const Lambda& f)
552{
553 run(nr.m_command, nr.m_traits, f);
554}
555
556template <typename TraitsType, typename... RemainingArgs> auto
558{
559 return ItemRunCommand<TraitsType, RemainingArgs...>(command, args.m_traits, args.m_remaining_args);
560}
561
562template <typename TraitsType, typename Lambda, typename... RemainingArgs>
563void operator<<(ItemRunCommand<TraitsType, RemainingArgs...>&& nr, const Lambda& f)
564{
565 if constexpr (sizeof...(RemainingArgs) > 0) {
566 std::apply([&](auto... vs) { impl::_applyItems<TraitsType>(nr.m_command, nr.m_traits.m_item_container, f, vs...); }, nr.m_remaining_args);
567 }
568 else
569 run(nr.m_command, nr.m_traits, f);
570}
571
572/*---------------------------------------------------------------------------*/
573/*---------------------------------------------------------------------------*/
574
575} // namespace Arcane::Accelerator
576
577namespace Arcane::Accelerator::impl
578{
579
580/*---------------------------------------------------------------------------*/
581/*---------------------------------------------------------------------------*/
582
583template <typename ItemTypeName, typename ItemContainerType, typename... RemainingArgs> auto
584makeExtendedItemEnumeratorLoop(const ItemContainerType& container_type,
585 const RemainingArgs&... remaining_args)
586{
588 return ItemRunCommandArgs<TraitsType, RemainingArgs...>(TraitsType(container_type), remaining_args...);
589}
590
591/*---------------------------------------------------------------------------*/
592/*---------------------------------------------------------------------------*/
593
594} // namespace Arcane::Accelerator::impl
595
596/*---------------------------------------------------------------------------*/
597/*---------------------------------------------------------------------------*/
617#define RUNCOMMAND_ENUMERATE(ItemTypeName, iter_name, item_group, ...) \
618 A_FUNCINFO << ::Arcane::Accelerator::impl::makeExtendedItemEnumeratorLoop<ItemTypeName>(item_group __VA_OPT__(, __VA_ARGS__)) \
619 << [=] ARCCORE_HOST_DEVICE(::Arcane::Accelerator::impl::RunCommandItemEnumeratorTraitsT<ItemTypeName>::ValueType iter_name \
620 __VA_OPT__(ARCCORE_RUNCOMMAND_REMAINING_FOR_EACH(__VA_ARGS__)))
621
622/*---------------------------------------------------------------------------*/
623/*---------------------------------------------------------------------------*/
624
625#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.