梳理caffe代码common(八)


梳理caffe代码common(八)

由于想梳理data_layer的过程,整理一半发现有几个非常重要的头文件就是题目列出的这几个:

追本溯源,先从根基开始学起。这里面都是些什么鬼呢?

common类

命名空间的使用:google、cv、caffe{boost、std}。然后在项目中就可以随意使用google、opencv、c++的标准库、以及c++高级库boost。caffe采用单例模式封装boost的智能指针(caffe的灵魂)、std一些标准的用法、重要的初始化内容(随机数生成器的内容以及google的gflags和glog的初始化)。 提供一个统一的接口,方便移植和开发。为毛使用随机数?我也不是很清楚,知乎的一个解释:

随机数在caffe中是非常重要的,最重要的应用是权值的初始化,如高斯、xavier等,初始化的好坏直接影响最终的训练结果,其他的应用如训练图像的随机crop和mirror、dropout层的神经元的选择。RNG类是对Boost以及STL中随机数函数的封装,以方便使用。至于想每次产生相同的随机数,只要设定固定的种子即可,见caffe.proto中random_seed的定义:
    // If non-negative, the seed with which the Solver will initialize the Caffe
    // random number generator -- useful for reproducible results. Otherwise,
    // (and by default) initialize using a seed derived from the system clock.
    optional int64 random_seed = 20 [default = -1];

头文件:

 

