24 #include "mpi/collectives.h" 73 std::vector<uint_type> mySeeds;
86 Children.push_back(std::make_unique<RandomGenerator>());
91 int baseoffset =
Offset + nprocs + nthreads *
rank;
92 std::vector<uint_type> myprimes;
94 for (
int ip = 0; ip < nthreads; ip++)
110 std::vector<double> avg(nthreads), avg2(nthreads);
111 #pragma omp parallel for 112 for (
int ip = 0; ip < nthreads; ++ip)
114 const int n = 1000000;
115 double sum = 0.0, sum2 = 0.0;
117 for (
int i = 0; i <
n; ++i)
123 avg[ip] = sum /
static_cast<double>(
n);
124 avg2[ip] = sum2 /
static_cast<double>(
n);
133 for (
int ip = 0; ip < nthreads; ++ip, ++ii)
135 app_log() <<
"RNGTest " << std::setw(4) << i << std::setw(4) << ip << std::setw(20) << avg_tot[ii]
136 << std::setw(20) << avg2_tot[ii] - avg_tot[ii] * avg_tot[ii] << std::endl;
137 avg_g += avg_tot[ii];
138 avg2_g += avg2_tot[ii];
144 << avg_g << std::setw(20) << avg2_g - avg_g * avg_g << std::endl;
152 bool init_mpi =
true;
156 std::string pname(
"yes");
158 oAttrib.
add(pname,
"parallel");
159 oAttrib.
add(offset_in,
"seed");
161 if (pname ==
"0" || pname ==
"false" || pname ==
"no")
177 offset_in =
static_cast<int>(
static_cast<uint_type>(std::time(0)) % 1024);
178 app_summary() <<
" Offset for the random number seeds based on time: " << offset_in << std::endl;
184 app_summary() <<
" Offset for the random number seeds from input file (mod 1024): " << offset_in << std::endl;
188 std::vector<uint_type> mySeeds;
191 Random.init(mySeeds[pid]);
192 app_log() <<
" Range of prime numbers to use as seeds over processors and threads = " << mySeeds[0] <<
"-" 208 std::string h5name = fname +
".random.h5";
210 hin.
open(h5name, H5F_ACC_RDONLY);
224 const std::string& fname,
227 std::string h5name = fname +
".random.h5";
241 const size_t comm_size =
static_cast<size_t>(
comm->
size());
242 const size_t comm_rank =
static_cast<size_t>(
comm->
rank());
244 std::vector<uint_type> vt, mt;
250 hin.
read(shape_hdf5,
"nprocs_nthreads_statesize");
253 if (shape_hdf5[0] != shape_now[0] || shape_hdf5[1] != shape_now[1] || shape_hdf5[2] != shape_now[2])
255 app_log() <<
"Mismatched random number generators." 256 <<
"\n Number of procs in streams : old=" << shape_hdf5[0] <<
" new= " << shape_now[0]
257 <<
"\n Number of threads in streams : old=" << shape_hdf5[1] <<
" new= " << shape_now[1]
258 <<
"\n State size per stream : old=" << shape_hdf5[2] <<
" new= " << shape_now[2]
259 <<
"\n Using the random streams generated at the initialization.\n";
262 app_log() <<
" Restart from the random number streams from the previous configuration.\n";
264 vt.resize(nthreads *
Random.state_size());
265 mt.resize(
Random.state_size());
267 std::array<size_t, 2> shape{comm_size * nthreads,
Random.state_size()};
268 std::array<size_t, 2> counts{nthreads,
Random.state_size()};
269 std::array<size_t, 2> offsets{comm_rank * nthreads, 0};
276 hin.
push(
"random_master");
284 std::vector<uint_type>::iterator vt_it(vt.begin());
285 for (
int ip = 0; ip < nthreads; ip++, vt_it += shape[1])
287 std::vector<uint_type> c(vt_it, vt_it + shape[1]);
300 const size_t comm_size =
static_cast<size_t>(
comm->
size());
301 const size_t comm_rank =
static_cast<size_t>(
comm->
rank());
303 std::vector<uint_type> vt, mt;
305 vt.reserve(nthreads *
Random.state_size());
306 mt.reserve(
Random.state_size());
308 std::vector<uint_type> c;
309 for (
int ip = 0; ip < nthreads; ++ip)
311 rng[ip].get().save(c);
312 vt.insert(vt.end(), c.begin(), c.end());
316 std::array<size_t, 2> shape{comm_size * nthreads,
Random.state_size()};
317 std::array<size_t, 2> counts{nthreads,
Random.state_size()};
318 std::array<size_t, 2> offsets{comm_rank * nthreads, 0};
321 hout.
write(shape_hdf5,
"nprocs_nthreads_statesize");
331 hout.
push(
"random_master");
342 const size_t comm_size =
static_cast<size_t>(
comm->
size());
343 const size_t comm_rank =
static_cast<size_t>(
comm->
rank());
345 std::vector<uint_type> vt, vt_tot, mt, mt_tot;
348 std::array<size_t, 2> shape{comm_size * nthreads,
Random.state_size()};
354 hin.
read(shape_hdf5,
"nprocs_nthreads_statesize");
360 if (shape_hdf5[0] != shape_now[0] || shape_hdf5[1] != shape_now[1] || shape_hdf5[2] != shape_now[2])
362 app_log() <<
"Mismatched random number generators." 363 <<
"\n Number of procs in streams : old=" << shape_hdf5[0] <<
" new= " << shape_now[0]
364 <<
"\n Number of threads in streams : old=" << shape_hdf5[1] <<
" new= " << shape_now[1]
365 <<
"\n State size per stream : old=" << shape_hdf5[2] <<
" new= " << shape_now[2]
366 <<
"\n Using the random streams generated at the initialization.\n";
369 app_log() <<
" Restart from the random number streams from the previous configuration.\n";
371 vt.resize(nthreads *
Random.state_size());
372 mt.resize(
Random.state_size());
383 hin.
push(
"random_master");
390 mpi::scatter(*
comm, vt_tot, vt);
391 mpi::scatter(*
comm, mt_tot, mt);
395 copy(vt_tot.begin(), vt_tot.end(), vt.begin());
396 copy(mt_tot.begin(), mt_tot.end(), mt.begin());
399 std::vector<uint_type>::iterator vt_it(vt.begin());
400 for (
int i = 0; i < nthreads; i++, vt_it += shape[1])
402 std::vector<uint_type> c(vt_it, vt_it + shape[1]);
415 const size_t comm_size =
static_cast<size_t>(
comm->
size());
416 const size_t comm_rank =
static_cast<size_t>(
comm->
rank());
418 std::vector<uint_type> vt, vt_tot, mt, mt_tot;
419 std::array<size_t, 2> shape{comm_size * nthreads,
Random.state_size()};
421 vt.reserve(nthreads *
Random.state_size());
422 mt.reserve(
Random.state_size());
424 for (
int i = 0; i < nthreads; ++i)
426 std::vector<uint_type> c;
427 rng[i].get().save(c);
428 vt.insert(vt.end(), c.begin(), c.end());
434 vt_tot.resize(vt.size() *
comm->
size());
435 mt_tot.resize(mt.size() *
comm->
size());
436 mpi::gather(*
comm, vt, vt_tot);
437 mpi::gather(*
comm, mt, mt_tot);
448 hout.
write(shape_hdf5,
"nprocs_nthreads_statesize");
455 hout.
push(
"random_master");
static void read(const std::string &fname, Communicate *comm)
read in parallel or serial
class to generate prime numbers
void write(T &data, const std::string &aname)
write the data to the group aname and check status runtime error is issued on I/O error ...
bool open(const std::filesystem::path &fname, unsigned flags=H5F_ACC_RDWR)
open a file
helper functions for EinsplineSetBuilder
int rank() const
return the rank
class to use file space hyperslab with a serialized container
static void read_parallel(hdf_archive &hin, Communicate *comm)
read random state from a hdf file in parallel
bool NeverBeenInitialized
std::ostream & app_summary()
bool put(xmlNodePtr cur)
assign attributes to the set
static PrimeNumberSet< uint_type > PrimeNumbers
initialize the static data members
void close()
close all the open groups and file
void readSlabReshaped(T &data, const std::array< IT, RANK > &shape, const std::string &aname)
read file dataset with a specific shape into a container and check status
Communicate * Controller
Global Communicator for a process.
static void write(const std::string &fname, Communicate *comm)
write in parallel or serial
int size() const
return the number of tasks
static RefVector< T > convertUPtrToRefVector(const UPtrVector< T > &ptr_list)
convert a vector of std::unique_ptrs<T> to a refvector<T>
class to handle xmlXPathObject
bool is_parallel() const
return true if parallel i/o
xmlNodePtr initialize(xmlXPathContextPtr)
void copy(const Array< T1, 3 > &src, Array< T2, 3 > &dest)
Wrapping information on parallelism.
void bcast(T &a, Communicate *comm)
void reset() override
reset the generator
static void write_parallel(const RefVector< RandomBase< FullPrecRealType >> &rng, hdf_archive &hout, Communicate *comm)
write random state to a hdf file in parallel
omp_int_t omp_get_max_threads()
Abstract class to provide xml-compatible I/O interfaces for the derived classes.
void writeSlabReshaped(T &data, const std::array< IT, RANK > &shape, const std::string &aname)
write the container data with a specific shape and check status
class to handle a set of attributes of an xmlNode
RandomBase< FullPrecRealType >::uint_type uint_type
bool get(std::ostream &os) const override
generic output
static UPtrVector< RandomBase< FullPrecRealType > > Children
void push(const std::string &gname, bool createit=true)
push a group to the group stack
std::vector< std::reference_wrapper< T > > RefVector
bool create(const std::filesystem::path &fname, unsigned flags=H5F_ACC_TRUNC)
create a file
bool put(std::istream &is) override
generic input
void read(T &data, const std::string &aname)
read the data from the group aname and check status runtime error is issued on I/O error ...
static void write_rank_0(const RefVector< RandomBase< FullPrecRealType >> &rng, hdf_archive &hout, Communicate *comm)
rank 0 gathers the random states from all the other ranks and write them to a hdf file ...
static void make_seeds()
reset the generator
void add(PDT &aparam, const std::string &aname, std::vector< PDT > candidate_values={}, TagStatus status=TagStatus::OPTIONAL)
add a new attribute
bool get(UIntType offset, int n, std::vector< UIntType > &primes_add)
add n new primes starting with an offset
static void make_children()
RandomNumberControl(const char *aname="random")
constructors and destructors
static void read_rank_0(hdf_archive &hin, Communicate *comm)
rank 0 reads random states from a hdf file and distributes them to all the other ranks ...