PetaVision  Alpha
Random.cpp
1 /*
2  * Random.cpp
3  *
4  * Created on: Aug 23, 2013
5  * Author: pschultz
6  */
7 
8 #include "Random.hpp"
9 #include "columns/RandomSeed.hpp"
10 #include "utils/PVLog.hpp"
11 
12 namespace PV {
13 
14 Random::Random() {
15  // Default constructor is called only by derived class constructors.
16  // Derived classes should call Random::initialize() themselves.
17  initialize_base();
18 }
19 
20 // N independent random number generators, all processes have the same N seeds.
21 Random::Random(int count) {
22  initialize_base();
23  initializeFromCount((unsigned int)count);
24 }
25 
26 // Each neuron in a layer has its own RNG. locptr defines the geometry of the
27 // layer.
28 // isExtended tells whether to consider getNumGlobalNeurons() or
29 // getNumGlobalExtended() neurons.
30 // The seed of each RNG is determined by *global* index; this way the initial
31 // state of the
32 // random number does not depend on the MPI configuration.
33 Random::Random(const PVLayerLoc *locptr, bool isExtended) {
34  initialize_base();
35  initializeFromLoc(locptr, isExtended);
36 }
37 
38 int Random::initialize_base() { return PV_SUCCESS; }
39 
40 // Initialize with repsect to nbatch, nx, ny, nf in extended space
41 int Random::initializeFromLoc(const PVLayerLoc *locptr, bool isExtended) {
42  int status = PV_SUCCESS;
43 
44  PVHalo halo;
45  if (isExtended) {
46  halo = locptr->halo;
47  }
48  else {
49  halo.lt = 0;
50  halo.rt = 0;
51  halo.dn = 0;
52  halo.up = 0;
53  }
54  int nxExt = locptr->nx + halo.lt + halo.rt;
55  int nyExt = locptr->ny + halo.up + halo.dn;
56  int nf = locptr->nf;
57  int nbatch = locptr->nbatch;
58  int rngCount = nxExt * nyExt * nf * nbatch;
59  // Calculate global size
60  int nxGlobalExt = locptr->nxGlobal + halo.lt + halo.rt;
61  int nyGlobalExt = locptr->nyGlobal + halo.up + halo.dn;
62  int nbatchGlobal = locptr->nbatchGlobal;
63  // Allocate buffer to store rngArraySize
64  rngArray.resize(rngCount);
65  if (status == PV_SUCCESS) {
66  int numTotalSeeds = nxGlobalExt * nyGlobalExt * nf * nbatchGlobal;
67  unsigned int seedBase = RandomSeed::instance()->allocate(numTotalSeeds);
68  int sb = nxExt * nyExt * nf;
69  int sy = nxExt * nf;
70  int sbGlobal = nxGlobalExt * nyGlobalExt * nf;
71  int syGlobal = nxGlobalExt * nf;
72 
73  // Only thing that is continuous in memory is nx and ny, so loop over batch
74  // and y
75  for (int kb = 0; kb < nbatch; kb++) {
76  for (int ky = 0; ky < nyExt; ky++) {
77  // Calculate start index into local rngArray
78  int localExtStart = kb * sb + ky * sy;
79  // Calculate offset of the seedBase
80  int globalExtStart =
81  (kb + locptr->kb0) * sbGlobal + (ky + locptr->ky0) * syGlobal + locptr->kx0;
82  size_t count = nxExt * nf;
83  cl_random_init(&(rngArray[localExtStart]), count, seedBase + globalExtStart);
84  }
85  }
86  }
87  return status;
88 }
89 
90 int Random::initializeFromCount(int count) {
91  int status = PV_SUCCESS;
92  rngArray.resize(count);
93  if (status == PV_SUCCESS) {
94  unsigned int seedBase = RandomSeed::instance()->allocate(count);
95  cl_random_init(rngArray.data(), (size_t)count, seedBase);
96  }
97  return status;
98 }
99 
100 float Random::uniformRandom(int localIndex) {
101  rngArray[localIndex] = cl_random_get(rngArray[localIndex]);
102  return rngArray[localIndex].s0 / (float)randomUIntMax();
103 }
104 
105 unsigned int Random::randomUInt(int localIndex) {
106  rngArray[localIndex] = cl_random_get(rngArray[localIndex]);
107  return rngArray[localIndex].s0;
108 }
109 
110 Random::~Random() {}
111 
112 } /* namespace PV */