tensorflow 环境检查 tensorflow parameter server_tensowflow 训练 远程提交


在广告/推荐/搜索场景,目前主流算法采用embedding+DNN的模型结构,随着数据量越来越多,单机训练已经无法满足实时要求。针对广告/推荐场景,一般采用Parameter Server的方式进行分布式训练,简称ps,ps可以同时做到对数据和模型的并行训练。Parameter Server直译就是参数服务器,这里的参数,指的是模型权重,以及中间的过程变量。最近一段时间,我了解和使用了一些ps训练平台,在此做个总结,我会分成上下两篇对ps进行介绍。本文是上篇,主要是对论文[1]进行介绍,这是李沐在14年的文章。跟开发同学交流了解到,李沐开源的代码和文章的描述不完全一致,本文主要是基于文章进行介绍。因为我没有从事过相关的系统开发工作,所以文中难免会出现疏漏和谬误,如果文中有不准确的地方,欢迎指正和讨论。

一,基本原理

以往的分布式计算,比如mapreduce的原理,是将任务和数据分配到多个节点中做并行计算,来缩短任务的执行时间。对于分布式训练来说,同样是希望将训练任务部署到多个节点上并行计算,但是因为反向传播涉及到梯度的汇总和权重的更新,相比之前的分布式计算更加复杂。也有采用hadoop或者spark的分布式训练,用单个driver或者master节点来汇总梯度及更新权重,但是受限于单节点的内存容量,支持的模型大小有限。另外,集群中运行最慢的那个worker,会拖累整个训练的迭代速度。为了解决这些问题,Parameter Server做了新的设计。

Parameter Server主要包括两类节点,一类是server节点,server节点可以有若干个,模型的权重和参数存储在这些server节点中,并在server节点中进行更新,每个server节点都存储和管理一部分模型参数,避免单个master节点内存和算力的不足,从而实现了模型的并行;另外一类是worker节点,也可以有若干个,全部训练样本均匀分配给所有worker节点,worker节点并行执行前向和后向计算,从而实现数据的并行。

worker节点主要通过pull和push这两个操作,和server节点进行通信和交互,pull和push是ps中的重要操作。在训练之前,所有server节点完成对模型权重的初始化。第一次训练,worker节点从全部server节点中,pull相应的权重,进行前后向计算得到梯度,然后把梯度push到对应的多个server节点。server节点获取到所有worker的梯度并做汇总之后,对权重进行一次更新。之后worker节点再一次进行pull和push操作,反复循环,直到worker节点跑完所有的训练数据。

每一次迭代,worker只拉取部分权重,而不需要拉取全部的权重,这是为什么?这要从广告/推荐场景的特点说起,就是特征高维稀疏。所谓高维,就是特征非常多,比如特征数量的规模可以从千万到千亿级别,单机都无法存储,需要分布式存储。所谓稀疏,就是每个训练样本用到的特征非常少,几十几百或者几千,所以每一次训练迭代,只更新了极少部分特征权重,绝大多数权重都没有更新,所以worker只需要拉取部分权重即可,不必把所有的权重都拉到本地,而且模型太大的情况下,worker也放不下。

每个server节点只存储部分权重,如果有多个worker同时用到这部分权重,那么server需要把所有worker的梯度都汇总起来,再去更新权重。而一个worker用到的权重,也可能分布在多个server上,需要从多个server做pull和push。所以worker和server在通信的时候是多对多的关系。

逻辑回归是广告/推荐场景中广泛使用的算法,论文以逻辑回归为例对算法做了描述。逻辑回归目标函数如下,包括loss和正则化这两项,一般采用L1正则化,目的是让大量权重为0,得到稀疏权重,降低线上推理复杂度。


tensorflow 环境检查 tensorflow parameter server_tensowflow 训练 远程提交_02


对照下图,完整的算法描述如下:

  • 任务调度器:调用LoadData函数,将训练样本分配给所有worker,然后对所有worker进行若干轮迭代;
  • worker节点:获取到训练数据,以及初始化权重,进行迭代;
  • server节点:从所有worker获取到梯度,并进行汇总aggregate,这里是采用求和,一般求和或平均都可以,计算正则化项的梯度,对权重进行更新。


tensorflow 环境检查 tensorflow parameter server_权重_03


结合下图进一步说明训练过程,在训练之前先将训练样本分配到各个worker上。

  1. worker根据本地的训练数据和权重w,计算得到梯度g。下图worker的细节很有意思,这里有m个worker,每个worker只分配到部分训练数据,每一部分训练数据只用到了部分特征,对应也只用到了部分权重w,反向传播计算出这部分权重的梯度g。特征,权重w,梯度g,在worker中非空的列是对应的,为空的列表示该worker没有用到的特征/权重/梯度。
  2. 将计算好的梯度push到servers,servers进行汇总。
  3. 根据汇总之后的梯度,对权重进行更新。
  4. worker将更新之后的权重pull到本地。反复循环上述过程,直到迭代结束。


tensorflow 环境检查 tensorflow parameter server_数据_04


二,整体架构

论文中提出的架构下图所示。系统包括一个server group和多个worker group,server group包括一个server manager和若干个server节点,每个worker group包含一个任务调度器task scheduler和多个worker节点,worker group连接分布式文件系统,例如hdfs/s3等,获取到training data。


tensorflow 环境检查 tensorflow parameter server_tensorflow 环境检查_05


为了保证伸缩性和可靠性,server group内部的server节点之间相互通信,用于备份或者迁移参数。server manager保存和管理所有server节点的元数据,例如权重参数如何分配,以及监控节点是否正常。

worker group中,各个worker之间不需要进行通信,worker只需要与server节点通信。worker group中的任务调度器,对worker分配任务,并监控任务进度。

