OpenLB 1.8.1
Loading...
Searching...
No Matches
512.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2021 Adrian Kummerlaender
4 * E-mail contact: info@openlb.net
5 * The most recent release of OpenLB can be downloaded at
6 * <http://www.openlb.net/>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22*/
23
24#ifndef SIMD_PACK_512_H_
25#define SIMD_PACK_512_H_
26
27#include <immintrin.h>
28
29#include <cstdint>
30#include <type_traits>
31
32namespace olb {
33
34namespace cpu {
35
36namespace simd {
37
38template <typename T> class Mask;
39template <typename T> class Pack;
40
41template <>
42class Mask<double> {
43private:
44 __mmask8 _reg;
45
46public:
47 using storage_t = std::uint8_t;
48 static constexpr unsigned storage_size = 8;
49
50 static storage_t encode(bool* value)
51 {
52 storage_t mask = value[0];
53 for (unsigned j=1; j < storage_size; ++j) {
54 mask |= value[j] << j;
55 }
56 return mask;
57 }
58
59 Mask(bool b0, bool b1, bool b2, bool b3, bool b4, bool b5, bool b6, bool b7):
60 _reg(std::uint16_t(b0 | b1<<1 | b2<<2 | b3<<3 | b4<<4 | b5<<5 | b6<<6 | b7<<7)) { }
61
62 Mask(std::uint8_t* ptr):
63 _reg(_load_mask16(reinterpret_cast<std::uint16_t*>(ptr))) { }
64
65 Mask(storage_t* ptr, std::size_t iCell):
66 Mask(ptr + iCell / storage_size) { }
67
68 Mask(__mmask8 reg):
69 _reg(reg) { }
70
71 operator __mmask8()
72 {
73 return _reg;
74 }
75
76 __mmask8 neg() const
77 {
78 return _knot_mask8(_reg);
79 }
80
81 operator bool() const
82 {
83 const std::uint8_t* value = reinterpret_cast<const std::uint8_t*>(&_reg);
84 return value[0] != 0;
85 }
86};
87
88template <>
89class Mask<float> {
90private:
91 __mmask16 _reg;
92
93public:
94 using storage_t = std::uint16_t;
95 static constexpr unsigned storage_size = 16;
96
97 static storage_t encode(bool* value)
98 {
99 storage_t mask = value[0];
100 for (unsigned j=1; j < storage_size; ++j) {
101 mask |= value[j] << j;
102 }
103 return mask;
104 }
105
106 Mask(std::uint16_t* ptr):
107 _reg(_load_mask16(ptr)) { }
108
109 Mask(storage_t* ptr, std::size_t iCell):
110 Mask(ptr + iCell / storage_size) { }
111
112 Mask(__mmask16 reg):
113 _reg(reg) { }
114
115 operator __mmask16()
116 {
117 return _reg;
118 }
119
120 __mmask16 neg() const
121 {
122 return _knot_mask16(_reg);
123 }
124
125 operator bool() const
126 {
127 const std::uint16_t* value = reinterpret_cast<const std::uint16_t*>(&_reg);
128 return value[0] != 0;
129 }
130};
131
132
133template <>
134class Pack<double> : public SimdBase {
135private:
136 __m512d _reg;
137
138public:
139 using mask_t = Mask<double>;
140 using index_t = std::uint32_t;
141
142 static constexpr std::size_t size = 8;
143
144 Pack() = default;
145
146 Pack(__m512d reg):
147 _reg(reg) { }
148
149 Pack(double val):
150 Pack(_mm512_set1_pd(val)) { }
151
152 Pack(int val):
153 Pack(static_cast<double>(val)) { }
154
155 Pack(std::size_t val):
156 Pack(static_cast<double>(val)) { }
157
158 Pack(double a, double b, double c, double d, double e, double f, double g, double h):
159 Pack(_mm512_set_pd(h,g,f,e,d,c,b,a)) { }
160
161 Pack(const double* ptr):
162 Pack(_mm512_loadu_pd(ptr)) { }
163
164 Pack(const double* ptr, const index_t* idx):
165 Pack(_mm512_i32gather_pd(_mm256_loadu_si256(reinterpret_cast<const __m256i*>(idx)), ptr, sizeof(double))) { }
166
167 operator __m512d()
168 {
169 return _reg;
170 }
171
173 {
174 _reg = rhs._reg;
175 return *this;
176 }
177
178 double operator[](unsigned i) const
179 {
180 return reinterpret_cast<const double*>(&_reg)[i];
181 }
182
183 double& operator[](unsigned i)
184 {
185 return reinterpret_cast<double*>(&_reg)[i];
186 }
187
188 Pack operator+(Pack rhs) const
189 {
190 return Pack(_mm512_add_pd(_reg, rhs));
191 }
192
194 {
195 _reg = _mm512_add_pd(_reg, rhs);
196 return *this;
197 }
198
199 Pack operator-(Pack rhs) const
200 {
201 return Pack(_mm512_sub_pd(_reg, rhs));
202 }
203
205 {
206 _reg = _mm512_sub_pd(_reg, rhs);
207 return *this;
208 }
209
210 Pack operator*(Pack rhs) const
211 {
212 return Pack(_mm512_mul_pd(_reg, rhs));
213 }
214
216 {
217 _reg = _mm512_mul_pd(_reg, rhs);
218 return *this;
219 }
220
221 Pack operator/(Pack rhs) const
222 {
223 return Pack(_mm512_div_pd(_reg, rhs));
224 }
225
227 {
228 _reg = _mm512_div_pd(_reg, rhs);
229 return *this;
230 }
231
233 {
234 return *this * Pack(-1);
235 }
236
237 Pack sqrt() const
238 {
239 return _mm512_sqrt_pd(_reg);
240 }
241};
242
243template <>
244class Pack<float> : public SimdBase {
245private:
246 __m512 _reg;
247
248public:
249 using mask_t = Mask<float>;
250 using index_t = std::uint32_t;
251
252 static constexpr std::size_t size = 16;
253
254 Pack() = default;
255
256 Pack(__m512 reg):
257 _reg(reg) { }
258
259 Pack(float val):
260 Pack(_mm512_set1_ps(val)) { }
261
262 Pack(double val):
263 Pack(static_cast<float>(val)) { }
264
265 Pack(int val):
266 Pack(static_cast<float>(val)) { }
267
268 Pack(std::size_t val):
269 Pack(static_cast<float>(val)) { }
270
271 Pack(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m, float n, float o, float p):
272 Pack(_mm512_set_ps(p,o,n,m,l,k,j,i,h,g,f,e,d,c,b,a)) { }
273
274 Pack(const float* ptr):
275 Pack(_mm512_loadu_ps(ptr)) { }
276
277 Pack(const float* ptr, const index_t* idx):
278 Pack(_mm512_i32gather_ps(_mm512_loadu_si512(reinterpret_cast<const __m512i*>(idx)), ptr, sizeof(float))) { }
279
280 operator __m512()
281 {
282 return _reg;
283 }
284
286 {
287 _reg = rhs._reg;
288 return *this;
289 }
290
291 float operator[](unsigned i) const
292 {
293 return reinterpret_cast<const float*>(&_reg)[i];
294 }
295
296 float& operator[](unsigned i)
297 {
298 return reinterpret_cast<float*>(&_reg)[i];
299 }
300
301 Pack operator+(Pack rhs) const
302 {
303 return Pack(_mm512_add_ps(_reg, rhs));
304 }
305
307 {
308 _reg = _mm512_add_ps(_reg, rhs);
309 return *this;
310 }
311
312 Pack operator-(Pack rhs) const
313 {
314 return Pack(_mm512_sub_ps(_reg, rhs));
315 }
316
318 {
319 _reg = _mm512_sub_ps(_reg, rhs);
320 return *this;
321 }
322
323 Pack operator*(Pack rhs) const
324 {
325 return Pack(_mm512_mul_ps(_reg, rhs));
326 }
327
329 {
330 _reg = _mm512_mul_ps(_reg, rhs);
331 return *this;
332 }
333
334 Pack operator/(Pack rhs) const
335 {
336 return Pack(_mm512_div_ps(_reg, rhs));
337 }
338
340 {
341 _reg = _mm512_div_ps(_reg, rhs);
342 return *this;
343 }
344
346 {
347 return *this * Pack(-1);
348 }
349
350 __m512 sqrt() const
351 {
352 return _mm512_sqrt_ps(_reg);
353 }
354};
355
356
357template <typename T>
358Pack<T> pow(Pack<T> base, Pack<T> exp)
359{
360 //if constexpr (std::is_same_v<T,double>) {
361 // return _mm512_pow_pd(base, exp);
362 //} else {
363 // return _mm512_pow_ps(base, exp);
364 //}
365 // Workaround until I figure out why the intrinsics are not available (anymore?)
366 Pack<T> result;
367 for (unsigned i=0; i < Pack<T>::size; ++i) {
368 result[i] = util::pow(base[i], exp[i]);
369 }
370 return result;
371}
372
373template <typename T>
374Pack<T> min(Pack<T> rhs, Pack<T> lhs)
375{
376 if constexpr (std::is_same_v<T,double>) {
377 return _mm512_min_pd(rhs, lhs);
378 } else {
379 return _mm512_min_ps(rhs, lhs);
380 }
381}
382
383template <typename T>
384Pack<T> max(Pack<T> rhs, Pack<T> lhs)
385{
386 if constexpr (std::is_same_v<T,double>) {
387 return _mm512_max_pd(rhs, lhs);
388 } else {
389 return _mm512_max_ps(rhs, lhs);
390 }
391}
392
393template <typename T>
394Pack<T> fabs(Pack<T> x)
395{
396 if constexpr (std::is_same_v<T,double>) {
397 return _mm512_abs_pd(x);
398 } else {
399 return _mm512_abs_ps(x);
400 }
401}
402
403template <typename T>
404void maskstore(T* target, Mask<T> mask, Pack<T> value);
405
406template <>
407void maskstore<double>(double* target, Mask<double> mask, Pack<double> value)
408{
409 _mm512_mask_storeu_pd(target, mask, value);
410}
411
412template <>
413void maskstore<float>(float* target, Mask<float> mask, Pack<float> value)
414{
415 _mm512_mask_storeu_ps(target, mask, value);
416}
417
418
419template <typename T>
420void store(T* target, Pack<T> value);
421
422template <>
423void store<double>(double* target, Pack<double> value)
424{
425 _mm512_storeu_pd(target, value);
426}
427
428template <>
429void store<float>(float* target, Pack<float> value)
430{
431 _mm512_storeu_ps(target, value);
432}
433
434
435template <typename T>
436void store(T* target, Pack<T> value, const typename Pack<T>::index_t* indices);
437
438template <>
439void store<double>(double* target, Pack<double> value, const Pack<double>::index_t* indices)
440{
441 _mm512_i32scatter_pd(target, _mm256_loadu_si256(reinterpret_cast<const __m256i*>(indices)), value, sizeof(double));
442}
443
444
445template <>
446void store<float>(float* target, Pack<float> value, const Pack<float>::index_t* indices)
447{
448 _mm512_i32scatter_ps(target, _mm512_loadu_si512(reinterpret_cast<const __m512i*>(indices)), value, sizeof(float));
449}
450
451}
452
453}
454
455}
456
457#endif
Mask(storage_t *ptr, std::size_t iCell)
Definition 512.h:65
static storage_t encode(bool *value)
Definition 512.h:50
__mmask8 neg() const
Definition 512.h:76
Mask(bool b0, bool b1, bool b2, bool b3, bool b4, bool b5, bool b6, bool b7)
Definition 512.h:59
std::uint64_t storage_t
Definition 256.h:47
Mask(std::uint8_t *ptr)
Definition 512.h:62
Mask(__mmask16 reg)
Definition 512.h:112
std::uint32_t storage_t
Definition 256.h:110
Mask(std::uint16_t *ptr)
Definition 512.h:106
__mmask16 neg() const
Definition 512.h:120
Mask(storage_t *ptr, std::size_t iCell)
Definition 512.h:109
static storage_t encode(bool *value)
Definition 512.h:97
Pack & operator+=(Pack rhs)
Definition 512.h:193
Pack operator/=(Pack rhs)
Definition 512.h:226
std::uint32_t index_t
Definition 256.h:177
Pack operator/(Pack rhs) const
Definition 512.h:221
Pack operator+(Pack rhs) const
Definition 512.h:188
double operator[](unsigned i) const
Definition 512.h:178
Pack operator-=(Pack rhs)
Definition 512.h:204
Pack operator-(Pack rhs) const
Definition 512.h:199
Pack & operator=(Pack rhs)
Definition 512.h:172
Pack(std::size_t val)
Definition 512.h:155
Pack(const double *ptr, const index_t *idx)
Definition 512.h:164
Pack(const double *ptr)
Definition 512.h:161
Pack operator*(Pack rhs) const
Definition 512.h:210
Pack & operator*=(Pack rhs)
Definition 512.h:215
double & operator[](unsigned i)
Definition 512.h:183
Pack(double a, double b, double c, double d, double e, double f, double g, double h)
Definition 512.h:158
Pack operator*(Pack rhs) const
Definition 512.h:323
Pack & operator*=(Pack rhs)
Definition 512.h:328
Pack operator-() const
Definition 512.h:345
Pack & operator+=(Pack rhs)
Definition 512.h:306
Pack operator+(Pack rhs) const
Definition 512.h:301
Pack(std::size_t val)
Definition 512.h:268
Pack(const float *ptr)
Definition 512.h:274
Pack & operator-=(Pack rhs)
Definition 512.h:317
Pack operator/(Pack rhs) const
Definition 512.h:334
float & operator[](unsigned i)
Definition 512.h:296
Pack operator-(Pack rhs) const
Definition 512.h:312
std::uint32_t index_t
Definition 256.h:287
Pack(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m, float n, float o, float p)
Definition 512.h:271
Pack(const float *ptr, const index_t *idx)
Definition 512.h:277
Pack & operator/=(Pack rhs)
Definition 512.h:339
__m512 sqrt() const
Definition 512.h:350
Pack & operator=(Pack rhs)
Definition 512.h:285
float operator[](unsigned i) const
Definition 512.h:291
void maskstore< double >(double *target, Mask< double > mask, Pack< double > value)
Definition 256.h:435
Pack< T > pow(Pack< T > base, Pack< T > exp)
Definition 256.h:395
void store< double >(double *target, Pack< double > value)
Definition 256.h:451
Pack< T > min(Pack< T > rhs, Pack< T > lhs)
Definition 256.h:406
Pack< T > max(Pack< T > rhs, Pack< T > lhs)
Definition 256.h:416
void maskstore< float >(float *target, Mask< float > mask, Pack< float > value)
Definition 256.h:441
void store(T *target, Pack< T > value)
void store< float >(float *target, Pack< float > value)
Definition 256.h:457
Pack< T > fabs(Pack< T > x)
Definition 256.h:426
void maskstore(T *target, Mask< T > mask, Pack< T > value)
Expr pow(Expr base, Expr exp)
Definition expr.cpp:235
Top level namespace for all of OpenLB.