[cpp]  view plain  copy
 
 在CODE上查看代码片派生到我的代码片
  1. #ifndef CAFFE_COMMON_HPP_  
  2. #define CAFFE_COMMON_HPP_  
  3.   
  4. #include <boost/shared_ptr.hpp>  
  5. #include <gflags/gflags.h>  
  6. #include <glog/logging.h>  
  7.   
  8. #include <climits>  
  9. #include <cmath>  
  10. #include <fstream>  // NOLINT(readability/streams)  
  11. #include <iostream>  // NOLINT(readability/streams)  
  12. #include <map>  
  13. #include <set>  
  14. #include <sstream>  
  15. #include <string>  
  16. #include <utility>  // pair  
  17. #include <vector>  
  18.   
  19. #include "caffe/util/device_alternate.hpp"  
  20.   
  21. // Convert macro to string  
  22. // 将宏转换为字符串  
  23. #define STRINGIFY(m) #m  
  24. #define AS_STRING(m) STRINGIFY(m)  
  25.   
  26. // gflags 2.1 issue: namespace google was changed to gflags without warning.  
  27. // Luckily we will be able to use GFLAGS_GFLAGS_H_ to detect if it is version  
  28. // 2.1. If yes, we will add a temporary solution to redirect the namespace.  
  29. // TODO(Yangqing): Once gflags solves the problem in a more elegant way, let's  
  30. // remove the following hack.  
  31. // 检测gflags2.1  
  32. #ifndef GFLAGS_GFLAGS_H_  
  33. namespace gflags = google;  
  34. #endif  // GFLAGS_GFLAGS_H_  
  35.   
  36. // Disable the copy and assignment operator for a class.  
  37. // 禁止某个类通过构造函数直接初始化另一个类  
  38. // 禁止某个类通过赋值来初始化另一个类  
  39. #define DISABLE_COPY_AND_ASSIGN(classname) \  
  40. private:\  
  41.   classname(const classname&);\  
  42.   classname& operator=(const classname&)  
  43.   
  44. // Instantiate a class with float and double specifications.  
  45. #define INSTANTIATE_CLASS(classname) \  
  46.   char gInstantiationGuard##classname; \  
  47.   template class classname<float>; \  
  48.   template class classname<double>  
  49.   
  50. // 初始化GPU的前向传播函数  
  51. #define INSTANTIATE_LAYER_GPU_FORWARD(classname) \  
  52.   template void classname<float>::Forward_gpu( \  
  53.       const std::vector<Blob<float>*>& bottom, \  
  54.       const std::vector<Blob<float>*>& top); \  
  55.   template void classname<double>::Forward_gpu( \  
  56.       const std::vector<Blob<double>*>& bottom, \  
  57.       const std::vector<Blob<double>*>& top);  
  58.   
  59. // 初始化GPU的反向传播函数  
  60. #define INSTANTIATE_LAYER_GPU_BACKWARD(classname) \  
  61.   template void classname<float>::Backward_gpu( \  
  62.       const std::vector<Blob<float>*>& top, \  
  63.       const std::vector<bool>& propagate_down, \  
  64.       const std::vector<Blob<float>*>& bottom); \  
  65.   template void classname<double>::Backward_gpu( \  
  66.       const std::vector<Blob<double>*>& top, \  
  67.       const std::vector<bool>& propagate_down, \  
  68.       const std::vector<Blob<double>*>& bottom)  
  69.   
  70. // 初始化GPU的前向反向传播函数  
  71. #define INSTANTIATE_LAYER_GPU_FUNCS(classname) \  
  72.   INSTANTIATE_LAYER_GPU_FORWARD(classname); \  
  73.   INSTANTIATE_LAYER_GPU_BACKWARD(classname)  
  74.   
  75. // A simple macro to mark codes that are not implemented, so that when the code  
  76. // is executed we will see a fatal log.  
  77. // NOT_IMPLEMENTED实际上调用的LOG(FATAL) << "Not Implemented Yet"  
  78. #define NOT_IMPLEMENTED LOG(FATAL) << "Not Implemented Yet"  
  79.   
  80. // See PR #1236  
  81. namespace cv { class Mat; }  
  82. /* 
  83. Caffe类里面有个RNG,RNG这个类里面还有个Generator类在RNG里面会用到Caffe里面的Get()函数来获取一个新的Caffe类的实例。然后RNG里面用到了Generator。Generator是实际产生随机数的。 
  84. */  
  85. namespace caffe {  
  86.   
  87. // We will use the boost shared_ptr instead of the new C++11 one mainly  
  88. // because cuda does not work (at least now) well with C++11 features.  
  89. using boost::shared_ptr;  
  90.   
  91. // Common functions and classes from std that caffe often uses.  
  92. using std::fstream;  
  93. using std::ios;  
  94. //using std::isnan;//vc++的编译器不支持这两个函数  
  95. //using std::isinf;  
  96. using std::iterator;  
  97. using std::make_pair;  
  98. using std::map;  
  99. using std::ostringstream;  
  100. using std::pair;  
  101. using std::set;  
  102. using std::string;  
  103. using std::stringstream;  
  104. using std::vector;  
  105.   
  106. // A global initialization function that you should call in your main function.  
  107. // Currently it initializes google flags and google logging.  
  108. void GlobalInit(int* pargc, char*** pargv);  
  109.   
  110. // A singleton class to hold common caffe stuff, such as the handler that  
  111. // caffe is going to use for cublas, curand, etc.  
  112. class Caffe {  
  113.  public:  
  114.   ~Caffe();  
  115.   
  116.   // Thread local context for Caffe. Moved to common.cpp instead of  
  117.   // including boost/thread.hpp to avoid a boost/NVCC issues (#1009, #1010)  
  118.   // on OSX. Also fails on Linux with CUDA 7.0.18.  
  119. //Get函数利用Boost的局部线程存储功能实现  
  120.   static Caffe& Get();  
  121. //Brew就是CPU,GPU的枚举类型,这个名字是不是来自Homebrew???Mac的软件包管理器,我猜的。。。。  
  122.   enum Brew { CPU, GPU };  
  123.   
  124.   // This random number generator facade hides boost and CUDA rng  
  125.   // implementation from one another (for cross-platform compatibility).  
  126.   class RNG {  
  127.    public:  
  128.     RNG();//利用系统的熵池或者时间来初始化RNG内部的generator_  
  129.     explicit RNG(unsigned int seed);  
  130.     explicit RNG(const RNG&);  
  131.     RNG& operator=(const RNG&);  
  132.     void* generator();  
  133.    private:  
  134.     class Generator;  
  135.     shared_ptr<Generator> generator_;  
  136.   };  
  137.   
  138.   // Getters for boost rng, curand, and cublas handles  
  139.   inline static RNG& rng_stream() {  
  140.     if (!Get().random_generator_) {  
  141.       Get().random_generator_.reset(new RNG());  
  142.     }  
  143.     return *(Get().random_generator_);  
  144.   }  
  145. #ifndef CPU_ONLY// GPU  
  146.   inline static cublasHandle_t cublas_handle() { return Get().cublas_handle_; }// cublas的句柄  
  147.   inline static curandGenerator_t curand_generator() {//curandGenerator句柄  
  148.     return Get().curand_generator_;  
  149.   }  
  150. #endif  
  151. //下面这一块就是设置CPU和GPU以及训练的时候线程并行数目吧  
  152.   // Returns the mode: running on CPU or GPU.  
  153.   inline static Brew mode() { return Get().mode_; }  
  154.   // The setters for the variables  
  155.   // Sets the mode. It is recommended that you don't change the mode halfway  
  156.   // into the program since that may cause allocation of pinned memory being  
  157.   // freed in a non-pinned way, which may cause problems - I haven't verified  
  158.   // it personally but better to note it here in the header file.  
  159.   inline static void set_mode(Brew mode) { Get().mode_ = mode; }  
  160.   // Sets the random seed of both boost and curand  
  161.   static void set_random_seed(const unsigned int seed);  
  162.   // Sets the device. Since we have cublas and curand stuff, set device also  
  163.   // requires us to reset those values.  
  164.   static void SetDevice(const int device_id);  
  165.   // Prints the current GPU status.  
  166.   static void DeviceQuery();  
  167.   // Parallel training info  
  168.   inline static int solver_count() { return Get().solver_count_; }  
  169.   inline static void set_solver_count(int val) { Get().solver_count_ = val; }  
  170.   inline static bool root_solver() { return Get().root_solver_; }  
  171.   inline static void set_root_solver(bool val) { Get().root_solver_ = val; }  
  172.   
  173.  protected:  
  174. #ifndef CPU_ONLY  
  175.   cublasHandle_t cublas_handle_;// cublas的句柄   
  176.   curandGenerator_t curand_generator_;// curandGenerator句柄  
  177. #endif  
  178.   shared_ptr<RNG> random_generator_;  
  179.   
  180.   Brew mode_;  
  181.   int solver_count_;  
  182.   bool root_solver_;  
  183.   
  184.  private:  
  185.   // The private constructor to avoid duplicate instantiation.  
  186. //避免实例化  
  187.   Caffe();  
  188.   // 禁止caffe这个类被复制构造函数和赋值进行构造  
  189.   DISABLE_COPY_AND_ASSIGN(Caffe);  
  190. };  
  191.   
  192. }  // namespace caffe  
  193.   
  194. #endif  // CAFFE_COMMON_HPP_  
