solver restructuring: now all prototxt are specified in the solver protocol buffer
[jacinto-ai/caffe-jacinto.git] / src / caffe / common.cpp
1 // Copyright 2013 Yangqing Jia
3 #include <cstdio>
4 #include <ctime>
6 #include "caffe/common.hpp"
8 namespace caffe {
10 shared_ptr<Caffe> Caffe::singleton_;
12 inline bool StillFresh() {
13   struct tm fresh_time;
14   fresh_time.tm_year = 200;
15   fresh_time.tm_mon = 1;
16   fresh_time.tm_mday = 1;
17   fresh_time.tm_hour = 0;
18   fresh_time.tm_min = 0;
19   fresh_time.tm_sec = 0;
20   return (difftime(time(NULL), mktime(&fresh_time)) < 0);
21 }
23 Caffe::Caffe()
24     : mode_(Caffe::CPU), phase_(Caffe::TRAIN), cublas_handle_(NULL),
25       curand_generator_(NULL), vsl_stream_(NULL) {
26   // A simple way to set an expire time - not for coding geeks, but meh.
27   // It simply works by skipping creating the streams.
28   if (!StillFresh()) {
29     return;
30   }
31   // Try to create a cublas handler, and report an error if failed (but we will
32   // keep the program running as one might just want to run CPU code).
33   if (cublasCreate(&cublas_handle_) != CUBLAS_STATUS_SUCCESS) {
34     LOG(ERROR) << "Cannot create Cublas handle. Cublas won't be available.";
35   }
36   // Try to create a curand handler.
37   if (curandCreateGenerator(&curand_generator_, CURAND_RNG_PSEUDO_DEFAULT)
38       != CURAND_STATUS_SUCCESS ||
39       curandSetPseudoRandomGeneratorSeed(curand_generator_, time(NULL))
40       != CURAND_STATUS_SUCCESS) {
41     LOG(ERROR) << "Cannot create Curand generator. Curand won't be available.";
42   }
43   // Try to create a vsl stream. This should almost always work, but we will
44   // check it anyway.
45   if (vslNewStream(&vsl_stream_, VSL_BRNG_MT19937, time(NULL)) != VSL_STATUS_OK) {
46     LOG(ERROR) << "Cannot create vsl stream. VSL random number generator "
47         << "won't be available.";
48   }
49 }
51 Caffe::~Caffe() {
52   if (cublas_handle_) CUBLAS_CHECK(cublasDestroy(cublas_handle_));
53   if (curand_generator_) {
54     CURAND_CHECK(curandDestroyGenerator(curand_generator_));
55   }
56   if (vsl_stream_) VSL_CHECK(vslDeleteStream(&vsl_stream_));
57 };
59 void Caffe::set_random_seed(const unsigned int seed) {
60   // Curand seed
61   // Yangqing's note: simply setting the generator seed does not seem to
62   // work on the tesla K20s, so I wrote the ugly reset thing below.
63   if (Get().curand_generator_) {
64     CURAND_CHECK(curandDestroyGenerator(curand_generator()));
65     CURAND_CHECK(curandCreateGenerator(&Get().curand_generator_,
66         CURAND_RNG_PSEUDO_DEFAULT));
67     CURAND_CHECK(curandSetPseudoRandomGeneratorSeed(curand_generator(),
68         seed));
69   } else {
70     LOG(ERROR) << "Curand not available. Skipping setting the curand seed.";
71   }
72   // VSL seed
73   VSL_CHECK(vslDeleteStream(&(Get().vsl_stream_)));
74   VSL_CHECK(vslNewStream(&(Get().vsl_stream_), VSL_BRNG_MT19937, seed));
75 }
77 void Caffe::SetDevice(const int device_id) {
78   int current_device;
79   CUDA_CHECK(cudaGetDevice(&current_device));
80   if (current_device == device_id) {
81     return;
82   }
83   if (Get().cublas_handle_) CUBLAS_CHECK(cublasDestroy(Get().cublas_handle_));
84   if (Get().curand_generator_) {
85     CURAND_CHECK(curandDestroyGenerator(Get().curand_generator_));
86   }
87   CUDA_CHECK(cudaSetDevice(device_id));
88   CUBLAS_CHECK(cublasCreate(&Get().cublas_handle_));
89   CURAND_CHECK(curandCreateGenerator(&Get().curand_generator_,
90       CURAND_RNG_PSEUDO_DEFAULT));
91   CURAND_CHECK(curandSetPseudoRandomGeneratorSeed(Get().curand_generator_,
92       time(NULL)));
93 }
95 void Caffe::DeviceQuery() {
96   cudaDeviceProp prop;
97   int device;
98   if (cudaSuccess != cudaGetDevice(&device)) {
99     printf("No cuda device present.\n");
100     return;
101   }
102   CUDA_CHECK(cudaGetDeviceProperties(&prop, device));
103   printf("Major revision number:         %d\n", prop.major);
104   printf("Minor revision number:         %d\n", prop.minor);
105   printf("Name:                          %s\n", prop.name);
106   printf("Total global memory:           %lu\n", prop.totalGlobalMem);
107   printf("Total shared memory per block: %lu\n", prop.sharedMemPerBlock);
108   printf("Total registers per block:     %d\n", prop.regsPerBlock);
109   printf("Warp size:                     %d\n", prop.warpSize);
110   printf("Maximum memory pitch:          %lu\n", prop.memPitch);
111   printf("Maximum threads per block:     %d\n", prop.maxThreadsPerBlock);
112   printf("Maximum dimension of block:    %d, %d, %d\n",
113       prop.maxThreadsDim[0], prop.maxThreadsDim[1], prop.maxThreadsDim[2]);
114   printf("Maximum dimension of grid:     %d, %d, %d\n",
115       prop.maxGridSize[0], prop.maxGridSize[1], prop.maxGridSize[2]);
116   printf("Clock rate:                    %d\n", prop.clockRate);
117   printf("Total constant memory:         %lu\n", prop.totalConstMem);
118   printf("Texture alignment:             %lu\n", prop.textureAlignment);
119   printf("Concurrent copy and execution: %s\n",
120       (prop.deviceOverlap ? "Yes" : "No"));
121   printf("Number of multiprocessors:     %d\n", prop.multiProcessorCount);
122   printf("Kernel execution timeout:      %s\n",
123       (prop.kernelExecTimeoutEnabled ? "Yes" : "No"));
124   return;
127 }  // namespace caffe