MCKL
Monte Carlo Kernel Library
philox_avx2_2x32.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/philox_avx2_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_AVX2_2X32_HPP
33 #define MCKL_RANDOM_INTERNAL_PHILOX_AVX2_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  "**Philox2x32GeneratorAVX2Impl** 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_avx2_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(__m256i) * S / (sizeof(T) * K);
108 
109  const int k0 = static_cast<int>(std::get<0>(key));
110  const __m256i ymmk0 = _mm256_set_epi32(k0, 0, k0, 0, k0, 0, k0, 0);
111 
112  __m256i ymmc =
113  _mm256_set1_epi64x(static_cast<MCKL_INT64>(std::get<0>(ctr)));
114  ctr.front() += n;
115 
116  __m256i *rptr = reinterpret_cast<__m256i *>(r);
117  while (n != 0) {
118  __m256i ymm0 = _mm256_add_epi64(
119  ymmc, _mm256_set_epi64x(0x04, 0x03, 0x02, 0x01));
120  __m256i ymm1 = _mm256_add_epi64(
121  ymmc, _mm256_set_epi64x(0x08, 0x07, 0x06, 0x05));
122  __m256i ymm2 = _mm256_add_epi64(
123  ymmc, _mm256_set_epi64x(0x0C, 0x0B, 0x0A, 0x09));
124  __m256i ymm3 = _mm256_add_epi64(
125  ymmc, _mm256_set_epi64x(0x10, 0x0F, 0x0E, 0x0D));
126  __m256i ymm4 = _mm256_add_epi64(
127  ymmc, _mm256_set_epi64x(0x14, 0x13, 0x12, 0x11));
128  __m256i ymm5 = _mm256_add_epi64(
129  ymmc, _mm256_set_epi64x(0x18, 0x17, 0x16, 0x15));
130  __m256i ymm6 = _mm256_add_epi64(
131  ymmc, _mm256_set_epi64x(0x1C, 0x1B, 0x1A, 0x19));
132  __m256i ymm7 = _mm256_add_epi64(
133  ymmc, _mm256_set_epi64x(0x20, 0x1F, 0x1E, 0x1D));
134  ymmc = _mm256_add_epi64(ymmc, _mm256_set1_epi64x(0x20));
135 
146 
147  if (n >= N) {
148  n -= N;
149  _mm256_storeu_si256(rptr++, ymm0);
150  _mm256_storeu_si256(rptr++, ymm1);
151  _mm256_storeu_si256(rptr++, ymm2);
152  _mm256_storeu_si256(rptr++, ymm3);
153  _mm256_storeu_si256(rptr++, ymm4);
154  _mm256_storeu_si256(rptr++, ymm5);
155  _mm256_storeu_si256(rptr++, ymm6);
156  _mm256_storeu_si256(rptr++, ymm7);
157  } else {
158  std::array<__m256i, S> s;
159  std::get<0>(s) = ymm0;
160  std::get<1>(s) = ymm1;
161  std::get<2>(s) = ymm2;
162  std::get<3>(s) = ymm3;
163  std::get<4>(s) = ymm4;
164  std::get<5>(s) = ymm5;
165  std::get<6>(s) = ymm6;
166  std::get<7>(s) = ymm7;
167  std::memcpy(rptr, s.data(), n * sizeof(T) * K);
168  break;
169  }
170  }
171 #endif // MCKL_USE_ASM_LIBRARY
172  }
173 }; // class Philox2x32GeneratorAVX2Impl
174 
175 } // namespace internal
176 
177 } // namespace mckl
178 
180 
181 #endif // MCKL_RANDOM_INTERNAL_PHILOX_AVX2_2X32_HPP
static void eval(const void *plain, void *cipher, const std::array< T, K/2 > &key)
#define MCKL_PUSH_GCC_WARNING(warning)
Definition: compiler.h:78
#define MCKL_RANDOM_INTERNAL_PHILOX_AVX2_32_RBOX(K, N, imm8)
void mckl_philox2x32_avx2_kernel(uint64_t *, size_t, void *, const void *)
static void eval(std::array< std::uint64_t, 1 > &ctr, std::size_t n, ResultType *r, const std::array< T, K/2 > &key)
static void eval(std::array< std::uint64_t, 1 > &ctr, ResultType *r, const std::array< T, K/2 > &key)
Definition: mcmc.hpp:40
#define MCKL_POP_GCC_WARNING
Definition: compiler.h:79