MCKL
Monte Carlo Kernel Library
philox_avx2_32.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/philox_avx2_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_AVX2_32_HPP
33 #define MCKL_RANDOM_INTERNAL_PHILOX_AVX2_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<__m256i, S> &)
58  {
59  }
60 
61  template <std::size_t S>
62  MCKL_INLINE static void round(std::array<__m256i, S> &s)
63  {
64  shuffle_epi32<0xB1>(s);
65  }
66 
67  template <std::size_t S>
68  MCKL_INLINE static void last(std::array<__m256i, S> &s)
69  {
70  shuffle_epi32<0xB1>(s);
71  }
72 }; // class PhiloxGeneratorAVX2Impl32Permute
73 
74 template <>
76 {
77  public:
78  template <std::size_t S>
79  MCKL_INLINE static void first(std::array<__m256i, S> &s)
80  {
81  shuffle_epi32<0xC6>(s);
82  }
83 
84  template <std::size_t S>
85  MCKL_INLINE static void round(std::array<__m256i, S> &s)
86  {
87  shuffle_epi32<0x93>(s);
88  }
89 
90  template <std::size_t S>
91  MCKL_INLINE static void last(std::array<__m256i, S> &s)
92  {
93  shuffle_epi32<0xB1>(s);
94  }
95 }; // class PhiloxGeneratorAVX2Impl32Permute
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(__m256i) * S / (sizeof(T) * K);
121  constexpr std::size_t R = sizeof(T) * K / sizeof(ResultType);
122 
123  const std::array<__m256i, Rounds> rk(round_key(key));
124  while (n >= N) {
125  std::array<__m256i, 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<__m256i, S> &,
144  const std::array<__m256i, Rounds> &, std::false_type)
145  {
146  }
147 
148  template <std::size_t N, std::size_t S>
149  static void round(std::array<__m256i, S> &s,
150  const std::array<__m256i, 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<__m256i, S> &s, const std::array<__m256i, 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<__m256i, S> &,
164  const std::array<__m256i, Rounds> &, std::false_type)
165  {
166  }
167 
168  template <std::size_t N, std::size_t S>
169  static void rbox(std::array<__m256i, S> &s,
170  const std::array<__m256i, 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 mask = static_cast<int>(0xFFFFFFFF);
181 
182  const __m256i m = _mm256_set_epi32(0, mul3, 0, mul2, 0, mul1, 0, mul0);
183  const __m256i a = _mm256_set_epi32(mask, 0, mask, 0, mask, 0, mask, 0);
184  const __m256i k = std::get<N - 1>(rk);
185 
186  std::array<__m256i, S> t;
187  mul_epu32(s, m, t);
188  and_si256(s, a);
189  xor_si256(s, k);
190  xor_si256(s, t);
191  permute<N>(s);
192  }
193 
194  MCKL_INLINE static std::array<__m256i, Rounds> round_key(
195  const std::array<T, K / 2> &k)
196  {
197  const int k0 = static_cast<int>(std::get<0 % (K / 2)>(k));
198  const int k1 = static_cast<int>(std::get<1 % (K / 2)>(k));
199  const int k2 = static_cast<int>(std::get<2 % (K / 2)>(k));
200  const int k3 = static_cast<int>(std::get<3 % (K / 2)>(k));
201 
202  std::array<__m256i, Rounds> rk;
203  set_key<0>(rk, _mm256_set_epi32(k3, 0, k2, 0, k1, 0, k0, 0),
204  std::true_type());
205 
206  return rk;
207  }
208 
209  template <std::size_t>
210  static void set_key(
211  std::array<__m256i, Rounds> &, const __m256i &, std::false_type)
212  {
213  }
214 
215  template <std::size_t N>
216  static void set_key(
217  std::array<__m256i, Rounds> &rk, const __m256i &k, std::true_type)
218  {
219  constexpr int w0 =
220  static_cast<int>(Constants::weyl::value[0 % (K / 2)] * N);
221  constexpr int w1 =
222  static_cast<int>(Constants::weyl::value[1 % (K / 2)] * N);
223  constexpr int w2 =
224  static_cast<int>(Constants::weyl::value[2 % (K / 2)] * N);
225  constexpr int w3 =
226  static_cast<int>(Constants::weyl::value[3 % (K / 2)] * N);
227 
228  std::get<N>(rk) =
229  _mm256_add_epi32(k, _mm256_set_epi32(w3, 0, w2, 0, w1, 0, w0, 0));
230  set_key<N + 1>(rk, k, std::integral_constant<bool, N + 1 < Rounds>());
231  }
232 
233  template <std::size_t N, std::size_t S>
234  static void permute(std::array<__m256i, S> &s)
235  {
236  permute(s, std::integral_constant<bool, (N > 0 && N < Rounds)>());
237  }
238 
239  template <std::size_t S>
240  static void permute(std::array<__m256i, S> &, std::false_type)
241  {
242  }
243 
244  template <std::size_t S>
245  static void permute(std::array<__m256i, S> &s, std::true_type)
246  {
248  }
249 }; // class PhiloxGeneratorImplAVX2
250 
251 template <typename T, typename Constants>
252 class PhiloxGeneratorAVX2Impl32<T, 2, 10, Constants>
253  : public Philox2x32GeneratorAVX2Impl<T, Constants>
254 {
255 }; // class PhiloxGeneratorAVX2Impl32
256 
257 template <typename T, typename Constants>
258 class PhiloxGeneratorAVX2Impl32<T, 4, 10, Constants>
259  : public Philox4x32GeneratorAVX2Impl<T, Constants>
260 {
261 }; // class PhiloxGeneratorAVX2Impl32
262 
263 } // namespace internal
264 
265 } // namespace mckl
266 
268 
269 #endif // MCKL_RANDOM_INTERNAL_PHILOX_AVX2_32_HPP
#define MCKL_PUSH_GCC_WARNING(warning)
Definition: compiler.h:78
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(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
static void eval(Counter< T, K > &ctr, std::size_t n, ResultType *r, const std::array< T, K/2 > &key)
static void eval(Counter< T, K > &ctr, ResultType *r, const std::array< T, K/2 > &key)
#define MCKL_INLINE
Definition: clang.h:147
#define MCKL_POP_GCC_WARNING
Definition: compiler.h:79
void increment_si256(std::array< T, K > &ctr, std::array< __m256i, S > &s, std::false_type)