#ifndef CAFFE_COMMON_HPP_ #define CAFFE_COMMON_HPP_ #include #include #include #include #include #include // NOLINT(readability/streams) #include // NOLINT(readability/streams) #include #include #include #include #include // pair #include #include "caffe/util/device_alternate.hpp" // Convert macro to string #define STRINGIFY(m) #m #define AS_STRING(m) STRINGIFY(m) // gflags 2.1 issue: namespace google was changed to gflags without warning. // Luckily we will be able to use GFLAGS_GFLAGS_H_ to detect if it is version // 2.1. If yes, we will add a temporary solution to redirect the namespace. // TODO(Yangqing): Once gflags solves the problem in a more elegant way, let's // remove the following hack. #ifndef GFLAGS_GFLAGS_H_ namespace gflags = google; #endif // GFLAGS_GFLAGS_H_ // Disable the copy and assignment operator for a class. #define DISABLE_COPY_AND_ASSIGN(classname) \ private:\ classname(const classname&);\ classname& operator=(const classname&) // Instantiate a class with float and double specifications. #define INSTANTIATE_CLASS(classname) \ char gInstantiationGuard##classname; \ template class classname; \ template class classname #define INSTANTIATE_LAYER_GPU_FORWARD(classname) \ template void classname::Forward_gpu( \ const std::vector*>& bottom, \ const std::vector*>& top); \ template void classname::Forward_gpu( \ const std::vector*>& bottom, \ const std::vector*>& top); #define INSTANTIATE_LAYER_GPU_BACKWARD(classname) \ template void classname::Backward_gpu( \ const std::vector*>& top, \ const std::vector& propagate_down, \ const std::vector*>& bottom); \ template void classname::Backward_gpu( \ const std::vector*>& top, \ const std::vector& propagate_down, \ const std::vector*>& bottom) #define INSTANTIATE_LAYER_GPU_FUNCS(classname) \ INSTANTIATE_LAYER_GPU_FORWARD(classname); \ INSTANTIATE_LAYER_GPU_BACKWARD(classname) // A simple macro to mark codes that are not implemented, so that when the code // is executed we will see a fatal log. #define NOT_IMPLEMENTED LOG(FATAL) << "Not Implemented Yet" // See PR #1236 namespace cv { class Mat; } namespace caffe { // We will use the boost shared_ptr instead of the new C++11 one mainly // because cuda does not work (at least now) well with C++11 features. using boost::shared_ptr; // Common functions and classes from std that caffe often uses. using std::fstream; using std::ios; using std::isnan; using std::isinf; using std::iterator; using std::make_pair; using std::map; using std::ostringstream; using std::pair; using std::set; using std::string; using std::stringstream; using std::vector; // A global initialization function that you should call in your main function. // Currently it initializes google flags and google logging. void GlobalInit(int* pargc, char*** pargv); // A singleton class to hold common caffe stuff, such as the handler that // caffe is going to use for cublas, curand, etc. class Caffe { public: ~Caffe(); // Thread local context for Caffe. Moved to common.cpp instead of // including boost/thread.hpp to avoid a boost/NVCC issues (#1009, #1010) // on OSX. Also fails on Linux with CUDA 7.0.18. static Caffe& Get(); enum Brew { CPU, GPU }; // This random number generator facade hides boost and CUDA rng // implementation from one another (for cross-platform compatibility). class RNG { public: RNG(); explicit RNG(unsigned int seed); explicit RNG(const RNG&); RNG& operator=(const RNG&); void* generator(); private: class Generator; shared_ptr generator_; }; // Getters for boost rng, curand, and cublas handles inline static RNG& rng_stream() { if (!Get().random_generator_) { Get().random_generator_.reset(new RNG()); } return *(Get().random_generator_); } #ifndef CPU_ONLY inline static cublasHandle_t cublas_handle() { return Get().cublas_handle_; } inline static curandGenerator_t curand_generator() { return Get().curand_generator_; } #endif // Returns the mode: running on CPU or GPU. inline static Brew mode() { return Get().mode_; } // The setters for the variables // Sets the mode. It is recommended that you don't change the mode halfway // into the program since that may cause allocation of pinned memory being // freed in a non-pinned way, which may cause problems - I haven't verified // it personally but better to note it here in the header file. inline static void set_mode(Brew mode) { Get().mode_ = mode; } // Sets the random seed of both boost and curand static void set_random_seed(const unsigned int seed); // Sets the device. Since we have cublas and curand stuff, set device also // requires us to reset those values. static void SetDevice(const int device_id); // Prints the current GPU status. static void DeviceQuery(); // Check if specified device is available static bool CheckDevice(const int device_id); // Search from start_id to the highest possible device ordinal, // return the ordinal of the first available device. static int FindDevice(const int start_id = 0); // Parallel training inline static int solver_count() { return Get().solver_count_; } inline static void set_solver_count(int val) { Get().solver_count_ = val; } inline static int solver_rank() { return Get().solver_rank_; } inline static void set_solver_rank(int val) { Get().solver_rank_ = val; } inline static bool multiprocess() { return Get().multiprocess_; } inline static void set_multiprocess(bool val) { Get().multiprocess_ = val; } inline static bool root_solver() { return Get().solver_rank_ == 0; } protected: #ifndef CPU_ONLY cublasHandle_t cublas_handle_; curandGenerator_t curand_generator_; #endif shared_ptr random_generator_; Brew mode_; // Parallel training int solver_count_; int solver_rank_; bool multiprocess_; private: // The private constructor to avoid duplicate instantiation. Caffe(); DISABLE_COPY_AND_ASSIGN(Caffe); }; } // namespace caffe #endif // CAFFE_COMMON_HPP_