您的位置:首页 > Web前端

学习笔记: 源码 caffe.cpp 初探

2017-05-06 19:42 387 查看
看 caffe 源码,首先从 caffe.proto 了解起,然后对caffe.cpp 进行阅读,毕竟整个庞大的 caffe 从这里的 main 函数开始。代码的阅读主要以 caffe.cpp 中的 train() 为主。以下是个人的一些笔记:

1. 关于 typedef 的一些性质
int (*BrewFunction)();

表示,声明一个变量 BrewFunction,该变量是一个函数指针变量,指向一个无形参的函数,函数返回值为 int 型。
typedef int (*BrewFunction)();

表示,BrewFunction是一个函数指针类型,该类型的变量是一个函数指针变量,指向一个无形参的函数,函数返回值为 int 型。

2. gflags
这是google出品的命令行参数解析库。
DEFINE_string(solver, "", "The solver definition protocol buffer text file.");

用于宏定义参数,这里定义了一个string类型的参数,该宏的三个参数含义分别为命令行参数名,参数默认值,以及参数的帮助信息。
而在使用的时候,该参数名实际为FLAG_solver,类型为string。

3. LOG(INFO)
ostringstream s;
for (int i = 0; i < gpus.size(); ++i) {
s << (i ? ", " : "") << gpus[i];
}
LOG(INFO) << "Using GPUs " << s.str();

这个功能是输出 使用哪几个GPU。
其中LOG(INFO)是 Glog 的功能,也是google出品。相似的还有CHECK_EQ。
如:
CHECK_EQ(registry.count(type), 0) << "Solver type " << type << " already registered.";

如果CHECK_EQ()不满足条件,则输出后面的内容。

4. shared_ptr指向一个Solver对象,变量名为solver,用智能指针包装。solver的初始化(注册)通过caffe::SolverRegistry<float>::CreateSolver()实现。
在solver_factory.hpp 中有 typedef std::map<string, Creator> CreatorRegistry;
在编译的时候就存在这么一个map,在编译阶段,src/caffe/solvers中的各种solver,如sgd_solver.cpp中,会通过REGISTER_SOLVER_CLASS(SGD);来声明相应的函数,并加入到CreatorRegistry这个map当中。然后再调用caffe::SolverRegistry<float>::CreateSolver(solver_param)传递solver_param来生成一个相应的对象SGDSolver。

这里再补充一下,
#define REGISTER_SOLVER_CREATOR(type, creator) \
static SolverRegisterer<float> g_creator_f_##type(#type, creator<float>); \
static SolverRegisterer<double> g_creator_d_##type(#type, creator<double>)

其中,#type表示字符串,##表示字符串连接。

5. Solver的初始化
Solver在构造函数中通过Solver::Init(param)初始化对象,在Solver::Init()中又分别通过Solver::InitTrainNet();和Solver::InitTestNet();来初始化网络训练网络net_和测试网络test_nets_;

6. GPUs的使用
当只有一个GPU时,直接运行solver->Solve()开始training。
当多个GPU时,在旧版的caffe里,用的是caffe::P2PSync<float>类型的 sync 来实现CPU与GPU之间的通信,以及GPU并行运算,包括用map-reduce来实现GPU之间的通信。在新版的caffe中运用了NCCL来加速并行计算。

7. 接下来就是solver->Solve(),开始 solver 对网络的训练了。下一阶段就是看 solver.cpp 了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: