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(¤t_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;
125 }
127 } // namespace caffe