MCKL
Monte Carlo Kernel Library
philox_avx512_32.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/philox_avx512_32.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_32_HPP
33 #define MCKL_RANDOM_INTERNAL_PHILOX_AVX512_32_HPP
34 
42 
43 MCKL_PUSH_GCC_WARNING("-Wignored-attributes")
44 
45 namespace mckl {
46 
47 namespace internal {
48 
49 template <std::size_t>
51 
52 template <>
54 {
55  public:
56  template <std::size_t S>
57  MCKL_INLINE static void first(std::array<__m512i, S> &)
58  {
59  }
60 
61  template <std::size_t S>
62  MCKL_INLINE static void round(std::array<__m512i, S> &s)
63  {
64  shuffle_epi32<0xB1>(s);
65  }
66 
67  template <std::size_t S>
68  MCKL_INLINE static void last(std::array<__m512i, S> &s)
69  {
70  shuffle_epi32<0xB1>(s);
71  }
72 }; // class PhiloxGeneratorAVX512Impl32Permute
73 
74 template <>
76 {
77  public:
78  template <std::size_t S>
79  MCKL_INLINE static void first(std::array<__m512i, S> &s)
80  {
81  shuffle_epi32<0xC6>(s);
82  }
83 
84  template <std::size_t S>
85  MCKL_INLINE static void round(std::array<__m512i, S> &s)
86  {
87  shuffle_epi32<0x93>(s);
88  }
89 
90  template <std::size_t S>
91  MCKL_INLINE static void last(std::array<__m512i, S> &s)
92  {
93  shuffle_epi32<0xB1>(s);
94  }
95 }; // class PhiloxGeneratorAVX512Impl32Permute
96 
97 template <typename T, std::size_t K, std::size_t Rounds, typename Constants>
99 {
100  public:
101  static void eval(
102  const void *plain, void *cipher, const std::array<T, K / 2> &key)
103  {
105  plain, cipher, key);
106  }
107 
108  template <typename ResultType>
109  static void eval(
110  Counter<T, K> &ctr, ResultType *r, const std::array<T, K / 2> &key)
111  {
113  }
114 
115  template <typename ResultType>
116  static void eval(Counter<T, K> &ctr, std::size_t n, ResultType *r,
117  const std::array<T, K / 2> &key)
118  {
119  constexpr std::size_t S = 8;
120  constexpr std::size_t N = sizeof(__m512i) * S / (sizeof(T) * K);
121  constexpr std::size_t R = sizeof(T) * K / sizeof(ResultType);
122 
123  const std::array<__m512i, Rounds> rk(round_key(key));
124  while (n >= N) {
125  std::array<__m512i, S> s;
130  std::memcpy(r, s.data(), sizeof(T) * K * N);
131  n -= N;
132  r += N * R;
133  }
134 
135  alignas(MCKL_ALIGNMENT) std::array<ResultType, N * R> t;
137  ctr, n, t.data(), key);
138  std::memcpy(r, t.data(), sizeof(T) * K * n);
139  }
140 
141  private:
142  template <std::size_t, std::size_t S>
143  static void round(std::array<__m512i, S> &,
144  const std::array<__m512i, Rounds> &, std::false_type)
145  {
146  }
147 
148  template <std::size_t N, std::size_t S>
149  static void round(std::array<__m512i, S> &s,
150  const std::array<__m512i, Rounds> &rk, std::true_type)
151  {
153  }
154 
155  template <std::size_t N, std::size_t S>
156  MCKL_INLINE static void rbox(
157  std::array<__m512i, S> &s, const std::array<__m512i, Rounds> &rk)
158  {
159  rbox<N>(s, rk, std::integral_constant<bool, (N > 0 && N <= Rounds)>());
160  }
161 
162  template <std::size_t, std::size_t S>
163  static void rbox(std::array<__m512i, S> &,
164  const std::array<__m512i, Rounds> &, std::false_type)
165  {
166  }
167 
168  template <std::size_t N, std::size_t S>
169  static void rbox(std::array<__m512i, S> &s,
170  const std::array<__m512i, Rounds> &rk, std::true_type)
171  {
172  constexpr int mul0 =
173  static_cast<int>(Constants::multiplier::value[0 % (K / 2)]);
174  constexpr int mul1 =
175  static_cast<int>(Constants::multiplier::value[1 % (K / 2)]);
176  constexpr int mul2 =
177  static_cast<int>(Constants::multiplier::value[2 % (K / 2)]);
178  constexpr int mul3 =
179  static_cast<int>(Constants::multiplier::value[3 % (K / 2)]);
180  constexpr int mul4 =
181  static_cast<int>(Constants::multiplier::value[4 % (K / 2)]);
182  constexpr int mul5 =
183  static_cast<int>(Constants::multiplier::value[5 % (K / 2)]);
184  constexpr int mul6 =
185  static_cast<int>(Constants::multiplier::value[6 % (K / 2)]);
186  constexpr int mul7 =
187  static_cast<int>(Constants::multiplier::value[7 % (K / 2)]);
188  constexpr int mask = static_cast<int>(0xFFFFFFFF);
189 
190  const __m512i m = _mm512_set_epi32(0, mul7, 0, mul6, 0, mul5, 0, mul4,
191  0, mul3, 0, mul2, 0, mul1, 0, mul0);
192  const __m512i a = _mm512_set_epi32(mask, 0, mask, 0, mask, 0, mask, 0,
193  mask, 0, mask, 0, mask, 0, mask, 0);
194  const __m512i k = std::get<N - 1>(rk);
195 
196  std::array<__m512i, S> t;
197  mul_epu32(s, m, t);
198  and_si512(s, a);
199  xor_si512(s, k);
200  xor_si512(s, t);
201  permute<N>(s);
202  }
203 
204  MCKL_INLINE static std::array<__m512i, Rounds> round_key(
205  const std::array<T, K / 2> &k)
206  {
207  const int k0 = static_cast<int>(std::get<0 % (K / 2)>(k));
208  const int k1 = static_cast<int>(std::get<1 % (K / 2)>(k));
209  const int k2 = static_cast<int>(std::get<2 % (K / 2)>(k));
210  const int k3 = static_cast<int>(std::get<3 % (K / 2)>(k));
211  const int k4 = static_cast<int>(std::get<4 % (K / 2)>(k));
212  const int k5 = static_cast<int>(std::get<5 % (K / 2)>(k));
213  const int k6 = static_cast<int>(std::get<6 % (K / 2)>(k));
214  const int k7 = static_cast<int>(std::get<7 % (K / 2)>(k));
215 
216  std::array<__m512i, Rounds> rk;
217  set_key<0>(rk,
218  _mm512_set_epi32(
219  k7, 0, k6, 0, k5, 0, k4, 0, k3, 0, k2, 0, k1, 0, k0, 0),
220  std::true_type());
221 
222  return rk;
223  }
224 
225  template <std::size_t>
226  static void set_key(
227  std::array<__m512i, Rounds> &, const __m512i &, std::false_type)
228  {
229  }
230 
231  template <std::size_t N>
232  static void set_key(
233  std::array<__m512i, Rounds> &rk, const __m512i &k, std::true_type)
234  {
235  constexpr int w0 =
236  static_cast<int>(Constants::weyl::value[0 % (K / 2)] * N);
237  constexpr int w1 =
238  static_cast<int>(Constants::weyl::value[1 % (K / 2)] * N);
239  constexpr int w2 =
240  static_cast<int>(Constants::weyl::value[2 % (K / 2)] * N);
241  constexpr int w3 =
242  static_cast<int>(Constants::weyl::value[3 % (K / 2)] * N);
243  constexpr int w4 =
244  static_cast<int>(Constants::weyl::value[4 % (K / 2)] * N);
245  constexpr int w5 =
246  static_cast<int>(Constants::weyl::value[5 % (K / 2)] * N);
247  constexpr int w6 =
248  static_cast<int>(Constants::weyl::value[6 % (K / 2)] * N);
249  constexpr int w7 =
250  static_cast<int>(Constants::weyl::value[7 % (K / 2)] * N);
251 
252  std::get<N>(rk) = _mm512_add_epi32(k,
253  _mm512_set_epi32(
254  w7, 0, w6, 0, w5, 0, w4, 0, w3, 0, w2, 0, w1, 0, w0, 0));
255  set_key<N + 1>(rk, k, std::integral_constant<bool, N + 1 < Rounds>());
256  }
257 
258  template <std::size_t N, std::size_t S>
259  static void permute(std::array<__m512i, S> &s)
260  {
261  permute(s, std::integral_constant<bool, (N > 0 && N < Rounds)>());
262  }
263 
264  template <std::size_t S>
265  static void permute(std::array<__m512i, S> &, std::false_type)
266  {
267  }
268 
269  template <std::size_t S>
270  static void permute(std::array<__m512i, S> &s, std::true_type)
271  {
273  }
274 }; // class PhiloxGeneratorImplAVX512
275 
276 template <typename T, typename Constants>
277 class PhiloxGeneratorAVX512Impl32<T, 2, 10, Constants>
278  : public Philox2x32GeneratorAVX512Impl<T, Constants>
279 {
280 }; // class PhiloxGeneratorAVX512Impl32
281 
282 template <typename T, typename Constants>
283 class PhiloxGeneratorAVX512Impl32<T, 4, 10, Constants>
284  : public Philox4x32GeneratorAVX512Impl<T, Constants>
285 {
286 }; // class PhiloxGeneratorAVX512Impl32
287 
288 } // namespace internal
289 
290 } // namespace mckl
291 
293 
294 #endif // MCKL_RANDOM_INTERNAL_PHILOX_AVX512_32_HPP
#define MCKL_PUSH_GCC_WARNING(warning)
Definition: compiler.h:78
void increment_si512(std::array< T, K > &ctr, std::array< __m512i, S > &s, std::false_type)
void round(std::size_t n, const float *a, float *y)
Definition: vmf.hpp:310
#define MCKL_INLINE_CALL
Definition: intel.h:142
typename internal::CounterImpl< T, K >::type Counter
A counter type with the same width as std::array<T, K> but with possibly fewer elements.
Definition: increment.hpp:104
#define MCKL_RANDOM_INTERNAL_PHILOX_UNROLL_ROUND(N, s, rk)
static void eval(Counter< T, K > &ctr, ResultType *r, const std::array< T, K/2 > &key)
static void eval(Counter< T, K > &ctr, std::size_t n, ResultType *r, const std::array< T, K/2 > &key)
static void eval(const void *plain, void *cipher, const std::array< T, K/2 > &key)
Definition: mcmc.hpp:40
#define MCKL_ALIGNMENT
The default alignment for scalar type.
Definition: config.h:187
#define MCKL_INLINE
Definition: clang.h:147
#define MCKL_POP_GCC_WARNING
Definition: compiler.h:79