学习笔记: 源码 caffe.cpp 初探
2017-05-06 19:42
387 查看
看 caffe 源码,首先从 caffe.proto 了解起,然后对caffe.cpp 进行阅读,毕竟整个庞大的 caffe 从这里的 main 函数开始。代码的阅读主要以 caffe.cpp 中的 train() 为主。以下是个人的一些笔记:
1. 关于 typedef 的一些性质
表示,声明一个变量 BrewFunction,该变量是一个函数指针变量,指向一个无形参的函数,函数返回值为 int 型。
表示,BrewFunction是一个函数指针类型,该类型的变量是一个函数指针变量,指向一个无形参的函数,函数返回值为 int 型。
2. gflags
这是google出品的命令行参数解析库。
用于宏定义参数,这里定义了一个string类型的参数,该宏的三个参数含义分别为命令行参数名,参数默认值,以及参数的帮助信息。
而在使用的时候,该参数名实际为FLAG_solver,类型为string。
3. LOG(INFO)
这个功能是输出 使用哪几个GPU。
其中LOG(INFO)是 Glog 的功能,也是google出品。相似的还有CHECK_EQ。
如:
如果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。
这里再补充一下,
其中,#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 了。
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 了。
相关文章推荐
- Cocos2d-x学习笔记(20)(TestCpp源码分析-4)
- Caffe 源码阅读笔记 [基本模块] Caffe.cpp
- CAFFE源码学习笔记之一
- CAFFE源码学习笔记之一
- CAFFE源码学习笔记之三-common
- CAFFE源码学习笔记之一
- Cocos2d-x学习笔记(17)(TestCpp源码分析-1)
- CAFFE源码学习笔记之一
- CAFFE源码学习笔记之一
- CAFFE源码学习笔记之三-common
- 深度学习(七)caffe源码c++学习笔记
- caffe学习笔记32-关于修改源码
- CAFFE源码学习笔记之一
- 深度学习(七)caffe源码c++学习笔记
- CAFFE源码学习笔记之一
- caffe学习笔记--写一个运行caffe.cpp的makefile
- caffe源码深入学习4:支持魔改的layer:layer.hpp与layer.cpp
- CAFFE源码学习笔记之一
- CAFFE源码学习笔记之三-common
- CAFFE源码学习笔记之一