Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
SimdItem.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/* SimdItem.h (C) 2000-2025 */
9/* */
10/* Types of entities and entity enumerators for vectorization. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_CORE_SIMDITEM_H
13#define ARCANE_CORE_SIMDITEM_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arcane/utils/Simd.h"
18
19// The ARCANE_SIMD_BENCH macro is only defined for the Simd
20// Simd (in contribs/Simd) bench and prevents including entity management.
21
22#ifndef ARCANE_SIMD_BENCH
24#endif
25
26/*---------------------------------------------------------------------------*/
27/*---------------------------------------------------------------------------*/
28
29/*!
30 * \file SimdItem.h
31 *
32 * This file contains the type declarations for managing
33 * vectorization with mesh entities (Item).
34 */
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39namespace Arcane
40{
41
42template <typename ItemType>
44
45/*---------------------------------------------------------------------------*/
46/*---------------------------------------------------------------------------*/
47
48/*!
49 * TODO:
50 * - Create a version of SimdItem by vector size (2, 4, 8).
51 * - Use a mask if possible.
52 * - aligned SimdItemBase
53 * - create a version of the SimdItemBase constructor without (nb_valid)
54 * for the case where the vector is full.
55 */
56
57/*---------------------------------------------------------------------------*/
58/*---------------------------------------------------------------------------*/
59
60/*!
61 * \ingroup ArcaneSimd
62 * \brief Class managing a SIMD vector of entities.
63 *
64 * This class stores \a N mesh entities, where \a N depends
65 * on the size of the SIMD registers and equals SimdInfo::Int32IndexSize.
66 *
67 * This class is not used directly. SimdItem or
68 * SimdItemT must be used.
69 */
70class ARCANE_CORE_EXPORT SimdItemBase
71{
72 protected:
73
74 typedef ItemInternal* ItemInternalPtr;
75
76 public:
77
78 typedef SimdInfo::SimdInt32IndexType SimdIndexType;
79
80 public:
81
82 /*!
83 * \brief Constructs an instance.
84 * \warning \a ids must have the required alignment for a SimdIndexType.
85 */
86 ARCANE_DEPRECATED_REASON("Y2022: Use another constructor")
87 SimdItemBase(const ItemInternalPtr* items, const SimdIndexType* ids)
88 : m_simd_local_ids(*ids)
89 , m_shared_info(ItemInternalCompatibility::_getSharedInfo(items, 1))
90 {}
91
92 protected:
93
94 SimdItemBase(ItemSharedInfo* shared_info, const SimdIndexType* ids)
95 : m_simd_local_ids(*ids)
96 , m_shared_info(shared_info)
97 {}
98
99 public:
100
101 //! Internal part (for internal use only)
102 ARCANE_DEPRECATED_REASON("Y2022: Use method SimdItem::item() instead")
103 ItemInternal* item(Integer si) const { return m_shared_info->m_items_internal[localId(si)]; }
104
105 ARCANE_DEPRECATED_REASON("Y2022: Use method SimdItem::operator[]() instead")
106 ItemInternal* operator[](Integer si) const { return m_shared_info->m_items_internal[localId(si)]; }
107
108 //! List of local IDs of the instance entities
109 const SimdIndexType& ARCANE_RESTRICT simdLocalIds() const { return m_simd_local_ids; }
110
111 //! List of local IDs of the instance entities
112 const Int32* ARCANE_RESTRICT localIds() const { return (const Int32*)&m_simd_local_ids; }
113
114 //! Local ID of the entity at index \a index.
115 Int32 localId(Int32 index) const { return m_simd_local_ids[index]; }
116
117 protected:
118
119 SimdIndexType m_simd_local_ids;
120 ItemSharedInfo* m_shared_info = ItemSharedInfo::nullInstance();
121};
122
123/*---------------------------------------------------------------------------*/
124/*---------------------------------------------------------------------------*/
125
126class SimdItemDirectBase
127{
128 protected:
129
130 typedef ItemInternal* ItemInternalPtr;
131
132 public:
133
134 ARCANE_DEPRECATED_REASON("Y2022: Use another constructor")
135 SimdItemDirectBase(const ItemInternalPtr* items, Int32 base_local_id, Integer nb_valid)
136 : m_base_local_id(base_local_id)
137 , m_nb_valid(nb_valid)
138 , m_shared_info(ItemInternalCompatibility::_getSharedInfo(items, nb_valid))
139 {}
140
141 protected:
142
143 SimdItemDirectBase(ItemSharedInfo* shared_info, Int32 base_local_id, Integer nb_valid)
144 : m_base_local_id(base_local_id)
145 , m_nb_valid(nb_valid)
146 , m_shared_info(shared_info)
147 {}
148
149 // TEMPORARY to avoid deprecated
150 SimdItemDirectBase(Int32 base_local_id, Integer nb_valid, const ItemInternalPtr* items)
151 : m_base_local_id(base_local_id)
152 , m_nb_valid(nb_valid)
153 , m_shared_info(ItemInternalCompatibility::_getSharedInfo(items, nb_valid))
154 {}
155
156 public:
157
158 //! Number of valid entities in the instance.
159 inline Integer nbValid() const { return m_nb_valid; }
160
161 //! List of local IDs of the instance entities
162 inline Int32 baseLocalId() const { return m_base_local_id; }
163
164 protected:
165
166 Int32 m_base_local_id;
167 Integer m_nb_valid;
168 ItemSharedInfo* m_shared_info = ItemSharedInfo::nullInstance();
169};
170
171/*---------------------------------------------------------------------------*/
172/*---------------------------------------------------------------------------*/
173
174/*!
175 * \brief Vector index with indirection for an entity type.
176 * TODO: store the indices in a vector register to be able
177 * to perform the gather quickly. For this, create the equivalent of AVXSimdReal
178 * for Int32.
179 */
180template <typename ItemType>
181class SimdItemIndexT
182{
183 public:
184
185 typedef SimdInfo::SimdInt32IndexType SimdIndexType;
186
187 public:
188
189 SimdItemIndexT(const SimdIndexType& ARCANE_RESTRICT local_ids)
190 : m_local_ids(local_ids)
191 {}
192 SimdItemIndexT(const SimdIndexType* ARCANE_RESTRICT local_ids)
193 : m_local_ids(*local_ids)
194 {}
195
196 public:
197
198 //! List of local IDs of the instance entities
199 const SimdIndexType& ARCANE_RESTRICT simdLocalIds() const { return m_local_ids; }
200
201 private:
202
203 const SimdIndexType& ARCANE_RESTRICT m_local_ids;
204};
205
206/*---------------------------------------------------------------------------*/
207/*---------------------------------------------------------------------------*/
208
209/*!
210 * \brief Vector index without indirection for an entity type
211 */
212template <typename ItemType>
213class SimdItemDirectIndexT
214{
215 public:
216
217 SimdItemDirectIndexT(Int32 base_local_id)
218 : m_base_local_id(base_local_id)
219 {}
220
221 public:
222
223 inline Int32 baseLocalId() const { return m_base_local_id; }
224
225 private:
226
227 Int32 m_base_local_id;
228};
229
230/*---------------------------------------------------------------------------*/
231/*---------------------------------------------------------------------------*/
232
233/*!
234 * \ingroup ArcaneSimd
235 * \brief Manages a vector of \a Item entities.
236 */
237class SimdItem
238: public SimdItemBase
239{
240 public:
241
242 ARCANE_DEPRECATED_REASON("Y2022: Use another constructor")
243 SimdItem(const ItemInternalPtr* items, const SimdInfo::SimdInt32IndexType* ids)
244 : SimdItemBase(ItemInternalCompatibility::_getSharedInfo(items, 1), ids)
245 {}
246
247 protected:
248
249 SimdItem(ItemSharedInfo* shared_info, const SimdInfo::SimdInt32IndexType* ids)
250 : SimdItemBase(shared_info, ids)
251 {}
252
253 public:
254
255 //! inline \a si-th entity of the instance
256 inline Item item(Int32 si) const { return Item(localId(si), m_shared_info); }
257
258 //! inline \a si-th entity of the instance
259 inline Item operator[](Int32 si) const { return Item(localId(si), m_shared_info); }
260};
261
262/*---------------------------------------------------------------------------*/
263/*---------------------------------------------------------------------------*/
264
265/*!
266 * \ingroup ArcaneSimd
267 * \brief Manages a vector of \a ItemType entities.
268 */
269template <typename ItemType>
270class SimdItemT
271: public SimdItem
272{
273 friend class SimdItemEnumeratorT<ItemType>;
274
275 protected:
276
277 typedef ItemInternal* ItemInternalPtr;
278
279 public:
280
281#if 0
282 ARCANE_DEPRECATED_REASON("Y2022: Use another constructor")
283 SimdItemT(const ItemInternalPtr* items,const SimdInfo::SimdInt32IndexType* ids)
284 : SimdItem(items,ids) { }
285#endif
286
287 private:
288
289 SimdItemT(ItemSharedInfo* shared_info, const SimdInfo::SimdInt32IndexType* ids)
290 : SimdItem(shared_info, ids)
291 {}
292
293 public:
294
295 //! Returns the \a si-th entity of the instance
296 ItemType item(Integer si) const
297 {
298 return ItemType(localId(si), m_shared_info);
299 }
300
301 //! Returns the \a si-th entity of the instance
302 ItemType operator[](Integer si) const
303 {
304 return ItemType(localId(si), m_shared_info);
305 }
306
307 operator SimdItemIndexT<ItemType>()
308 {
310 }
311};
312
313/*---------------------------------------------------------------------------*/
314/*---------------------------------------------------------------------------*/
315
316/*!
317 * \ingroup ArcaneSimd
318 * \brief Manages a vector of \a ItemType entities.
319 */
320template <typename ItemType>
321class SimdItemDirectT
322: public SimdItemDirectBase
323{
324 friend class SimdItemEnumeratorT<ItemType>;
325
326 protected:
327
328 typedef ItemInternal* ItemInternalPtr;
329
330 public:
331
332 ARCANE_DEPRECATED_REASON("Y2022: Use another constructor")
333 SimdItemDirectT(const ItemInternalPtr* items, Int32 base_local_id, Integer nb_valid)
334 : SimdItemDirectBase(base_local_id, nb_valid, items)
335 {}
336
337 private:
338
339 SimdItemDirectT(ItemSharedInfo* shared_info, Int32 base_local_id, Integer nb_valid)
340 : SimdItemDirectBase(shared_info, base_local_id, nb_valid)
341 {}
342
343 public:
344
346 {
347 return SimdItemDirectIndexT<ItemType>(this->m_base_local_id);
348 }
349};
350
351/*---------------------------------------------------------------------------*/
352/*---------------------------------------------------------------------------*/
353
354/*!
355 * \internal
356 * \ingroup ArcaneSimd
357 * \brief Object allowing positioning of values in a SIMD vector.
358 */
359template <typename DataType>
360class SimdSetter
361{
362 typedef typename SimdTypeTraits<DataType>::SimdType SimdType;
363
364 public:
365
366 SimdSetter(DataType* ARCANE_RESTRICT _data,
367 const SimdInfo::SimdInt32IndexType& ARCANE_RESTRICT _indexes)
368 : idx(_indexes)
369 , m_data(_data)
370 {
371 }
372
373 public:
374
375 void operator=(const SimdType& vr)
376 {
377 vr.set(m_data, idx);
378 }
379 void operator=(const DataType& v)
380 {
381 SimdType vr(v);
382 vr.set(m_data, idx);
383 }
384
385 private:
386
387 const SimdInfo::SimdInt32IndexType& ARCANE_RESTRICT idx;
388 DataType* ARCANE_RESTRICT m_data;
389};
390
391/*---------------------------------------------------------------------------*/
392/*---------------------------------------------------------------------------*/
393
394/*!
395 * \ingroup ArcaneSimd
396 * \brief Object allowing positioning of values in a SIMD vector.
397 */
398template <typename DataType>
399class SimdDirectSetter
400{
401 typedef typename SimdTypeTraits<DataType>::SimdType SimdType;
402
403 public:
404
405 SimdDirectSetter(DataType* ARCANE_RESTRICT _data)
406 : m_data(_data)
407 {}
408
409 public:
410
411 void operator=(const SimdType& vr)
412 {
413 vr.set(m_data);
414 }
415
416 private:
417
418 DataType* ARCANE_RESTRICT m_data;
419};
420
421/*---------------------------------------------------------------------------*/
422/*---------------------------------------------------------------------------*/
423
424/*---------------------------------------------------------------------------*/
425/*---------------------------------------------------------------------------*/
426
427/*!
428 * \ingroup ArcaneSimd
429 * \brief Base class for enumerators over vectorial entities (SimdItem).
430 */
431class ARCANE_CORE_EXPORT SimdItemEnumeratorBase
432: public SimdEnumeratorBase
433{
434 protected:
435
436 typedef ItemInternal* ItemInternalPtr;
437
438 public:
439
440 typedef SimdInfo::SimdInt32IndexType SimdIndexType;
441
442 public:
443
444 // TODO: Handle m_local_id_offset for this class
445
446 // TODO: By end of 2024, make certain constructors internal to Arcane and deprecate others.
447 // Do the same for derived classes
448
449 SimdItemEnumeratorBase() = default;
450
451 // TODO: Make internal to Arcane
452 SimdItemEnumeratorBase(const ItemInternalVectorView& view)
453 : SimdEnumeratorBase(view.localIds())
454 , m_shared_info(view.m_shared_info)
455 {}
456 // TODO: Make internal to Arcane
457 SimdItemEnumeratorBase(const ItemEnumerator& rhs)
458 : SimdEnumeratorBase(rhs.m_view.m_local_ids, rhs.count())
459 , m_shared_info(rhs.m_item.m_shared_info)
460 {}
461
462 // TODO: deprecate
463 SimdItemEnumeratorBase(const ItemInternalPtr* items, const Int32* local_ids, Integer n)
464 : SimdEnumeratorBase(local_ids, n)
465 , m_shared_info(ItemInternalCompatibility::_getSharedInfo(items, n))
466 {}
467 // TODO: deprecate
468 SimdItemEnumeratorBase(const ItemInternalArrayView& items, const Int32ConstArrayView& local_ids)
469 : SimdEnumeratorBase(local_ids)
470 , m_shared_info(ItemInternalCompatibility::_getSharedInfo(items.data(), local_ids.size()))
471 {}
472
473 public:
474
475 // TODO: deprecate
476 //! List of entities
477 const ItemInternalPtr* unguardedItems() const { return m_shared_info->m_items_internal.data(); }
478
479 protected:
480
481 ItemSharedInfo* m_shared_info = ItemSharedInfo::nullInstance();
482};
483
484/*---------------------------------------------------------------------------*/
485/*---------------------------------------------------------------------------*/
486
487/*!
488 * \ingroup ArcaneSimd
489 * \brief Enumerator over a list of entities.
490 */
491template <typename ItemType>
492class SimdItemEnumeratorT
493: public SimdItemEnumeratorBase
494{
495 protected:
496
497 typedef ItemInternal* ItemInternalPtr;
498
499 public:
500
501 typedef SimdItemT<ItemType> SimdItemType;
502
503 SimdItemEnumeratorT()
504 : SimdItemEnumeratorBase()
505 {}
506 SimdItemEnumeratorT(const ItemEnumerator& rhs)
507 : SimdItemEnumeratorBase(rhs)
508 {}
509 SimdItemEnumeratorT(const ItemEnumeratorT<ItemType>& rhs)
510 : SimdItemEnumeratorBase(rhs)
511 {}
512 SimdItemEnumeratorT(const ItemVectorViewT<ItemType>& rhs)
513 : SimdItemEnumeratorBase(rhs)
514 {}
515
516 // TODO: deprecate
517 SimdItemEnumeratorT(const ItemInternalPtr* items, const Int32* local_ids, Integer n)
518 : SimdItemEnumeratorBase(items, local_ids, n)
519 {}
520 // TODO: deprecate
521 SimdItemEnumeratorT(const ItemInternalArrayView& items, const Int32ConstArrayView& local_ids)
522 : SimdItemEnumeratorBase(items, local_ids)
523 {}
524
525 public:
526
527 SimdItemType operator*() const
528 {
529 return SimdItemType(m_shared_info, _currentSimdIndex());
530 }
531
532 SimdItemDirectT<ItemType> direct() const
533 {
534 return SimdItemDirectT<ItemType>(m_shared_info, m_index, nbValid());
535 }
536
537 operator SimdItemIndexT<ItemType>()
538 {
539 return SimdItemIndexT<ItemType>(_currentSimdIndex());
540 }
541
542#ifndef ARCANE_SIMD_BENCH
543 inline ItemEnumeratorT<ItemType> enumerator() const
544 {
545 return ItemEnumeratorT<ItemType>(m_shared_info, Int32ConstArrayView(nbValid(), m_local_ids + m_index));
546 }
547#endif
548
549 protected:
550};
551
552/*---------------------------------------------------------------------------*/
553/*---------------------------------------------------------------------------*/
554
555#ifndef ARCANE_SIMD_BENCH
556/*!
557 * \ingroup ArcaneSimd
558 * \brief SIMD vector of \a Node.
559 */
561/*!
562 * \ingroup ArcaneSimd
563 * \brief SIMD vector of \a Edge.
564 */
566/*!
567 * \ingroup ArcaneSimd
568 * \brief SIMD vector of \a Face.
569 */
571/*!
572 * \ingroup ArcaneSimd
573 * \brief SIMD vector of \a Cell.
574 */
576/*!
577 * \ingroup ArcaneSimd
578 * \brief SIMD vector of \a Particle.
579 */
581#else
582/*!
583 * \ingroup ArcaneSimd
584 * \brief SIMD vector of \a Cell.
585 */
587#endif
588
589/*---------------------------------------------------------------------------*/
590/*---------------------------------------------------------------------------*/
591
592template <typename ItemType>
594{
595 public:
596
597 static SimdItemEnumeratorT<ItemType> getSimdEnumerator(const ItemGroupT<ItemType>& g)
598 {
599 return g._simdEnumerator();
600 }
601 // Create an iterator from an ItemVectorView. This view must have padding
602 // equal to the vector size.
603 static SimdItemEnumeratorT<ItemType> getSimdEnumerator(const ItemVectorViewT<ItemType>& g)
604 {
605 return g.enumerator();
606 }
607
608 // For compatibility with existing code
609 // If we are here, it means that the type 'T' is not an Arcane type.
610 // This call should eventually be forbidden (e.g., by end of 2025)
611 template <typename T>
612 static SimdItemEnumeratorT<ItemType> getSimdEnumerator(const T& g)
613 {
614 return g.enumerator();
615 }
616};
617
618/*---------------------------------------------------------------------------*/
619/*---------------------------------------------------------------------------*/
620
621#define ENUMERATE_SIMD_(type, iname, view) \
622 for (A_TRACE_ITEM_ENUMERATOR(SimdItemEnumeratorT<type>) iname(::Arcane::SimdItemEnumeratorContainerTraits<type>::getSimdEnumerator(view) A_TRACE_ENUMERATOR_WHERE); iname.hasNext(); ++iname)
623
624// TODO: To be removed. Use ENUMERATE_SIMD_ instead
625#define ENUMERATE_SIMD_GENERIC(type, iname, view) \
626 ENUMERATE_SIMD_(type, iname, view)
627
628/*!
629 * \ingroup ArcaneSimd
630 * \brief SIMD enumerator over a group or list of nodes.
631 */
632#define ENUMERATE_SIMD_NODE(name, group) ENUMERATE_SIMD_(::Arcane::Node, name, group)
633
634/*!
635 * \ingroup ArcaneSimd
636 * \brief SIMD enumerator over a group or list of edges.
637 */
638#define ENUMERATE_SIMD_EDGE(name, group) ENUMERATE_SIMD_(::Arcane::Edge, name, group)
639
640/*!
641 * \ingroup ArcaneSimd
642 * \brief SIMD enumerator over a group or list of faces.
643 */
644#define ENUMERATE_SIMD_FACE(name, group) ENUMERATE_SIMD_(::Arcane::Face, name, group)
645
646/*!
647 * \ingroup ArcaneSimd
648 * \brief SIMD enumerator over a group or list of cells.
649 */
650#define ENUMERATE_SIMD_CELL(name, group) ENUMERATE_SIMD_(::Arcane::Cell, name, group)
651
652/*!
653 * \ingroup ArcaneSimd
654 * \brief SIMD enumerator over a group or list of particles.
655 */
656#define ENUMERATE_SIMD_PARTICLE(name, group) ENUMERATE_SIMD_(::Arcane::Particle, name, group)
657
658/*---------------------------------------------------------------------------*/
659/*---------------------------------------------------------------------------*/
660
661} // End namespace Arcane
662
663/*---------------------------------------------------------------------------*/
664/*---------------------------------------------------------------------------*/
665
666#endif
Types and macros for iterating over mesh entities.
constexpr Integer count() const
Number of elements in the enumerator.
Enumerator over a typed list of entities of type ItemType.
Enumerator over a list of entities.
Reference to a group of a given kind.
Definition ItemGroup.h:420
Int32ConstArrayView localIds() const
Array of local entity IDs.
View on a typed array of entities.
Base class for a mesh element.
Definition Item.h:84
Integer nbValid() const
Number of valid values for the current iterator.
Definition Simd.h:457
Class managing a SIMD vector of entities.
Definition SimdItem.h:71
const Int32 *ARCANE_RESTRICT localIds() const
List of local IDs of the instance entities.
Definition SimdItem.h:112
const SimdIndexType &ARCANE_RESTRICT simdLocalIds() const
List of local IDs of the instance entities.
Definition SimdItem.h:109
Int32 localId(Int32 index) const
Local ID of the entity at index index.
Definition SimdItem.h:115
ItemInternal * item(Integer si) const
Internal part (for internal use only).
Definition SimdItem.h:103
SimdItemBase(const ItemInternalPtr *items, const SimdIndexType *ids)
Constructs an instance.
Definition SimdItem.h:87
Int32 baseLocalId() const
List of local IDs of the instance entities.
Definition SimdItem.h:162
Integer nbValid() const
Number of valid entities in the instance.
Definition SimdItem.h:159
Vector index without indirection for an entity type.
Definition SimdItem.h:214
Manages a vector of ItemType entities.
Definition SimdItem.h:323
const ItemInternalPtr * unguardedItems() const
List of entities.
Definition SimdItem.h:477
Enumerator over a list of entities.
Definition SimdItem.h:494
Vector index with indirection for an entity type. TODO: store the indices in a vector register to be ...
Definition SimdItem.h:182
const SimdIndexType &ARCANE_RESTRICT simdLocalIds() const
List of local IDs of the instance entities.
Definition SimdItem.h:199
Manages a vector of ItemType entities.
Definition SimdItem.h:272
ItemType operator[](Integer si) const
Returns the si-th entity of the instance.
Definition SimdItem.h:302
ItemType item(Integer si) const
Returns the si-th entity of the instance.
Definition SimdItem.h:296
Item item(Int32 si) const
inline si-th entity of the instance
Definition SimdItem.h:256
Item operator[](Int32 si) const
inline si-th entity of the instance
Definition SimdItem.h:259
SimdItemT< Edge > SimdEdge
SIMD vector of Edge.
Definition SimdItem.h:565
SimdItemT< Cell > SimdCell
SIMD vector of Cell.
Definition SimdItem.h:575
SimdItemT< Face > SimdFace
SIMD vector of Face.
Definition SimdItem.h:570
SimdItemT< Particle > SimdParticle
SIMD vector of Particle.
Definition SimdItem.h:580
SimdItemT< Node > SimdNode
SIMD vector of Node.
Definition SimdItem.h:560
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Int32 Integer
Type representing an integer.
ConstArrayView< Int32 > Int32ConstArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:482
std::int32_t Int32
Signed integer type of 32 bits.