1 /* 2 * random_manager.h 3 * 4 * This file is part of NEST. 5 * 6 * Copyright (C) 2004 The NEST Initiative 7 * 8 * NEST is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation, either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * NEST is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with NEST. If not, see <http://www.gnu.org/licenses/>. 20 * 21 */ 22 23 #ifndef RANDOM_MANAGER_H 24 #define RANDOM_MANAGER_H 25 26 // Generated includes: 27 #include "config.h" 28 29 // C++ includes: 30 #include <string> 31 #include <vector> 32 33 // Includes from libnestutil: 34 #include "manager_interface.h" 35 36 // Includes from nestkernel: 37 #include "dictdatum.h" 38 #include "nest_types.h" 39 #include "random_generators.h" 40 41 namespace nest 42 { 43 44 /** 45 * Manage the kernel's random number generators. 46 * 47 * This manager provides one random number generator per thread plus 48 * the global RNG. It also handles selection of RNG type and seeding. 49 */ 50 class RandomManager : public ManagerInterface 51 { 52 public: 53 RandomManager(); 54 ~RandomManager(); 55 56 /** 57 * Register available RNG types, set default RNG type and create RNGs. 58 */ 59 virtual void initialize(); 60 virtual void finalize(); 61 62 virtual void set_status( const DictionaryDatum& ); 63 virtual void get_status( DictionaryDatum& ); 64 65 /** 66 * Get rank-synchronized random number generator. 67 * 68 * The rank-synchronized generator provides identical random number 69 * sequences on all MPI ranks. It may be used only by the master thread 70 * on each rank and must be used in lock-step across all ranks. Synchronization 71 * is checked by MPI exchange at certain points during a simulation. 72 **/ 73 RngPtr get_rank_synced_rng() const; 74 75 /** 76 * Get VP-synchronized random number generator. 77 * 78 * The kernel maintains one instance of a synchronized random number generator 79 * for each thread (and thus, across ranks, for each VP). The purpose of these 80 * synchronized generators is to provide identical random number sequences on 81 * each VP while VPs execute in parallel. All VPs (ie all threads on all ranks) 82 * must use the generators in lock-step to maintain synchrony. Synchronization 83 * is checked by MPI exchange at certain points during a simulation. 84 * 85 * @param tid ID of thread requesting generator 86 **/ 87 RngPtr get_vp_synced_rng( thread tid ) const; 88 89 /** 90 * Get VP-specific random number generator. 91 * 92 * Each VP (thread) can use this RNG freely and will receive an independent 93 * random number sequence. 94 */ 95 RngPtr get_vp_specific_rng( thread tid ) const; 96 97 /** 98 * Confirm that rank- and thread-synchronized RNGs are in sync. 99 * 100 * @throws KernelException if RNGs are out of sync. 101 */ 102 void check_rng_synchrony() const; 103 104 /** 105 * Register new random number generator type with manager. 106 * 107 * This allows NEST modules to add new RNG types. 108 * 109 * @param RNG_TYPE Class fulfilling requirements of C++ RNG. 110 **/ 111 template < typename RNG_TYPE > 112 void register_rng_type( std::string name ); 113 114 private: 115 /** Available RNG types. */ 116 std::map< std::string, BaseRandomGeneratorFactory* > rng_types_; 117 118 /** Name of currently used RNG type. */ 119 std::string current_rng_type_; 120 121 /** Base seed used when RNGs were last created. */ 122 std::uint32_t base_seed_; 123 124 /** Random number generator synchronized across ranks. */ 125 RngPtr rank_synced_rng_; 126 127 /** Random number generators synchronized across VPs. */ 128 std::vector< RngPtr > vp_synced_rngs_; 129 130 /** Random number generators specific to VPs. */ 131 std::vector< RngPtr > vp_specific_rngs_; 132 133 /** 134 * Replace current RNGs with newly seeded generators. 135 * 136 * The new generators will be of type `current_rng_type_` and will be 137 * seeded using `base_seed_`. 138 **/ 139 void reset_rngs_(); 140 141 /** RNG type used by default. */ 142 static const std::string DEFAULT_RNG_TYPE_; 143 144 /** Base seed used by default. */ 145 static const std::uint32_t DEFAULT_BASE_SEED_; 146 147 /** Rank-synchronized seed-sequence initializer component. */ 148 static const std::uint32_t RANK_SYNCED_SEEDER_; 149 150 /** Thread-synchronized seed-sequence initializer component. */ 151 static const std::uint32_t THREAD_SYNCED_SEEDER_; 152 153 /** Thread-specific seed-sequence initializer component. */ 154 static const std::uint32_t THREAD_SPECIFIC_SEEDER_; 155 }; 156 157 inline RngPtr get_rank_synced_rng()158nest::RandomManager::get_rank_synced_rng() const 159 { 160 return rank_synced_rng_; 161 } 162 163 inline RngPtr get_vp_synced_rng(thread tid)164nest::RandomManager::get_vp_synced_rng( thread tid ) const 165 { 166 assert( tid >= 0 ); 167 assert( tid < static_cast< thread >( vp_specific_rngs_.size() ) ); 168 return vp_synced_rngs_[ tid ]; 169 } 170 171 inline RngPtr get_vp_specific_rng(thread tid)172nest::RandomManager::get_vp_specific_rng( thread tid ) const 173 { 174 assert( tid >= 0 ); 175 assert( tid < static_cast< thread >( vp_specific_rngs_.size() ) ); 176 return vp_specific_rngs_[ tid ]; 177 } 178 179 } // namespace nest 180 181 #endif /* RANDOM_MANAGER_H */ 182