写点什么

美团深度学习系统的工程实践

  • 2020-02-27
  • 本文字数:4444 字

    阅读完需:约 15 分钟

美团深度学习系统的工程实践

背景

深度学习作为 AI 时代的核心技术,已经被应用于多个场景。在系统设计层面,由于其具有计算密集型的特性,所以与传统的机器学习算法在工程实践过程中存在诸多的不同。本文将介绍美团平台在应用深度学习技术的过程中,相关系统设计的一些经验。


本文将首先列举部分深度学习算法所需的计算量,然后再介绍为满足这些计算量,目前业界比较常见的一些解决方案。最后,我们将介绍美团平台在 NLU 和语音识别两个领域中,设计相关系统的经验。

深度学习的计算量

ModelInput SizeParam SizeFlops
AlexNet227 x 227233 MB727 MFLOPs
CaffeNet224 x 224233 MB724 MFLOPs
VGG-VD-16224 x 224528 MB16 GFLOPs
VGG-VD-19224 x 224548 MB20 GFLOPs
GoogleNet224 x 22451 MB2 GFLOPs
ResNet-34224 x 22483 MB4 GFLOPs
ResNet-152224 x 224230 MB11 GFLOPs
SENet224 x 224440 MB21 GFLOPs


数据来源


上表列举了,ImageNet 图像识别中常见算法的模型大小以及单张图片一次训练(One Pass)所需要的计算量。


自 2012 年,Hinton 的学生 Alex Krizhevsky 提出 AlexNet,一举摘下 ILSVRC 2012 的桂冠后,ILSVRC 比赛冠军的准确率越来越高。与此同时,其中使用到的深度学习算法也越来越复杂,所需要的计算量也越来越大。SENet 与 AlexNet 相比,计算量多了近 30 倍。我们知道,ImageNet 大概有 120 万张图片,以 SENet 为例,如果要完成 100 个 epoch 的完整训练,将需要 2.52 * 10^18 的计算量。如此庞大的计算量,已经远远超出传统的机器学习算法的范畴。更别说,Google 在论文《Revisiting Unreasonable Effectiveness of Data in Deep Learning Era》中提及的、比 ImageNet 大 300 倍的数据集。

物理计算性能

面对如此庞大的计算量,那么,我们业界当前常用的计算单元的计算力是多少呢?


  • CPU 物理核:一般浮点运算能力在 10^10 FLOPS 量级。一台 16 Cores 的服务器,大致上有 200 GFLOPS 的运算能力。实际运行,CPU 大概能用到 80%的性能,那就 160 GFLOPS 的运算能力。完成上述 SENet 运行,需要 182 天。

  • NVIDIA GPGPU: 目前的 V100,单精度浮点运算的峰值大概为 14 TFLOPS, 实际运行中,我们假设能用到 50%的峰值性能,那就是 7 TFLOPS,需要 4 天。


根据以上数据结果可以看出:在深度学习领域,GPU 训练数据集所需要耗费的时间,远远少于 CPU,这也是当前深度学习训练都是采用 GPU 的重要原因。

业界的解决方案

从前面的计算可知,即使使用 GPU 来计算,训练一次 ImageNet 也需要 4 天的时间。但对于算法工程师做实验、调参而言,这种耗时数天的等待是难以忍受的。为此,目前业界针对深度学习训练的加速,提出了各种各样的解决方案。

异构计算的并行方案

数据并行(Data Parallelism)


数据并行,即每个计算单元都保留一份完整的模型拷贝,分别训练不同的数据,经过一个 Iteration 或若干个 Iteration 后,把各个计算单元的模型做一次同步。这是最常见的深度学习训练方式,好处在于逻辑简单、代码实现方便。

模型并行(Model Parallelism)


模型并行,即各个计算单元存储同一层模型数据的不同部分,训练相同的数据。相对于数据并行,因为各个运算单元每训练完一层神经网络,就必须要同步一次,频繁的同步通信导致系统不能充分地利用硬件的运算能力,所以更为少见。但是在一些业务场景下,Softmax 层需要分类的类别可能会有很多,导致 Softmax 层太大,单个计算单元无法存储,这个时候,需要把模型切割成若干部分,存储在不同的运算单元。模型并行常见于 NLU、推荐、金融等领域。

