Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
Simd.h
Aller à la documentation de ce fichier.
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2022 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 pour la vectorisation. */
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/*---------------------------------------------------------------------------*/
53/*---------------------------------------------------------------------------*/
54/*---------------------------------------------------------------------------*/
55
56/*
57 * Les compilateurs (gcc et icc) définissent les macros suivantes
58 * sur x64 suivant le support de la vectorisation
59 * : avx: __AVX__
60 * : avx2: __AVX2__
61 * : avx512f: __AVX512F__
62 * : sse2: __SSE2__
63 *
64 * A noter que pour l'avx2 avec gcc, il n'y a pas par défaut le FMA.
65 * Par exemple:
66 * - gcc -mavx2 : pas de fma
67 * - gcc -mavx2 -mfma : fma actif
68 * - gcc -march=haswell : fma actif
69 */
70
71// Simd via émulation.
72#include "arcane/utils/SimdEMUL.h"
73
74// Ajoute support de SSE s'il existe
75#if (defined(_M_X64) || defined(__x86_64__)) && !defined(ARCANE_NO_SSE)
76// SSE2 est disponible sur tous les CPU x64
77// La macro __x64_64__ est définie pour les machines linux
78// La macro _M_X64 est définie pour les machines Windows
79#define ARCANE_HAS_SSE
80#include <emmintrin.h>
81#include "arcane/utils/SimdSSE.h"
82#endif
83
84// Ajoute support de AVX si dispo
85#if defined(ARCANE_HAS_AVX) || defined(ARCANE_HAS_AVX512)
86#include <immintrin.h>
87#include "arcane/utils/SimdAVX.h"
88#endif
89
90// Ajoute support de l'AVX512 si dispo
91#if defined(ARCANE_HAS_AVX512)
92#include <immintrin.h>
93#include "arcane/utils/SimdAVX512.h"
94#endif
95
96/*---------------------------------------------------------------------------*/
97/*---------------------------------------------------------------------------*/
103#define ENUMERATE_SIMD_REAL(_iter) \
104 for( ::Arcane::Integer _iter(0); _iter < SimdReal ::BLOCK_SIZE; ++ _iter )
105
106/*---------------------------------------------------------------------------*/
107/*---------------------------------------------------------------------------*/
108
109ARCANE_BEGIN_NAMESPACE
110
111/*---------------------------------------------------------------------------*/
112/*---------------------------------------------------------------------------*/
113/*
114 * Définit le type SimdInfo en fonction de la vectorisation disponible.
115 * On prend le type qui permet le plus de vectorisation.
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
135const int SimdSize = SimdReal::Length;
136
137/*---------------------------------------------------------------------------*/
138/*---------------------------------------------------------------------------*/
139
140/*---------------------------------------------------------------------------*/
141/*---------------------------------------------------------------------------*/
142
143/*---------------------------------------------------------------------------*/
144/*---------------------------------------------------------------------------*/
149class ARCANE_UTILS_EXPORT SimdReal3
150{
151 public:
153 public:
154 SimdReal x;
155 SimdReal y;
156 SimdReal z;
157 SimdReal3() {}
158 SimdReal3(SimdReal _x,SimdReal _y,SimdReal _z) : x(_x), y(_y), z(_z){}
159 SimdReal3(const Real3* base,const Int32IndexType& idx)
160 {
161 for( Integer i=0, n=SimdReal::BLOCK_SIZE; i<n; ++i ){
162 Real3 v = base[idx[i]];
163 this->set(i,v);
164 }
165 }
166 const Real3 operator[](Integer i) const { return Real3(x[i],y[i],z[i]); }
167
168 void set(Real3* base,const Int32IndexType& idx) const
169 {
170 for( Integer i=0, n=SimdReal::BLOCK_SIZE; i<n; ++i ){
171 base[idx[i]] = this->get(i);
172 }
173 }
174
175 // TODO: renommer cette méthode
176 void set(Integer i,Real3 r)
177 {
178 x[i] = r.x;
179 y[i] = r.y;
180 z[i] = r.z;
181 }
182 Real3 get(Integer i) const
183 {
184 return Real3(x[i],y[i],z[i]);
185 }
186};
187
188/*---------------------------------------------------------------------------*/
189/*---------------------------------------------------------------------------*/
194class ARCANE_UTILS_EXPORT SimdReal2
195{
196 public:
198 public:
199 SimdReal x;
200 SimdReal y;
201 SimdReal2() {}
202 SimdReal2(SimdReal _x,SimdReal _y) : x(_x), y(_y){}
203 SimdReal2(const Real2* base,const Int32IndexType& idx)
204 {
205 for( Integer i=0, n=SimdReal::BLOCK_SIZE; i<n; ++i ){
206 Real2 v = base[idx[i]];
207 this->set(i,v);
208 }
209 }
210 const Real2 operator[](Integer i) const { return Real2(x[i],y[i]); }
211
212 void set(Real2* base,const Int32IndexType& idx) const
213 {
214 for( Integer i=0, n=SimdReal::BLOCK_SIZE; i<n; ++i ){
215 base[idx[i]] = this->get(i);
216 }
217 }
218
219 void set(Integer i,Real2 r)
220 {
221 x[i] = r.x;
222 y[i] = r.y;
223 }
224 Real2 get(Integer i) const
225 {
226 return Real2(x[i],y[i]);
227 }
228};
229
230/*---------------------------------------------------------------------------*/
231/*---------------------------------------------------------------------------*/
236class ARCANE_UTILS_EXPORT SimdReal3x3
237{
238 public:
240 public:
241 SimdReal3 x;
242 SimdReal3 y;
243 SimdReal3 z;
244 SimdReal3x3() {}
245 SimdReal3x3(SimdReal3 _x,SimdReal3 _y,SimdReal3 _z) : x(_x), y(_y), z(_z){}
246 SimdReal3x3(const Real3x3* base,const Int32IndexType& idx)
247 {
248 for( Integer i=0, n=SimdReal::BLOCK_SIZE; i<n; ++i ){
249 Real3x3 v = base[idx[i]];
250 this->set(i,v);
251 }
252 }
253 const Real3x3 operator[](Integer i) const { return Real3x3(x[i],y[i],z[i]); }
254
255 void set(Real3x3* base,const Int32IndexType& idx) const
256 {
257 for( Integer i=0, n=SimdReal::BLOCK_SIZE; i<n; ++i ){
258 base[idx[i]] = this->get(i);
259 }
260 }
261
262 // TODO: renommer cette méthode
263 void set(Integer i,Real3x3 r)
264 {
265 x.set(i,r.x);
266 y.set(i,r.y);
267 z.set(i,r.z);
268 }
269 Real3x3 get(Integer i) const
270 {
271 return Real3x3(x[i],y[i],z[i]);
272 }
273};
274
275/*---------------------------------------------------------------------------*/
276/*---------------------------------------------------------------------------*/
281class ARCANE_UTILS_EXPORT SimdReal2x2
282{
283 public:
285 public:
286 SimdReal2 x;
287 SimdReal2 y;
288 SimdReal2x2() {}
289 SimdReal2x2(SimdReal2 _x,SimdReal2 _y) : x(_x), y(_y){}
290 SimdReal2x2(const Real2x2* base,const Int32IndexType& idx)
291 {
292 for( Integer i=0, n=SimdReal::BLOCK_SIZE; i<n; ++i ){
293 Real2x2 v = base[idx[i]];
294 this->set(i,v);
295 }
296 }
297 const Real2x2 operator[](Integer i) const { return Real2x2(x[i],y[i]); }
298
299 void set(Real2x2* base,const Int32IndexType& idx) const
300 {
301 for( Integer i=0, n=SimdReal::BLOCK_SIZE; i<n; ++i ){
302 base[idx[i]] = this->get(i);
303 }
304 }
305
306 // TODO: renommer cette méthode
307 void set(Integer i,Real2x2 r)
308 {
309 x.set(i,r.x);
310 y.set(i,r.y);
311 }
312 Real2x2 get(Integer i) const
313 {
314 return Real2x2(x[i],y[i]);
315 }
316};
317
318/*---------------------------------------------------------------------------*/
319/*---------------------------------------------------------------------------*/
328template<typename DataType>
330{
331 public:
332 typedef void SimdType;
333};
334
335template<>
336class SimdTypeTraits<Real>
337{
338 public:
339 typedef SimdReal SimdType;
340};
341
342template<>
344{
345 public:
346 typedef SimdReal2 SimdType;
347};
348
349template<>
351{
352 public:
353 typedef SimdReal2x2 SimdType;
354};
355
356template<>
358{
359 public:
360 typedef SimdReal3 SimdType;
361};
362
363template<>
365{
366 public:
367 typedef SimdReal3x3 SimdType;
368};
369
370/*---------------------------------------------------------------------------*/
371/*---------------------------------------------------------------------------*/
379class ARCANE_UTILS_EXPORT SimdEnumeratorBase
380{
381 public:
382
384
385 public:
386
388 : m_local_ids(nullptr), m_index(0), m_count(0) { }
389 SimdEnumeratorBase(const Int32* local_ids,Integer n)
390 : m_local_ids(local_ids), m_index(0), m_count(n)
391 { _checkValid(); }
393 : m_local_ids(local_ids.data()), m_index(0), m_count(local_ids.size())
394 { _checkValid(); }
395
396 public:
397
398 bool hasNext() { return m_index<m_count; }
399
401 const Int32* unguardedLocalIds() const { return m_local_ids; }
402
403 void operator++() { m_index += SimdSize; }
404
409 inline Integer nbValid() const
410 {
411 Integer nb_valid = (m_count-m_index);
412 if (nb_valid>SimdSize)
413 nb_valid = SimdSize;
414 return nb_valid;
415 }
416
417 Integer count() const { return m_count; }
418
419 protected:
420
421 const Int32* ARCANE_RESTRICT m_local_ids;
422 Integer m_index;
423 Integer m_count;
424
425 const SimdIndexType* ARCANE_RESTRICT
426 _currentSimdIndex() const
427 {
428 return (const SimdIndexType*)(m_local_ids+m_index);
429 }
430
431 private:
432
433 // Vérifie que m_local_ids est correctement aligné.
434 void _checkValid()
435 {
436#ifdef ARCANE_SIMD_BENCH
437 Int64 modulo = (Int64)(m_local_ids) % SimdIndexType::Alignment;
438 if (modulo!=0){
439 throw BadAlignmentException();
440 }
441#else
442 _checkValidHelper();
443#endif
444 }
445 void _checkValidHelper();
446};
447
448/*---------------------------------------------------------------------------*/
449/*---------------------------------------------------------------------------*/
450
451ARCANE_END_NAMESPACE
452
453/*---------------------------------------------------------------------------*/
454/*---------------------------------------------------------------------------*/
455
456#endif
Vectorisation des réels par émulation.
Definition SimdEMUL.h:155
Vectorisation des entiers en utilisant une émulation.
Definition SimdEMUL.h:35
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Classe gérant un vecteur de réel de dimension 2.
Definition Real2.h:121
Classe gérant une matrice de réel de dimension 2x2.
Definition Real2x2.h:53
Classe gérant un vecteur de réel de dimension 3.
Definition Real3.h:132
Classe gérant une matrice de réel de dimension 3x3.
Definition Real3x3.h:66
Classe de base des énumérateurs vectoriels avec indirection.
Definition Simd.h:380
const Int32 * unguardedLocalIds() const
Indices locaux.
Definition Simd.h:401
Integer nbValid() const
Nombre de valeurs valides pour l'itérateur courant.
Definition Simd.h:409
Représente un Real2 vectoriel.
Definition Simd.h:195
Représente un Real2x2 vectoriel.
Definition Simd.h:282
Représente un Real3 vectoriel.
Definition Simd.h:150
Représente un Real3x3 vectoriel.
Definition Simd.h:237
Charactéristiques des types vectoriels.
Definition Simd.h:330
Vue constante d'un tableau de type T.