Branch data Line data Source code
1 : : // *****************************************************************************
2 : : /*!
3 : : \file src/RNG/RNGStack.cpp
4 : : \copyright 2012-2015 J. Bakosi,
5 : : 2016-2018 Los Alamos National Security, LLC.,
6 : : 2019-2021 Triad National Security, LLC.
7 : : All rights reserved. See the LICENSE file for details.
8 : : \brief Stack of random number generators
9 : : \details This file defines class RNGStack, which implements various
10 : : functionality related to registering and instantiating random number
11 : : generators interfacing to multiple RNG libraries. Registration and
12 : : instantiation use a random number generator factory, which is a std::map (an
13 : : associative container), associating unique RNG keys to their constructor
14 : : calls. For more details, see the in-code documentation of the constructor.
15 : : */
16 : : // *****************************************************************************
17 : :
18 : : #include <iterator>
19 : : #include <utility>
20 : :
21 : : #include "NoWarning/charm.hpp"
22 : : #include "NoWarning/threefry.hpp"
23 : : #include "NoWarning/philox.hpp"
24 : :
25 : : #include "Tags.hpp"
26 : : #include "Factory.hpp"
27 : : #include "Exception.hpp"
28 : : #include "RNGStack.hpp"
29 : : #include "RNGSSE.hpp"
30 : : #include "Options/RNGSSESeqLen.hpp"
31 : : #include "Random123.hpp"
32 : : #include "WalkerBuildConfig.hpp"
33 : :
34 : : #ifdef HAS_RNGSSE2
35 : : #include <gm19.h>
36 : : #include <gm29.h>
37 : : #include <gm31.h>
38 : : #include <gm55.h>
39 : : #include <gm61.h>
40 : : #include <gq58x1.h>
41 : : #include <gq58x3.h>
42 : : #include <gq58x4.h>
43 : : #include <mt19937.h>
44 : : #include <lfsr113.h>
45 : : #include <mrg32k3a.h>
46 : : #endif
47 : :
48 : : #ifdef HAS_MKL
49 : : #include "MKLRNG.hpp"
50 : : #include "Options/MKLBetaMethod.hpp"
51 : : #include "Options/MKLGammaMethod.hpp"
52 : : #include "Options/MKLGaussianMethod.hpp"
53 : : #include "Options/MKLGaussianMVMethod.hpp"
54 : : #include "Options/MKLUniformMethod.hpp"
55 : : #endif
56 : :
57 : : using tk::RNGStack;
58 : :
59 : 297 : RNGStack::RNGStack(
60 : : #ifdef HAS_MKL
61 : : const tk::ctr::RNGMKLParameters& mklparam,
62 : : #endif
63 : : #ifdef HAS_RNGSSE2
64 : : const tk::ctr::RNGSSEParameters& rngsseparam,
65 : : #endif
66 : 297 : const tk::ctr::RNGRandom123Parameters& r123param )
67 : 297 : : m_factory()
68 : : // *****************************************************************************
69 : : // Constructor: register generators into factory for each supported library
70 : : //! \param[in] mklparam MKL RNG parameters to use to configure MKL RNGs
71 : : //! \param[in] rngsseparam RNGSSE RNG parameters to use to configure RNGSSE RNGs
72 : : //! \param[in] r123param Random123 RNG parameters to use to configure
73 : : //! Random123 RNGs
74 : : // *****************************************************************************
75 : : {
76 : : #ifdef HAS_MKL
77 [ + - ]: 297 : regMKL( CkNumPes(), mklparam );
78 : : #endif
79 : : #ifdef HAS_RNGSSE2
80 [ + - ]: 297 : regRNGSSE( CkNumPes(), rngsseparam );
81 : : #endif
82 [ + - ]: 297 : regRandom123( CkNumPes(), r123param );
83 : 297 : }
84 : :
85 : : std::map< tk::ctr::RawRNGType, tk::RNG >
86 : 297 : RNGStack::selected( const std::vector< tk::ctr::RNGType >& sel ) const
87 : : // *****************************************************************************
88 : : // Instantiate selected RNGs from factory and place them in map
89 : : //! \param[in] sel Vector of selected RNGs to instantiate (selected by the user)
90 : : //! \return A std::map of keys and their associated instantiated RNG objects
91 : : // *****************************************************************************
92 : : {
93 : : using tk::ctr::RawRNGType;
94 : 297 : std::map< RawRNGType, tk::RNG > rng;
95 [ + + ]: 644 : for (const auto& s : sel) {
96 [ + - ]: 347 : const auto r = m_factory.find(s);
97 [ + - ]: 347 : if (r != end(m_factory))
98 [ + - ][ + - ]: 347 : rng.emplace( static_cast< RawRNGType >( s ), r->second() );
99 [ - - ][ - - ]: 0 : else Throw( "RNG not found in factory" );
[ - - ]
100 : : }
101 : 297 : return rng;
102 : : }
103 : :
104 : : #ifdef HAS_MKL
105 : : void
106 : 297 : RNGStack::regMKL( int nstreams, const tk::ctr::RNGMKLParameters& param )
107 : : // *****************************************************************************
108 : : // Register MKL random number generators into factory
109 : : //! \details Note that registering these entries in the map does not
110 : : //! invoke the constructors. The mapped value simply stores how the
111 : : //! constructors should be invoked at a later time. At some point later,
112 : : //! based on user input, we then instantiate only the RNGs (correctly
113 : : //! configured by the pre-bound constructor arguments) that are requested by
114 : : //! the user.
115 : : //! \param[in] nstreams Register MKL RNG using this many independent streams
116 : : //! \param[in] param MKL RNG parameters to use to configure the RNGs
117 : : // *****************************************************************************
118 : : {
119 : : using tk::ctr::RNGType;
120 : : using tk::ctr::MKLUniformMethodType;
121 : : using tk::ctr::MKLGaussianMethodType;
122 : : using tk::ctr::MKLGaussianMVMethodType;
123 : : using tk::ctr::MKLBetaMethodType;
124 : : using tk::ctr::MKLGammaMethodType;
125 : : using tag::uniform_method;
126 : : using tag::gaussian_method;
127 : : using tag::gaussianmv_method;
128 : : using tag::beta_method;
129 : : using tag::gamma_method;
130 : :
131 : : // Defaults for MKL RNGs
132 : 297 : unsigned int s_def = 0;
133 : 297 : MKLUniformMethodType u_def = MKLUniformMethodType::STANDARD;
134 : 297 : MKLGaussianMethodType g_def = MKLGaussianMethodType::BOXMULLER;
135 : 297 : MKLGaussianMVMethodType gmv_def = MKLGaussianMVMethodType::BOXMULLER;
136 : 297 : MKLBetaMethodType b_def = MKLBetaMethodType::CJA;
137 : 297 : MKLGammaMethodType ga_def = MKLGammaMethodType::GNORM;
138 : :
139 [ + - ]: 594 : tk::ctr::RNG opt;
140 [ + - ]: 594 : tk::ctr::MKLUniformMethod um_opt;
141 [ + - ]: 594 : tk::ctr::MKLGaussianMethod gm_opt;
142 [ + - ]: 594 : tk::ctr::MKLGaussianMVMethod gmvm_opt;
143 [ + - ]: 594 : tk::ctr::MKLBetaMethod bm_opt;
144 [ + - ]: 594 : tk::ctr::MKLGammaMethod gam_opt;
145 : :
146 : : //! Lambda to register a MKL random number generator into factory
147 : 3267 : auto regMKLRNG = [&]( RNGType rng ) {
148 : : recordModel< tk::RNG, tk::MKLRNG >
149 : 6534 : ( m_factory, rng,
150 : 3267 : nstreams,
151 [ + - ]: 3267 : opt.param( rng ),
152 [ + - ]: 3267 : opt.param< tag::seed >( rng, s_def, param ),
153 : 3267 : um_opt.param( opt.param< uniform_method >( rng, u_def, param ) ),
154 : 3267 : gm_opt.param( opt.param< gaussian_method >( rng, g_def, param) ),
155 : 3267 : gmvm_opt.param( opt.param< gaussianmv_method >( rng, gmv_def, param) ),
156 : 3267 : bm_opt.param( opt.param< beta_method >( rng, b_def, param) ),
157 : 3267 : gam_opt.param( opt.param< gamma_method >( rng, ga_def, param) ) );
158 : 3267 : };
159 : :
160 : : // Register MKL RNGs
161 [ + - ]: 297 : regMKLRNG( RNGType::MKL_MCG31 );
162 [ + - ]: 297 : regMKLRNG( RNGType::MKL_R250 );
163 [ + - ]: 297 : regMKLRNG( RNGType::MKL_MRG32K3A );
164 [ + - ]: 297 : regMKLRNG( RNGType::MKL_MCG59 );
165 [ + - ]: 297 : regMKLRNG( RNGType::MKL_WH );
166 [ + - ]: 297 : regMKLRNG( RNGType::MKL_MT19937 );
167 [ + - ]: 297 : regMKLRNG( RNGType::MKL_MT2203 );
168 [ + - ]: 297 : regMKLRNG( RNGType::MKL_SFMT19937 );
169 [ + - ]: 297 : regMKLRNG( RNGType::MKL_SOBOL );
170 [ + - ]: 297 : regMKLRNG( RNGType::MKL_NIEDERR );
171 : : //regMKLRNG( RNGType::MKL_IABSTRACT );
172 : : //regMKLRNG( RNGType::MKL_DABSTRACT );
173 : : //regMKLRNG( RNGType::MKL_SABSTRACT );
174 [ + - ]: 297 : regMKLRNG( RNGType::MKL_NONDETERM );
175 : 297 : }
176 : : #endif
177 : :
178 : : #ifdef HAS_RNGSSE2
179 : : void
180 : 297 : RNGStack::regRNGSSE( int nstreams, const tk::ctr::RNGSSEParameters& param )
181 : : // *****************************************************************************
182 : : // Register RNGSSE random number generators into factory
183 : : //! \details Note that registering these entries in the map does not
184 : : //! invoke the constructors. The mapped value simply stores how the
185 : : //! constructors should be invoked at a later time. At some point later,
186 : : //! based on user input, we then instantiate only the RNGs (correctly
187 : : //! configured by the pre-bound constructor arguments) that are requested by
188 : : //! the user.
189 : : //! \param[in] nstreams Register RNGSSE RNG using this many independent streams
190 : : //! \param[in] param RNGSSE RNG parameters to use to configure the RNGs
191 : : // *****************************************************************************
192 : : {
193 : : using tk::RNG;
194 : : using tk::RNGSSE;
195 : : using tk::ctr::RNGType;
196 : : using tk::ctr::RNGSSESeqLenType;
197 : : using tag::seqlen;
198 : :
199 [ + - ]: 297 : tk::ctr::RNG opt;
200 : :
201 : : // Defaults for RNGSSE RNGs
202 : 297 : RNGSSESeqLenType l_def = RNGSSESeqLenType::SHORT;
203 : :
204 : : // Register RNGSSE RNGs
205 : : recordModel< RNG, RNGSSE< gm19_state, unsigned, gm19_generate_ > >
206 : 0 : ( m_factory, RNGType::RNGSSE_GM19,
207 : : nstreams,
208 [ + - ]: 297 : &gm19_init_sequence_ );
209 : :
210 : 0 : recordModel< RNG, RNGSSE< gm29_state, unsigned, &gm29_generate_ > >
211 : 0 : ( m_factory, RNGType::RNGSSE_GM29,
212 : : nstreams,
213 : 0 : &gm29_init_short_sequence_,
214 [ + - ]: 297 : opt.param< seqlen >( RNGType::RNGSSE_GM29, l_def, param ),
215 : 0 : &gm29_init_long_sequence_,
216 [ + - ]: 297 : &gm29_init_medium_sequence_ );
217 : :
218 : : recordModel< RNG, RNGSSE< gm31_state, unsigned, gm31_generate_ > >
219 : 0 : ( m_factory, RNGType::RNGSSE_GM31,
220 : : nstreams,
221 : 0 : &gm31_init_short_sequence_,
222 [ + - ]: 297 : opt.param< seqlen >( RNGType::RNGSSE_GM31, l_def, param ),
223 : 0 : &gm31_init_long_sequence_,
224 [ + - ]: 297 : &gm31_init_medium_sequence_ );
225 : :
226 : : recordModel< RNG, RNGSSE< gm55_state, unsigned long long, gm55_generate_ > >
227 : 0 : ( m_factory, RNGType::RNGSSE_GM55,
228 : : nstreams,
229 : 0 : &gm55_init_short_sequence_,
230 [ + - ]: 297 : opt.param< seqlen >( RNGType::RNGSSE_GM55, l_def, param ),
231 [ + - ]: 297 : &gm55_init_long_sequence_ );
232 : :
233 : : recordModel< RNG, RNGSSE< gm61_state, unsigned long long, gm61_generate_ > >
234 : 0 : ( m_factory, RNGType::RNGSSE_GM61,
235 : : nstreams,
236 : 0 : &gm61_init_sequence_,
237 [ + - ]: 297 : opt.param< seqlen >( RNGType::RNGSSE_GM61, l_def, param ),
238 [ + - ]: 297 : &gm61_init_long_sequence_ );
239 : :
240 : : recordModel< RNG, RNGSSE< gq58x1_state, unsigned, gq58x1_generate_ > >
241 : 0 : ( m_factory, RNGType::RNGSSE_GQ581,
242 : : nstreams,
243 : 0 : &gq58x1_init_short_sequence_,
244 [ + - ]: 297 : opt.param< seqlen >( RNGType::RNGSSE_GQ581, l_def, param ),
245 : 0 : &gq58x1_init_long_sequence_,
246 [ + - ]: 297 : &gq58x1_init_medium_sequence_ );
247 : :
248 : : recordModel< RNG, RNGSSE< gq58x3_state, unsigned, gq58x3_generate_ > >
249 : 0 : ( m_factory, RNGType::RNGSSE_GQ583,
250 : : nstreams,
251 : 0 : &gq58x3_init_short_sequence_,
252 [ + - ]: 297 : opt.param< seqlen >( RNGType::RNGSSE_GQ583, l_def, param ),
253 : 0 : &gq58x3_init_long_sequence_,
254 [ + - ]: 297 : &gq58x3_init_medium_sequence_ );
255 : :
256 : : recordModel< RNG, RNGSSE< gq58x4_state, unsigned, gq58x4_generate_ > >
257 : 0 : ( m_factory, RNGType::RNGSSE_GQ584,
258 : : nstreams,
259 : 0 : &gq58x4_init_short_sequence_,
260 [ + - ]: 297 : opt.param< seqlen >( RNGType::RNGSSE_GQ584, l_def, param ),
261 : 0 : &gq58x4_init_long_sequence_,
262 [ + - ]: 297 : &gq58x4_init_medium_sequence_ );
263 : :
264 : : recordModel< RNG,
265 : : RNGSSE< mt19937_state, unsigned long long, mt19937_generate_ > >
266 : 0 : ( m_factory, RNGType::RNGSSE_MT19937,
267 : : nstreams,
268 [ + - ]: 297 : &mt19937_init_sequence_ );
269 : :
270 : : recordModel< RNG,
271 : : RNGSSE< lfsr113_state, unsigned long long, lfsr113_generate_ > >
272 : 0 : ( m_factory, RNGType::RNGSSE_LFSR113,
273 : : nstreams,
274 : 0 : &lfsr113_init_sequence_,
275 [ + - ]: 297 : opt.param< seqlen >( RNGType::RNGSSE_LFSR113, l_def, param ),
276 [ + - ]: 297 : &lfsr113_init_long_sequence_ );
277 : :
278 : : recordModel< RNG,
279 : : RNGSSE<mrg32k3a_state, unsigned long long, mrg32k3a_generate_> >
280 : 0 : ( m_factory, RNGType::RNGSSE_MRG32K3A,
281 : : nstreams,
282 [ + - ]: 297 : &mrg32k3a_init_sequence_ );
283 : 297 : }
284 : : #endif
285 : :
286 : : void
287 : 297 : RNGStack::regRandom123( int nstreams,
288 : : const tk::ctr::RNGRandom123Parameters& param )
289 : : // *****************************************************************************
290 : : // Register Random123 random number generators into factory
291 : : //! \details Note that registering these entries in the map does not
292 : : //! invoke the constructors. The mapped value simply stores how the
293 : : //! constructors should be invoked at a later time. At some point later,
294 : : //! based on user input, we then instantiate only the RNGs (correctly
295 : : //! configured by the pre-bound constructor arguments) that are requested by
296 : : //! the user.
297 : : //! \param[in] nstreams Register Randomer123 RNG using this many independent
298 : : //! streams
299 : : //! \param[in] param Random123 RNG parameters to use to configure the RNGs
300 : : // *****************************************************************************
301 : : {
302 : : using tk::ctr::RNGType;
303 : :
304 : : // Defaults for MKL RNGs
305 : 297 : uint32_t s_def = 0;
306 : :
307 [ + - ]: 297 : tk::ctr::RNG opt;
308 : :
309 : : // Register Random123 RNGs
310 : : recordModel< tk::RNG, tk::Random123< r123::Threefry2x64 > >
311 : 0 : ( m_factory, RNGType::R123_THREEFRY,
312 : : nstreams,
313 [ + - ][ + - ]: 297 : opt.param< tag::seed >( RNGType::R123_THREEFRY, s_def, param ) );
314 : :
315 : : recordModel< tk::RNG, tk::Random123< r123::Philox2x64 > >
316 : 0 : ( m_factory, RNGType::R123_PHILOX,
317 : : nstreams,
318 [ + - ][ + - ]: 297 : opt.param< tag::seed >( RNGType::R123_PHILOX, s_def, param ) );
319 : 297 : }
|