流式并行(Stream Parallelism)


流式并行,即每个计算单元都存储不同层的模型数据,训练相同的数据。如上图所示,GPU1 只负责第一层神经网络的计算,GPU2 只负责 2~5 层神经网络的计算,GPU3 只负责第 6 层的计算。流式并行的好处在于每个运算单元之间的通信和计算重叠(overlap),如果配置得当,可以非常充分地利用硬件资源。缺点在于,根据不同的模型,需要平衡好各个计算单元的计算量,如果配置不好,很容易形成“堰塞湖”。如上图所示,很有可能出现 GPU1 负责的运算量太少,而 GPU2 负责的运算量太多,导致 GPU1 和 GPU2 之间堵塞住大量的 Mini-batch,更常见于线上环境。

混合并行(Hybrid Parallelism)


混合并行,即上面提到的并行方式的混合。如对于一些图像识别任务来说,可能前几层使用数据并行,最后的 Softmax 层,使用模型并行。

异构计算的硬件解决方案

  • 单机单卡:一个主机内安装上一块 GPU 运算卡。常见于个人计算机。

  • 单机多卡:一个主机内安装上多块 GPU 运算卡。常见的有:1 机 4 卡,1 机 8 卡,甚至有 1 机 10 卡。一般公司都采取这种硬件方案。

  • 多机多卡:多台主机内安装多块 GPU 运算卡。常见于公司内部的计算集群,一般多机之间采取 Infiniband 来实现网络的快速通信。

  • 定制化:即类似于 Google 的 TPU 解决方案。常见于“巨无霸”公司内部。

异构计算的通信解决方案

根据上面的硬件解决方案,我们以 ResNet 为例:模型的大小为 230M,单张图片运算量为 11 GFLPOS,Mini-batch 假设为 128。可以计算出各个硬件模块在深度学习训练中的耗时比较:


  • GPU:对于 V100,假设有 6 TFLOPS,一次 Mini-batch 理论耗时:0.23s。

  • PCI-E:常见 PCI-E 3.0 * 16,速度为 10 GB/s,传输一个模型的理论耗时为:0.023s。

  • 网络:假设为 10 GB/s 的高速网络,传输一个模型的理论耗时:0.023s。

  • Disk:普通的磁盘,我们假设 200M/s 的读取速度,读取一次 Mini-batch 所需要的图片耗时:0.094s。


根据上面的数据结果,我们似乎可以得出一个结论:PCI-E 和网络的传输耗时,相对于 GPU 来说,整整少了一个数量级,所以网络通信同步的时间可以忽略不计。然而问题并没有那么简单,上面例子中的耗时只是单个模型的耗时,但是对于 8 卡的集群来说,如果使用数据并行,每次同步就需要传输 8 份模型,这就导致数据传输的时间和 GPU 的计算时间“旗鼓相当”。这样的话,GPU 就得每训练完一个 Mini-batch,都得等候很久的一段时间(采取同步更新),这会浪费很多计算资源。因此,网络通信也需要制定对应的解决方案。下面我们以 Nvidia NCCL 中单机多卡的通信解决方案为例介绍,而多机多卡的通信解决方案其实是类似的。



上图是单机 4 卡机器,在硬件上,两种不同的通信体系。左边为普通的 PCI-E 通信,即 4 个 GPU 之间组成一个环状。右边为 NVLink 通信,即两两之间相互连接。


常见的通信类型如下图所示



对于深度学习训练而言,关键的两种通信类型为:Broadcast 和 Reduce。Broadcast 用于 Master 分发最新的模型给各个 GPU。Reduce 用于各个 GPU 计算完 Mini-batch 后,把模型更新值汇总到 Master 上。以 Broadcast 为例,最简单的通信方式是 Master 往各个 GPU 上发送数据,这样的耗时就是 4 次模型传输的时间,通信时间就会太长,一种简单的优化方法如下图所示:



