Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
Paddle
提交
3bfb898f
P
Paddle
项目概览
PaddlePaddle
/
Paddle
1 年多 前同步成功
通知
2302
Star
20931
Fork
5422
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1423
列表
看板
标记
里程碑
合并请求
543
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1,423
Issue
1,423
列表
看板
标记
里程碑
合并请求
543
合并请求
543
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
3bfb898f
编写于
11月 23, 2016
作者:
C
chenguoyan01
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add mfs fullname
上级
eeca7be7
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
14 addition
and
12 deletion
+14
-12
doc_cn/cluster/k8s/distributed_training_on_kubernetes.md
doc_cn/cluster/k8s/distributed_training_on_kubernetes.md
+14
-12
未找到文件。
doc_cn/cluster/k8s/distributed_training_on_kubernetes.md
浏览文件 @
3bfb898f
# Paddle on Kubernetes:分布式训练
# Paddle
Paddle
on Kubernetes:分布式训练
前一篇文章介绍了如何在Kubernetes集群上启动一个单机PaddlePaddle训练作业 (Job)。在这篇文章里,我们介绍如何在Kubernetes集群上进行分布式PaddlePaddle训练作业。关于PaddlePaddle的分布式训练,
可以参考
[
Cluster Training
](
https://github.com/baidu/Paddle/blob/develop/doc/cluster/opensource/cluster_train.md
)
,本文利用Kubernetes的调度功能与容器编排能力,快速构建PaddlePaddle容器集群,进行分布式训练任务
。
前一篇文章介绍了如何在Kubernetes集群上启动一个单机PaddlePaddle训练作业 (Job)。在这篇文章里,我们介绍如何在Kubernetes集群上进行分布式PaddlePaddle训练作业。关于PaddlePaddle的分布式训练,
文章
[
Cluster Training
](
https://github.com/baidu/Paddle/blob/develop/doc/cluster/opensource/cluster_train.md
)
介绍了一种通过SSH远程分发任务,进行分布式训练的方法,与此不同的是,本文将介绍在Kubernetes容器管理平台上快速构建PaddlePaddle容器集群,进行分布式训练的方案
。
## Kubernetes 基本概念
## Kubernetes 基本概念
[
*Kubernetes*
](
http://kubernetes.io/
)
是Google开源的容器集群管理系统,其提供应用部署、维护、 扩展机制等功能,利用Kubernetes能方便地管理跨机器运行容器化的应用。
在
介绍分布式训练之前,需要对
[
Kubernetes
](
http://kubernetes.io/
)
有一个基本的认识,下面先简要介绍一下本文用到的几个Kubernetes概念。
[
*Kubernetes*
](
http://kubernetes.io/
)
是Google开源的容器集群管理系统,其提供应用部署、维护、 扩展机制等功能,利用Kubernetes能方便地管理跨机器运行容器化的应用。
Kubernetes可以在物理机或虚拟机上运行,且支持部署到
[
AWS
](
http://kubernetes.io/docs/getting-started-guides/aws
)
,
[
Azure
](
http://kubernetes.io/docs/getting-started-guides/azure/
)
,
[
GCE
](
http://kubernetes.io/docs/getting-started-guides/gce
)
等多种公有云环境。
介绍分布式训练之前,需要对
[
Kubernetes
](
http://kubernetes.io/
)
有一个基本的认识,下面先简要介绍一下本文用到的几个Kubernetes概念。
-
[
*Node*
](
http://kubernetes.io/docs/admin/node/
)
表示一个Kubernetes集群中的一个工作节点,这个节点可以是物理机或者虚拟机,Kubernetes集群就是由node节点与master节点组成的。
-
[
*Node*
](
http://kubernetes.io/docs/admin/node/
)
表示一个Kubernetes集群中的一个工作节点,这个节点可以是物理机或者虚拟机,Kubernetes集群就是由node节点与master节点组成的。
...
@@ -21,17 +21,19 @@
...
@@ -21,17 +21,19 @@
### 部署Kubernetes集群
### 部署Kubernetes集群
首先,我们需要拥有一个Kubernetes集群,在这个集群中所有node与pod都可以互相通信。关于Kubernetes集群搭建,可以参考
[
官方文档
](
http://kubernetes.io/docs/getting-started-guides/kubeadm/
)
,在以后的文章中我们也会介绍AWS上搭建的方案。本文假设大家能找到几台物理机,并且可以按照官方文档在上面部署Kubernetes。在本文的环境中,Kubernetes集群中所有node都挂载了一个
*mfs*
(分布式文件系统)共享目录,我们通过这个目录来存放训练文件与最终输出的模型。在训练之前,用户将配置与训练数据切分好放在mfs目录中,训练时,程序从此目录拷贝文件到容器内进行训练,将结果保存到此目录里。整体的结果
图如下:
首先,我们需要拥有一个Kubernetes集群,在这个集群中所有node与pod都可以互相通信。关于Kubernetes集群搭建,可以参考
[
官方文档
](
http://kubernetes.io/docs/getting-started-guides/kubeadm/
)
,在以后的文章中我们也会介绍AWS上搭建的方案。本文假设大家能找到几台物理机,并且可以按照官方文档在上面部署Kubernetes。在本文的环境中,Kubernetes集群中所有node都挂载了一个
[
MFS
](
http://moosefs.org/
)
(Moose filesystem,一种分布式文件系统)共享目录,我们通过这个目录来存放训练文件与最终输出的模型。关于MFS的安装部署,可以参考
[
MooseFS documentation
](
https://moosefs.com/documentation.html
)
。在训练之前,用户将配置与训练数据切分好放在MFS目录中,训练时,程序从此目录拷贝文件到容器内进行训练,将结果保存到此目录里。整体的结构
图如下:
![
paddle on kubernetes结构图
](
k8s-paddle-arch.png
)
![
paddle on kubernetes结构图
](
k8s-paddle-arch.png
)
上图描述了一个3节点的分布式训练场景,Kubernetes集群的每个node上都挂载了一个MFS目录,这个目录可以通过volume的形式挂载到容器中。Kubernetes为这次训练创建了3个pod并且调度到了3个node上运行,每个pod包含一个PaddlePaddle容器。在容器创建后,会启动pserver与trainer进程,读取volume中的数据进行这次分布式训练。
### 使用 Job
### 使用 Job
我们使用Kubernetes中的job这个概念来代表一次分布式训练。Job表示一次性作业,在作业完成后,Kubernetes会销毁job产生的容器并且释放相关资源。
我们使用Kubernetes中的job这个概念来代表一次分布式训练。Job表示一次性作业,在作业完成后,Kubernetes会销毁job产生的容器并且释放相关资源。
在Kubernetes中,可以通过编写一个YAML文件,来描述这个job,在这个文件中,主要包含了一些配置信息,例如PaddlePaddle的节点个数,
`paddle pserver`
开放的端口个数与端口号,使用的网卡设备等,这些信息通过环境变量的形式传递给容器内的程序使用。
在Kubernetes中,可以通过编写一个YAML文件,来描述这个job,在这个文件中,主要包含了一些配置信息,例如PaddlePaddle的节点个数,
`paddle pserver`
开放的端口个数与端口号,使用的网卡设备等,这些信息通过环境变量的形式传递给容器内的程序使用。
在一次分布式训练中,用户确定好本次训练需要的PaddlePaddle节点个数,将切分好的训练数据与配置文件上传到
mfs
共享目录中。然后编写这次训练的job YAML文件,提交给Kubernetes集群创建并开始作业。
在一次分布式训练中,用户确定好本次训练需要的PaddlePaddle节点个数,将切分好的训练数据与配置文件上传到
MFS
共享目录中。然后编写这次训练的job YAML文件,提交给Kubernetes集群创建并开始作业。
### 创建PaddlePaddle节点
### 创建PaddlePaddle节点
...
@@ -39,14 +41,14 @@
...
@@ -39,14 +41,14 @@
### 启动训练
### 启动训练
在容器启动后,会通过脚本来启动这次分布式训练,我们知道
`paddle train`
进程启动时需要知道其他节点的IP地址以及本节点的trainer_id,由于Paddle本身不提供类似服务发现的功能,所以在本文的启动脚本中,每个节点会根据job name向Kubernetes apiserver查询这个job对应的所有pod信息(Kubernetes默认会在每个容器的环境变量中写入apiserver的地址)。
在容器启动后,会通过脚本来启动这次分布式训练,我们知道
`paddle train`
进程启动时需要知道其他节点的IP地址以及本节点的trainer_id,由于Paddle
Paddle
本身不提供类似服务发现的功能,所以在本文的启动脚本中,每个节点会根据job name向Kubernetes apiserver查询这个job对应的所有pod信息(Kubernetes默认会在每个容器的环境变量中写入apiserver的地址)。
根据这些pod信息,就可以通过某种方式,为每个pod分配一个唯一的trainer_id。本文把所有pod的IP地址进行排序,将顺序作为每个PaddlePaddle节点的trainer_id。启动脚本的工作流程大致如下:
根据这些pod信息,就可以通过某种方式,为每个pod分配一个唯一的trainer_id。本文把所有pod的IP地址进行排序,将顺序作为每个PaddlePaddle节点的trainer_id。启动脚本的工作流程大致如下:
1.
查询Kubernetes apiserver获取pod信息,根据IP分配trainer_id
1.
查询Kubernetes apiserver获取pod信息,根据IP分配trainer_id
1.
从
mfs
共享目录中拷贝训练文件到容器内
1.
从
MFS
共享目录中拷贝训练文件到容器内
1.
根据环境变量,解析出
`paddle pserver`
与
`paddle train`
的启动参数,启动进程
1.
根据环境变量,解析出
`paddle pserver`
与
`paddle train`
的启动参数,启动进程
1.
训练时,PaddlePaddle会自动将结果保存在trainer_id为0的节点上,将输出路径设置为
mfs
目录,保存输出的文件
1.
训练时,PaddlePaddle会自动将结果保存在trainer_id为0的节点上,将输出路径设置为
MFS
目录,保存输出的文件
## 搭建过程
## 搭建过程
...
@@ -160,7 +162,7 @@ docker push your_repo/paddle:mypaddle
...
@@ -160,7 +162,7 @@ docker push your_repo/paddle:mypaddle
### 上传训练文件
### 上传训练文件
本文使用Paddle
官方的
[
recommendation demo
](
http://www.paddlepaddle.org/doc/demo/index.html#recommendation
)
作为这次训练的内容,我们将训练文件与数据放在一个job name命名的目录中,上传到mfs共享存储。完成后mfs
上的文件内容大致如下:
本文使用Paddle
Paddle官方的
[
recommendation demo
](
http://www.paddlepaddle.org/doc/demo/index.html#recommendation
)
作为这次训练的内容,我们将训练文件与数据放在一个job name命名的目录中,上传到MFS共享存储。完成后MFS
上的文件内容大致如下:
```
bash
```
bash
[
root@paddle-kubernetes-node0 mfs]# tree
-d
[
root@paddle-kubernetes-node0 mfs]# tree
-d
...
@@ -176,7 +178,7 @@ docker push your_repo/paddle:mypaddle
...
@@ -176,7 +178,7 @@ docker push your_repo/paddle:mypaddle
└── recommendation
└── recommendation
```
```
目录中paddle-cluster-job是本次训练对应的job name,本次训练要求有3个Paddle节点,在paddle-cluster-job/data目录中存放切分好的数据,文件夹0,1,2分别代表3个节点的trainer_id。recommendation文件夹内存放训练文件,output文件夹存放训练结果与日志。
目录中paddle-cluster-job是本次训练对应的job name,本次训练要求有3个Paddle
Paddle
节点,在paddle-cluster-job/data目录中存放切分好的数据,文件夹0,1,2分别代表3个节点的trainer_id。recommendation文件夹内存放训练文件,output文件夹存放训练结果与日志。
### 创建Job
### 创建Job
...
@@ -229,7 +231,7 @@ spec:
...
@@ -229,7 +231,7 @@ spec:
restartPolicy
:
Never
restartPolicy
:
Never
```
```
文件中,
`metadata`
下的
`name`
表示这个job的名字。
`parallelism,completions`
字段表示这个job会同时开启3个Paddle
节点,成功训练且退出的pod数目为3时,这个job才算成功结束。然后申明一个存储卷
`jobpath`
,代表宿主机目录
`/home/work/mfs`
,在对容器的描述
`containers`
字段中,将此目录挂载为容器的
`/home/jobpath`
目录,这样容器的
`/home/jobpath`
目录就成为了共享存储,放在这个目录里的文件其实是保存到了mfs
上。
文件中,
`metadata`
下的
`name`
表示这个job的名字。
`parallelism,completions`
字段表示这个job会同时开启3个Paddle
Paddle节点,成功训练且退出的pod数目为3时,这个job才算成功结束。然后申明一个存储卷
`jobpath`
,代表宿主机目录
`/home/work/mfs`
,在对容器的描述
`containers`
字段中,将此目录挂载为容器的
`/home/jobpath`
目录,这样容器的
`/home/jobpath`
目录就成为了共享存储,放在这个目录里的文件其实是保存到了MFS
上。
`env`
字段表示容器的环境变量,我们将
`paddle`
运行的一些参数通过这种方式传递到容器内。
`env`
字段表示容器的环境变量,我们将
`paddle`
运行的一些参数通过这种方式传递到容器内。
...
@@ -254,7 +256,7 @@ kubectl create -f job.yaml
...
@@ -254,7 +256,7 @@ kubectl create -f job.yaml
### 查看输出
### 查看输出
在训练过程中,可以在共享存储上查看输出的日志和模型,例如output目录下就存放了输出结果。注意node_0,node_1,node_2这几个目录表示Paddle节点与trainer_id,并不是Kubernetes中的node概念。
在训练过程中,可以在共享存储上查看输出的日志和模型,例如output目录下就存放了输出结果。注意node_0,node_1,node_2这几个目录表示Paddle
Paddle
节点与trainer_id,并不是Kubernetes中的node概念。
```
bash
```
bash
[
root@paddle-kubernetes-node0 output]# tree
-d
[
root@paddle-kubernetes-node0 output]# tree
-d
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录