一个ps系统可以同时跑多个applications,一个application即一个训练任务。一个worker group是application的最小单位,即一个worker group最多只能跑一个application。而一个application可以跑在一个或者多个worker group上。application之间通过独立参数命名空间对worker group进行资源隔离。

在这个系统中,server节点和worker节点是分离的,这与目前主流的ps系统设计不太一样,下篇文章会进行比较。

三,技术细节

在整个系统的实现上,有很多技术细节,这里逐一进行介绍。

1.哈希表和副本

server节点采用(key, value)的方式存储权重参数,例如对LR来说,key和value分别对应特征ID和权重。

系统采用环状的分布式哈希表存储所有key,如下图所示。server节点通过插入点,插入到哈希环中,下图中的


等即为server的插入点。整个环被server插入点分隔为若干段key range。server节点,按照逆时针方向,管理和存储自己的插入点到下一个server插入点的key range。下图中,


之间的key range由S1节点进行管理,S1节点称为该key range的主节点master。出于负载均衡的考虑,一个物理server节点可以管理多个key range。


tensorflow 环境检查 tensorflow parameter server_tensowflow 训练 远程提交_06


生产环境需要考虑容错,为了防止服务器故障导致数据丢失,需要对数据做副本。server节点需要保存,hash环中逆时针方向k个相邻key range的副本。上图中,S1节点需要保存


这两个副本,这里k=2,S1节点称为这两个key range的从节点slave。worker节点每一次push新的梯度到server,server节点都要更新权重。为了保证数据的一致性,master的每一次修改和更新,都要同步到slave上去,同步完成之后,worker的push操作才算完成,如下图所示。


tensorflow 环境检查 tensorflow parameter server_数据_07


2.动态伸缩

集群中有大量的服务器,难免会有服务器出现故障。为了保证任务持续进行不被中断,系统需要具备动态伸缩的能力,可以随时添加或者删除节点。

对于server和worker,添加和删除节点有不同的操作。可以再回顾下前面的系统架构图,这里结合架构图进行说明。添加server节点步骤如下:

  1. server manager给新节点分配一个key range,原来的master需要分割和删除相应的key range;
  2. 新节点获取到该key range的数据成为master,同时获取另外k个key range的副本数据成为slave;
  3. server manager广播节点的变化,其他节点基于key range的变化,释放相应的数据,并且将未完成的任务,提交到新加入的节点。

server节点删除也是类似步骤,server manager会将丢失节点的key range分配给其他节点。server manager会检查server节点的心跳,判断是否出现异常。

添加worker节点比较简单,步骤如下:

  1. 任务调度器给新的worker节点分配一部分训练数据;
  2. 新节点获取相应的训练数据,并开始进行训练;
  3. 任务调度器广播节点的变化,其他节点释放相应的训练数据。

3.异步任务和灵活一致性

整个ps系统有很多节点,节点之间通过远程过程调用,即RPC来启动任务,例如pull或push操作等。异步任务指的是,当调用者发起远程任务之后,可以不用等到应答和任务结束,就立即执行下一步计算,下一步任务的执行不需要依赖上一步任务的完成。下图中描述了两种依赖关系,第一种,worker计算出第10次迭代的梯度之后,立即进行第11次迭代,而不需要pull新的权重过来,没有等待时间,效率较高;第二种,第12次迭代依赖第11次迭代的完成,需要等待。如果希望提高整个系统的效率,需要减少等待时间,尽可能减少任务之间的依赖。但是减少依赖可能导致数据不一致,仍以下图为例,当第10次迭代之后,立即进行第11次迭代,权重没有得到更新,这可能影响到训练任务的收敛速度。因此系统的效率和算法的收敛速度之间是一对矛盾体,需要平衡和折中。


tensorflow 环境检查 tensorflow parameter server_权重_08


有一些算法对一致性不太敏感,即使采用异步训练,对收敛速度影响也不大。只限定一种依赖关系,缺少了灵活性。所以ps系统将依赖关系开放给算法开发者,由算法开发者决定采用什么样的依赖关系和一致性。

论文[1]中给出了3种任务依赖关系,如下图的DAG所示。第一种是顺序关系,任务1开始执行要等任务0完成,任务2开始执行要等任务1完成,即下一个任务必须要等待上一个任务执行完成。第二种是完全并行,任务之间相互不存在依赖。第三种是受限依赖,设定一个延迟时间


,在新的任务开始执行之前,时间


之前的任务必须要全部完成,否则新任务会被阻塞。受限依赖更加灵活,当


时,就变成第一种顺序依赖,当


时,就变成第二种情况。


tensorflow 环境检查 tensorflow parameter server_tensorflow 环境检查_09


论文[1]中的异步训练主要是针对worker节点的,目前主流的ps系统,worker节点都是同步的,而server节点是异步的,下篇文章会进行介绍和对比。

4.用户定义函数

在server节点上,可以执行用户定义函数User-Defined Functions(UDF)。server节点拥有完整的,最新的模型参数,有一些操作在server节点上更容易实现。例如,在前面的Algorithm1那张图中,在server节点求正则项


的梯度就属于UDF。server节点还可以执行更复杂的UDF来更新模型权重,这取决于所采用的优化算法。


论文[1]提出的ps,是从分布式系统的角度出发,希望构建一个尽可能完备高可用的分布式训练平台,所以设计的比较复杂。概述下篇 张备:Parameter Server分布式训练概述(下篇) 对目前几个主流的ps系统进行介绍,与本文的ps相比,做了一些简化,同时为了满足业务需求也增加了一些功能,欢迎戳进去看下篇。

参考文献

[1] 2014. Scaling Distributed Machine Learning with the Parameter Server.