即把所需要传输的数据分成若干块,然后通过接力的方式逐个传递,每个 GPU 都把自己最新的一块数据发送到下一个 GPU 卡上。这种传输方式能充分利用硬件层面的通信结构,使得需要的耗时大幅缩减。与此类似的,Reduce 的通信优化也可以采取相同的方式进行提速。

美团的定制化深度学习系统

尽管目前在业界已经推出了很多著名的深度学习训练平台,通用的训练平台如 TensorFlow、MxNet 等等,还有领域专用的训练平台,如语音识别中的 Kaldi,但是我们经过调研后,决定内部自主开发一套深度学习系统,理由如下:


  • 通用的训练平台,缺乏了领域特色的功能。如语音识别中的特征提取模块和算法。

  • 通用的训练平台,通常是基于 Data-flow Graph,来对计算图中的每个 operator 进行建模,所以颗粒度很小,需要调度的单元多,导任务调度复杂。

  • 领域特色的训练平台,如 Kaldi,在神经网络训练的时候,性能不足。

  • 线上业务存在很多特殊性,如果使用 TensorFlow 之类作为训练平台,不太适合线上业务的情景。

NLU 线上系统

线上系统的业务特点

我们在设计 NLU 线上系统时,考虑了 NLU 业务的一些特性。发现其具备如下的一些特点:


  • 随着业务和技术的变化,算法流程也经常发生变化。

  • 算法流程是多个算法串联组成的,不单纯的只有深度学习算法。如分词等算法就不是 DL 算法。

  • 为了能够快速响应一些紧急问题,需要经常对模型进行热更新。

  • 更重要的是,我们希望构建一个能以“数据驱动”的自动迭代闭环。


业务多变


NLU 任务的算法流程是多层级的,并且业务经常发生变化。如下图所示:



即随着业务要求的变化,NLU 系统一开始的算法流程,只需要把一个 Query 分为两个类,但是到后面,极有可能会变成需要分为三个类别。


热更新


根据业务需求,或者为了紧急处理一些特殊问题,NLU 线上系统经常需要做出快速响应,热更新算法模型。如最近的热点词“skr”,几乎是一夜之间,突然火爆起来。如下图所示的微博,如果不能正确理解“skr”的正确语义,可能就不能准确理解这条微博想要表达的意思。



为了避免影响用户体验,我们可能会对 NLU 系统,马上进行热更新,把新模型紧急进行上线。


数据驱动的自动迭代闭环



对于线上系统而言,构建如上图所示的自动迭代闭环,能更好地利用业务数据来提升服务质量。

NLU 线上系统的核心设计

算法流程的抽象


为了适应线上系统串联、多变的算法流程,我们把线上系统的算法进行抽象,如下图所示:



即每一个算法,都依赖于若干个槽位(Slot)和资源(Resource),一旦槽位和资源就位,就会触发对应的算法执行。算法的执行先通过算法适配器,来适配槽位和资源中的数据,转换成算子的输入格式。然后算子执行算法本身,执行完算子后,再经过算法解析器。算法解析器主要用于解析算法执行的结果,触发对应的槽位。如根据算法的结果,触发 Top 3 的结果。


多个算法串联起来,就构建成如下结果:



热更新流程的设计



如上图所示,我们把算法的热更新流程设计如上。初试状态为左上角,即多个 Query 使用同一份模型数据。当遇到模型更新的请求后,系统将会 block 住新的 query(右上角状态)。然后更新模型完后,新的 query 使用新的模型,旧 query 依然使用旧模型(右下角状态)。最后,当使用旧模型的 query 结束后,把旧的模型从内存中删除(左下角),然后系统恢复到初始状态。

声学模型训练系统

