入口
我们先从caffe的入口main
函数入手. 该函数定义在caffe.cpp
中 (caffe.hpp
只是包含了一堆需要用到的头文件而已). caffe提供了一系列可以调用的方法, 比如train, test, time, device_query
等. 这些函数都定义在caffe.cpp
里, 可以调用的函数名都注册在BrewMap g_brew_map
里, 调用时通过下列函数来返回函数句柄
static BrewFunction GetBrewFunction(const caffe::string& name)
我们具体来看一下caffe主程序提供了功能. 以caffe train
为例, 入口函数会通过注册的BrewFunction找到train
函数, 该函数会调用Caffe
类的set_mode, SetDevice
等函数, 创建solver, 并且调用solver->Solve()
进行网络的训练.
common
common主要包含两部分内容: 通用的宏定义, 以及Caffe
类
宏定义
这里宏定义的作用主要是对一些模板类和模板函数进行实例化. 例如下面这个宏定义我们就经常会在layer的类定义(.cpp文件)的最后看到.
// Instantiate a class with float and double specifications.
#define INSTANTIATE_CLASS(classname) \
char gInstantiationGuard##classname; \
template class classname<float>; \
template class classname<double>
Caffe类
Caffe类的定义比较奇特, 定义了嵌套类(nested class) RNG
, 以及RNG
的私有嵌套类 Generator
. 嵌套类的目的主要是更好的封装吧.
RNG
类顾名思义, 就是Caffe的随机数产生器. 值得注意的是, Caffe
类在实现时采用单例(singleton)模式, 主要通过下列几个步骤实现:
- 禁止复制和赋值
DISABLE_COPY_AND_ASSIGN(Caffe);
- 私有化构造函数
private:
// The private constructor to avoid duplicate instantiation.
Caffe();
-
Get
方法用来获取当前实例
Caffe& Caffe::Get() {
if (!thread_instance_.get()) {
thread_instance_.reset(new Caffe());
}
return *(thread_instance_.get());
}