Caffe源码中common文件分析
Caffe源碼(caffe version:09868ac , date: 2015.08.15)中的一些重要頭文件如caffe.hpp、blob.hpp等或者外部調用Caffe庫使用時,一般都會include<caffe/common.hpp>文件,下面分析此文件的內容:
1.??????include的文件:
boost中的智能指針頭文件<boost/shared_ptr.hpp>,作用類似于C++11中的模板類shared_ptr,通過引用計數方式自動釋放所指的對象,不用顯示執行delete,關于C++11中shared_ptr的使用可以參考http://blog.csdn.net/fengbingchun/article/details/52202007?.
在Caffe中,封裝boost的智能指針using boost::shared_ptr,不使用C++11中的shared_ptr。
GFlags庫的<gflags/gflags.h>,它是google的一個開源的處理命令行參數的庫,其使用可以參考 http://blog.csdn.net/fengbingchun/article/details/48768039?。
GLog庫的<glog/logging.h>,它是google的一個開源的日志庫,其使用可以參考 ?http://blog.csdn.net/fengbingchun/article/details/48768039?。
一些系統頭文件,如<climits>、<cmath>、<utility>等。
< caffe/util/device_alternate.hpp >文件。
2.??????caffe/util/device_alternate.hpp文件:
定義了一些在CPU或GPU+CPU模式下使用的宏和函數。
在CPU模式下(通過#ifdef CPU_ONLY)定義了四個宏用于提示在CPU模式下如果調用GPU函數給出error信息:
#define NO_GPU
#define STUB_GPU(classname)
#define STUB_GPU_FORWARD(classname, funcname)
#define STUB_GPU_BACKWARD(classname, funcname)
在GPU+CPU模式下定義了五個cuda宏、三個函數和一個常量:
#define CUDA_CHECK(condition)
#define CUBLAS_CHECK(condition)
#define CURAND_CHECK(condition)
#define CUDA_KERNEL_LOOP
#define CUDA_POST_KERNEL_CHECK
const char* cublasGetErrorString(cublasStatus_t error);
const char* curandGetErrorString(curandStatus_t error);
inline int CAFFE_GET_BLOCKS(const int N);
const int CAFFE_CUDA_NUM_THREADS;
3.??????common.hpp文件中定義的宏:
#define DISABLE_COPY_AND_ASSIGN(classname)
#define INSTANTIATE_CLASS(classname)
#define INSTANTIATE_LAYER_GPU_FORWARD
#define INSTANTIATE_LAYER_GPU_BACKWARD
#define INSTANTIATE_LAYER_GPU_FUNCS
#define NOT_IMPLEMENTED
其中宏DISABLE_COPY_AND_ASSIGN的作用是禁用指定類的拷貝和賦值操作;宏NOT_IMPLEMENTED的作用是標記沒有實現的代碼,并給出fatal log;宏INSTANTIATE_CLASS的作用是用于實例化指定的模板類(類模板顯示實例化);剩余的三個宏的作用是用于GPU模式下實例化指定的模板類的函數(GPU forward/backward,類似于函數模板顯示實例化)。
關于模板顯示實例化的介紹可以參考:http://blog.csdn.net/fengbingchun/article/details/51339659
4.??????GlobalInit函數:
全局初始化函數,用于初始化google開源庫gflags(gflags::ParseCommandLineFlags)和glog(google::InitGoogleLogging)。
5.??????Caffe類:
(1)、采用單例模式(singleton)實現,封裝了boost和cuda的一些操作,提供了一套統一的接口,關于單例模式的內容可以參考: http://blog.csdn.net/fengbingchun/article/details/22584107?。
(2)、內部定義了嵌套類RNG,RNG類內部又定義了私有嵌套類Generator,Generator類用于產生隨機數.RNG類為隨機數生成器,隱藏了boost和CUDA的rng實現,對外提供了一套統一的RNG類。
(3)、構造函數為private,防止直接通過構造函數創建對象,也可防止重復實例化。
(4)、禁止執行拷貝和賦值操作。
(5)、通過Get方法來創建或獲取實例。
(6)、枚舉類型Brew,指定運行模式:CPU、GPU。
以下是common文件的測試代碼:
int test_caffe_common()
{// 1. test macro NOT_IMPLEMENTED//NOT_IMPLEMENTED; // error, fatal log// 2. test global initialization function GlobalInitint argc = 2;char** argv = nullptr;argv = new char*[2];
#ifdef _DEBUGargv[0] = "E:/GitCode/Caffe_Test/lib/dbg/x64_vc12/Caffe_Test.exe";
#elseargv[0] = "E:/GitCode/Caffe_Test/lib/rel/x64_vc12/Caffe_Test.exe";
#endifargv[1] = "caffe_test";caffe::GlobalInit(&argc, &argv);delete[] argv;// 3. test caffe class// caffe::Caffe caffe_; // error, can't create Caffe object directly// verify Caffe is a singleton classcaffe::Caffe& caffe1 = caffe::Caffe::Get();caffe::Caffe& caffe2 = caffe::Caffe::Get();fprintf(stderr, "caffe1 addr: %p\n", &caffe1);fprintf(stderr, "caffe2 addr: %p\n", &caffe2);auto addr_caffe1 = std::addressof(caffe1);auto addr_caffe2 = std::addressof(caffe2);if (addr_caffe1 != addr_caffe2) {fprintf(stderr, "caffe1 and caffe2 addr are different: caffe1 addr: %p, caffe2 addr: %p\n", &caffe1, &caffe2);return -1;}// get run mode: CPU or GPUcaffe::Caffe::Brew run_mode = caffe1.mode();fprintf(stderr, "0: CPU, 1: GPU, run_mode: %d\n", run_mode);// set solver_countcaffe::Caffe::set_solver_count(5);// get solver_countint solver_count = caffe::Caffe::solver_count();fprintf(stderr, "solver count: %d\n", solver_count);// set root_solvercaffe::Caffe::set_root_solver(false);// get root_solverbool root_solver = caffe::Caffe::root_solver();fprintf(stderr, "root solver: %d\n", root_solver);// set device// caffe::Caffe::SetDevice(2); // error, fatal log: Cannot use GPU in CPU-only Caffe: check mode.// device query// caffe::Caffe::DeviceQuery(); // error, fatal log: Cannot use GPU in CPU-only Caffe: check mode.// RNG: generate random numbercaffe::SyncedMemory data_a(10 * sizeof(int));caffe::Caffe::set_random_seed(8888);caffe::caffe_rng_bernoulli(10, 0.5, static_cast<int*>(data_a.mutable_cpu_data()));caffe::SyncedMemory data_b(10 * sizeof(int));caffe::Caffe::set_random_seed(8888);caffe::caffe_rng_bernoulli(10, 0.5, static_cast<int*>(data_b.mutable_cpu_data()));for (int i = 0; i < 10; ++i) {fprintf(stderr, "%d, %d\n", static_cast<const int*>(data_a.cpu_data())[i], static_cast<const int*>(data_b.cpu_data())[i]);if (static_cast<const int*>(data_a.cpu_data())[i] != static_cast<const int*>(data_b.cpu_data())[i]) {fprintf(stderr, "same seed should be generate same random number\n");return - 1;}}// set run modecaffe::Caffe::set_mode(caffe::Caffe::GPU);run_mode = caffe1.mode();fprintf(stderr, "0: CPU, 1: GPU, run_mode: %d\n", run_mode);return 0;
}
執行結果如下圖:
GitHub:https://github.com/fengbingchun/Caffe_Test
總結
以上是生活随笔為你收集整理的Caffe源码中common文件分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 正则表达式简介及在C++11中的简单使用
- 下一篇: C++中前置声明介绍