Apache SINGA
A distributed deep learning platform .
 All Classes Namespaces Files Functions Variables Typedefs Macros
tensor_random.h
Go to the documentation of this file.
1 #ifndef MSHADOW_TENSOR_RANDOM_H
2 #define MSHADOW_TENSOR_RANDOM_H
3 
9 #include <cstdlib>
10 #include <random>
11 #include <chrono>
12 #include "tensor.h"
13 #include "tensor_container.h"
14 
15 namespace mshadow {
22  template<typename Device>
23  class Random {};
24 
26  template<>
27  class Random<cpu> {
28  public:
33  // obtain a seed from the system clock:
34  unsigned s= std::chrono::system_clock::now().time_since_epoch().count();
35  Seed(s);
36  }
41  Random<cpu>( int seed ){
42  #if MSHADOW_USE_MKL
43  int status = vslNewStream(&vStream_, VSL_BRNG_MT19937, seed);
44  utils::Assert( status == VSL_STATUS_OK, "MKL VSL Random engine failed to be initialized.\n" );
45  #else
46  //srand(seed);
47  gen_.seed(seed);
48  #endif
49  buffer_.Resize( Shape1( kRandBufferSize ) );
50  }
51  ~Random<cpu>() {
52  #if MSHADOW_USE_MKL
53  vslDeleteStream(&vStream_);
54  #endif
55  }
60  inline void Seed( int seed ){
61  #if MSHADOW_USE_MKL
62  int status = vslDeleteStream(&vStream_);
63  utils::Assert(status == VSL_STATUS_OK);
64  status = vslNewStream(&vStream_, VSL_BRNG_MT19937, seed);
65  utils::Assert(status == VSL_STATUS_OK);
66  #else
67  // srand( seed );
68  gen_.seed(seed);
69  #endif
70  }
71  template<int dim>
72  inline void SampleBinary(Tensor<cpu, dim> &src) {
73  SampleBinary(src, src);
74  }
75 
84  template<int dim>
86  real_t a=0.0f;
87  real_t b=1.0f;
88  Tensor<cpu, 2> dmat = dst.FlatTo2D();
89  Tensor<cpu, 2> smat = src.FlatTo2D();
90  std::uniform_real_distribution<real_t> distribution (a,b);
91  for ( index_t i = 0; i < dmat.shape[1]; ++i ) {
92  #if MSHADOW_USE_MKL
93  #if MSHADOW_SINGLE_PRECISION
94  int status = vsRngUniform( 0, vStream_, mat.shape[0], mat[i].dptr, a, b );
95  #else
96  int status = vdRngUniform( 0, vStream_, mat.shape[0], mat[i].dptr, a, b );
97  #endif
98  utils::Assert(status == VSL_STATUS_OK, "Failed to generate random number by MKL.\n" );
99  #else
100  // use stdlib
101  /*
102  for ( index_t j = 0; j < mat.shape[0]; ++j ) {
103  mat[i][j] = this->RandNext()*(b-a) + a;
104  }
105  */
106  for ( index_t j = 0; j < dmat.shape[0]; ++j ) {
107  dmat[i][j] = distribution(gen_) > smat[i][j] ? 0.0f: 1.0f;
108  }
109  #endif
110  }
111  }
119  template<int dim>
120  inline void SampleUniform( Tensor<cpu, dim> &dst, real_t a=0.0f, real_t b=1.0f ) {
121  Tensor<cpu, 2> mat = dst.FlatTo2D();
122  std::uniform_real_distribution<real_t> distribution (a,b);
123  for ( index_t i = 0; i < mat.shape[1]; ++i ) {
124  #if MSHADOW_USE_MKL
125  #if MSHADOW_SINGLE_PRECISION
126  int status = vsRngUniform( 0, vStream_, mat.shape[0], mat[i].dptr, a, b );
127  #else
128  int status = vdRngUniform( 0, vStream_, mat.shape[0], mat[i].dptr, a, b );
129  #endif
130  utils::Assert(status == VSL_STATUS_OK, "Failed to generate random number by MKL.\n" );
131  #else
132  // use stdlib
133  /*
134  for ( index_t j = 0; j < mat.shape[0]; ++j ) {
135  mat[i][j] = this->RandNext()*(b-a) + a;
136  }
137  */
138  for ( index_t j = 0; j < mat.shape[0]; ++j ) {
139  mat[i][j] = distribution(gen_);
140  }
141  #endif
142  }
143  }
151  template<int dim>
152  inline void SampleGaussian( Tensor<cpu, dim> &dst, real_t mu = 0.0f, real_t sigma = 1.0f ) {
153  if( sigma <= 0.0f ) {
154  dst = mu; return;
155  }
156  Tensor<cpu, 2> mat = dst.FlatTo2D();
157  std::normal_distribution<real_t> distribution (mu, sigma);
158  for (index_t i = 0; i < mat.shape[1]; ++i) {
159  #if MSHADOW_USE_MKL
160  #if MSHADOW_SINGLE_PRECISION
161  int status = vsRngGaussian( 0, vStream_, mat.shape[0], mat[i].dptr, mu, sigma );
162  #else
163  int status = vdRngGaussian( 0, vStream_, mat.shape[0], mat[i].dptr, mu, sigma );
164  #endif
165  utils::Assert(status == VSL_STATUS_OK, "Failed to generate random number by MKL.\n" );
166  #else
167  /*
168  real_t g1 = 0.0f, g2 = 0.0f;
169  for (index_t j = 0; j < mat.shape[0]; ++j) {
170  if( (j & 1) == 0 ){
171  this->SampleNormal2D( g1, g2 );
172  mat[i][j] = mu + g1 * sigma;
173  }else{
174  mat[i][j] = mu + g2 * sigma;
175  }
176  }
177  */
178  for (index_t j = 0; j < mat.shape[0]; ++j) {
179  mat[i][j] = distribution(gen_);
180  }
181  #endif
182  }
183  }
194  template<int dim>
196  buffer_.Resize( Shape1( shape.Size() ) );
197  this->SampleGaussian( buffer_, 0.0f, 1.0f );
198  return expr::reshape( buffer_, shape );
199  }
210  template<int dim>
212  buffer_.Resize( Shape1( shape.Size() ) );
213  this->SampleUniform( buffer_, 0.0f, 1.0f );
214  return expr::reshape( buffer_, shape );
215  }
216  private:
218  inline real_t RandNext( void ){
219  return static_cast<real_t>(rand()) / (static_cast<real_t>(RAND_MAX)+1.0f);
220  }
222  inline real_t RandNext2( void ){
223  return (static_cast<real_t>( rand() ) + 1.0 ) / (static_cast<real_t>(RAND_MAX) + 2.0);
224  }
230  inline void SampleNormal2D( real_t &xx, real_t &yy ){
231  real_t x,y,s;
232  do{
233  x = 2.0f * RandNext2() - 1.0f;
234  y = 2.0f * RandNext2() - 1.0f;
235  s = x*x + y*y;
236  }while( s >= 1.0f || s == 0.0f );
237  real_t t = std::sqrt( -2.0f * std::log( s ) / s ) ;
238  xx = x * t; yy = y * t;
239  }
240  private:
241  #if MSHADOW_USE_MKL
242 
243  VSLStreamStatePtr vStream_;
244  #endif
245 
246  TensorContainer<cpu,1> buffer_;
247 
249  std::mt19937 gen_;
250  }; // class Random<cpu>
251 
252 #ifdef __CUDACC__
253 
255  template<>
256  class Random<gpu> {
257  public:
262  Random<gpu>(int seed) {
263  curandStatus_t status;
264  status = curandCreateGenerator(&gen_, CURAND_RNG_PSEUDO_DEFAULT);
265  utils::Assert(status == CURAND_STATUS_SUCCESS, "Can not create CURAND Generator");
266  this->Seed( seed );
267  buffer_.Resize( Shape1(kRandBufferSize) );
268  }
269 
270  ~Random<gpu>() {
271  curandStatus_t status;
272  status = curandDestroyGenerator(gen_);
273  utils::Assert(status == CURAND_STATUS_SUCCESS, "Destory CURAND Gen failed");
274  }
279  inline void Seed( int seed ){
280  curandStatus_t status;
281  status = curandSetPseudoRandomGeneratorSeed(gen_, seed);
282  utils::Assert(status == CURAND_STATUS_SUCCESS, "Set CURAND seed failed.");
283  }
291  template<int dim>
292  inline void SampleUniform(Tensor<gpu, dim> &dst, real_t a=0.0f, real_t b=1.0f) {
293  if( a == 0.0f && b == 1.0f ){
294  dst = this->uniform( dst.shape );
295  }else{
296  dst = this->uniform( dst.shape ) *(b-a) + a;
297  }
298  }
306  template<int dim>
307  inline void SampleGaussian(Tensor<gpu, dim> &dst, real_t mu = 0.0f, real_t sigma = 1.0f) {
308  dst = this->gaussian( dst.shape, mu, sigma );
309  }
322  template<int dim>
323  inline expr::ReshapeExp<Tensor<gpu,1>,dim,1> gaussian( Shape<dim> shape, real_t mu=0.0f, real_t sigma=1.0f){
324  size_t aligned_sz = ((shape.Size() + 1UL)>>1)<<1;
325  // allocate alligned size
326  buffer_.Resize( Shape1( aligned_sz ) );
327  buffer_.Resize( Shape1( shape.Size() ) );
328  curandStatus_t status;
329  #if MSHADOW_SINGLE_PRECISION
330  status = curandGenerateNormal(gen_, buffer_.dptr, aligned_sz , mu, sigma);
331  #else
332  status = curandGenerateNormalDouble(gen_, buffer_.dptr, buffer_.shape[0], mu, sigma);
333  #endif
334  utils::Assert(status == CURAND_STATUS_SUCCESS, "CURAND Gen Uniform failed\n");
335  return expr::reshape( buffer_, shape );
336  }
347  template<int dim>
348  inline expr::ReshapeExp<Tensor<gpu,1>,dim,1> uniform(Shape<dim> shape) {
349  buffer_.Resize( Shape1( shape.Size() ) );
350  curandStatus_t status;
351  #if MSHADOW_SINGLE_PRECISION
352  status = curandGenerateUniform(gen_, buffer_.dptr, buffer_.shape[0] );
353  #else
354  status = curandGenerateUniformDouble(gen_, buffer_.dptr, buffer_.shape[0] );
355  #endif
356  utils::Assert(status == CURAND_STATUS_SUCCESS, "CURAND Gen Uniform failed\n");
357  return expr::reshape( buffer_, shape );
358  }
359  private:
361  curandGenerator_t gen_;
363  TensorContainer<gpu, 1> buffer_;
364  }; // class Random<gpu>
365  #endif
366 
367 }; // namespace mshadow
368 
369 #endif // MSHADOW_TENSOR_RANDOM_H
random number generator
Definition: tensor_random.h:23
expr::ReshapeExp< Tensor< cpu, 1 >, dim, 1 > uniform(Shape< dim > shape)
return a temporal expression storing standard uniform [0,1) the temporal tensor is only valid before ...
Definition: tensor_random.h:211
unsigned index_t
type that will be used for index
Definition: tensor_base.h:123
void Assert(bool exp)
assert a expression is true
Definition: tensor_base.h:285
float real_t
type that will be used for content
Definition: tensor_base.h:118
void SampleBinary(Tensor< cpu, dim > &dst, Tensor< cpu, dim > &src)
generate binary data according to a probability matrix
Definition: tensor_random.h:85
header file of tensor data structure and functions covention: this lib requires explicit memory alloc...
device name CPU
Definition: tensor.h:185
const unsigned kRandBufferSize
buffer size for each random number generator
Definition: tensor_base.h:112
expr::ReshapeExp< Tensor< cpu, 1 >, dim, 1 > gaussian(Shape< dim > shape)
return a temporal expression storing standard gaussian random variables the temporal tensor is only v...
Definition: tensor_random.h:195
MSHADOW_XINLINE Shape< 1 > Shape1(index_t s0)
construct a one dimension shape, stride will equal s0
Definition: tensor.h:142
CPU random number generator.
Definition: tensor_random.h:27
real_t * dptr
pointer to the data
Definition: tensor.h:215
MSHADOW_XINLINE Tensor< Device, 2 > FlatTo2D(void) const
flatten the tensor to 2 dimension, collapse the higher dimensions together
Definition: tensor.h:229
void SampleGaussian(Tensor< cpu, dim > &dst, real_t mu=0.0f, real_t sigma=1.0f)
generate data from standard gaussian
Definition: tensor_random.h:152
reshape the content to another shape input: Tensor<Device,dimsrc>: ishape output: Tensor<Device...
Definition: tensor_expr_ext.h:102
Shape< dimension > shape
shape of the tensor
Definition: tensor.h:217
void Seed(int seed)
seed random number generator using this seed
Definition: tensor_random.h:60
void SampleUniform(Tensor< cpu, dim > &dst, real_t a=0.0f, real_t b=1.0f)
generate data from uniform [a,b)
Definition: tensor_random.h:120
tensor container that does memory allocation and resize like STL
MSHADOW_XINLINE size_t Size(void) const
Definition: tensor.h:82
general tensor
Definition: tensor.h:206
ReshapeExp< SrcExp, dimdst, ExpInfo< SrcExp >::kDim > reshape(const Exp< SrcExp, etype > &src, Shape< dimdst > oshape)
a expression that reshapes a tensor to another shape
Definition: tensor_expr_ext.h:406