Apache SINGA
A distributed deep learning platform .
 All Classes Namespaces Files Functions Variables Typedefs Enumerator 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 "tensor.h"
11 #include "tensor_container.h"
12 
13 namespace mshadow {
18  template<typename Device>
19  class Random {};
20 
22  template<>
23  class Random<cpu> {
24  public:
29  Random<cpu>( int seed ){
30  #if MSHADOW_USE_MKL
31  int status = vslNewStream(&vStream_, VSL_BRNG_MT19937, seed);
32  utils::Assert( status == VSL_STATUS_OK, "MKL VSL Random engine failed to be initialized.\n" );
33  #else
34  srand(seed);
35  #endif
36  buffer_.Resize( Shape1( kRandBufferSize ) );
37  }
38  ~Random<cpu>() {
39  #if MSHADOW_USE_MKL
40  vslDeleteStream(&vStream_);
41  #endif
42  }
47  inline void Seed( int seed ){
48  #if MSHADOW_USE_MKL
49  int status = vslDeleteStream(&vStream_);
50  utils::Assert(status == VSL_STATUS_OK);
51  status = vslNewStream(&vStream_, VSL_BRNG_MT19937, seed);
52  utils::Assert(status == VSL_STATUS_OK);
53  #else
54  srand( seed );
55  #endif
56  }
64  template<int dim>
65  inline void SampleUniform( Tensor<cpu, dim> &dst, real_t a=0.0f, real_t b=1.0f ) {
66  Tensor<cpu, 2> mat = dst.FlatTo2D();
67  for ( index_t i = 0; i < mat.shape[1]; ++i ) {
68  #if MSHADOW_USE_MKL
69  #if MSHADOW_SINGLE_PRECISION
70  int status = vsRngUniform( 0, vStream_, mat.shape[0], mat[i].dptr, a, b );
71  #else
72  int status = vdRngUniform( 0, vStream_, mat.shape[0], mat[i].dptr, a, b );
73  #endif
74  utils::Assert(status == VSL_STATUS_OK, "Failed to generate random number by MKL.\n" );
75  #else
76  // use stdlib
77  for ( index_t j = 0; j < mat.shape[0]; ++j ) {
78  mat[i][j] = this->RandNext()*(b-a) + a;
79  }
80  #endif
81  }
82  }
90  template<int dim>
91  inline void SampleGaussian( Tensor<cpu, dim> &dst, real_t mu = 0.0f, real_t sigma = 1.0f ) {
92  if( sigma <= 0.0f ) {
93  dst = mu; return;
94  }
95  Tensor<cpu, 2> mat = dst.FlatTo2D();
96  for (index_t i = 0; i < mat.shape[1]; ++i) {
97  #if MSHADOW_USE_MKL
98  #if MSHADOW_SINGLE_PRECISION
99  int status = vsRngGaussian( 0, vStream_, mat.shape[0], mat[i].dptr, mu, sigma );
100  #else
101  int status = vdRngGaussian( 0, vStream_, mat.shape[0], mat[i].dptr, mu, sigma );
102  #endif
103  utils::Assert(status == VSL_STATUS_OK, "Failed to generate random number by MKL.\n" );
104  #else
105  real_t g1 = 0.0f, g2 = 0.0f;
106  for (index_t j = 0; j < mat.shape[0]; ++j) {
107  if( (j & 1) == 0 ){
108  this->SampleNormal2D( g1, g2 );
109  mat[i][j] = mu + g1 * sigma;
110  }else{
111  mat[i][j] = mu + g2 * sigma;
112  }
113  }
114  #endif
115  }
116  }
127  template<int dim>
129  buffer_.Resize( Shape1( shape.Size() ) );
130  this->SampleGaussian( buffer_, 0.0f, 1.0f );
131  return expr::reshape( buffer_, shape );
132  }
143  template<int dim>
145  buffer_.Resize( Shape1( shape.Size() ) );
146  this->SampleUniform( buffer_, 0.0f, 1.0f );
147  return expr::reshape( buffer_, shape );
148  }
149  private:
151  inline real_t RandNext( void ){
152  return static_cast<real_t>(rand()) / (static_cast<real_t>(RAND_MAX)+1.0f);
153  }
155  inline real_t RandNext2( void ){
156  return (static_cast<real_t>( rand() ) + 1.0 ) / (static_cast<real_t>(RAND_MAX) + 2.0);
157  }
163  inline void SampleNormal2D( real_t &xx, real_t &yy ){
164  real_t x,y,s;
165  do{
166  x = 2.0f * RandNext2() - 1.0f;
167  y = 2.0f * RandNext2() - 1.0f;
168  s = x*x + y*y;
169  }while( s >= 1.0f || s == 0.0f );
170  real_t t = std::sqrt( -2.0f * std::log( s ) / s ) ;
171  xx = x * t; yy = y * t;
172  }
173  private:
174  #if MSHADOW_USE_MKL
175 
176  VSLStreamStatePtr vStream_;
177  #endif
178 
179  TensorContainer<cpu,1> buffer_;
180  }; // class Random<cpu>
181 
182 #ifdef __CUDACC__
183 
185  template<>
186  class Random<gpu> {
187  public:
192  Random<gpu>(int seed) {
193  curandStatus_t status;
194  status = curandCreateGenerator(&gen_, CURAND_RNG_PSEUDO_DEFAULT);
195  utils::Assert(status == CURAND_STATUS_SUCCESS, "Can not create CURAND Generator");
196  this->Seed( seed );
197  buffer_.Resize( Shape1(kRandBufferSize) );
198  }
199 
200  ~Random<gpu>() {
201  curandStatus_t status;
202  status = curandDestroyGenerator(gen_);
203  utils::Assert(status == CURAND_STATUS_SUCCESS, "Destory CURAND Gen failed");
204  }
209  inline void Seed( int seed ){
210  curandStatus_t status;
211  status = curandSetPseudoRandomGeneratorSeed(gen_, seed);
212  utils::Assert(status == CURAND_STATUS_SUCCESS, "Set CURAND seed failed.");
213  }
221  template<int dim>
222  inline void SampleUniform(Tensor<gpu, dim> &dst, real_t a=0.0f, real_t b=1.0f) {
223  if( a == 0.0f && b == 1.0f ){
224  dst = this->uniform( dst.shape );
225  }else{
226  dst = this->uniform( dst.shape ) *(b-a) + a;
227  }
228  }
236  template<int dim>
237  inline void SampleGaussian(Tensor<gpu, dim> &dst, real_t mu = 0.0f, real_t sigma = 1.0f) {
238  dst = this->gaussian( dst.shape, mu, sigma );
239  }
252  template<int dim>
253  inline expr::ReshapeExp<Tensor<gpu,1>,dim,1> gaussian( Shape<dim> shape, real_t mu=0.0f, real_t sigma=1.0f){
254  size_t aligned_sz = ((shape.Size() + 1UL)>>1)<<1;
255  // allocate alligned size
256  buffer_.Resize( Shape1( aligned_sz ) );
257  buffer_.Resize( Shape1( shape.Size() ) );
258  curandStatus_t status;
259  #if MSHADOW_SINGLE_PRECISION
260  status = curandGenerateNormal(gen_, buffer_.dptr, aligned_sz , mu, sigma);
261  #else
262  status = curandGenerateNormalDouble(gen_, buffer_.dptr, buffer_.shape[0], mu, sigma);
263  #endif
264  utils::Assert(status == CURAND_STATUS_SUCCESS, "CURAND Gen Uniform failed\n");
265  return expr::reshape( buffer_, shape );
266  }
277  template<int dim>
278  inline expr::ReshapeExp<Tensor<gpu,1>,dim,1> uniform(Shape<dim> shape) {
279  buffer_.Resize( Shape1( shape.Size() ) );
280  curandStatus_t status;
281  #if MSHADOW_SINGLE_PRECISION
282  status = curandGenerateUniform(gen_, buffer_.dptr, buffer_.shape[0] );
283  #else
284  status = curandGenerateUniformDouble(gen_, buffer_.dptr, buffer_.shape[0] );
285  #endif
286  utils::Assert(status == CURAND_STATUS_SUCCESS, "CURAND Gen Uniform failed\n");
287  return expr::reshape( buffer_, shape );
288  }
289  private:
291  curandGenerator_t gen_;
293  TensorContainer<gpu, 1> buffer_;
294  }; // class Random<gpu>
295  #endif
296 
297 }; // namespace mshadow
298 
299 #endif // MSHADOW_TENSOR_RANDOM_H
random number generator
Definition: tensor_random.h:19
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:144
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
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:128
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:23
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:91
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:47
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:65
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