Expression Templates Library (ETL)
normal.hpp
Go to the documentation of this file.
1 //=======================================================================
2 // Copyright (c) 2014-2023 Baptiste Wicht
3 // Distributed under the terms of the MIT License.
4 // (See accompanying file LICENSE or copy at
5 // http://opensource.org/licenses/MIT)
6 //=======================================================================
7 
13 #pragma once
14 
15 #ifdef ETL_CURAND_MODE
17 #endif
18 
19 #include <chrono> //for std::time
20 
21 namespace etl {
22 
26 template <typename T = double>
28  using value_type = T;
29 
30  const T mean;
31  const T stddev;
33  std::normal_distribution<value_type> distribution;
34 
38  static constexpr bool gpu_computable = (is_single_precision_t<T> && curand_enabled) || (is_double_precision_t<T> && curand_enabled);
39 
45  normal_generator_op(T mean, T stddev) : mean(mean), stddev(stddev), rand_engine(std::time(nullptr)), distribution(mean, stddev) {}
46 
52  return distribution(rand_engine);
53  }
54 
55 #ifdef ETL_CURAND_MODE
56 
63  template <typename Y>
64  auto gpu_compute_hint(Y& y) noexcept {
65  auto t1 = etl::force_temporary_gpu_dim_only_t<T>(y);
66 
67  curandGenerator_t gen;
68 
69  // Create the generator
70  curand_call(curandCreateGenerator(&gen, CURAND_RNG_PSEUDO_DEFAULT));
71 
72  // Seed it with the internal random engine
73  std::uniform_int_distribution<long> seed_dist;
74  curand_call(curandSetPseudoRandomGeneratorSeed(gen, seed_dist(rand_engine)));
75 
76  // Generate the random numbers
77  impl::curand::generate_normal(gen, t1.gpu_memory(), etl::size(y), mean, stddev);
78 
79  // Destroy the generator
80  curand_call(curandDestroyGenerator(gen));
81 
82  return t1;
83  }
84 
91  template <typename Y>
92  Y& gpu_compute(Y& y) noexcept {
93  y.ensure_gpu_allocated();
94 
95  curandGenerator_t gen;
96 
97  // Create the generator
98  curand_call(curandCreateGenerator(&gen, CURAND_RNG_PSEUDO_DEFAULT));
99 
100  // Seed it with the internal random engine
101  std::uniform_int_distribution<long> seed_dist;
102  curand_call(curandSetPseudoRandomGeneratorSeed(gen, seed_dist(rand_engine)));
103 
104  // Generate the random numbers
105  impl::curand::generate_normal(gen, y.gpu_memory(), etl::size(y), mean, stddev);
106 
107  // Destroy the generator
108  curand_call(curandDestroyGenerator(gen));
109 
110  y.validate_gpu();
111  y.invalidate_cpu();
112 
113  return y;
114  }
115 
116 #endif
117 
124  friend std::ostream& operator<<(std::ostream& os, [[maybe_unused]] const normal_generator_op& s) {
125  return os << "N(0,1)";
126  }
127 };
128 
132 template <typename G, typename T = double>
134  using value_type = T;
135 
136  const T mean;
137  const T stddev;
139  std::normal_distribution<value_type> distribution;
140 
144  static constexpr bool gpu_computable = (is_single_precision_t<T> && curand_enabled) || (is_double_precision_t<T> && curand_enabled);
145 
151  normal_generator_g_op(G& g, T mean, T stddev) : mean(mean), stddev(stddev), rand_engine(g), distribution(mean, stddev) {}
152 
158  return distribution(rand_engine);
159  }
160 
161 #ifdef ETL_CURAND_MODE
162 
169  template <typename Y>
170  auto gpu_compute_hint(Y& y) noexcept {
171  auto t1 = etl::force_temporary_gpu_dim_only_t<T>(y);
172 
173  curandGenerator_t gen;
174 
175  // Create the generator
176  curand_call(curandCreateGenerator(&gen, CURAND_RNG_PSEUDO_DEFAULT));
177 
178  // Seed it with the internal random engine
179  std::uniform_int_distribution<long> seed_dist;
180  curand_call(curandSetPseudoRandomGeneratorSeed(gen, seed_dist(rand_engine)));
181 
182  // Generate the random numbers
183  impl::curand::generate_normal(gen, t1.gpu_memory(), etl::size(y), mean, stddev);
184 
185  return t1;
186  }
187 
194  template <typename Y>
195  Y& gpu_compute(Y& y) noexcept {
196  y.ensure_gpu_allocated();
197 
198  curandGenerator_t gen;
199 
200  // Create the generator
201  curand_call(curandCreateGenerator(&gen, CURAND_RNG_PSEUDO_DEFAULT));
202 
203  // Seed it with the internal random engine
204  std::uniform_int_distribution<long> seed_dist;
205  curand_call(curandSetPseudoRandomGeneratorSeed(gen, seed_dist(rand_engine)));
206 
207  // Generate the random numbers
208  impl::curand::generate_normal(gen, y.gpu_memory(), etl::size(y), mean, stddev);
209 
210  y.validate_gpu();
211  y.invalidate_cpu();
212 
213  return y;
214  }
215 
216 #endif
217 
224  friend std::ostream& operator<<(std::ostream& os, [[maybe_unused]] const normal_generator_g_op& s) {
225  return os << "N(0,1)";
226  }
227 };
228 
229 } //end of namespace etl
Generator from a normal distribution using a custom random engine.
Definition: normal.hpp:133
std::normal_distribution< value_type > distribution
The used distribution.
Definition: normal.hpp:139
auto s(T &&value)
Force the evaluation of the given expression.
Definition: stop.hpp:18
value_type operator()()
Generate a new value.
Definition: normal.hpp:51
T value_type
The value type.
Definition: normal.hpp:28
const T stddev
The standard deviation.
Definition: normal.hpp:31
normal_generator_op(T mean, T stddev)
Construct a new generator with the given mean and standard deviation.
Definition: normal.hpp:45
constexpr bool curand_enabled
Indicates if the NVIDIA CURAND library is available for ETL.
Definition: config.hpp:109
Root namespace for the ETL library.
Definition: adapter.hpp:15
static constexpr bool gpu_computable
Indicates if the operator can be computed on GPU.
Definition: normal.hpp:38
friend std::ostream & operator<<(std::ostream &os, [[maybe_unused]] const normal_generator_g_op &s)
Outputs the given generator to the given stream.
Definition: normal.hpp:224
random_engine rand_engine
The random engine.
Definition: normal.hpp:32
G & rand_engine
The random engine.
Definition: normal.hpp:138
const T stddev
The standard deviation.
Definition: normal.hpp:137
friend std::ostream & operator<<(std::ostream &os, [[maybe_unused]] const normal_generator_op &s)
Outputs the given generator to the given stream.
Definition: normal.hpp:124
value_type operator()()
Generate a new value.
Definition: normal.hpp:157
constexpr size_t size(const E &expr) noexcept
Returns the size of the given ETL expression.
Definition: helpers.hpp:108
T value_type
The value type.
Definition: normal.hpp:134
normal_generator_g_op(G &g, T mean, T stddev)
Construct a new generator with the given mean and standard deviation.
Definition: normal.hpp:151
const T mean
The mean.
Definition: normal.hpp:136
std::mt19937_64 random_engine
The random engine used by the library.
Definition: random.hpp:22
Utility functions for curand.
const auto & gpu_compute_hint([[maybe_unused]] Y &y) const
Return a GPU computed version of this expression.
Definition: sub_view.hpp:653
Generator from a normal distribution.
Definition: normal.hpp:27
const T mean
The mean.
Definition: normal.hpp:30
std::normal_distribution< value_type > distribution
The used distribution.
Definition: normal.hpp:33