cpp文件:

 

 

[cpp]  view plain  copy
 
 在CODE上查看代码片派生到我的代码片
  1. #include <boost/thread.hpp>  
  2. #include <glog/logging.h>  
  3. #include <cmath>  
  4. #include <cstdio>  
  5. #include <ctime>  
  6.   
  7. #include "caffe/common.hpp"  
  8. #include "caffe/util/rng.hpp"  
  9.   
  10. namespace caffe {  
  11.   
  12. // Make sure each thread can have different values.  
  13. // boost::thread_specific_ptr是线程局部存储机制  
  14. // 一开始的值是NULL  
  15. static boost::thread_specific_ptr<Caffe> thread_instance_;  
  16.   
  17. Caffe& Caffe::Get() {  
  18.   if (!thread_instance_.get()) {// 如果当前线程没有caffe实例  
  19.     thread_instance_.reset(new Caffe());// 则新建一个caffe的实例并返回  
  20.   }  
  21.   return *(thread_instance_.get());  
  22. }  
  23.   
  24. // random seeding  
  25. // linux下的熵池下获取随机数的种子  
  26. int64_t cluster_seedgen(void) {  
  27.   int64_t s, seed, pid;  
  28.   FILE* f = fopen("/dev/urandom", "rb");  
  29.   if (f && fread(&seed, 1, sizeof(seed), f) == sizeof(seed)) {  
  30.     fclose(f);  
  31.     return seed;  
  32.   }  
  33.   
  34.   LOG(INFO) << "System entropy source not available, "  
  35.               "using fallback algorithm to generate seed instead.";  
  36.   if (f)  
  37.     fclose(f);  
  38.   // 采用传统的基于时间来生成随机数种子  
  39.   pid = getpid();  
  40.   s = time(NULL);  
  41.   seed = std::abs(((s * 181) * ((pid - 83) * 359)) % 104729);  
  42.   return seed;  
  43. }  
  44. // 初始化gflags和glog  
  45. void GlobalInit(int* pargc, char*** pargv) {  
  46.   // Google flags.  
  47.   ::gflags::ParseCommandLineFlags(pargc, pargv, true);  
  48.   // Google logging.  
  49.   ::google::InitGoogleLogging(*(pargv)[0]);  
  50.   // Provide a backtrace on segfault.  
  51.   ::google::InstallFailureSignalHandler();  
  52. }  
  53. #ifdef CPU_ONLY  // CPU-only Caffe.  
  54. Caffe::Caffe()  
  55.     : random_generator_(), mode_(Caffe::CPU),// shared_ptr<RNG> random_generator_;   Brew mode_;  
  56.       solver_count_(1), root_solver_(true) { }// int solver_count_;   bool root_solver_;  
  57. Caffe::~Caffe() { }  
  58. //  手动设定随机数生成器的种子  
  59. void Caffe::set_random_seed(const unsigned int seed) {  
  60.   // RNG seed  
  61.   Get().random_generator_.reset(new RNG(seed));  
  62. <span style="font-family:Microsoft YaHei;">}</span>  
  63. void Caffe::SetDevice(const int device_id) {  
  64.   NO_GPU;  
  65. }  
  66. void Caffe::DeviceQuery() {  
  67.   NO_GPU;  
  68. }  
  69. // 定义RNG内部的Generator类  
  70. class Caffe::RNG::Generator {  
  71.  public:  
  72.   Generator() : rng_(new caffe::rng_t(cluster_seedgen())) {}// linux下的熵池生成随机数种子,注意typedef boost::mt19937 rng_t;这个在utils/rng.hpp头文件里面  
  73.   explicit Generator(unsigned int seed) : rng_(new caffe::rng_t(seed)) {}// 采用给定的种子初始化  
  74.   caffe::rng_t* rng() { return rng_.get(); }// 属性  
  75.  private:  
  76.   shared_ptr<caffe::rng_t> rng_;// 内部变量  
  77. };  
  78. // 实现RNG内部的构造函数  
  79. Caffe::RNG::RNG() : generator_(new Generator()) { }  
  80. Caffe::RNG::RNG(unsigned int seed) : generator_(new Generator(seed)) { }  
  81. // 实现RNG内部的运算符重载  
  82. Caffe::RNG& Caffe::RNG::operator=(const RNG& other) {  
  83.   generator_ = other.generator_;  
  84.   return *this;  
  85. }  
  86. void* Caffe::RNG::generator() {  
  87.   return static_cast<void*>(generator_->rng());  
  88. }  
  89. #else  // Normal GPU + CPU Caffe.  
  90. // 构造函数,初始化cublas和curand库的句柄  
  91. Caffe::Caffe()  
  92.     : cublas_handle_(NULL), curand_generator_(NULL), random_generator_(),  
  93.     mode_(Caffe::CPU), solver_count_(1), root_solver_(true) {  
  94.   // Try to create a cublas handler, and report an error if failed (but we will  
  95.   // keep the program running as one might just want to run CPU code).  
  96.   // 初始化cublas并获得句柄  
  97.   if (cublasCreate(&cublas_handle_) != CUBLAS_STATUS_SUCCESS) {  
  98.     LOG(ERROR) << "Cannot create Cublas handle. Cublas won't be available.";  
  99.   }  
  100.   // Try to create a curand handler.  
  101.   if (curandCreateGenerator(&curand_generator_, CURAND_RNG_PSEUDO_DEFAULT)  
  102.       != CURAND_STATUS_SUCCESS ||  
  103.       curandSetPseudoRandomGeneratorSeed(curand_generator_, cluster_seedgen())  
  104.       != CURAND_STATUS_SUCCESS) {  
  105.     LOG(ERROR) << "Cannot create Curand generator. Curand won't be available.";  
  106.   }  
  107. }  
  108.   
  109. Caffe::~Caffe() {  
  110.   // 销毁句柄  
  111.   if (cublas_handle_) CUBLAS_CHECK(cublasDestroy(cublas_handle_));  
  112.   if (curand_generator_) {  
  113.     CURAND_CHECK(curandDestroyGenerator(curand_generator_));  
  114.   }  
  115. }  
  116. // 初始化CUDA的随机数种子以及cpu的随机数种子  
  117. void Caffe::set_random_seed(const unsigned int seed) {  
  118.   // Curand seed  
  119.   static bool g_curand_availability_logged = false;// 判断是否log了curand的可用性,如果没有则log一次,log之后则再也不log,用的是静态变量  
  120.   if (Get().curand_generator_) {  
  121.     // CURAND_CHECK见/utils/device_alternate.hpp中的宏定义  
  122.     CURAND_CHECK(curandSetPseudoRandomGeneratorSeed(curand_generator(),  
  123.         seed));  
  124.     CURAND_CHECK(curandSetGeneratorOffset(curand_generator(), 0));  
  125.   } else {  
  126.     if (!g_curand_availability_logged) {  
  127.         LOG(ERROR) <<  
  128.             "Curand not available. Skipping setting the curand seed.";  
  129.         g_curand_availability_logged = true;  
  130.     }  
  131.   }  
  132.   // RNG seed  
  133.   // CPU code  
  134.   Get().random_generator_.reset(new RNG(seed));  
  135. }  
  136.   
  137. // 设置GPU设备并初始化句柄以及随机数种子  
  138. void Caffe::SetDevice(const int device_id) {  
  139.   int current_device;  
  140.   CUDA_CHECK(cudaGetDevice(¤t_device));// 获取当前设备id  
  141.   if (current_device == device_id) {  
  142.     return;  
  143.   }  
  144.   // The call to cudaSetDevice must come before any calls to Get, which  
  145.   // may perform initialization using the GPU.  
  146.   // 在Get之前必须先执行cudasetDevice函数  
  147.   CUDA_CHECK(cudaSetDevice(device_id));  
  148.   // 清理以前的句柄  
  149.   if (Get().cublas_handle_) CUBLAS_CHECK(cublasDestroy(Get().cublas_handle_));  
  150.   if (Get().curand_generator_) {  
  151.     CURAND_CHECK(curandDestroyGenerator(Get().curand_generator_));  
  152.   }  
  153.   // 创建新句柄  
  154.   CUBLAS_CHECK(cublasCreate(&Get().cublas_handle_));  
  155.   CURAND_CHECK(curandCreateGenerator(&Get().curand_generator_,  
  156.       CURAND_RNG_PSEUDO_DEFAULT));  
  157.   // 设置随机数种子  
  158.   CURAND_CHECK(curandSetPseudoRandomGeneratorSeed(Get().curand_generator_,  
  159.       cluster_seedgen()));  
  160. }  
  161.   
  162. // 获取设备信息  
  163. void Caffe::DeviceQuery() {  
  164.   cudaDeviceProp prop;  
  165.   int device;  
  166.   if (cudaSuccess != cudaGetDevice(&device)) {  
  167.     printf("No cuda device present.\n");  
  168.     return;  
  169.   }  
  170.   // #define CUDA_CHECK(condition) \  
  171.   /* Code block avoids redefinition of cudaError_t error */ \  
  172.   //do { \  
  173.   //  cudaError_t error = condition; \  
  174.   //  CHECK_EQ(error, cudaSuccess) << " " << cudaGetErrorString(error); \  
  175.   //} while (0)  
  176.   CUDA_CHECK(cudaGetDeviceProperties(&prop, device));  
  177.   LOG(INFO) << "Device id:                     " << device;  
  178.   LOG(INFO) << "Major revision number:         " << prop.major;  
  179.   LOG(INFO) << "Minor revision number:         " << prop.minor;  
  180.   LOG(INFO) << "Name:                          " << prop.name;  
  181.   LOG(INFO) << "Total global memory:           " << prop.totalGlobalMem;  
  182.   LOG(INFO) << "Total shared memory per block: " << prop.sharedMemPerBlock;  
  183.   LOG(INFO) << "Total registers per block:     " << prop.regsPerBlock;  
  184.   LOG(INFO) << "Warp size:                     " << prop.warpSize;  
  185.   LOG(INFO) << "Maximum memory pitch:          " << prop.memPitch;  
  186.   LOG(INFO) << "Maximum threads per block:     " << prop.maxThreadsPerBlock;  
  187.   LOG(INFO) << "Maximum dimension of block:    "  
  188.       << prop.maxThreadsDim[0] << ", " << prop.maxThreadsDim[1] << ", "  
  189.       << prop.maxThreadsDim[2];  
  190.   LOG(INFO) << "Maximum dimension of grid:     "  
  191.       << prop.maxGridSize[0] << ", " << prop.maxGridSize[1] << ", "  
  192.       << prop.maxGridSize[2];  
  193.   LOG(INFO) << "Clock rate:                    " << prop.clockRate;  
  194.   LOG(INFO) << "Total constant memory:         " << prop.totalConstMem;  
  195.   LOG(INFO) << "Texture alignment:             " << prop.textureAlignment;  
  196.   LOG(INFO) << "Concurrent copy and execution: "  
  197.       << (prop.deviceOverlap ? "Yes" : "No");  
  198.   LOG(INFO) << "Number of multiprocessors:     " << prop.multiProcessorCount;  
  199.   LOG(INFO) << "Kernel execution timeout:      "  
  200.       << (prop.kernelExecTimeoutEnabled ? "Yes" : "No");  
  201.   return;  
  202. }  
  203.   
  204.   
  205. class Caffe::RNG::Generator {  
  206.  public:  
  207.   Generator() : rng_(new caffe::rng_t(cluster_seedgen())) {}  
  208.   explicit Generator(unsigned int seed) : rng_(new caffe::rng_t(seed)) {}  
  209.   caffe::rng_t* rng() { return rng_.get(); }  
  210.  private:  
  211.   shared_ptr<caffe::rng_t> rng_;  
  212. };  
  213.   
  214. Caffe::RNG::RNG() : generator_(new Generator()) { }  
  215.   
  216. Caffe::RNG::RNG(unsigned int seed) : generator_(new Generator(seed)) { }  
  217.   
  218. Caffe::RNG& Caffe::RNG::operator=(const RNG& other) {  
  219.   generator_.reset(other.generator_.get());  
  220.   return *this;  
  221. }  
  222.   
  223. void* Caffe::RNG::generator() {  
  224.   return static_cast<void*>(generator_->rng());  
  225. }  
  226. // cublas的geterrorstring  
  227. const char* cublasGetErrorString(cublasStatus_t error) {  
  228.   switch (error) {  
  229.   case CUBLAS_STATUS_SUCCESS:  
  230.     return "CUBLAS_STATUS_SUCCESS";  
  231.   case CUBLAS_STATUS_NOT_INITIALIZED:  
  232.     return "CUBLAS_STATUS_NOT_INITIALIZED";  
  233.   case CUBLAS_STATUS_ALLOC_FAILED:  
  234.     return "CUBLAS_STATUS_ALLOC_FAILED";  
  235.   case CUBLAS_STATUS_INVALID_VALUE:  
  236.     return "CUBLAS_STATUS_INVALID_VALUE";  
  237.   case CUBLAS_STATUS_ARCH_MISMATCH:  
  238.     return "CUBLAS_STATUS_ARCH_MISMATCH";  
  239.   case CUBLAS_STATUS_MAPPING_ERROR:  
  240.     return "CUBLAS_STATUS_MAPPING_ERROR";  
  241.   case CUBLAS_STATUS_EXECUTION_FAILED:  
  242.     return "CUBLAS_STATUS_EXECUTION_FAILED";  
  243.   case CUBLAS_STATUS_INTERNAL_ERROR:  
  244.     return "CUBLAS_STATUS_INTERNAL_ERROR";  
  245. #if CUDA_VERSION >= 6000  
  246.   case CUBLAS_STATUS_NOT_SUPPORTED:  
  247.     return "CUBLAS_STATUS_NOT_SUPPORTED";  
  248. #endif  
  249. #if CUDA_VERSION >= 6050  
  250.   case CUBLAS_STATUS_LICENSE_ERROR:  
  251.     return "CUBLAS_STATUS_LICENSE_ERROR";  
  252. #endif  
  253.   }  
  254.   return "Unknown cublas status";  
  255. }  
  256. // curand的getlasterrorstring  
  257. const char* curandGetErrorString(curandStatus_t error) {  
  258.   switch (error) {  
  259.   case CURAND_STATUS_SUCCESS:  
  260.     return "CURAND_STATUS_SUCCESS";  
  261.   case CURAND_STATUS_VERSION_MISMATCH:  
  262.     return "CURAND_STATUS_VERSION_MISMATCH";  
  263.   case CURAND_STATUS_NOT_INITIALIZED:  
  264.     return "CURAND_STATUS_NOT_INITIALIZED";  
  265.   case CURAND_STATUS_ALLOCATION_FAILED:  
  266.     return "CURAND_STATUS_ALLOCATION_FAILED";  
  267.   case CURAND_STATUS_TYPE_ERROR:  
  268.     return "CURAND_STATUS_TYPE_ERROR";  
  269.   case CURAND_STATUS_OUT_OF_RANGE:  
  270.     return "CURAND_STATUS_OUT_OF_RANGE";  
  271.   case CURAND_STATUS_LENGTH_NOT_MULTIPLE:  
  272.     return "CURAND_STATUS_LENGTH_NOT_MULTIPLE";  
  273.   case CURAND_STATUS_DOUBLE_PRECISION_REQUIRED:  
  274.     return "CURAND_STATUS_DOUBLE_PRECISION_REQUIRED";  
  275.   case CURAND_STATUS_LAUNCH_FAILURE:  
  276.     return "CURAND_STATUS_LAUNCH_FAILURE";  
  277.   case CURAND_STATUS_PREEXISTING_FAILURE:  
  278.     return "CURAND_STATUS_PREEXISTING_FAILURE";  
  279.   case CURAND_STATUS_INITIALIZATION_FAILED:  
  280.     return "CURAND_STATUS_INITIALIZATION_FAILED";  
  281.   case CURAND_STATUS_ARCH_MISMATCH:  
  282.     return "CURAND_STATUS_ARCH_MISMATCH";  
  283.   case CURAND_STATUS_INTERNAL_ERROR:  
  284.     return "CURAND_STATUS_INTERNAL_ERROR";  
  285.   }  
  286.   return "Unknown curand status";  
  287. }  
  288. #endif  // CPU_ONLY  
  289. }  // namespace caffe  

 

 
0


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM