MCKL
Monte Carlo Kernel Library
philox_avx512_4x32.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/philox_avx512_4x32.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_4X32_HPP
33 #define MCKL_RANDOM_INTERNAL_PHILOX_AVX512_4X32_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  "**Philox4x32GeneratorAVX512Impl** used with T other than a 32-bit "
52  "unsigned integers");
53 
54  static constexpr std::size_t K = 4;
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, 2> &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, 2> &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, 2> &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 m1 = Constants::multiplier::value[1];
102  constexpr T w0 = Constants::weyl::value[0];
103  constexpr T w1 = Constants::weyl::value[1];
104 
105  const T mwk[12] = {m0, 0, m1, 0, 0, w0, 0, w1, 0, std::get<0>(key), 0,
106  std::get<1>(key)};
107  mckl_philox4x32_avx512_kernel(ctr.data(), n, r, mwk);
108 #else // MCKL_USE_ASM_LIBRARY
109  constexpr std::size_t S = 8;
110  constexpr std::size_t N = sizeof(__m512i) * S / (sizeof(T) * K);
111 
112  const int k0 = static_cast<int>(std::get<0>(key));
113  const int k1 = static_cast<int>(std::get<1>(key));
114  const __m512i ymmk0 = _mm512_set_epi32(
115  k1, 0, k0, 0, k1, 0, k0, 0, k1, 0, k0, 0, k1, 0, k0, 0);
116 
117  __m512i ymmc =
118  _mm512_set_epi64(static_cast<MCKL_INT64>(std::get<1>(ctr)),
119  static_cast<MCKL_INT64>(std::get<0>(ctr)),
120  static_cast<MCKL_INT64>(std::get<1>(ctr)),
121  static_cast<MCKL_INT64>(std::get<0>(ctr)),
122  static_cast<MCKL_INT64>(std::get<1>(ctr)),
123  static_cast<MCKL_INT64>(std::get<0>(ctr)),
124  static_cast<MCKL_INT64>(std::get<1>(ctr)),
125  static_cast<MCKL_INT64>(std::get<0>(ctr)));
126  ctr.front() += n;
127 
128  __m512i *rptr = reinterpret_cast<__m512i *>(r);
129  while (n != 0) {
130  __m512i ymm0 = _mm512_add_epi64(
131  ymmc, _mm512_set_epi64(0, 0x04, 0, 0x03, 0, 0x02, 0, 0x01));
132  __m512i ymm1 = _mm512_add_epi64(
133  ymmc, _mm512_set_epi64(0, 0x08, 0, 0x07, 0, 0x06, 0, 0x05));
134  __m512i ymm2 = _mm512_add_epi64(
135  ymmc, _mm512_set_epi64(0, 0x0C, 0, 0x0B, 0, 0x0A, 0, 0x09));
136  __m512i ymm3 = _mm512_add_epi64(
137  ymmc, _mm512_set_epi64(0, 0x10, 0, 0x0F, 0, 0x0E, 0, 0x0D));
138  __m512i ymm4 = _mm512_add_epi64(
139  ymmc, _mm512_set_epi64(0, 0x14, 0, 0x13, 0, 0x12, 0, 0x11));
140  __m512i ymm5 = _mm512_add_epi64(
141  ymmc, _mm512_set_epi64(0, 0x18, 0, 0x17, 0, 0x16, 0, 0x15));
142  __m512i ymm6 = _mm512_add_epi64(
143  ymmc, _mm512_set_epi64(0, 0x1C, 0, 0x1B, 0, 0x1A, 0, 0x19));
144  __m512i ymm7 = _mm512_add_epi64(
145  ymmc, _mm512_set_epi64(0, 0x20, 0, 0x1F, 0, 0x1E, 0, 0x1D));
146  ymmc = _mm512_add_epi64(
147  ymmc, _mm512_set_epi64(0, 0x20, 0, 0x20, 0, 0x20, 0, 0x20));
148 
149  ymm0 = _mm512_shuffle_epi32(ymm0, 0xC6);
150  ymm1 = _mm512_shuffle_epi32(ymm1, 0xC6);
151  ymm2 = _mm512_shuffle_epi32(ymm2, 0xC6);
152  ymm3 = _mm512_shuffle_epi32(ymm3, 0xC6);
153  ymm4 = _mm512_shuffle_epi32(ymm4, 0xC6);
154  ymm5 = _mm512_shuffle_epi32(ymm5, 0xC6);
155  ymm6 = _mm512_shuffle_epi32(ymm6, 0xC6);
156  ymm7 = _mm512_shuffle_epi32(ymm7, 0xC6);
157 
168 
169  if (n >= N) {
170  n -= N;
171  _mm512_storeu_si512(rptr++, ymm0);
172  _mm512_storeu_si512(rptr++, ymm1);
173  _mm512_storeu_si512(rptr++, ymm2);
174  _mm512_storeu_si512(rptr++, ymm3);
175  _mm512_storeu_si512(rptr++, ymm4);
176  _mm512_storeu_si512(rptr++, ymm5);
177  _mm512_storeu_si512(rptr++, ymm6);
178  _mm512_storeu_si512(rptr++, ymm7);
179  } else {
180  std::array<__m512i, S> s;
181  std::get<0>(s) = ymm0;
182  std::get<1>(s) = ymm1;
183  std::get<2>(s) = ymm2;
184  std::get<3>(s) = ymm3;
185  std::get<4>(s) = ymm4;
186  std::get<5>(s) = ymm5;
187  std::get<6>(s) = ymm6;
188  std::get<7>(s) = ymm7;
189  std::memcpy(rptr, s.data(), n * sizeof(T) * K);
190  break;
191  }
192  }
193 #endif // MCKL_USE_ASM_LIBRARY
194  }
195 }; // class Philox4x32GeneratorAVX512Impl
196 
197 } // namespace internal
198 
199 } // namespace mckl
200 
202 
203 #endif // MCKL_RANDOM_INTERNAL_PHILOX_AVX512_4X32_HPP
void mckl_philox4x32_avx512_kernel(uint64_t *, size_t, void *, const void *)
#define MCKL_PUSH_GCC_WARNING(warning)
Definition: compiler.h:78
#define MCKL_RANDOM_INTERNAL_PHILOX_AVX512_32_RBOX(K, N, imm8)
static void eval(std::array< std::uint64_t, 2 > &ctr, std::size_t n, ResultType *r, const std::array< T, K/2 > &key)
static void eval(std::array< std::uint64_t, 2 > &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