Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
Simd.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/* Simd.h (C) 2000-2017 */
9/* */
10/* Types for vectorization. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_UTILS_SIMD_H
13#define ARCANE_UTILS_SIMD_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arcane/utils/SimdCommon.h"
18#include "arcane/utils/Real3.h"
19#include "arcane/utils/Real2.h"
20#include "arcane/utils/Real3x3.h"
21#include "arcane/utils/Real2x2.h"
22#include "arcane/utils/ArrayView.h"
23
24/*---------------------------------------------------------------------------*/
25/*---------------------------------------------------------------------------*/
51/*---------------------------------------------------------------------------*/
52/*---------------------------------------------------------------------------*/
53
54/*
55 * The compilers (gcc and icc) define the following macros
56 * on x64 depending on vectorization support:
57 * : avx: __AVX__
58 * : avx2: __AVX2__
59 * : avx512f: __AVX512F__
60 * : sse2: __SSE2__
61 *
62 * Note that for avx2 with gcc, FMA is not enabled by default.
63 * For example:
64 * - gcc -mavx2 : no fma
65 * - gcc -mavx2 -mfma : fma active
66 * - gcc -march=haswell : fma active
67 */
68
69// Simd via emulation.
70#include "arcane/utils/SimdEMUL.h"
71
72// Add SSE support if available
73#if (defined(_M_X64) || defined(__x86_64__)) && !defined(ARCANE_NO_SSE)
74// SSE2 is available on all x64 CPUs
75// The macro __x64_64__ is defined for Linux machines
76// The macro _M_X64 is defined for Windows machines
77#define ARCANE_HAS_SSE
78#include <emmintrin.h>
79#include "arcane/utils/SimdSSE.h"
80#endif
81
82// Add AVX support if available
83#if defined(ARCANE_HAS_AVX) || defined(ARCANE_HAS_AVX512)
84#include <immintrin.h>
85#include "arcane/utils/SimdAVX.h"
86#endif
87
88// Add AVX512 support if available
89#if defined(ARCANE_HAS_AVX512)
90#include <immintrin.h>
91#include "arcane/utils/SimdAVX512.h"
92#endif
93
94/*---------------------------------------------------------------------------*/
95/*---------------------------------------------------------------------------*/
96
101#define ENUMERATE_SIMD_REAL(_iter) \
102 for (::Arcane::Integer _iter(0); _iter < SimdReal ::BLOCK_SIZE; ++_iter)
103
104/*---------------------------------------------------------------------------*/
105/*---------------------------------------------------------------------------*/
106
107namespace Arcane
108{
109
110/*---------------------------------------------------------------------------*/
111/*---------------------------------------------------------------------------*/
112
113/*
114 * Defines the SimdInfo type based on available vectorization.
115 * It takes the type that allows the most vectorization.
116 */
117#if defined(ARCANE_HAS_AVX512)
118typedef AVX512SimdInfo SimdInfo;
119#elif defined(ARCANE_HAS_AVX)
120typedef AVXSimdInfo SimdInfo;
121#elif defined(ARCANE_HAS_SSE)
122typedef SSESimdInfo SimdInfo;
123#else
124typedef EMULSimdInfo SimdInfo;
125#endif
126
127/*---------------------------------------------------------------------------*/
128/*---------------------------------------------------------------------------*/
129
134typedef SimdInfo::SimdReal SimdReal;
135const int SimdSize = SimdReal::Length;
136
137/*---------------------------------------------------------------------------*/
138/*---------------------------------------------------------------------------*/
139
140/*---------------------------------------------------------------------------*/
141/*---------------------------------------------------------------------------*/
142
143/*---------------------------------------------------------------------------*/
144/*---------------------------------------------------------------------------*/
145
150class ARCANE_UTILS_EXPORT SimdReal3
151{
152 public:
153
154 typedef SimdReal::Int32IndexType Int32IndexType;
155
156 public:
157
158 SimdReal x;
159 SimdReal y;
160 SimdReal z;
161 SimdReal3() {}
162 SimdReal3(SimdReal _x, SimdReal _y, SimdReal _z)
163 : x(_x)
164 , y(_y)
165 , z(_z)
166 {}
167 SimdReal3(const Real3* base, const Int32IndexType& idx)
168 {
169 for (Integer i = 0, n = SimdReal::BLOCK_SIZE; i < n; ++i) {
170 Real3 v = base[idx[i]];
171 this->set(i, v);
172 }
173 }
174 const Real3 operator[](Integer i) const { return Real3(x[i], y[i], z[i]); }
175
176 void set(Real3* base, const Int32IndexType& idx) const
177 {
178 for (Integer i = 0, n = SimdReal::BLOCK_SIZE; i < n; ++i) {
179 base[idx[i]] = this->get(i);
180 }
181 }
182
183 // TODO: rename this method
184 void set(Integer i, Real3 r)
185 {
186 x[i] = r.x;
187 y[i] = r.y;
188 z[i] = r.z;
189 }
190 Real3 get(Integer i) const
191 {
192 return Real3(x[i], y[i], z[i]);
193 }
194};
195
196/*---------------------------------------------------------------------------*/
197/*---------------------------------------------------------------------------*/
198
203class ARCANE_UTILS_EXPORT SimdReal2
204{
205 public:
206
207 typedef SimdReal::Int32IndexType Int32IndexType;
208
209 public:
210
211 SimdReal x;
212 SimdReal y;
213 SimdReal2() {}
214 SimdReal2(SimdReal _x, SimdReal _y)
215 : x(_x)
216 , y(_y)
217 {}
218 SimdReal2(const Real2* base, const Int32IndexType& idx)
219 {
220 for (Integer i = 0, n = SimdReal::BLOCK_SIZE; i < n; ++i) {
221 Real2 v = base[idx[i]];
222 this->set(i, v);
223 }
224 }
225 const Real2 operator[](Integer i) const { return Real2(x[i], y[i]); }
226
227 void set(Real2* base, const Int32IndexType& idx) const
228 {
229 for (Integer i = 0, n = SimdReal::BLOCK_SIZE; i < n; ++i) {
230 base[idx[i]] = this->get(i);
231 }
232 }
233
234 void set(Integer i, Real2 r)
235 {
236 x[i] = r.x;
237 y[i] = r.y;
238 }
239 Real2 get(Integer i) const
240 {
241 return Real2(x[i], y[i]);
242 }
243};
244
245/*---------------------------------------------------------------------------*/
246/*---------------------------------------------------------------------------*/
247
252class ARCANE_UTILS_EXPORT SimdReal3x3
253{
254 public:
255
256 typedef SimdReal::Int32IndexType Int32IndexType;
257
258 public:
259
260 SimdReal3 x;
261 SimdReal3 y;
262 SimdReal3 z;
263 SimdReal3x3() {}
264 SimdReal3x3(SimdReal3 _x, SimdReal3 _y, SimdReal3 _z)
265 : x(_x)
266 , y(_y)
267 , z(_z)
268 {}
269 SimdReal3x3(const Real3x3* base, const Int32IndexType& idx)
270 {
271 for (Integer i = 0, n = SimdReal::BLOCK_SIZE; i < n; ++i) {
272 Real3x3 v = base[idx[i]];
273 this->set(i, v);
274 }
275 }
276 const Real3x3 operator[](Integer i) const { return Real3x3(x[i], y[i], z[i]); }
277
278 void set(Real3x3* base, const Int32IndexType& idx) const
279 {
280 for (Integer i = 0, n = SimdReal::BLOCK_SIZE; i < n; ++i) {
281 base[idx[i]] = this->get(i);
282 }
283 }
284
285 // TODO: rename this method
286 void set(Integer i, Real3x3 r)
287 {
288 x.set(i, r.x);
289 y.set(i, r.y);
290 z.set(i, r.z);
291 }
292 Real3x3 get(Integer i) const
293 {
294 return Real3x3(x[i], y[i], z[i]);
295 }
296};
297
298/*---------------------------------------------------------------------------*/
299/*---------------------------------------------------------------------------*/
300
305class ARCANE_UTILS_EXPORT SimdReal2x2
306{
307 public:
308
309 typedef SimdReal::Int32IndexType Int32IndexType;
310
311 public:
312
313 SimdReal2 x;
314 SimdReal2 y;
315 SimdReal2x2() {}
316 SimdReal2x2(SimdReal2 _x, SimdReal2 _y)
317 : x(_x)
318 , y(_y)
319 {}
320 SimdReal2x2(const Real2x2* base, const Int32IndexType& idx)
321 {
322 for (Integer i = 0, n = SimdReal::BLOCK_SIZE; i < n; ++i) {
323 Real2x2 v = base[idx[i]];
324 this->set(i, v);
325 }
326 }
327 const Real2x2 operator[](Integer i) const { return Real2x2(x[i], y[i]); }
328
329 void set(Real2x2* base, const Int32IndexType& idx) const
330 {
331 for (Integer i = 0, n = SimdReal::BLOCK_SIZE; i < n; ++i) {
332 base[idx[i]] = this->get(i);
333 }
334 }
335
336 // TODO: rename this method
337 void set(Integer i, Real2x2 r)
338 {
339 x.set(i, r.x);
340 y.set(i, r.y);
341 }
342 Real2x2 get(Integer i) const
343 {
344 return Real2x2(x[i], y[i]);
345 }
346};
347
348/*---------------------------------------------------------------------------*/
349/*---------------------------------------------------------------------------*/
350
358template <typename DataType>
360{
361 public:
362
363 typedef void SimdType;
364};
365
366template <>
368{
369 public:
370
371 typedef SimdReal SimdType;
372};
373
374template <>
376{
377 public:
378
379 typedef SimdReal2 SimdType;
380};
381
382template <>
384{
385 public:
386
387 typedef SimdReal2x2 SimdType;
388};
389
390template <>
392{
393 public:
394
395 typedef SimdReal3 SimdType;
396};
397
398template <>
400{
401 public:
402
403 typedef SimdReal3x3 SimdType;
404};
405
406/*---------------------------------------------------------------------------*/
407/*---------------------------------------------------------------------------*/
408
416class ARCANE_UTILS_EXPORT SimdEnumeratorBase
417{
418 public:
419
420 typedef SimdInfo::SimdInt32IndexType SimdIndexType;
421
422 public:
423
424 SimdEnumeratorBase()
425 : m_local_ids(nullptr)
426 , m_index(0)
427 , m_count(0)
428 {}
429 SimdEnumeratorBase(const Int32* local_ids, Integer n)
430 : m_local_ids(local_ids)
431 , m_index(0)
432 , m_count(n)
433 {
434 _checkValid();
435 }
436 explicit SimdEnumeratorBase(Int32ConstArrayView local_ids)
437 : m_local_ids(local_ids.data())
438 , m_index(0)
439 , m_count(local_ids.size())
440 {
441 _checkValid();
442 }
443
444 public:
445
446 bool hasNext() { return m_index < m_count; }
447
449 const Int32* unguardedLocalIds() const { return m_local_ids; }
450
451 void operator++() { m_index += SimdSize; }
452
457 inline Integer nbValid() const
458 {
459 Integer nb_valid = (m_count - m_index);
460 if (nb_valid > SimdSize)
461 nb_valid = SimdSize;
462 return nb_valid;
463 }
464
465 Integer count() const { return m_count; }
466
467 protected:
468
469 const Int32* ARCANE_RESTRICT m_local_ids;
470 Integer m_index;
471 Integer m_count;
472
473 const SimdIndexType* ARCANE_RESTRICT
474 _currentSimdIndex() const
475 {
476 return (const SimdIndexType*)(m_local_ids + m_index);
477 }
478
479 private:
480
481 // Checks that m_local_ids is correctly aligned.
482 void _checkValid()
483 {
484#ifdef ARCANE_SIMD_BENCH
485 Int64 modulo = (Int64)(m_local_ids) % SimdIndexType::Alignment;
486 if (modulo != 0) {
487 throw BadAlignmentException();
488 }
489#else
490 _checkValidHelper();
491#endif
492 }
493 void _checkValidHelper();
494};
495
496/*---------------------------------------------------------------------------*/
497/*---------------------------------------------------------------------------*/
498
499} // namespace Arcane
500
501/*---------------------------------------------------------------------------*/
502/*---------------------------------------------------------------------------*/
503
504#endif
Class managing a 2-dimensional real vector.
Definition Real2.h:122
Class managing a 2x2 matrix of reals.
Definition Real2x2.h:55
Real2 x
First component.
Definition Real2x2.h:112
Real2 y
Second component.
Definition Real2x2.h:113
Class managing a 3-dimensional real vector.
Definition Real3.h:132
Class managing a 3x3 real matrix.
Definition Real3x3.h:67
Real3 z
first element of the triplet
Definition Real3x3.h:131
Real3 y
first element of the triplet
Definition Real3x3.h:130
Real3 x
first element of the triplet
Definition Real3x3.h:129
const Int32 * unguardedLocalIds() const
Local indices.
Definition Simd.h:449
Integer nbValid() const
Number of valid values for the current iterator.
Definition Simd.h:457
Represents a vectorized Real2.
Definition Simd.h:204
Represents a vectorized Real2x2.
Definition Simd.h:306
Represents a vectorized Real3.
Definition Simd.h:151
Represents a vectorized Real3x3.
Definition Simd.h:253
Characteristics of vector types.
Definition Simd.h:360
SimdInfo::SimdReal SimdReal
SIMD vector of real numbers.
Definition Simd.h:134
-- 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
double Real
Type representing a real number.
std::int32_t Int32
Signed integer type of 32 bits.
Real y
second component of the pair
Definition Real2.h:35
Real x
first component of the pair
Definition Real2.h:34
Real y
second component of the triplet
Definition Real3.h:36
Real z
third component of the triplet
Definition Real3.h:37
Real x
first component of the triplet
Definition Real3.h:35