You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mxnet.apache.org by GitBox <gi...@apache.org> on 2017/12/22 23:48:48 UTC

[GitHub] sxjscience commented on a change in pull request #9119: fix random generator: do not gen seed each time

sxjscience commented on a change in pull request #9119: fix random generator: do not gen seed each time
URL: https://github.com/apache/incubator-mxnet/pull/9119#discussion_r158569884
 
 

 ##########
 File path: src/common/random_generator.h
 ##########
 @@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*!
+ * Copyright (c) 2017 by Contributors
+ * \file random_generator.h
+ * \brief Native random number generator.
+ */
+#ifndef MXNET_COMMON_RANDOM_GENERATOR_H_
+#define MXNET_COMMON_RANDOM_GENERATOR_H_
+
+#include <mxnet/base.h>
+#include <random>
+#include <new>
+
+#if MXNET_USE_CUDA
+#include <cuda.h>
+#include <cuda_runtime.h>
+#include <curand_kernel.h>
+#endif  // MXNET_USE_CUDA
+
+using namespace mshadow;
+
+namespace mxnet {
+namespace common {
+namespace random {
+
+template<typename Device, typename DType MSHADOW_DEFAULT_DTYPE>
+class RandGenerator;
+
+// Elementary random number generation for int/uniform/gaussian in CPU and GPU.
+// Will use float data type whenever instantiated for half_t or any other non
+// standard real type.
+template<typename Device, typename DType MSHADOW_DEFAULT_DTYPE>
+class RandGeneratorImpl;
+
+// at least how many random numbers should be generated by one CPU thread.
+const int kCPUMinRndNumberPerThread = 64;
+// store how many global random states for CPU.
+const int kCPURndStateNum = 1024;
+
+template<typename DType>
+class RandGeneratorImpl<cpu, DType> {
+ public:
+  typedef typename std::conditional<std::is_floating_point<DType>::value,
+                                    DType, double>::type FType;
+
+  explicit RandGeneratorImpl<cpu, DType>(std::mt19937 *ptr_engine) : engine_(ptr_engine) {}
+
+  MSHADOW_XINLINE int rand() { return engine_->operator()(); }
+
+  MSHADOW_XINLINE FType uniform() {
+    typedef typename std::conditional<std::is_integral<DType>::value,
+                                      std::uniform_int_distribution<DType>,
+                                      std::uniform_real_distribution<FType>>::type GType;
+    GType dist_uniform;
+    return dist_uniform(*engine_);
+  }
+
+  MSHADOW_XINLINE FType normal() {
+    std::normal_distribution<FType> dist_normal;
+    return dist_normal(*engine_);
+  }
+
+ private:
+  std::mt19937 *engine_;
+};
+
+template<typename DType>
+class RandGenerator<cpu, DType> {
+ public:
+  MSHADOW_XINLINE void dispose() {}
+
+  MSHADOW_XINLINE RandGeneratorImpl<cpu, DType> Get(int idx = 0) {
+    std::mt19937 *ptr_engine = &states_[idx];
+    RandGeneratorImpl<cpu, DType> gen(ptr_engine);
+    return gen;
+  }
+
+  MSHADOW_XINLINE void Seed(Stream<cpu> *, uint32_t seed) {
+    for (int i = 0; i < kCPURndStateNum; ++i) (states_ + i)->seed(seed + i);
+  }
+
+  MSHADOW_XINLINE void set_state(int idx, const std::mt19937 &state) {
+    states_[idx] = state;
+  }
+
+ private:
+  std::mt19937 states_[kCPURndStateNum];
+};
+
+#if MXNET_USE_CUDA
+
+// at least how many random numbers should be generated by one GPU thread.
+const int kGPUMinRndNumberPerThread = 64;
+// store how many global random states for GPU.
+const int kGPURndStateNum = 32768;
+
+// uniform number generation in Cuda made consistent with stl (include 0 but exclude 1)
+// by using 1.0-curand_uniform().
+// Needed as some samplers in sampler.h won't be able to deal with
+// one of the boundary cases.
+template<typename DType>
+class RandGeneratorImpl<gpu, DType> {
+ public:
+  // Copy state to local memory for efficiency.
+  __device__ explicit RandGeneratorImpl(curandStatePhilox4_32_10_t *state)
+      : state_(*state) {}
+
+  MSHADOW_FORCE_INLINE __device__ int rand() {
+    return curand(&state_);
+  }
+
+  MSHADOW_FORCE_INLINE __device__ float uniform() {
+    return static_cast<float>(1.0) - curand_uniform(&state_);
+  }
+
+  MSHADOW_FORCE_INLINE __device__ float normal() {
+    return curand_normal(&state_);
+  }
+
+  MSHADOW_FORCE_INLINE __device__ curandStatePhilox4_32_10_t get_state() {
+    return state_;
+  }
+
+ private:
+  curandStatePhilox4_32_10_t state_;
+};
+
+template<>
+class RandGeneratorImpl<gpu, double> {
+ public:
+  // Copy state to local memory for efficiency.
+  __device__ explicit RandGeneratorImpl(curandStatePhilox4_32_10_t *state)
+      : state_(*state) {}
 
 Review comment:
   I haven't tested the case for multiple runs of the generator. I should add that.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services