使用Kubernetes进行Paddle分布式训练思路
Created by: drinktee
目前我在Kubernetes上进行Paddle的分布式训练,中间遇到了几个问题与解决思路,想在这个ISSUE中与大家探讨一下。
使用job
job 是Kubernetes中的一个概念,主要代表一次性任务,任务运行结束后容器生命就结束了。我认为这符合Paddle分布式训练的使用场景。比如在一个Kubernetes集群中,我要进行一次需要10个节点的训练,那么这个job就表示这一次任务,当训练结束以后,训练结果已经保存到持久化存储上,这个job就算完成了,对应的资源会自动释放。
Paddle分布式训练的启动
我参考了Paddle文档中关于Cluster training的内容,看到其方法是通过SSH的方式启动每个节点的Paddle进程,这种方式并不符合Kubernetes的思路,所以我通过在Paddle容器启动时,让其运行一个启动脚来运行整个分布式训练,而不是在容器中安装sshd通过脚本进行操作。这个启动脚本主要的功能就是访问Kubernetes api,发现其他节点的IP地址,为自己分配一个trainerID(这里我直接根据IP地址进行排序,把序号作为trainerID),然后启动paddle trainer
pserver 与 trainer的分离
在训练时,Paddle其实启动了两类进程,pserver与trainer,如果我们直接用docker启动一个paddle容器,我们可以在容器内同时开启pserver与trainer,也能完成训练。为了配置的方便(pserver启动时并不需要知道其他节点的IP地址,trainer启动时需要知道pserver的端口以及地址),我在Kubernenets上部署时,这两个进程分别在两个容器中运行,pserver容器启动相对简单,只要早yaml文件中配好启动参数就可以运行。trainer容器就通过前文的脚本来启动。这两个容器在同一个Pod中(Pod是Kubernetes的概念,Pod是k8s的最小调度单元,Pod中的容器使用同一个net namespace,且都在同一台物理机/虚拟机上)
关于训练数据的分发
关于训练数据的分发,我目前的做法是先将数据切分成N个文件(N=trainer个数),按照traineridl命名。将数据提前存放在共享存储中,然后通过(volume)[http://kubernetes.io/docs/user-guide/volumes/]挂载到容器里,训练时通过启动脚本去获得对应的数据。
遇到的问题
在分布式训练时,Paddle启动每次都需要知道其他pserver的IP地址,是否需要一个服务发现机制来改善分布式训练?例如每个server启动时向一个组件去注册/获取训练信息