MCKL
Monte Carlo Kernel Library
philox_avx512_2x32.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/philox_avx512_2x32.hpp
3 //----------------------------------------------------------------------------
4 // MCKL: Monte Carlo Kernel Library
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2018, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef MCKL_RANDOM_INTERNAL_PHILOX_AVX512_2X32_HPP
33 #define MCKL_RANDOM_INTERNAL_PHILOX_AVX512_2X32_HPP
34 
40 
41 MCKL_PUSH_GCC_WARNING("-Wignored-attributes")
42 
43 namespace mckl {
44 
45 namespace internal {
46 
47 template <typename T, typename Constants>
49 {
50  static_assert(std::numeric_limits<T>::digits == 32,
51  "**Philox2x32GeneratorAVX512Impl** used with T other than a 32-bit "
52  "unsigned integers");
53 
54  static constexpr std::size_t K = 2;
55  static constexpr std::size_t Rounds = 10;
56 
57  public:
58  static void eval(
59  const void *plain, void *cipher, const std::array<T, K / 2> &key)
60  {
62  }
63 
64  template <typename ResultType>
65  static void eval(std::array<std::uint64_t, 1> &ctr, ResultType *r,
66  const std::array<T, K / 2> &key)
67  {
69  }
70 
71  template <typename ResultType>
72  static void eval(std::array<std::uint64_t, 1> &ctr, std::size_t n,
73  ResultType *r, const std::array<T, K / 2> &key)
74  {
75  constexpr std::size_t R = sizeof(T) * K / sizeof(ResultType);
76 
77  const std::size_t n0 =
78  static_cast<std::size_t>(std::min(static_cast<std::uint64_t>(n),
79  std::numeric_limits<std::uint64_t>::max() - ctr.front()));
80 
81  eval_kernel(ctr, n0, r, key);
82  n -= n0;
83  r += n0 * R;
84 
85  if (n != 0) {
86  eval(ctr, r, key);
87  n -= 1;
88  r += R;
89  }
90 
91  eval_kernel(ctr, n, r, key);
92  }
93 
94  private:
95  template <typename ResultType>
96  static void eval_kernel(std::array<std::uint64_t, 1> &ctr, std::size_t n,
97  ResultType *r, const std::array<T, K / 2> &key)
98  {
99 #if MCKL_USE_ASM_LIBRARY
100  constexpr T m0 = Constants::multiplier::value[0];
101  constexpr T w0 = Constants::weyl::value[0];
102 
103  const T mwk[6] = {m0, 0, 0, w0, 0, std::get<0>(key)};
104  mckl_philox2x32_avx512_kernel(ctr.data(), n, r, mwk);
105 #else // MCKL_USE_ASM_LIBRARY
106  constexpr std::size_t S = 8;
107  constexpr std::size_t N = sizeof(__m512i) * S / (sizeof(T) * K);
108 
109  const int k0 = static_cast<int>(std::get<0>(key));
110  const __m512i ymmk0 = _mm512_set_epi32(
111  k0, 0, k0, 0, k0, 0, k0, 0, k0, 0, k0, 0, k0, 0, k0, 0);
112 
113  __m512i ymmc =
114  _mm512_set1_epi64(static_cast<MCKL_INT64>(std::get<0>(ctr)));
115  ctr.front() += n;
116 
117  __m512i *rptr = reinterpret_cast<__m512i *>(r);
118  while (n != 0) {
119  __m512i ymm0 = _mm512_add_epi64(ymmc,
120  _mm512_set_epi64(
121  0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01));
122  __m512i ymm1 = _mm512_add_epi64(ymmc,
123  _mm512_set_epi64(
124  0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09));
125  __m512i ymm2 = _mm512_add_epi64(ymmc,
126  _mm512_set_epi64(
127  0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11));
128  __m512i ymm3 = _mm512_add_epi64(ymmc,
129  _mm512_set_epi64(
130  0x20, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19));
131  __m512i ymm4 = _mm512_add_epi64(ymmc,
132  _mm512_set_epi64(
133  0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21));
134  __m512i ymm5 = _mm512_add_epi64(ymmc,
135  _mm512_set_epi64(
136  0x30, 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29));
137  __m512i ymm6 = _mm512_add_epi64(ymmc,
138  _mm512_set_epi64(
139  0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31));
140  __m512i ymm7 = _mm512_add_epi64(ymmc,
141  _mm512_set_epi64(
142  0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39));
143  ymmc = _mm512_add_epi64(ymmc, _mm512_set1_epi64(0x40));
144 
155 
156  if (n >= N) {
157  n -= N;
158  _mm512_storeu_si512(rptr++, ymm0);
159  _mm512_storeu_si512(rptr++, ymm1);
160  _mm512_storeu_si512(rptr++, ymm2);
161  _mm512_storeu_si512(rptr++, ymm3);
162  _mm512_storeu_si512(rptr++, ymm4);
163  _mm512_storeu_si512(rptr++, ymm5);
164  _mm512_storeu_si512(rptr++, ymm6);
165  _mm512_storeu_si512(rptr++, ymm7);
166  } else {
167  std::array<__m512i, S> s;
168  std::get<0>(s) = ymm0;
169  std::get<1>(s) = ymm1;
170  std::get<2>(s) = ymm2;
171  std::get<3>(s) = ymm3;
172  std::get<4>(s) = ymm4;
173  std::get<5>(s) = ymm5;
174  std::get<6>(s) = ymm6;
175  std::get<7>(s) = ymm7;
176  std::memcpy(rptr, s.data(), n * sizeof(T) * K);
177  break;
178  }
179  }
180 #endif // MCKL_USE_ASM_LIBRARY
181  }
182 }; // class Philox2x32GeneratorAVX512Impl
183 
184 } // namespace internal
185 
186 } // namespace mckl
187 
189 
190 #endif // MCKL_RANDOM_INTERNAL_PHILOX_AVX512_2X32_HPP
#define MCKL_PUSH_GCC_WARNING(warning)
Definition: compiler.h:78
void mckl_philox2x32_avx512_kernel(uint64_t *, size_t, void *, const void *)
#define MCKL_RANDOM_INTERNAL_PHILOX_AVX512_32_RBOX(K, N, imm8)
static void eval(std::array< std::uint64_t, 1 > &ctr, ResultType *r, const std::array< T, K/2 > &key)
Definition: mcmc.hpp:40
static void eval(const void *plain, void *cipher, const std::array< T, K/2 > &key)
#define MCKL_POP_GCC_WARNING
Definition: compiler.h:79
static void eval(std::array< std::uint64_t, 1 > &ctr, std::size_t n, ResultType *r, const std::array< T, K/2 > &key)