NEURON
nrnran123.h
Go to the documentation of this file.
1 /*
2 # =============================================================================
3 # Copyright (c) 2016 - 2022 Blue Brain Project/EPFL
4 #
5 # See top-level LICENSE file for details.
6 # =============================================================================.
7 */
8 #pragma once
9 
10 /* interface to Random123 */
11 /* http://www.thesalmons.org/john/random123/papers/random123sc11.pdf */
12 
13 /*
14 The 4x32 generators utilize a uint32x4 counter and uint32x4 key to transform
15 into an almost cryptographic quality uint32x4 random result.
16 There are many possibilites for balancing the sharing of the internal
17 state instances while reserving a uint32 counter for the stream sequence
18 and reserving other portions of the counter vector for stream identifiers
19 and global index used by all streams.
20 
21 We currently provide a single instance by default in which the policy is
22 to use the 0th counter uint32 as the stream sequence, words 2 and 3 as the
23 stream identifier, and word 0 of the key as the global index. Unused words
24 are constant uint32 0.
25 
26 It is also possible to use Random123 directly without reference to this
27 interface. See Random123-1.02/docs/html/index.html
28 of the full distribution available from
29 http://www.deshawresearch.com/resources_random123.html
30 */
31 
32 #ifdef __bgclang__
33 #define R123_USE_MULHILO64_MULHI_INTRIN 0
34 #define R123_USE_GNU_UINT128 1
35 #endif
36 
38 
39 #include <Random123/philox.h>
40 #include <inttypes.h>
41 
42 #include <cmath>
43 
44 #if defined(CORENEURON_ENABLE_GPU)
45 #define CORENRN_RAN123_USE_UNIFIED_MEMORY true
46 #else
47 #define CORENRN_RAN123_USE_UNIFIED_MEMORY false
48 #endif
49 
50 namespace coreneuron {
51 
53  philox4x32_ctr_t c;
54  philox4x32_ctr_t r;
55  char which_;
56 };
57 
58 } // namespace coreneuron
59 
60 /** @brief Provide a helper function in global namespace that is declared target for OpenMP
61  * offloading to function correctly with NVHPC
62  */
63 nrn_pragma_acc(routine seq)
64 nrn_pragma_omp(declare target)
67 
68 namespace coreneuron {
71 
72 /* global index. eg. run number */
73 /* all generator instances share this global index */
74 void nrnran123_set_globalindex(uint32_t gix);
75 uint32_t nrnran123_get_globalindex();
76 
77 // Utilities used for calculating model size, only called from the CPU.
78 std::size_t nrnran123_instance_count();
79 inline std::size_t nrnran123_state_size() {
80  return sizeof(nrnran123_State);
81 }
82 
83 /* routines for creating and deleting streams are called from cpu */
85  uint32_t id2,
86  uint32_t id3,
87  bool use_unified_memory = CORENRN_RAN123_USE_UNIFIED_MEMORY);
89  uint32_t id1,
90  uint32_t id2,
91  bool use_unified_memory = CORENRN_RAN123_USE_UNIFIED_MEMORY) {
92  return nrnran123_newstream3(id1, id2, 0, use_unified_memory);
93 }
95  bool use_unified_memory = CORENRN_RAN123_USE_UNIFIED_MEMORY);
96 
97 /* minimal data stream */
98 constexpr void nrnran123_getseq(nrnran123_State* s, uint32_t* seq, char* which) {
99  *seq = s->c.v[0];
100  *which = s->which_;
101 }
102 constexpr void nrnran123_getids(nrnran123_State* s, uint32_t* id1, uint32_t* id2) {
103  *id1 = s->c.v[2];
104  *id2 = s->c.v[3];
105 }
106 constexpr void nrnran123_getids3(nrnran123_State* s, uint32_t* id1, uint32_t* id2, uint32_t* id3) {
107  *id3 = s->c.v[1];
108  *id1 = s->c.v[2];
109  *id2 = s->c.v[3];
110 }
111 
112 // Uniform 0 to 2*32-1
113 inline uint32_t nrnran123_ipick(nrnran123_State* s) {
114  char which = s->which_;
115  uint32_t rval{s->r.v[int{which++}]};
116  if (which > 3) {
117  which = 0;
118  s->c.v[0]++;
120  }
121  s->which_ = which;
122  return rval;
123 }
124 
125 constexpr double nrnran123_uint2dbl(uint32_t u) {
126  constexpr double SHIFT32 = 1.0 / 4294967297.0; /* 1/(2^32 + 1) */
127  /* 0 to 2^32-1 transforms to double value in open (0,1) interval */
128  /* min 2.3283064e-10 to max (1 - 2.3283064e-10) */
129  return (static_cast<double>(u) + 1.0) * SHIFT32;
130 }
131 
132 // Uniform open interval (0,1), minimum value is 2.3283064e-10 and max value is 1-min
133 inline double nrnran123_dblpick(nrnran123_State* s) {
134  return nrnran123_uint2dbl(nrnran123_ipick(s));
135 }
136 
137 // same as dblpick
138 inline double nrnran123_uniform(nrnran123_State* s) {
139  return nrnran123_uint2dbl(nrnran123_ipick(s));
140 }
141 
142 inline double nrnran123_uniform(nrnran123_State* s, double low, double high) {
143  return low + nrnran123_uint2dbl(nrnran123_ipick(s)) * (high - low);
144 }
145 
146 /* this could be called from openacc parallel construct (in INITIAL block) */
147 inline void nrnran123_setseq(nrnran123_State* s, uint32_t seq, char which) {
148  if (which > 3) {
149  s->which_ = 0;
150  } else {
151  s->which_ = which;
152  }
153  s->c.v[0] = seq;
155 }
156 
157 /* this could be called from openacc parallel construct (in INITIAL block) */
158 inline void nrnran123_setseq(nrnran123_State* s, double seq34) {
159  if (seq34 < 0.0) {
160  seq34 = 0.0;
161  }
162  if (seq34 > double(0XffffffffffLL)) {
163  seq34 = 0.0;
164  }
165 
166  // at least 64 bits even on 32 bit machine (could be more)
167  unsigned long long x = ((unsigned long long) seq34) & 0X3ffffffffLL;
168  char which = x & 0X3;
169  uint32_t seq = x >> 2;
170  nrnran123_setseq(s, seq, which);
171 }
172 
173 // nrnran123_negexp min value is 2.3283064e-10, max is 22.18071, mean 1.0
174 inline double nrnran123_negexp(nrnran123_State* s) {
175  return -std::log(nrnran123_dblpick(s));
176 }
177 
178 /* at cost of a cached value we could compute two at a time. */
179 inline double nrnran123_normal(nrnran123_State* s) {
180  double w, u1;
181  do {
182  u1 = nrnran123_dblpick(s);
183  double u2{nrnran123_dblpick(s)};
184  u1 = 2. * u1 - 1.;
185  u2 = 2. * u2 - 1.;
186  w = (u1 * u1) + (u2 * u2);
187  } while (w > 1);
188  double y{std::sqrt((-2. * std::log(w)) / w)};
189  return u1 * y;
190 }
191 
192 // nrnran123_gauss, nrnran123_iran were declared but not defined in CoreNEURON
193 // nrnran123_array4x32 was declared but not used in CoreNEURON
194 } // namespace coreneuron
CORENRN_HOST_DEVICE philox4x32_ctr_t coreneuron_random123_philox4x32_helper(coreneuron::nrnran123_State *s)
Definition: nrnran123.cpp:102
#define CORENRN_RAN123_USE_UNIFIED_MEMORY
Definition: nrnran123.h:47
nrn_pragma_acc(routine seq) nrn_pragma_omp(declare target) philox4x32_ctr_t coreneuron_random123_philox4x32_helper(coreneuron nrn_pragma_omp(end declare target) namespace coreneuron
Provide a helper function in global namespace that is declared target for OpenMP offloading to functi...
Definition: nrnran123.h:66
void declare(long subtype, Item *q, Item *qa)
Definition: declare.cpp:17
void nrnran123_getids3(nrnran123_State *, std::uint32_t *id1, std::uint32_t *id2, std::uint32_t *id3)
Definition: nrnran123.cpp:97
void nrnran123_getids(nrnran123_State *s, std::uint32_t *id1, std::uint32_t *id2)
Get stream IDs from Random123 State object.
Definition: nrnran123.cpp:82
double nrnran123_uniform(nrnran123_State *)
Definition: nrnran123.cpp:128
double nrnran123_normal(nrnran123_State *)
Definition: nrnran123.cpp:148
double nrnran123_dblpick(nrnran123_State *)
Definition: nrnran123.cpp:122
nrnran123_State * nrnran123_newstream(std::uint32_t id1, std::uint32_t id2=0, std::uint32_t id3=0)
Construct a new Random123 stream based on the philox4x32 generator.
Definition: nrnran123.cpp:37
void nrnran123_setseq(nrnran123_State *s, std::uint32_t seq, char which)
Set a Random123 sequence for a sequnece ID and which selector.
Definition: nrnran123.cpp:55
std::uint32_t nrnran123_ipick(nrnran123_State *)
Definition: nrnran123.cpp:110
double nrnran123_negexp(nrnran123_State *)
Definition: nrnran123.cpp:141
void nrnran123_getseq(nrnran123_State *s, std::uint32_t *seq, char *which)
Get sequence number and selector from an nrnran123_State object.
Definition: nrnran123.cpp:50
static const double SHIFT32
Definition: mcran4.cpp:116
sqrt
Definition: extdef.h:3
log
Definition: extdef.h:4
THIS FILE IS AUTO GENERATED DONT MODIFY IT.
nrnran123_State * nrnran123_newstream3(uint32_t id1, uint32_t id2, uint32_t id3, bool use_unified_memory)
Allocate a new Random123 stream.
Definition: nrnran123.cpp:172
void nrnran123_set_globalindex(uint32_t gix)
Definition: nrnran123.cpp:117
void nrnran123_deletestream(nrnran123_State *s, bool use_unified_memory)
Definition: nrnran123.cpp:205
void nrnran123_destroy_global_state_on_device()
Definition: nrnran123.cpp:158
std::size_t nrnran123_instance_count()
Definition: nrnran123.cpp:107
void nrnran123_initialise_global_state_on_device()
Definition: nrnran123.cpp:150
uint32_t nrnran123_get_globalindex()
Definition: nrnran123.cpp:112
s
Definition: multisend.cpp:521
#define nrn_pragma_acc(x)
Definition: offload.hpp:20
philox4x32_ctr_t r
Definition: nrnran123.h:54
philox4x32_ctr_t c
Definition: nrnran123.h:53