RAJA
RAJA provides a collection of platform portability abstractions for C++ HPC applications.
avx512_double.hpp
Go to the documentation of this file.
1 
11 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
12 // Copyright (c) Lawrence Livermore National Security, LLC and other
13 // RAJA Project Developers. See top-level LICENSE and COPYRIGHT
14 // files for dates and other details. No copyright assignment is required
15 // to contribute to RAJA.
16 //
17 // SPDX-License-Identifier: (BSD-3-Clause)
18 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
19 
20 #ifdef __AVX512F__
21 
22 #ifndef RAJA_policy_vector_register_avx512_double_HPP
23 #define RAJA_policy_vector_register_avx512_double_HPP
24 
25 #include "RAJA/config.hpp"
26 #include "RAJA/util/macros.hpp"
28 
29 // Include SIMD intrinsics header file
30 #include <immintrin.h>
31 #include <cmath>
32 
33 namespace RAJA
34 {
35 namespace expt
36 {
37 
38 template<>
39 class Register<double, avx512_register>
40  : public internal::expt::RegisterBase<Register<double, avx512_register>>
41 {
42 public:
43  using base_type =
44  internal::expt::RegisterBase<Register<double, avx512_register>>;
45 
46 
47  using register_policy = avx512_register;
48  using self_type = Register<double, avx512_register>;
49  using element_type = double;
50  using register_type = __m512d;
51 
52  using int_vector_type = Register<int64_t, avx512_register>;
53 
54 
55 private:
56  register_type m_value;
57 
58  RAJA_INLINE
59  __mmask8 createMask(camp::idx_t N) const
60  {
61  // Generate a mask
62  switch (N)
63  {
64  case 0:
65  return __mmask8(0x00);
66  case 1:
67  return __mmask8(0x01);
68  case 2:
69  return __mmask8(0x03);
70  case 3:
71  return __mmask8(0x07);
72  case 4:
73  return __mmask8(0x0F);
74  case 5:
75  return __mmask8(0x1F);
76  case 6:
77  return __mmask8(0x3F);
78  case 7:
79  return __mmask8(0x7F);
80  case 8:
81  return __mmask8(0xFF);
82  }
83  return __mmask8(0);
84  }
85 
86  RAJA_INLINE
87  __m512i createStridedOffsets(camp::idx_t stride) const
88  {
89  // Generate a strided offset list
90  auto vstride = _mm512_set1_epi64(stride);
91  auto vseq = _mm512_set_epi64(7, 6, 5, 4, 3, 2, 1, 0);
92  return _mm512_mullo_epi64(vstride, vseq);
93  }
94 
95 public:
96  static constexpr camp::idx_t s_num_elem = 8;
97 
101  // AVX512F
102  RAJA_INLINE
103  Register() : base_type(), m_value(_mm512_setzero_pd()) {}
104 
108  RAJA_INLINE
109  explicit Register(register_type const& c) : base_type(), m_value(c) {}
110 
114  RAJA_INLINE
115  Register(self_type const& c) : base_type(), m_value(c.m_value) {}
116 
120  RAJA_INLINE
121  self_type& operator=(self_type const& c)
122  {
123  m_value = c.m_value;
124  return *this;
125  }
126 
131  // AVX512F
132  RAJA_INLINE
133  Register(element_type const& c) : base_type(), m_value(_mm512_set1_pd(c)) {}
134 
139  RAJA_INLINE
140  self_type& load_packed(element_type const* ptr)
141  {
142  // AVX512F
143  m_value = _mm512_loadu_pd(ptr);
144  return *this;
145  }
146 
152  RAJA_INLINE
153  self_type& load_packed_n(element_type const* ptr, camp::idx_t N)
154  {
155  // AVX512F
156  m_value = _mm512_mask_loadu_pd(_mm512_setzero_pd(), createMask(N), ptr);
157  return *this;
158  }
159 
164  RAJA_INLINE
165  self_type& load_strided(element_type const* ptr, camp::idx_t stride)
166  {
167  // AVX512F
168  m_value = _mm512_i64gather_pd(createStridedOffsets(stride), ptr,
169  sizeof(element_type));
170  return *this;
171  }
172 
178  RAJA_INLINE
179  self_type& load_strided_n(element_type const* ptr,
180  camp::idx_t stride,
181  camp::idx_t N)
182  {
183  // AVX512F
184  m_value = _mm512_mask_i64gather_pd(_mm512_setzero_pd(), createMask(N),
185  createStridedOffsets(stride), ptr,
186  sizeof(element_type));
187  return *this;
188  }
189 
194  RAJA_INLINE
195  self_type const& store_packed(element_type* ptr) const
196  {
197  // AVX512F
198  _mm512_storeu_pd(ptr, m_value);
199  return *this;
200  }
201 
206  RAJA_INLINE
207  self_type const& store_packed_n(element_type* ptr, camp::idx_t N) const
208  {
209  // AVX512F
210  _mm512_mask_storeu_pd(ptr, createMask(N), m_value);
211  return *this;
212  }
213 
218  RAJA_INLINE
219  self_type const& store_strided(element_type* ptr, camp::idx_t stride) const
220  {
221  // AVX512F
222  _mm512_i64scatter_pd(ptr, createStridedOffsets(stride), m_value,
223  sizeof(element_type));
224  return *this;
225  }
226 
231  RAJA_INLINE
232  self_type const& store_strided_n(element_type* ptr,
233  camp::idx_t stride,
234  camp::idx_t N) const
235  {
236  // AVX512F
237  _mm512_mask_i64scatter_pd(ptr, createMask(N), createStridedOffsets(stride),
238  m_value, sizeof(element_type));
239  return *this;
240  }
241 
247  RAJA_INLINE
248  element_type get(camp::idx_t i) const { return m_value[i]; }
249 
255  RAJA_INLINE
256  self_type& set(element_type value, camp::idx_t i)
257  {
258  m_value[i] = value;
259  return *this;
260  }
261 
263 
264  RAJA_INLINE
265  self_type& broadcast(element_type const& value)
266  {
267  m_value = _mm512_set1_pd(value);
268  return *this;
269  }
270 
272 
273  RAJA_INLINE
274  self_type& copy(self_type const& src)
275  {
276  m_value = src.m_value;
277  return *this;
278  }
279 
281 
282  RAJA_INLINE
283  self_type add(self_type const& b) const
284  {
285  return self_type(_mm512_add_pd(m_value, b.m_value));
286  }
287 
289 
290  RAJA_INLINE
291  self_type subtract(self_type const& b) const
292  {
293  return self_type(_mm512_sub_pd(m_value, b.m_value));
294  }
295 
297 
298  RAJA_INLINE
299  self_type multiply(self_type const& b) const
300  {
301  return self_type(_mm512_mul_pd(m_value, b.m_value));
302  }
303 
305 
306  RAJA_INLINE
307  self_type divide(self_type const& b) const
308  {
309  return self_type(_mm512_div_pd(m_value, b.m_value));
310  }
311 
313 
314  RAJA_INLINE
315  self_type divide_n(self_type const& b, camp::idx_t N) const
316  {
317  return self_type(_mm512_maskz_div_pd(createMask(N), m_value, b.m_value));
318  }
319 
320 // only use FMA's if the compiler has them turned on
321 #ifdef __FMA__
322  RAJA_INLINE
323 
325  self_type multiply_add(self_type const& b, self_type const& c) const
326  {
327  return self_type(_mm512_fmadd_pd(m_value, b.m_value, c.m_value));
328  }
329 
330  RAJA_INLINE
331 
333  self_type multiply_subtract(self_type const& b, self_type const& c) const
334  {
335  return self_type(_mm512_fmsub_pd(m_value, b.m_value, c.m_value));
336  }
337 #endif
338 
343  RAJA_INLINE
344  element_type sum() const { return _mm512_reduce_add_pd(m_value); }
345 
350  RAJA_INLINE
351  element_type max() const { return _mm512_reduce_max_pd(m_value); }
352 
357  RAJA_INLINE
358  element_type max_n(camp::idx_t N) const
359  {
360  return _mm512_mask_reduce_max_pd(createMask(N), m_value);
361  }
362 
367  RAJA_INLINE
368  self_type vmax(self_type a) const
369  {
370  return self_type(_mm512_max_pd(m_value, a.m_value));
371  }
372 
377  RAJA_INLINE
378  element_type min() const { return _mm512_reduce_min_pd(m_value); }
379 
384  RAJA_INLINE
385  element_type min_n(camp::idx_t N) const
386  {
387  return _mm512_mask_reduce_min_pd(createMask(N), m_value);
388  }
389 
394  RAJA_INLINE
395  self_type vmin(self_type a) const
396  {
397  return self_type(_mm512_min_pd(m_value, a.m_value));
398  }
399 };
400 
401 
402 } // namespace expt
403 
404 } // namespace RAJA
405 
406 
407 #endif
408 
409 #endif //__AVX512F__
RAJA header file defining SIMD/SIMT register operations.
Header file for common RAJA internal macro definitions.
#define RAJA_HOST_DEVICE
Definition: macros.hpp:65
Definition: AlignedRangeIndexSetBuilders.cpp:35
RAJA_HOST_DEVICE constexpr RAJA_INLINE Result min(Args... args)
Definition: foldl.hpp:161
RAJA_HOST_DEVICE constexpr RAJA_INLINE Result sum(Args... args)
Definition: foldl.hpp:143
RAJA_HOST_DEVICE constexpr RAJA_INLINE RAJA::zip_tuple_element_t< I, zip_tuple< is_val, Ts... > > & get(zip_tuple< is_val, Ts... > &z) noexcept
Definition: zip_tuple.hpp:56
RAJA_HOST_DEVICE constexpr RAJA_INLINE Result max(Args... args)
Definition: foldl.hpp:155