IMP logo
IMP Reference Guide  develop.cb469e0f11,2024/05/28
The Integrative Modeling Platform
random_utils.h
Go to the documentation of this file.
1 /**
2  * \file IMP/random_utils.h
3  * \brief Random number utility functions used by IMP.
4  *
5  * Copyright 2007-2022 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef IMPKERNEL_RANDOM_UTILS_H
10 #define IMPKERNEL_RANDOM_UTILS_H
11 
12 #include <IMP/kernel_config.h>
13 #include <IMP/Vector.h>
14 #include <IMP/random.h>
15 #ifdef IMP_KERNEL_CUDA_LIB
16 // #warning "random_utils - kernel CUDA_LIB!"
17 #include "IMP/internal/random_number_generation_cuda.h"
18 #else
19 // #warning "random_utils - kernel CUDA_BOOST!"
20 #include "IMP/internal/random_number_generation_boost.h"
21 #endif
22 
23 #include <boost/random/mersenne_twister.hpp>
24 #include <boost/random/uniform_real_distribution.hpp>
25 
26 // #include <ctime> // DEBUG
27 //#include <sys/time.h> // DEBUG
28 
29 IMPKERNEL_BEGIN_NAMESPACE
30 
31 //! Fill the double array with random normally distributed values.
32 /** The pre-allocated array is filled with n double numbers with
33  random normally distributed values with specified mean and
34  standard deviation.
35 
36  @param v vector array that will be resized to n
37  @param n size of array
38  @param mean mean of normal distribution
39  @param stddev standard deviation
40 
41  @note Implementation relies on random_number_generator (a boost
42  random number generator), or on the CUDA random number
43  generator if kernel is built with IMP_KERNEL_CUDA_LIB cmake
44  flag. Either is initially seeded with get_random_seed().
45 */
46 template<typename RealType>
48 (Vector<RealType>& v, unsigned int n,
49  RealType mean=0.0, RealType stddev=1.0)
50 {
51  if(n==0) return;
52  if(n>v.size())
53  v.resize(n);
54  // struct timeval start_time; // DEBUG
55  //struct timeval t_time; // DEBUG
56  //gettimeofday(&start_time, 0); // DEBUG
57 #ifdef IMP_KERNEL_CUDA_LIB
58  static unsigned last_seeded = 0;
59  IMPcuda::kernel::internal::init_gpu_rng_once(
60  random_number_generator.get_last_seed(),
61  random_number_generator.get_seed_counter(),
62  last_seeded);
63  IMPcuda::kernel::internal::get_random_numbers_normal_cuda
64  (&v[0], n, mean, stddev);
65 #else
66  internal::get_random_numbers_normal_boost(&v[0], n, mean, stddev);
67 #endif
68  // gettimeofday(&t_time, 0); // DEBUG
69  // double time_diff_sec= (double)( (t_time.tv_sec - start_time.tv_sec)
70  // + 0.000001 * (t_time.tv_usec - start_time.tv_usec) ); // DEBUG
71  // std::cout << "get_random_numbers_uniform_cuda(" << n
72  // << ") " << time_diff_sec << " seconds" << std::endl; // DEBUG
73 
74 }
75 
76 //! Fill the float array with random uniformly distributed values.
77 /** Fill a pre-allocated array of n float numbers with random uniformly
78  distributed values in the [0..1) range.
79 
80  @param v vector array that will be resized to n
81  @param n size of array
82 
83  @note Implementation relies on random_number_generator (a boost
84  random number generator), or on the CUDA random number generator
85  if kernel is built with CUDA flag. Either is initially seeded with
86  get_random_seed().
87  */
88 template<typename RealType>
90 (Vector<RealType>& v, unsigned int n)
91 {
92  if(n==0) return;
93  if(n>v.size())
94  v.resize(n);
95 #ifdef IMP_KERNEL_CUDA_LIB
96  static unsigned last_seeded = 0;
97  IMPcuda::kernel::internal::init_gpu_rng_once(
98  random_number_generator.get_last_seed(),
99  random_number_generator.get_seed_counter(),
100  last_seeded);
101  IMPcuda::kernel::internal::get_random_numbers_uniform_cuda (&v[0], n);
102 #else
103  internal::get_random_numbers_uniform_boost(&v[0], n);
104 #endif
105 }
106 
107 //! Return a uniformly distributed float number in range [0..1)
108 /** @note the random number is retrieved from a cache of random
109  numbers generated using GPU if compiled with CUDA, or from boost
110  without a cache otherwise.
111  */
113 
114 //! Return a uniformly distributed float number in range [min..max)
115 /** @note the random number is retrieved from a cache of random
116  numbers generated using GPU if compiled with CUDA, or from boost
117  without a cache otherwise.
118  */
119 float get_random_float_uniform(float min, float max);
120 
121 //! Return a uniformly distributed double number in range [0..1)
122 /** @note the random number is retrieved from a cache of random
123  numbers generated using GPU if compiled with CUDA, or from boost
124  without a cache otherwise.
125  */
127 
128 //! Return a uniformly distributed double number in range [min..max)
129 /** @note the random number is retrieved from a cache of random
130  numbers generated using GPU if compiled with CUDA, or from boost
131  without a cache otherwise.
132  */
133 double get_random_double_uniform(double min, double max);
134 
135 /************ implementation of inline functions *******/
136 
137 inline float
139 {
140  // use cache only with cuda
141 #ifdef IMP_KERNEL_CUDA_LIB
142  const static unsigned int cache_n=20000000;
143  static IMP::Vector<float> cache;
144  static unsigned int i=0;
145  static unsigned last_seeded = 0;
146  if (i >= cache.size()
147  || last_seeded != random_number_generator.get_seed_counter()) {
148  last_seeded = random_number_generator.get_seed_counter();
149  get_random_numbers_uniform(cache, cache_n);
150  i=0;
151  }
152  return cache[i++];
153 #else
154  static boost::random::uniform_real_distribution<float> rand(0.0, 1.0);
155  return rand(random_number_generator);
156 #endif
157 }
158 
159 inline float
160 get_random_float_uniform(float min, float max)
161 {
162  // use cache only with cuda
163 #ifdef IMP_KERNEL_CUDA_LIB
164  return get_random_float_uniform()*(max-min)+min;
165 #else
166  ::boost::random::uniform_real_distribution<float> rand(min, max);
167  return rand(random_number_generator);
168 #endif
169 }
170 
171 
172 inline double
174 {
175 #ifdef IMP_KERNEL_CUDA_LIB
176  const static unsigned int cache_n=2000000;
177  static IMP::Vector<double> cache;
178  static unsigned int i=0;
179  static unsigned last_seeded = 0;
180  if (i >= cache.size()
181  || last_seeded != random_number_generator.get_seed_counter()) {
182  last_seeded = random_number_generator.get_seed_counter();
183  get_random_numbers_uniform(cache, cache_n);
184  i=0;
185  }
186  return cache[i++];
187 #else
188  static boost::random::uniform_real_distribution<double> rand(0.0, 1.0);
189  return rand(random_number_generator);
190 #endif
191 }
192 
193 inline double
194 get_random_double_uniform(double min, double max)
195 {
196 #ifdef IMP_KERNEL_CUDA_LIB
197  return get_random_double_uniform()*(max-min)+min;
198 #else
199  ::boost::random::uniform_real_distribution<double> rand(min, max);
200  return rand(random_number_generator);
201 #endif
202 }
203 
204 
205 
206 IMPKERNEL_END_NAMESPACE
207 
208 #endif /* IMPKERNEL_RANDOM_UTILS_H */
void get_random_numbers_uniform(Vector< RealType > &v, unsigned int n)
Fill the float array with random uniformly distributed values.
Definition: random_utils.h:90
A more IMP-like version of the std::vector.
Definition: Vector.h:50
double get_random_double_uniform(double min, double max)
Return a uniformly distributed double number in range [min..max)
Definition: random_utils.h:194
float get_random_float_uniform(float min, float max)
Return a uniformly distributed float number in range [min..max)
Definition: random_utils.h:160
A class for storing lists of IMP items.
void get_random_numbers_normal(Vector< RealType > &v, unsigned int n, RealType mean=0.0, RealType stddev=1.0)
Fill the double array with random normally distributed values.
Definition: random_utils.h:48
Random number generators used by IMP.
RandomNumberGenerator random_number_generator
A shared non-GPU random number generator.