tensorflow模型使用,tensorflow输出模型结构
简介TensorFlow是Google开发的第二代人工智能学习系统,可以处理多种深度学习算法模型,以高性能和高可扩展性著称。TensorFlow是完全开源的,所以很多企业都在用。但美团使用分布式TensorFlow训练WDL模型时,被评估训练速度慢,难以满足业务需求。
通过对TensorFlow框架和Hadoop的分析定位,发现在数据输入、集群网络和计算内存分配等方面存在性能瓶颈。主要原因有:TensorFlow数据输入接口效率低、PS/Worker操作符分配策略不完善、Hadoop参数配置不合理等。调整调用TensorFlow接口,优化系统配置后,WDL模型训练性能提升10倍,分布式线性加速达到32个工人,基本满足美团的评测广告、推荐等业务需求。
tensor flow——Google发布的开源深度学习框架
操作缩写,张量流操作符
参数服务器
WDL-Wide Deep Learning,谷歌发布的推荐场景深度学习算法模型
YARN开发的一个深度学习调度框架,基于AI框架,支持张量流、MXNet等深度学习框架。
TensorFlow分布式架构概述为了解决大量参数的模型计算和参数更新问题,TensorFlow支持分布式计算。与其他深度学习框架方法一样,分布式TensorFlow也部署参数服务器(PS)存储和更新训练参数,模型训练在工作者节点上进行。
张量流分布式体系结构
TensorFlow支持图形并行(图内)和数据并行(图间)模式,以及同步更新和异步更新。In-graph只在一个节点上输入和分发数据,严重影响了并行训练的速度。在实际生产中,通常使用中间图。
在同步更新时,它控制是否所有的worker都进入下一个迭代,负责输出检查点的worker节点必须是Chief。异步更新时,所有工人都是平等的,迭代过程不受同步屏障控制,训练过程更快。
AFO架构设计TensorFlow只是一个计算框架,没有集群资源管理和调度功能,分布式训练也缺乏集群容错能力。为了解决这些问题,我们研究了基于纱线的AFO框架来解决这个问题。
AFO建筑的特点:
*扩展性强,PS和workers是任务,角色可配置。
*基于状态机的容错设计
*提供日志服务和Tensorboard服务,便于识别问题和调试模型。
AFO建筑
AFO模块描述:
*应用主:用于管理整个张量流集群的资源应用,监控任务状态。
* AFO子级:tensorflow执行引擎,负责PS、Worker运行时管理和状态同步。
*历史服务器:管理张量流训练生成的日志。
* AFO客户端:用户客户端
WDL模型在推荐系统和CTR估计的场景下,训练样本数据一般是查询、用户和上下文信息,系统返回排序后的候选列表。推荐系统面临的主要问题是如何同时实现模型的记忆能力和泛化能力。建议WDL将线性模型Wide]与深度神经网络Deep]结合起来用于泛化。
以谷歌Play商店推荐系统中使用的WDL模型为例。该模型输入用户访问应用商店的日志、用户和设备信息,对应用进行评分,并输出用户感兴趣的应用列表。
WDL模型网络
其中,已安装应用、印象应用等特征较为稀疏(在庞大的应用空间中,用户兴趣的一小部分),对应的是模型的“宽泛部分”。适合线性模型的稀疏特征维数过高,不适合神经网络处理。需要去除嵌入的维度,转化为稠密特征,结合其他稠密特征输入到三层ReLU深度网络中。最后的宽和深估计结果将被加权到逻辑损失函数中,例如Sigmoid。
WD模型包含了稀疏嵌入式计算,TensorFlow中对应的接口是tf.embedding_lookup_sparse,但是这个接口包含的OP是GPU access。发现分布式TensorFlow在嵌入式计算时会造成大量的网络流量,严重影响训练性能。
在使用性能瓶颈分析和优化TensorFlow来训练WDL模型时,我们发现了三个主要的性能问题。
1.每次训练输入数据的时间太长,60%以上的时间都花在读取数据上。
2.在训练中分娩
由于集群网络的高网络流量和大带宽资源,很难实现分布式性能的线性加速。
3.Hadoop的默认参数配置导致glibc malloc变慢,一个保护malloc内存池的内核自旋锁成为性能瓶颈。
TensorFlow输入数据瓶颈TensorFlow支持管道形式的训练数据输入。如下图所示,一个典型的输入数据管道由两个队列组成:Filename Queue shuffle一组文件,几个Reader线程从这个队列中获取文件名,读取训练数据,然后通过解码过程将数据放入Example Queue,供训练线程从中读取数据。流水线,多线程多队列的设计,可以使训练线程和数据读取线程并行。理想情况下,队列示例队列总是充满数据,训练线程在完成一轮训练后可以立即读取下一批数据。如果示例队列总是处于“饥饿”状态,训练线程将不得不阻塞并等待读取器线程将示例队列插入足够的数据。使用TensorFlow时间轴工具,可以直观的看到OP调用过程。
张量流输入数据管道
要使用Timeline,您需要向tf添加以下代码行。会话.运行():
用tf。会话为sess:options=TF。RunOptions(trace_level=tf。run options . FULL _ TRACE)run _元数据=tf。run metadata()_=sess . run([train _ op,global_step],options=run_options,run _ metadata=run _ metadata)if global _ step 1000 global _ step 1010:from tensor flow . python . client导入时间轴fetched_timeline=timeline。Timeline(run _ metadata . step _ stats)Chrome _ trace=fetched _ Timeline . generate _ Chrome _ trace _ format()with open(/tmp/timeline_01.json ,W) as f: f.write(Chrome_trace)当全局步长以这种方式训练1000轮左右时,此轮训练的时间轴信息将保存在Timeline _ 01 . JSON文件中。在chrome浏览器的地址栏输入chrome://tracing,然后加载文件,就可以看到可视化的评测结果。
商业模式的时间表如图所示:
时间线显示数据输入是一个性能瓶颈。
可以看出QueueDequeueManyV2是耗时最长的OP,占整体延迟的60%以上。通过分析TensorFlow源代码,我们判断有两个原因:
(1)阅读器线程是Python线程,受制于Python的全局解释锁(GIL),训练时阅读器线程没有得到足够的调度执行;
(2)2)Reader的默认接口函数TFRecordReader.read函数,一次只读取一条数据。如果批量比较大,需要频繁调用接口读取一批数据,系统开销很大;
对于第一个问题,解决方法是使用TensorFlow Dataset接口。该接口不再由Python线程读取,而是由C线程实现,避免了Python GIL问题。
针对第二个问题,社区提供了一个批量数据读取接口TFRecordReader.read_up_to,可以指定每次读取的数据量。我们设置每次读入1000条数据,使调用读句接口的次数从10000次减少到10次,每轮训练延迟减少2-3次。
优化数据输入,将性能提高2-3倍。
可以看到,调优后QueueDequeueManyV2只需要十几毫秒,每轮的训练延迟从原来的800毫秒降低到300毫秒以内。
虽然Mellanox的25G网卡用于集群瓶颈,但在WDL的培训过程中,我们观察到Worker上的上下游网络流量波动剧烈,波动范围在2-10Gbps,这是由于全ps网络带宽造成的丢包。由于分布式的训练参数都是在PS上保存和更新的,参数太多,而且模型网络浅,计算快,容易形成多个Worker打一个PS的情况,导致PS的网络接口带宽被占满。
在推荐服务的WDL模型中,嵌入甜蜜台灯的参数规模是几千万,TensorFlow的tf.embedding_lookup_sparse接口包含了几个op,默认分别放在Ps和Worker上。如图,颜色代表设备,嵌入查找需要在不同设备之前传递整个嵌入变量,这意味着嵌入的每一轮迭代更新都需要在PS和Worker之间来回传递大量的参数。
嵌入_查找_稀疏的OP拓扑图
减少网络流量的有效方法是尽可能在一台设备上完成参数更新,即
与。设备(PS): Do嵌入式计算社区提供了一个接口方法,按照这个思路实现:embedding_lookup_sparse_with_distributed_aggregation接口。这个接口可以把嵌入计算中用到的所有OP放到变量所在的PS上,然后变成密密甜甜的台灯发给Worker继续网络模型的计算。
从下图可以看出,嵌入计算涉及的OP都在PS上,测试工的上下行网络流量也稳定在正常值2-3g bps。
embedding _ lookup _ spare _ with _ distributed _ aggregation的op拓扑PS上的独特OP性能瓶颈
在使用分布式TensorFlow运行广告推荐的WDL算法时,发现了一个奇怪的现象:WDL算法在AFO上的性能只有手动分布式算法的1/4。手动分配是指通过命令行在集群上启动PS和Worker作业,独立于YARN调度。
用Perf诊断PS进程的热点,发现PS多线程在争用一个内核自旋锁,PS整体30%-50%的CPU时间都花在malloc在内核的spin_lock上。
PS计算瓶颈的性能诊断
进一步观察PS进程栈,发现竞争的内核自旋锁来自malloc相关的系统调用。WD的embedding_lookup_sparse会使用UniqueOp运算符,TensorFlow支持Op多线程,计算时UniqueOp会打开多线程,线程执行时会调用glibc的malloc申请内存。
经过测试,发现Hadoop有一个默认的环境变量配置:
Export MALLOC_ARENA_MAX=4 该配置意味着将进程可以使用的glibc内存池的数量限制为4。这意味着当一个进程启动多线程调用malloc时,它最多会从四个内存池中竞争应用程序,这就限制了并行调用malloc的线程数量为四个。
查了一下Hadoop社区相关讨论,最开始加这个配置的主要原因是glibc的升级带来了多线程竞技场的特性,可以提高malloc的并发性能,但同时也增加了进程的虚拟内存(即top结果中的virt)。YARN管理进程树的虚拟内存和物理内存使用情况,超过限制的进程树将被杀死。将MALLOC_ARENA_MAX默认设置改为4后,VIRT不会增加很多,一般作业性能不会受到明显影响。
然而,这种默认配置对WDL深度学习工作有很大的影响。我们已经删除了这个环境配置,malloc并发性能得到了很大的提高。经过测试,WDL模型的平均训练时间性能降低到原来的1/4。
调谐结果注意:以下测试都去掉了Hadoop MALLOC_ARENA_MAX的默认配置
在AFO,我们对WDL商业模式进行了性能调整前后的对比测试。测试环境参数如下:
模特:推荐广告模特WDL
操作系统:CentOS 7.1
CPU:至强E5 2.2G,40个内核
GPU:英伟达P40
磁盘:本地旋转磁盘
网卡:Mellanox 25G(不带RoCE)
TensorFlow版本:1.4版
CUDA/cuDNN: 8.0/5.1
分布线性加速度效应
可以看出,调优后训练性能提升2-3倍,性能可以达到32 GPU线性加速。这意味着,如果使用同样的资源,业务培训时间会更快,或者在一定
综上所述,我们使用TensorFlow对WDL模型进行训练,发现了系统上的一些性能瓶颈。有针对性的调优不仅可以大大加快训练过程,还可以提高GPU、带宽等资源的利用率。在深入挖掘系统热点瓶颈的过程中,我们也加深了对业务算法模型和TensorFlow框架的理解,具有技术储备的意义,有助于我们进一步优化深度学习平台的性能,更好地为业务提供工程和技术支持。
作者简介虚幻河马,美团点评技术专家,2015年加入美团点评,负责深度学习平台和Docker平台的研发。
美团点评GPU计算团队招聘致力于打造公司一体化深度学习基础平台。涉及的技术包括:资源调度、高性能存储、高性能网络、深度学习框架等。目前平台还在建设中,系统底层、分布式架构、算法工程优化都有很大挑战!我们真诚地邀请对这一领域感兴趣的学生加入我们。工程背景和算法背景都欢迎。感兴趣的学生可以把简历寄到zhengkun@meituan.com。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。