GGEMS  1.1
GPU GEant4-based Monte Carlo Simulations
GGEMSPseudoRandomGenerator.cc
Go to the documentation of this file.
1 // ************************************************************************
2 // * This file is part of GGEMS. *
3 // * *
4 // * GGEMS is free software: you can redistribute it and/or modify *
5 // * it under the terms of the GNU General Public License as published by *
6 // * the Free Software Foundation, either version 3 of the License, or *
7 // * (at your option) any later version. *
8 // * *
9 // * GGEMS is distributed in the hope that it will be useful, *
10 // * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 // * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 // * GNU General Public License for more details. *
13 // * *
14 // * You should have received a copy of the GNU General Public License *
15 // * along with GGEMS. If not, see <https://www.gnu.org/licenses/>. *
16 // * *
17 // ************************************************************************
18 
31 #include <random>
32 
35 
37 
39 
40 #ifdef __linux__
41 #include <unistd.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <fcntl.h>
45 #endif
46 
50 
52 : pseudo_random_numbers_(nullptr),
53  seed_(0)
54 {
55  GGcout("GGEMSPseudoRandomGenerator", "GGEMSPseudoRandomGenerator", 3) << "GGEMSPseudoRandomGenerator creating..." << GGendl;
56 
57  GGcout("GGEMSPseudoRandomGenerator", "GGEMSPseudoRandomGenerator", 3) << "GGEMSPseudoRandomGenerator created!!!" << GGendl;
58 }
59 
63 
65 {
66  GGcout("GGEMSPseudoRandomGenerator", "~GGEMSPseudoRandomGenerator", 3) << "GGEMSPseudoRandomGenerator erasing..." << GGendl;
67 
69 
71  for (GGsize i = 0; i < number_activated_devices_; ++i) {
72  opencl_manager.Deallocate(pseudo_random_numbers_[i], sizeof(GGEMSRandom), i);
73  }
74  delete[] pseudo_random_numbers_;
75  pseudo_random_numbers_ = nullptr;
76  }
77 
78  GGcout("GGEMSPseudoRandomGenerator", "~GGEMSPseudoRandomGenerator", 3) << "GGEMSPseudoRandomGenerator erased!!!" << GGendl;
79 }
80 
84 
86 {
87  #ifdef _WIN32
88  HCRYPTPROV seedWin32;
89  if (CryptAcquireContext(&seedWin32, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE) {
90  std::ostringstream oss(std::ostringstream::out);
91  char buffer_error[256];
92  oss << "Error finding a seed: " << strerror_s(buffer_error, 256, errno) << std::endl;
93  GGEMSMisc::ThrowException("GGEMSPseudoRandomGenerator", "GenerateSeed", oss.str());
94  }
95  return static_cast<uint32_t>(seedWin32);
96  #else
97  // Open a system random file
98  GGint file_descriptor = ::open("/dev/urandom", O_RDONLY | O_NONBLOCK);
99  if (file_descriptor < 0) {
100  std::ostringstream oss( std::ostringstream::out );
101  oss << "Error opening the file '/dev/urandom': " << strerror(errno) << std::endl;
102  GGEMSMisc::ThrowException("GGEMSPseudoRandomGenerator", "GenerateSeed", oss.str());
103  }
104 
105  // Buffer storing 8 characters
106  char seedArray[sizeof(GGuint)];
107  ssize_t bytes_read = ::read(file_descriptor, reinterpret_cast<GGuint*>(seedArray), sizeof(GGuint));
108  if (bytes_read == -1) {
109  std::ostringstream oss( std::ostringstream::out );
110  oss << "Error reading the file '/dev/urandom': " << strerror(errno) << std::endl;
111  GGEMSMisc::ThrowException("GGEMSPseudoRandomGenerator", "GenerateSeed", oss.str());
112  }
113  ::close(file_descriptor);
114  GGuint *seedUInt = reinterpret_cast<GGuint*>(seedArray);
115  return *seedUInt;
116  #endif
117 }
118 
122 
124 {
125  GGcout("GGEMSPseudoRandomGenerator", "Initialize", 1) << "Initialization of GGEMSPseudoRandomGenerator..." << GGendl;
126 
127  seed_ = seed == 0 ? GenerateSeed() : seed;
128 
129  // Allocation of the Random structure
130  AllocateRandom();
131 
132  // Generate seeds for each particle
133  InitializeSeeds();
134 }
135 
139 
141 {
142  GGcout("GGEMSPseudoRandomGenerator", "InitializeSeeds", 1) << "Initialization of seeds for each particles..." << GGendl;
143 
144  // Initialize the Mersenne Twister engine
145  std::mt19937 mt_gen(seed_);
146 
147  // Get the OpenCL manager
149 
150  // Loop over activated device
151  for (GGsize i = 0; i < number_activated_devices_; ++i) {
152  // Get the pointer on device
153  GGEMSRandom* random_device = opencl_manager.GetDeviceBuffer<GGEMSRandom>(pseudo_random_numbers_[i], sizeof(GGEMSRandom), i);
154 
155  // For each particle a seed is generated
156  for (GGsize i = 0; i < MAXIMUM_PARTICLES; ++i) {
157  random_device->prng_state_1_[i] = static_cast<GGuint>(mt_gen());
158  random_device->prng_state_2_[i] = static_cast<GGuint>(mt_gen());
159  random_device->prng_state_3_[i] = static_cast<GGuint>(mt_gen());
160  random_device->prng_state_4_[i] = static_cast<GGuint>(mt_gen());
161  random_device->prng_state_5_[i] = 0;
162  }
163 
164  // Release the pointer, mandatory step!!!
165  opencl_manager.ReleaseDeviceBuffer(pseudo_random_numbers_[i], random_device, i);
166  }
167 }
168 
172 
174 {
175  GGcout("GGEMSPseudoRandomGenerator", "AllocateRandom", 1) << "Allocation of random numbers..." << GGendl;
176 
177  // Get the OpenCL manager
179 
180  // Getting number of activated device
182 
183  // Allocation of memory on OpenCL device
185  for (GGsize i = 0; i < number_activated_devices_; ++i) {
186  pseudo_random_numbers_[i] = opencl_manager.Allocate(nullptr, sizeof(GGEMSRandom), i, CL_MEM_READ_WRITE, "GGEMSPseudoRandomGenerator");
187  }
188 }
189 
193 
195 {
196  GGcout("GGEMSPseudoRandomGenerator", "PrintInfos", 0) << "Printing infos about random" << GGendl;
197  GGcout("GGEMSPseudoRandomGenerator", "PrintInfos", 0) << "Seed: " << seed_ << GGendl;
198 
199  // Getting OpenCL manager
201 
202  // Loop over the activated devices
203  for (GGsize i = 0; i < number_activated_devices_; ++i) {
204  GGsize device_index = opencl_manager.GetIndexOfActivatedDevice(i);
205 
206  GGEMSRandom* random_device = opencl_manager.GetDeviceBuffer<GGEMSRandom>(pseudo_random_numbers_[i], sizeof(GGEMSRandom), i);
207 
208  GGuint state[2][5] = {
209  {
210  random_device->prng_state_1_[0],
211  random_device->prng_state_2_[0],
212  random_device->prng_state_3_[0],
213  random_device->prng_state_4_[0],
214  random_device->prng_state_5_[0]
215  },
216  {
217  random_device->prng_state_1_[1],
218  random_device->prng_state_2_[1],
219  random_device->prng_state_3_[1],
220  random_device->prng_state_4_[1],
221  random_device->prng_state_5_[1]
222  }
223  };
224 
225  // Release the pointer, mandatory step!!!
226  opencl_manager.ReleaseDeviceBuffer(pseudo_random_numbers_[i], random_device, i);
227 
228  GGcout("GGEMSPseudoRandomGenerator", "PrintInfos", 0) << "Device: " << opencl_manager.GetDeviceName(device_index) << GGendl;
229  GGcout("GGEMSPseudoRandomGenerator", "PrintInfos", 0) << "-------" << GGendl;
230  GGcout("GGEMSPseudoRandomGenerator", "PrintInfos", 0) << "Random state of two first particles for JKISS engine:" << GGendl;
231  GGcout("GGEMSPseudoRandomGenerator", "PrintInfos", 0) << " * state 0: " << state[0][0] << " " << state[1][0] << GGendl;
232  GGcout("GGEMSPseudoRandomGenerator", "PrintInfos", 0) << " * state 1: " << state[0][1] << " " << state[1][1] << GGendl;
233  GGcout("GGEMSPseudoRandomGenerator", "PrintInfos", 0) << " * state 2: " << state[0][2] << " " << state[1][2] << GGendl;
234  GGcout("GGEMSPseudoRandomGenerator", "PrintInfos", 0) << " * state 3: " << state[0][3] << " " << state[1][3] << GGendl;
235  GGcout("GGEMSPseudoRandomGenerator", "PrintInfos", 0) << " * state 4: " << state[0][4] << " " << state[1][4] << GGendl;
236  }
237 }
GGEMSRAMManager.hh
GGEMS class handling RAM memory.
GGEMSPseudoRandomGenerator::PrintInfos
void PrintInfos(void) const
printing infos about random
Definition: GGEMSPseudoRandomGenerator.cc:194
FALSE
#define FALSE
Definition: GGEMSTypes.hh:34
GGEMSOpenCLManager::GetNumberOfActivatedDevice
GGsize GetNumberOfActivatedDevice(void) const
get the number of activated devices
Definition: GGEMSOpenCLManager.hh:167
GGEMSOpenCLManager::Deallocate
void Deallocate(cl::Buffer *buffer, GGsize size, GGsize const &thread_index, std::string const &class_name="Undefined")
Deallocation of OpenCL memory.
Definition: GGEMSOpenCLManager.cc:981
GGEMSOpenCLManager::ReleaseDeviceBuffer
void ReleaseDeviceBuffer(cl::Buffer *const device_ptr, T *host_ptr, GGsize const &thread_index)
Get the device pointer on host to write on it. Mandatory after a GetDeviceBufferWrite ou GetDeviceBuf...
Definition: GGEMSOpenCLManager.hh:495
GGEMSPseudoRandomGenerator::GGEMSPseudoRandomGenerator
GGEMSPseudoRandomGenerator(void)
GGEMSPseudoRandomGenerator constructor.
Definition: GGEMSPseudoRandomGenerator.cc:51
GGEMSPseudoRandomGenerator::seed_
GGuint seed_
Definition: GGEMSPseudoRandomGenerator.hh:134
GGEMSPseudoRandomGenerator::InitializeSeeds
void InitializeSeeds(void)
Initialize seeds for random.
Definition: GGEMSPseudoRandomGenerator.cc:140
GGsize
#define GGsize
Definition: GGEMSTypes.hh:252
GGint
#define GGint
Definition: GGEMSTypes.hh:224
GGEMSRandom_t::prng_state_4_
GGuint prng_state_4_[MAXIMUM_PARTICLES]
Definition: GGEMSRandom.hh:46
GGEMSRandom_t::prng_state_3_
GGuint prng_state_3_[MAXIMUM_PARTICLES]
Definition: GGEMSRandom.hh:45
GGEMSPseudoRandomGenerator::number_activated_devices_
GGsize number_activated_devices_
Definition: GGEMSPseudoRandomGenerator.hh:133
GGEMSOpenCLManager::Allocate
cl::Buffer * Allocate(void *host_ptr, GGsize const &size, GGsize const &thread_index, cl_mem_flags flags, std::string const &class_name="Undefined")
Allocation of OpenCL memory.
Definition: GGEMSOpenCLManager.cc:945
GGEMSPseudoRandomGenerator::~GGEMSPseudoRandomGenerator
~GGEMSPseudoRandomGenerator(void)
GGEMSPseudoRandomGenerator destructor.
Definition: GGEMSPseudoRandomGenerator.cc:64
GGEMSRandom.hh
Structure storing the random buffers for both OpenCL and GGEMS.
GGEMSRandom_t::prng_state_1_
GGuint prng_state_1_[MAXIMUM_PARTICLES]
Definition: GGEMSRandom.hh:43
GGEMSRandom_t
Structure storing informations about random.
Definition: GGEMSRandom.hh:42
GGcout
GGEMSStream GGcout
Definition: GGEMSPrint.cc:34
GGEMSPseudoRandomGenerator::Initialize
void Initialize(GGuint const &seed)
Initialize the Random object.
Definition: GGEMSPseudoRandomGenerator.cc:123
GGEMSRandom
struct GGEMSRandom_t GGEMSRandom
GGEMSSourceManager.hh
GGEMS class handling the source(s)
GGEMSOpenCLManager::GetDeviceBuffer
T * GetDeviceBuffer(cl::Buffer *device_ptr, GGsize const &size, GGsize const &thread_index)
Get the device pointer on host to write on it. ReleaseDeviceBuffer must be used after this method!...
Definition: GGEMSOpenCLManager.hh:480
GGendl
#define GGendl
overload C++ std::endl
Definition: GGEMSPrint.hh:60
GGEMSOpenCLManager
Singleton class storing all informations about OpenCL and managing GPU/CPU devices,...
Definition: GGEMSOpenCLManager.hh:54
GGEMSRandom_t::prng_state_5_
GGuint prng_state_5_[MAXIMUM_PARTICLES]
Definition: GGEMSRandom.hh:47
GGEMSOpenCLManager::GetDeviceName
std::string GetDeviceName(GGsize const &device_index) const
Get the name of the activated device.
Definition: GGEMSOpenCLManager.hh:145
GGEMSPseudoRandomGenerator::pseudo_random_numbers_
cl::Buffer ** pseudo_random_numbers_
Definition: GGEMSPseudoRandomGenerator.hh:132
GGEMSPseudoRandomGenerator.hh
Class managing the random number in GGEMS.
GGEMSOpenCLManager::GetIndexOfActivatedDevice
GGsize GetIndexOfActivatedDevice(GGsize const &thread_index) const
get the index of activated device
Definition: GGEMSOpenCLManager.hh:175
GGuint
#define GGuint
Definition: GGEMSTypes.hh:231
GGEMSRandom_t::prng_state_2_
GGuint prng_state_2_[MAXIMUM_PARTICLES]
Definition: GGEMSRandom.hh:44
GGEMSPseudoRandomGenerator::AllocateRandom
void AllocateRandom(void)
Allocate memory for random numbers.
Definition: GGEMSPseudoRandomGenerator.hh:109
GGEMSMisc::ThrowException
void ThrowException(std::string const &class_name, std::string const &method_name, std::string const &message)
Throw a C++ exception.
Definition: GGEMSTools.cc:61
GGEMSOpenCLManager::GetInstance
static GGEMSOpenCLManager & GetInstance(void)
Create at first time the Singleton.
Definition: GGEMSOpenCLManager.hh:72
GGEMSPseudoRandomGenerator::GenerateSeed
GGuint GenerateSeed(void) const
generate a seed by GGEMS and return it
Definition: GGEMSPseudoRandomGenerator.cc:85