实现的训练过程的效果
因为主要目的是为了节点通讯,所以其他地方没改,下图是四个节点训练过程
1. 目的
使用OpenMPI进行节点间的通讯,搭建参数服务器,实现4节点同时训练一个模型
2. 思路
采用最简单的基于同步的并行数据训练。
首先分布数据,每个节点负责一部分数据,在每个节点上面算出一些局部统计量,然后整合出全局统计量,并且再分配给各个节点去进行下一轮的训练。
所以我们首先要改的是与图片数据分配有关的image_data_layer.cpp文件;
然后改的是与训练迭代有关的solver.cpp文件
3. 修改image_data_layer.cpp
因为是数据并行训练,需要把数据分布给不同的节点,只需要小改load_batch批处理函数
- 每行数据分配给一个进程
// modified 1, 数据分配,lines_id代表数据文件中某行数据,每行数据分配给一个节点
int rank, numproc;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &numproc);
lines_id_ = (lines_id_ + rank) % lines_.size();
- 注意 lines_id_ 递增遍历完整个文件后从头开始遍历
// modified 2, 每个进程循环跳到数据文件种自己相应的下一个lines_id
int count = 0;
while (count++ < numproc) {
lines_id_++;
if (lines_id_ >= lines_size) {
// We have reached the end. Restart from the first.
DLOG(INFO) << "Restarting data prefetching from start.";
lines_id_ = 0;
if (this->layer_param_.image_data_param().shuffle()) {
ShuffleImages();
}
}
4. 修改solver.cpp
主要是Step函数的修改,第一次训练前,把节点0的参数用于初始化所有节点;以后每次训练结束,都要强制同步,整合所有节点的各层参数的梯度。
4.1 增加的辅助函数有SyncParameter,Display
函数 | 作用 |
---|---|
SyncParameter | 把节点0的参数广播到所有节点 |
Display | 打印每次迭代每个节点的信息,实际是从Step函数中抽离出来的代码 |
4.2 修改的函数有Init,Step,SnapshotFilename
函数 | 改后新增的作用 |
---|---|
Init | 初始化MPI环境 |
Step | ①训练开始前用节点0的参数权值初始化全部节点 ②每轮迭代结束强制同步整合各节点各层参数的残差和梯度 |
SnapshotFilename | 根据当前迭代数和相应节点序号,生成相应快照文件名用于Snapshot |
5. 两个文件代码
涉及改动的只有这两个源文件,不贴代码了
cpp以及hpp文件