工程师:“在你辉煌的时刻,让我为你唱首歌,个人好兄弟,内心有苦你对我说。”算法
计算机:“哥啊,那我可就说了,我是真的苦啊,如今一个模型动辄好几亿参数,数据集也是大的吓人,兄弟我内存都快被掏空了,实在训练不动了呀。”编程
工程师:“前方大路一块儿走,哪怕是河也一块儿过…”服务器
计算机:“你怎么还唱啊,兄弟我真的坚持不住了。”网络
工程师:“担忧啥,哥有的是办法救你,就这招吧——分布式训练之参数服务器!”架构
计算机:“分布式训练?参数服务器?真的很好用吗?”异步
工程师:“好吧,接下来咱们就来看看什么是分布式训练参数服务器功能。”分布式
何谓分布式训练呢?你们想一想《火影忍者》中鸣人搓螺旋丸的方法,要知道鸣人一我的可搓不出来,他是怎么作的呢?对!影分身,再变出两个分身来帮他一块儿搓丸子,分布式训练其实用的是相同的原理。通俗的讲就是把原先交给一台计算机上完成的训练任务改成交由多台计算机完成。每台计算机上都会有一个或多个计算单元,例如CPU、GPU、AI芯片等,合做的计算机越多,参与训练的计算单元也就越多。可想而知那速度确定是噌噌的!函数
什么是参数服务器工具
如图1所示,参数服务器是分布式训练领域广泛采用的编程架构,主要包含Server和Worker两个部分,其中Server负责参数的存储和更新,而Worker负责训练。飞桨的参数服务器功能也是基于这种经典的架构进行设计和开发的,同时在这基础上进行了SGD(Stochastic Gradient Descent)算法的创新(Geometric Stochastic Gradient Descent)。当前通过大量的实验验证,最佳的方案是每台机器上启动Server和Worker两个进程,而一个Worker进程中能够包含多个用于训练的线程。oop
图1 参数服务器架构示意图
飞桨参数服务器功能支持三种模式,分别是同步训练模式、异步训练模式和GEO异步训练模式:
图2 同步训练模式示意图
异步训练模式:如图3所示,在训练一个batch的数据后,Worker的每一个线程会发送梯度给Server。而Server不会等待接收全部节点的梯度,而是直接基于已收到的梯度进行参数更新。异步训练去除了训练过程当中的等待机制,训练速度获得了极大的提高,可是缺点也很明显,那就是Loss降低不稳定,容易发生抖动。建议在个性化推荐(召回、排序)、语义匹配等数据量大的场景使用。
尤为是推荐领域的点击率预估场景,该场景可能会出现千亿甚至万亿规模的稀疏特征,而稀疏参数也能够达到万亿数量级,且须要小时级或分钟级流式增量训练。若是使用异步训练模式,能够很好的知足该场景的online-learning需求。
图3 异步训练模式示意图
GEO异步训练:GEO是飞桨自研的异步训练模式,如图4所示,其最大的特色是将参数的更新从Server转移到Worker上。每一个Worker在本地训练过程当中会使用SGD优化算法更新本地模型参数,在训练若干个batch的数据后,Worker将发送参数更新信息给Server。Server在接收后会经过加和方式更新保存的参数信息。因此显而易见,在GEO异步训练模式下,Worker不用再等待Server发来新的参数便可执行训练,在训练效果和训练速度上有了极大的提高。可是此模式比较适合能够在单机内能完整保存的模型,在搜索、NLP等类型的业务上应用普遍,推荐在词向量、语义匹配等场景中使用。
图4 异步训练模式示意图
通过上述介绍,我想小伙伴们应该对飞桨的参数服务器功能有了必定了解,但是这个参数服务器不只包括了三种模式,还一下子Worker一下子Server的,用起来应该会很复杂吧?这个请放心,这个用起来其实很是简单,甚至比鸣人结手印召唤影分身还要简单!
参数服务器模式
飞桨的分布式训练功能确实是比较复杂,其不只包含参数服务器(同步、异步、GEO)模式,还包含collective、hybrid等其它模式。为了能让开发者们方便得使用这些功能,飞桨的工程师们很是贴心的专门为分布式训练设计了一套FleetAPI接口。如图5所示,使用FleetAPI能够轻松的将原先的单机训练转换为分布式参数服务器模式:
图5 FleetAPI功能示意图
具体操做方法请参见下面的代码示例。
以下为模型单机训练的代码,为了简化说明,这里省略了模型网络定义和数据读取等部分的代码。
exe = Executor(place) optimizer = optimizer.Adam(learning_rate=0.001) optimizer.minimize(avg_cost) exe.run(default_startup_program()) for batch_id, data in enumerate(train_reader()): avg_loss_value, auc_value = exe.run(main_program(), feed=feeder.feed(data))
用户只须要加入十行代码便可将上面的单机训练过程转换为分布式训练:
exe = Executor(place) #设置节点角色 role = role_maker.PaddleCloudRoleMaker() fleet.init(role) optimizer = optimizer.Adam(learning_rate=0.001) #配置策略 strategy = StrategyFactory.create_sync_strategy() optimizer = fleet.distributed_optimizer(optimizer, strategy) optimizer.minimize(avg_cost) # 初始化并运行Server进程 if fleet.is_server(): fleet.init_server() fleet.run_server() # 初始化并运行Worker进程 if fleet.is_worker(): fleet.init_worker() exe.run(fleet.startup_program) for batch_id, data in enumerate(train_reader()): avg_loss_value, auc_value = exe.run(fleet.main_program, feed=feeder.feed(data)) # 通知Server中止监听Worker请求 fleet.stop_worker()
性能远超业界同类最优产品!
在训练效果相同的状况下,飞桨的参数服务器训练模式在训练速度上有很大优点。相比于业界同类最优产品,参数服务器训练模式在相同机器数量和硬件配置条件下可以大幅提高模型训练速度。
如图6所示,在词向量Word2Vector模型上,采用GEO训练模式的飞桨分布式训练的训练速度可以超越同类最优产品 18倍。
图6 Word2Vector模型性能示意图
在CTR-DNN模型上,如图7所示,采用全异步训练的训练模式也可以有6倍的速度提高。此外飞桨的推荐模型库还提供有包括DeepFM、Deep Cross Network、Gru4Rec等一系列经典个性化推荐类模型,方便开发者选择使用。
图7 CTR-DNN模型性能示意图
飞桨参数服务器功能在提供巨大性能优点的同时,也进一步支持了分布式训练相关的工具组件给用户使用。
飞桨参数服务器模式现在已经在百度公司内外获得了广泛的应用,包括信息流、搜索等业务。下面以视频推荐场景为例介绍飞桨参数服务器的几种模式在业务中的具体应用。
图8 视频推荐系统示意图
如图8因此,视频推荐系统采用了漏斗模型,即召回->粗排->精排->融合的架构:
通过实际业务验证,飞桨参数服务器功能能够轻松应对千万级用户数量、百亿特征规模的业务场景。
若是您加入官方QQ群,您将赶上大批志同道合的深度学习同窗。官方QQ群:703252161。