alpaka
Abstraction Library for Parallel Kernel Acceleration
PhiloxStateless.hpp
Go to the documentation of this file.
1 /* Copyright 2022 Jiri Vyskocil, Bernhard Manfred Gruber, Jeffrey Kelling
2  * SPDX-License-Identifier: MPL-2.0
3  */
4 
5 #pragma once
6 
7 #include "alpaka/core/Unroll.hpp"
10 #include "alpaka/vec/Vec.hpp"
11 
12 #include <utility>
13 
14 namespace alpaka::rand::engine
15 {
16  /** Philox algorithm parameters
17  *
18  * @tparam TCounterSize number of elements in the counter
19  * @tparam TWidth width of one counter element (in bits)
20  * @tparam TRounds number of S-box rounds
21  */
22  template<unsigned TCounterSize, unsigned TWidth, unsigned TRounds>
23  struct PhiloxParams
24  {
25  static constexpr unsigned counterSize = TCounterSize;
26  static constexpr unsigned width = TWidth;
27  static constexpr unsigned rounds = TRounds;
28  };
29 
30  /** Class basic Philox family counter-based PRNG
31  *
32  * Checks the validity of passed-in parameters and calls the backend methods to perform N rounds of the
33  * Philox shuffle.
34  *
35  * @tparam TParams Philox algorithm parameters \sa PhiloxParams
36  */
37  template<typename TParams>
38  class PhiloxStateless : public PhiloxConstants<TParams>
39  {
40  static constexpr unsigned numRounds()
41  {
42  return TParams::rounds;
43  }
44 
45  static constexpr unsigned vectorSize()
46  {
47  return TParams::counterSize;
48  }
49 
50  static constexpr unsigned numberWidth()
51  {
52  return TParams::width;
53  }
54 
55  static_assert(numRounds() > 0, "Number of Philox rounds must be > 0.");
56  static_assert(vectorSize() % 2 == 0, "Philox counter size must be an even number.");
57  static_assert(vectorSize() <= 16, "Philox SP network is not specified for sizes > 16.");
58  static_assert(numberWidth() % 8 == 0, "Philox number width in bits must be a multiple of 8.");
59 
60  static_assert(numberWidth() == 32, "Philox implemented only for 32 bit numbers.");
61 
62  public:
64  using Key = alpaka::Vec<alpaka::DimInt<TParams::counterSize / 2>, std::uint32_t>;
66 
67  protected:
68  /** Single round of the Philox shuffle
69  *
70  * @param counter state of the counter
71  * @param key value of the key
72  * @return shuffled counter
73  */
74  static ALPAKA_FN_HOST_ACC auto singleRound(Counter const& counter, Key const& key)
75  {
76  std::uint32_t H0, L0, H1, L1;
79  return Counter{H1 ^ counter[1] ^ key[0], L1, H0 ^ counter[3] ^ key[1], L0};
80  }
81 
82  /** Bump the \a key by the Weyl sequence step parameter
83  *
84  * @param key the key to be bumped
85  * @return the bumped key
86  */
87  static ALPAKA_FN_HOST_ACC auto bumpKey(Key const& key)
88  {
89  return Key{key[0] + Constants::WEYL_32_0(), key[1] + Constants::WEYL_32_1()};
90  }
91 
92  /** Performs N rounds of the Philox shuffle
93  *
94  * @param counter_in initial state of the counter
95  * @param key_in initial state of the key
96  * @return result of the PRNG shuffle; has the same size as the counter
97  */
98  static ALPAKA_FN_HOST_ACC auto nRounds(Counter const& counter_in, Key const& key_in) -> Counter
99  {
100  Key key{key_in};
101  Counter counter = singleRound(counter_in, key);
102 
103  ALPAKA_UNROLL(numRounds())
104  for(unsigned int n = 0; n < numRounds(); ++n)
105  {
106  key = bumpKey(key);
107  counter = singleRound(counter, key);
108  }
109 
110  return counter;
111  }
112 
113  public:
114  /** Generates a random number (\p TCounterSize x32-bit)
115  *
116  * @param counter initial state of the counter
117  * @param key initial state of the key
118  * @return result of the PRNG shuffle; has the same size as the counter
119  */
120  static ALPAKA_FN_HOST_ACC auto generate(Counter const& counter, Key const& key) -> Counter
121  {
122  return nRounds(counter, key);
123  }
124  };
125 } // namespace alpaka::rand::engine
#define ALPAKA_UNROLL(...)
Suggests unrolling of the directly following loop to the compiler.
Definition: Unroll.hpp:24
A n-dimensional vector.
Definition: Vec.hpp:38
static constexpr std::uint32_t WEYL_32_0()
1st Weyl sequence parameter, 32 bits
static constexpr std::uint32_t MULTIPLITER_4x32_1()
Second Philox S-box multiplier.
static constexpr std::uint32_t WEYL_32_1()
2nd Weyl sequence parameter, 32 bits
static constexpr std::uint32_t MULTIPLITER_4x32_0()
First Philox S-box multiplier.
static ALPAKA_FN_HOST_ACC auto generate(Counter const &counter, Key const &key) -> Counter
static ALPAKA_FN_HOST_ACC auto nRounds(Counter const &counter_in, Key const &key_in) -> Counter
static ALPAKA_FN_HOST_ACC auto bumpKey(Key const &key)
static ALPAKA_FN_HOST_ACC auto singleRound(Counter const &counter, Key const &key)
#define ALPAKA_FN_HOST_ACC
Definition: Common.hpp:39
The random number generator engine specifics.
constexpr ALPAKA_FN_HOST_ACC void multiplyAndSplit64to32(std::uint64_t const a, std::uint64_t const b, std::uint32_t &resultHigh, std::uint32_t &resultLow)
std::integral_constant< std::size_t, N > DimInt
static constexpr unsigned counterSize
static constexpr unsigned rounds
static constexpr unsigned width