因为 TensorFlow 等通用深度学习训练平台,缺乏了特征提取等业务相关的领域功能,而 Kaldi 的声学模型训练过程又太慢。所以美团开发了一个声学模型训练系统——Mimir,其具备如下特性:


  • 使用比 TensorFlow 更粗颗粒度的建模单元,使得任务调度、优化更简单方便易行。

  • 使用数据并行的并行方案,单机多卡可达到近线性加速。(采取同步更新策略下,4 卡加速比达到 3.8)

  • 移植了 Kaldi 的一些特有的训练算法。

  • 速度上为 Kaldi 的 6~7 倍。(800 个小时的训练数据,单机单卡的条件下,Kaldi 需要 6~7 天, Mimir 只需 20 个小时)

  • 业务上,移植了 Kaldi 的特征提取等领域的相关模块。

参考资料

作者简介

  • 剑鹏,美团点评算法专家。2017 年加入美团,目前作为语音识别团队的声学模型负责人,负责声学模型相关的算法和系统设计与开发。


2020-02-27 10:50937

评论

发布
暂无评论
发现更多内容

一夜之间火爆GitHub的好文!!阿里资深架构师整理分享

Java 程序员 后端

一文读懂 spring MVC 请求处理流程,Java开发新手入门教程

Java 程序员 后端

【线程】,Java自学宝典pdf

Java 程序员 后端

【网络信息安全】身份认证,hadoop环境搭建教程

Java 程序员 后端

【数据库实验】,java语言零基础自学

Java 程序员 后端

【源码分析设计模式 7】Integer中的享元模式

Java 程序员 后端

【线程】(1),java高级特性编程及实战pdf百度云

Java 程序员 后端

【被面试官吊打】从系统角度考虑性能优化,kafkajvm调优

Java 程序员 后端

一文带你了解Java并发中的锁优化,让你的代码运行效率翻倍

Java 程序员 后端

一文带你深扒ClassLoader内核,揭开它的神秘面纱

Java 程序员 后端

一文彻底弄懂如何选择抽象类还是接口,linux基础入门知识

Java 程序员 后端

【Spring框架03】DI依赖注入,spring菜鸟教程pdf

Java 程序员 后端

【嵌入式实验】,面试官必问的技术问题之一

Java 程序员 后端

一次完整的JVM NativeMemoryTracking 堆外内存泄露分析

Java 程序员 后端

【数据结构与算法 10】算法的时间复杂度和空间复杂度

Java 程序员 后端

一份秀出新天际的SpringCloudAlibaba笔记,把微服务玩的出神入化

Java 程序员 后端

一场哔哩哔哩Java开发面试之旅,分享面试经历及复习资料

Java 程序员 后端

【SpringMVC笔记】Ajax 入门,springboot源码解读与原理分析

Java 程序员 后端

【备战秋招冲击大厂】Java面试题系列(1),springboot入门程序

Java 程序员 后端

【大厂面经】我通过了某独角兽公司的魔鬼五面

Java 程序员 后端

【并发编程】深入了解volatile,linux高级编程pdf

Java 程序员 后端

【计算机网络 1】计算机网络概述,Java高级工程师进阶学习—Java热修复原理

Java 程序员 后端

一年Java开发经验,阿里巴巴五面(已offer,java原理视频

Java 程序员 后端

【关于封装的那些事】 缺失封装,2021年腾讯Java高级面试题及答案

Java 程序员 后端

【备战秋招冲击大厂】Java面试题系列,你还没弄明白存储键值对

Java 程序员 后端

一口气面试6家大厂,已拿5家offer,大厂没有你想象中的难

Java 程序员 后端

一文掌握大数据架构师需要具备的能力和格局,别再说你不会JVM性能监控和调优了

Java 程序员 后端

【初学入门Demo注解版】SpringBoot ,java面试大全下载

Java 程序员 后端

【白话设计模式】去哪儿网一面,java面试题刷题软件

Java 程序员 后端

一招搞定 Spring Boot 可视化监控!,java进阶教程云盘

Java 程序员 后端

一文看透Java高并发:Synchronized锁的性质、原理及其缺陷

Java 程序员 后端

美团深度学习系统的工程实践_文化 & 方法_美团技术团队_InfoQ精选文章