Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
RunCommandEnumerate.h
Go to the documentation of this file.
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 for iterating over a list of entities. */
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/*---------------------------------------------------------------------------*/
40
44template <typename TraitsType_>
45class ItemLocalIdsLoopRanges
46{
47 public:
48
49 using TraitsType = TraitsType_;
50 using BuilderType = TraitsType::BuilderType;
51
52 public:
53
54 explicit ItemLocalIdsLoopRanges(SmallSpan<const Int32> ids)
55 : m_ids(ids)
56 {}
57 constexpr SmallSpan<const Int32> ids() const { return m_ids; }
58 constexpr Int64 nbElement() const { return m_ids.size(); }
59
60 public:
61
63};
64
65/*---------------------------------------------------------------------------*/
66/*---------------------------------------------------------------------------*/
67
68#if defined(ARCCORE_COMPILING_CUDA_OR_HIP)
69
70template <typename LoopBoundsType, typename Lambda, typename... RemainingArgs> __global__ void
71doIndirectGPULambda2(LoopBoundsType bounds, Lambda func, RemainingArgs... remaining_args)
72{
73 // TODO: to be removed when old reductions are no longer needed
74 auto privatizer = privatize(func);
75 auto& body = privatizer.privateCopy();
76
77 Int32 i = blockDim.x * blockIdx.x + threadIdx.x;
78
80
81 if constexpr (requires { bounds.nbStride(); }) {
82 // Experimental test to use a stride of the grid size. The number of
83 // strides is given by bounds.nbStride().
84 using BuilderType = LoopBoundsType::LoopBoundType::BuilderType;
85 using LocalIdType = BuilderType::ValueType;
86 Int32 nb_grid_stride = bounds.nbStride();
87 Int32 offset = blockDim.x * gridDim.x;
88 Int64 nb_item = bounds.nbOriginalElement();
89 SmallSpan<const Int32> ids = bounds.originalLoop().ids();
90#pragma unroll 4
91 for (Int32 k = 0; k < nb_grid_stride; ++k) {
92 Int32 true_i = i + (offset * k);
93 if (true_i < nb_item) {
94 LocalIdType lid(ids[true_i]);
95 body(BuilderType::create(true_i, lid), remaining_args...);
96 }
97 }
98 }
99 else {
100 using BuilderType = LoopBoundsType::BuilderType;
101 using LocalIdType = BuilderType::ValueType;
102
103 SmallSpan<const Int32> ids = bounds.ids();
104 if (i < ids.size()) {
105 LocalIdType lid(ids[i]);
106 body(BuilderType::create(i, lid), remaining_args...);
107 }
108 }
109
111}
112
113/*---------------------------------------------------------------------------*/
114/*---------------------------------------------------------------------------*/
115
116#endif // ARCCORE_COMPILING_CUDA_OR_HIP
117
118/*---------------------------------------------------------------------------*/
119/*---------------------------------------------------------------------------*/
120
121#if defined(ARCCORE_COMPILING_SYCL)
122
124template <typename TraitsType, typename Lambda, typename... RemainingArgs>
125class DoIndirectSYCLLambda
126{
127 public:
128
129 void operator()(sycl::nd_item<1> x, SmallSpan<std::byte> shared_memory,
130 SmallSpan<const Int32> ids, Lambda func,
131 RemainingArgs... remaining_args) const
132 {
133 using BuilderType = TraitsType::BuilderType;
134 using LocalIdType = BuilderType::ValueType;
135 auto privatizer = privatize(func);
136 auto& body = privatizer.privateCopy();
137
138 Int32 i = static_cast<Int32>(x.get_global_id(0));
139 SyclKernelRemainingArgsHelper::applyAtBegin(x, shared_memory, remaining_args...);
140 if (i < ids.size()) {
141 LocalIdType lid(ids[i]);
142 body(BuilderType::create(i, lid), remaining_args...);
143 }
144 SyclKernelRemainingArgsHelper::applyAtEnd(x, shared_memory, remaining_args...);
145 }
146 void operator()(sycl::id<1> x, SmallSpan<const Int32> ids, Lambda func) const
147 {
148 using BuilderType = TraitsType::BuilderType;
149 using LocalIdType = BuilderType::ValueType;
150 auto privatizer = privatize(func);
151 auto& body = privatizer.privateCopy();
152
153 Int32 i = static_cast<Int32>(x);
154 if (i < ids.size()) {
155 LocalIdType lid(ids[i]);
156 body(BuilderType::create(i, lid));
157 }
158 }
159};
160
161#endif
162
163} // namespace Arcane::Accelerator::Impl
164
165/*---------------------------------------------------------------------------*/
166/*---------------------------------------------------------------------------*/
167
168namespace Arcane
169{
170
171/*---------------------------------------------------------------------------*/
172/*---------------------------------------------------------------------------*/
173
175{
176};
177
178/*---------------------------------------------------------------------------*/
179/*---------------------------------------------------------------------------*/
180
184template <typename T>
185class IteratorWithIndex
187{
188 public:
189
190 constexpr ARCCORE_HOST_DEVICE IteratorWithIndex(Int32 i, T v)
191 : m_index(i)
192 , m_value(v)
193 {}
194
195 public:
196
197 constexpr ARCCORE_HOST_DEVICE Int32 index() const { return m_index; }
198 constexpr ARCCORE_HOST_DEVICE T value() const { return m_value; }
199
200 private:
201
202 Int32 m_index;
203 T m_value;
204};
205
206} // namespace Arcane
207
208/*---------------------------------------------------------------------------*/
209/*---------------------------------------------------------------------------*/
210
211namespace Arcane::impl
212{
213
214template <typename T>
216{
217 public:
218
219 using ValueType = T;
220
221 public:
222
223 constexpr ARCCORE_HOST_DEVICE static IteratorWithIndex<T> create(Int32 index, T value)
224 {
225 return IteratorWithIndex<T>(index, value);
226 }
227};
228
229template <typename T>
231{
232 public:
233
234 using ValueType = T;
235
236 public:
237
238 constexpr ARCCORE_HOST_DEVICE static T create(Int32, T value)
239 {
240 return value;
241 }
242};
243
244} // namespace Arcane::impl
245
246/*---------------------------------------------------------------------------*/
247/*---------------------------------------------------------------------------*/
248
249namespace Arcane::Accelerator::impl
250{
251
252/*---------------------------------------------------------------------------*/
253/*---------------------------------------------------------------------------*/
254
261template <typename T>
262concept RunCommandEnumerateIteratorConcept = std::derived_from<T, Item> || std::derived_from<T, ItemLocalId> || std::derived_from<T, IteratorWithIndexBase>;
263
265template <typename T>
267{
268 public:
269
270 using ItemType = T;
271 using ValueType = typename ItemTraitsT<ItemType>::LocalIdType;
273};
274
276template <typename T>
278{
279 public:
280
281 using ItemType = typename ItemLocalIdT<T>::ItemType;
282 using ValueType = ItemLocalIdT<T>;
284};
285
287template <typename T>
288requires std::derived_from<T, ItemLocalId> class RunCommandItemEnumeratorSubTraitsT<IteratorWithIndex<T>>
289{
290 public:
291
292 using ItemType = typename T::ItemType;
293 using ValueType = IteratorWithIndex<T>;
294 using BuilderType = Arcane::impl::IterBuilderWithIndex<T>;
295};
296
297/*---------------------------------------------------------------------------*/
298/*---------------------------------------------------------------------------*/
299
310template <typename ItemType>
311class RunCommandItemContainer
312{
313 public:
314
315 explicit RunCommandItemContainer(const ItemGroupT<ItemType>& group)
316 : m_item_group(group)
317 , m_unpadded_vector_view(group._unpaddedView())
318 {}
319 explicit RunCommandItemContainer(const ItemVectorViewT<ItemType>& item_vector_view)
320 : m_item_vector_view(item_vector_view)
321 , m_unpadded_vector_view(item_vector_view)
322 {
323 }
324
325 public:
326
327 Int32 size() const { return m_unpadded_vector_view.size(); }
328 SmallSpan<const Int32> localIds() const { return m_unpadded_vector_view.localIds(); }
329 ItemVectorView paddedView() const
330 {
331 if (!m_item_group.null())
332 return m_item_group._paddedView();
333 return m_item_vector_view;
334 }
335
336 private:
337
338 ItemVectorViewT<ItemType> m_item_vector_view;
339 ItemGroupT<ItemType> m_item_group;
340 ItemVectorViewT<ItemType> m_unpadded_vector_view;
341};
342
343/*---------------------------------------------------------------------------*/
344/*---------------------------------------------------------------------------*/
345
355template <RunCommandEnumerateIteratorConcept IteratorValueType_>
356class RunCommandItemEnumeratorTraitsT
357{
358 public:
359
361 using ItemType = typename SubTraitsType::ItemType;
362 using LocalIdType = typename ItemTraitsT<ItemType>::LocalIdType;
363 using ValueType = typename SubTraitsType::ValueType;
364 using ContainerType = RunCommandItemContainer<ItemType>;
365 using BuilderType = typename SubTraitsType::BuilderType;
366
367 public:
368
369 explicit RunCommandItemEnumeratorTraitsT(const ItemGroupT<ItemType>& group)
370 : m_item_container(group)
371 {}
372 explicit RunCommandItemEnumeratorTraitsT(const ItemVectorViewT<ItemType>& vector_view)
373 : m_item_container(vector_view)
374 {
375 }
376
377 public:
378
379 RunCommandItemContainer<ItemType> m_item_container;
380};
381
382/*---------------------------------------------------------------------------*/
383/*---------------------------------------------------------------------------*/
384
385template <typename TraitsType, typename ContainerType, typename Lambda, typename... RemainingArgs>
386void _doItemsLambda(Int32 base_index, ContainerType sub_items, const Lambda& func, RemainingArgs... remaining_args)
387{
388 using ItemType = TraitsType::ItemType;
389 using BuilderType = TraitsType::BuilderType;
390 using LocalIdType = BuilderType::ValueType;
391 auto privatizer = Impl::privatize(func);
392 auto& body = privatizer.privateCopy();
393
395 ENUMERATE_NO_TRACE_(ItemType, iitem, sub_items)
396 {
397 body(BuilderType::create(iitem.index() + base_index, LocalIdType(iitem.itemLocalId())), remaining_args...);
398 }
400}
401
402/*---------------------------------------------------------------------------*/
403/*---------------------------------------------------------------------------*/
404
408template <typename TraitsType, typename Lambda, typename... RemainingArgs> void
409_applyItems(RunCommand& command, typename TraitsType::ContainerType items,
410 const Lambda& func, const RemainingArgs&... remaining_args)
411{
412 // TODO: merge the common part with 'applyLoop'
413 Integer vsize = items.size();
414 if (vsize == 0)
415 return;
416 using ItemType = typename TraitsType::ItemType;
417 using LoopBoundType = Impl::ItemLocalIdsLoopRanges<TraitsType>;
418 [[maybe_unused]] SmallSpan<const Int32> ids = items.localIds();
419 [[maybe_unused]] LoopBoundType bounds(ids);
420
421#if defined(ARCCORE_EXPERIMENTAL_GRID_STRIDE) && defined(ARCCORE_COMPILING_CUDA_OR_HIP)
422 using TrueLoopBoundType = Impl::StridedLoopRanges<LoopBoundType>;
423 TrueLoopBoundType bounds2(command.nbStride(), bounds);
424 Impl::RunCommandLaunchInfo launch_info(command, bounds2.strideValue());
425#else
426 using TrueLoopBoundType = LoopBoundType;
427 [[maybe_unused]] const TrueLoopBoundType& bounds2 = bounds;
428 Impl::RunCommandLaunchInfo launch_info(command, vsize);
429#endif
430
431 const eExecutionPolicy exec_policy = launch_info.executionPolicy();
432
433 launch_info.beginExecute();
434 switch (exec_policy) {
436 ARCCORE_KERNEL_CUDA_FUNC((Impl::doIndirectGPULambda2<TrueLoopBoundType, Lambda, RemainingArgs...>),
437 launch_info, func, bounds2, remaining_args...);
438 break;
440 ARCCORE_KERNEL_HIP_FUNC((Impl::doIndirectGPULambda2<TrueLoopBoundType, Lambda, RemainingArgs...>),
441 launch_info, func, bounds2, remaining_args...);
442 break;
444 ARCCORE_KERNEL_SYCL_FUNC((Impl::DoIndirectSYCLLambda<TraitsType, Lambda, RemainingArgs...>{}),
445 launch_info, func, ids, remaining_args...);
446 break;
448 impl::_doItemsLambda<TraitsType>(0, items.paddedView(), func, remaining_args...);
449 break;
451 arcaneParallelForeach(items.paddedView(), launch_info.loopRunInfo(),
452 [&](ItemVectorViewT<ItemType> sub_items, Int32 base_index) {
453 impl::_doItemsLambda<TraitsType>(base_index, sub_items, func, remaining_args...);
454 });
455 break;
456 default:
457 ARCCORE_FATAL("Invalid execution policy '{0}'", exec_policy);
458 }
459 launch_info.endExecute();
460}
461
462/*---------------------------------------------------------------------------*/
463/*---------------------------------------------------------------------------*/
464
465template <typename TraitsType, typename... RemainingArgs>
466class ItemRunCommandArgs
467{
468 public:
469
470 ItemRunCommandArgs(const TraitsType& traits, const RemainingArgs&... remaining_args)
471 : m_traits(traits)
472 , m_remaining_args(remaining_args...)
473 {
474 }
475
476 public:
477
478 TraitsType m_traits;
479 std::tuple<RemainingArgs...> m_remaining_args;
480};
481
482/*---------------------------------------------------------------------------*/
483/*---------------------------------------------------------------------------*/
484
485} // namespace Arcane::Accelerator::impl
486
487namespace Arcane::Accelerator
488{
489
490/*---------------------------------------------------------------------------*/
491/*---------------------------------------------------------------------------*/
492
493template <typename TraitsType, typename Lambda> void
494run(RunCommand& command, const TraitsType& traits, const Lambda& func)
495{
496 impl::_applyItems<TraitsType>(command, traits.m_item_container, func);
497}
498
499/*---------------------------------------------------------------------------*/
500/*---------------------------------------------------------------------------*/
501
502template <typename TraitsType, typename... RemainingArgs>
503class ItemRunCommand
504{
505 public:
506
507 ItemRunCommand(RunCommand& command, const TraitsType& traits)
508 : m_command(command)
509 , m_traits(traits)
510 {
511 }
512
513 ItemRunCommand(RunCommand& command, const TraitsType& traits, const std::tuple<RemainingArgs...>& remaining_args)
514 : m_command(command)
515 , m_traits(traits)
516 , m_remaining_args(remaining_args)
517 {
518 }
519
520 public:
521
522 RunCommand& m_command;
523 TraitsType m_traits;
524 std::tuple<RemainingArgs...> m_remaining_args;
525};
526
527/*---------------------------------------------------------------------------*/
528/*---------------------------------------------------------------------------*/
529
530template <typename ItemType> auto
531operator<<(RunCommand& command, const impl::RunCommandItemEnumeratorTraitsT<ItemType>& traits)
532{
534 return ItemRunCommand<TraitsType>(command, traits);
535}
536
537/*---------------------------------------------------------------------------*/
538/*---------------------------------------------------------------------------*/
539
540// This method is kept for compatibility with existing code.
541// To be deprecated mid-2024
542template <typename ItemType> auto
543operator<<(RunCommand& command, const ItemVectorViewT<ItemType>& items)
544{
545 using TraitsType = impl::RunCommandItemEnumeratorTraitsT<ItemType>;
546 return ItemRunCommand<TraitsType>(command, TraitsType(items));
547}
548
549// This method is kept for compatibility with existing code.
550// To be deprecated mid-2024
551template <typename ItemType> auto
552operator<<(RunCommand& command, const ItemGroupT<ItemType>& items)
553{
554 using TraitsType = impl::RunCommandItemEnumeratorTraitsT<ItemType>;
555 return ItemRunCommand<TraitsType>(command, TraitsType(items));
556}
557
558template <typename TraitsType, typename Lambda>
559void operator<<(ItemRunCommand<TraitsType>& nr, const Lambda& f)
560{
561 run(nr.m_command, nr.m_traits, f);
562}
563
564template <typename TraitsType, typename... RemainingArgs> auto
566{
567 return ItemRunCommand<TraitsType, RemainingArgs...>(command, args.m_traits, args.m_remaining_args);
568}
569
570template <typename TraitsType, typename Lambda, typename... RemainingArgs>
571void operator<<(ItemRunCommand<TraitsType, RemainingArgs...>&& nr, const Lambda& f)
572{
573 if constexpr (sizeof...(RemainingArgs) > 0) {
574 std::apply([&](auto... vs) { impl::_applyItems<TraitsType>(nr.m_command, nr.m_traits.m_item_container, f, vs...); }, nr.m_remaining_args);
575 }
576 else
577 run(nr.m_command, nr.m_traits, f);
578}
579
580/*---------------------------------------------------------------------------*/
581/*---------------------------------------------------------------------------*/
582
583} // namespace Arcane::Accelerator
584
585namespace Arcane::Accelerator::impl
586{
587
588/*---------------------------------------------------------------------------*/
589/*---------------------------------------------------------------------------*/
590
591template <typename ItemTypeName, typename ItemContainerType, typename... RemainingArgs> auto
592makeExtendedItemEnumeratorLoop(const ItemContainerType& container_type,
593 const RemainingArgs&... remaining_args)
594{
596 return ItemRunCommandArgs<TraitsType, RemainingArgs...>(TraitsType(container_type), remaining_args...);
597}
598
599/*---------------------------------------------------------------------------*/
600/*---------------------------------------------------------------------------*/
601
602} // namespace Arcane::Accelerator::impl
603
604/*---------------------------------------------------------------------------*/
605/*---------------------------------------------------------------------------*/
606
626#define RUNCOMMAND_ENUMERATE(ItemTypeName, iter_name, item_group, ...) \
627 A_FUNCINFO << ::Arcane::Accelerator::impl::makeExtendedItemEnumeratorLoop<ItemTypeName>(item_group __VA_OPT__(, __VA_ARGS__)) \
628 << [=] ARCCORE_HOST_DEVICE(::Arcane::Accelerator::impl::RunCommandItemEnumeratorTraitsT<ItemTypeName>::ValueType iter_name \
629 __VA_OPT__(ARCCORE_RUNCOMMAND_REMAINING_FOR_EACH(__VA_ARGS__)))
630
631/*---------------------------------------------------------------------------*/
632/*---------------------------------------------------------------------------*/
633
634#endif
#define ARCCORE_FATAL(...)
Macro throwing a FatalErrorException.
Classes, Types, and macros for managing concurrency.
#define ENUMERATE_NO_TRACE_(type, name, group)
Generic enumerator for an entity group.
Declarations of types on entities.
void _applyItems(RunCommand &command, typename TraitsType::ContainerType items, const Lambda &func, const RemainingArgs &... remaining_args)
Applies the enumeration func on the entity list items.
static ARCCORE_DEVICE void applyAtEnd(Int32 index, RemainingArgs &... remaining_args)
Applies the functors of additional arguments at the end of the kernel.
static ARCCORE_DEVICE void applyAtBegin(Int32 index, RemainingArgs &... remaining_args)
Applies the functors of additional arguments at the beginning of the kernel.
Information for the accelerator loop over entities.
Temporary object to store the execution information of a command and group tests.
void beginExecute()
Indicates that command execution is starting.
Class to manage the decomposition of a loop into multiple parts.
Int32 nbStride() const
Number of loop decomposition strides.
Template to know the entity type associated with T.
Characteristics of an enumerator for a command on entities.
static void applyAtEnd(RemainingArgs &... remaining_args)
Applies the functors of additional arguments at the end of the iteration.
static void applyAtBegin(RemainingArgs &... remaining_args)
Applies the functors of additional arguments at the beginning of the iteration.
Reference to a group of a given kind.
Definition ItemGroup.h:420
ItemVectorView _unpaddedView() const
View of the group entities without padding for vectorization.
Definition ItemGroup.cc:598
Index of an ItemType entity in a variable.
Definition ItemLocalId.h:92
View on a typed array of entities.
View on a vector of entities.
Base class for an iterator that preserves the iteration index.
View of an array of elements of type T.
Definition Span.h:805
Concept to constrain values in RUNCOMMAND_ENUMERATE.
void arcaneParallelForeach(const ItemVectorView &items_view, const ForLoopRunInfo &run_info, InstanceType *instance, void(InstanceType::*function)(ItemVectorViewT< ItemType > items))
Applies the method function of the instance instance concurrently on the view items_view with the opt...
Definition Concurrency.h:57
eExecutionPolicy
Execution policy for a Runner.
@ SYCL
Execution policy using the SYCL environment.
@ HIP
Execution policy using the HIP environment.
@ CUDA
Execution policy using the CUDA environment.
@ Thread
Multi-threaded execution policy.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
Int32 LocalIdType
Type of integers used to store local identifiers of entities.
std::int32_t Int32
Signed integer type of 32 bits.