diff --git a/lib/lattice/Lattice_rng.h b/lib/lattice/Lattice_rng.h index 51cc16ec..88f508d9 100644 --- a/lib/lattice/Lattice_rng.h +++ b/lib/lattice/Lattice_rng.h @@ -33,6 +33,7 @@ Author: paboyle namespace Grid { + //http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf ? ////////////////////////////////////////////////////////////// // Allow the RNG state to be less dense than the fine grid @@ -68,6 +69,7 @@ namespace Grid { } // Wrap seed_seq to give common interface with random_device + // Should rather wrap random_device and have a generate class fixedSeed { public: @@ -75,20 +77,31 @@ namespace Grid { std::seed_seq src; - fixedSeed(const std::vector &seeds) : src(seeds.begin(),seeds.end()) {}; - - result_type operator () (void){ - - std::vector list(1); - - src.generate(list.begin(),list.end()); - - return list[0]; + template fixedSeed(const std::vector &seeds) : src(seeds.begin(),seeds.end()) {}; + template< class RandomIt > void generate( RandomIt begin, RandomIt end ) { + src.generate(begin,end); } }; + + class deviceSeed { + public: + + std::random_device rd; + + typedef std::random_device::result_type result_type; + + deviceSeed(void) : rd(){}; + + template< class RandomIt > void generate( RandomIt begin, RandomIt end ) { + for(RandomIt it=begin; it!=end;it++){ + *it = rd(); + } + } + }; + // real scalars are one component template void fillScalar(scalar &s,distribution &dist,generator & gen) { @@ -122,7 +135,7 @@ namespace Grid { std::vector _generators; std::vector> _uniform; std::vector> _gaussian; - std::vector> _bernoulli; + std::vector> _bernoulli; void GetState(std::vector & saved,int gen) { saved.resize(RngStateCount); @@ -150,13 +163,6 @@ namespace Grid { // FIXME ... do we require lockstep draws of randoms // from all nodes keeping seeds consistent. // place a barrier/broadcast in the fill routine - template void Seed(source &src) - { - typename source::result_type init = src(); - CartesianCommunicator::BroadcastWorld(0,(void *)&init,sizeof(init)); - _generators[0] = RngEngine(init); - _seeded=1; - } GridSerialRNG() : GridRNGbase() { _generators.resize(1); @@ -239,12 +245,17 @@ namespace Grid { CartesianCommunicator::BroadcastWorld(0,(void *)&l,sizeof(l)); } - + template void Seed(source &src) + { + _generators[0] = RngEngine(src); + _seeded=1; + } void SeedRandomDevice(void){ - std::random_device rd; - Seed(rd); + deviceSeed src; + Seed(src); } void SeedFixedIntegers(const std::vector &seeds){ + CartesianCommunicator::BroadcastWorld(0,(void *)&seeds[0],sizeof(int)*seeds.size()); fixedSeed src(seeds); Seed(src); } @@ -273,46 +284,6 @@ namespace Grid { } - // This loop could be made faster to avoid the Ahmdahl by - // i) seed generators on each timeslice, for x=y=z=0; - // ii) seed generators on each z for x=y=0 - // iii)seed generators on each y,z for x=0 - // iv) seed generators on each y,z,x - // made possible by physical indexing. - template void Seed(source &src) - { - std::vector gcoor; - - int gsites = _grid->_gsites; - - typename source::result_type init = src(); - RngEngine pseeder(init); - std::uniform_int_distribution ui; - - for(int gidx=0;gidxGlobalIndexToGlobalCoor(gidx,gcoor); - _grid->GlobalCoorToRankIndex(rank,o_idx,i_idx,gcoor); - - int l_idx=generator_idx(o_idx,i_idx); - - const int num_rand_seed=16; - std::vector site_seeds(num_rand_seed); - for(int i=0;iBroadcast(0,(void *)&site_seeds[0],sizeof(int)*site_seeds.size()); - - if( rank == _grid->ThisRank() ){ - fixedSeed ssrc(site_seeds); - typename source::result_type sinit = ssrc(); - _generators[l_idx] = RngEngine(sinit); - } - } - _seeded=1; - } //FIXME implement generic IO and create state save/restore //void SaveState(const std::string &file); @@ -354,11 +325,75 @@ PARALLEL_FOR_LOOP } }; + // This loop could be made faster to avoid the Ahmdahl by + // i) seed generators on each timeslice, for x=y=z=0; + // ii) seed generators on each z for x=y=0 + // iii)seed generators on each y,z for x=0 + // iv) seed generators on each y,z,x + // made possible by physical indexing. + template void Seed(source &src) + { + + typedef typename source::result_type seed_t; + std::uniform_int_distribution uid; + + int numseed=4; + int gsites = _grid->_gsites; + std::vector site_init(numseed); + std::vector gcoor; + + + // Master RngEngine + std::vector master_init(numseed); src.generate(master_init.begin(),master_init.end()); + _grid->Broadcast(0,(void *)&master_init[0],sizeof(seed_t)*numseed); + fixedSeed master_seed(master_init); + RngEngine master_engine(master_seed); + + // Per node RngEngine + std::vector node_init(numseed); + for(int r=0;r<_grid->ProcessorCount();r++) { + + std::vector rank_init(numseed); + for(int i=0;iThisRank() ) { + for(int i=0;iGlobalIndexToGlobalCoor(gidx,gcoor); + _grid->GlobalCoorToRankIndex(rank,o_idx,i_idx,gcoor); + + if( rank == _grid->ThisRank() ){ + int l_idx=generator_idx(o_idx,i_idx); + for(int i=0;i &seeds){ + CartesianCommunicator::BroadcastWorld(0,(void *)&seeds[0],sizeof(int)*seeds.size()); fixedSeed src(seeds); Seed(src); }