(转载:http://www.36dsj.com/archives/85383)机器学习与人工智能,相信你们已经耳熟能详,随着大规模标记数据的积累、神经网络算法的成熟以及高性能通用GPU的推广,深度学习逐渐成为计算机专家以及大数据科学家的研究重点。近年来,不管是图像的分类、识别和检测,仍是语音生成、天然语言处理,甚至是AI下围棋或者打游戏都基于深度学习有了很大的突破。而随着TensorFlow、Caffe等开源框架的发展,深度学习的门槛变得愈来愈低,甚至初中生均可以轻易实现一个图像分类或者自动驾驶的神经网络模型,但目前最前沿的成果主要仍是出自Google、微软等巨头企业。算法
Google不只拥有优秀的人才储备和大数据资源,其得天独厚的基础架构也极大推进了AI业务的发展,得益于内部的大规模集群调度系统Borg,开发者能够快速申请大量GPU资源进行模型训练和上线模型服务,而且经过资源共享和自动调度保证总体资源利用率也很高。Google开源了TensorFlow深度学习框架,让开发者能够在本地轻易地组合MLP、CNN和RNN等模块实现复杂的神经网络模型,但TensorFlow只是一个数值计算库,并不能解决资源隔离、任务调度等问题,将深度学习框架集成到基于云计算的基础架构上将是下一个关键任务。数据库
除了Google、微软,国内的百度也开源了PaddlePaddle分布式计算框架,而且官方集成了Kubernetes等容器调度系统,用户能够基于PaddlePaddle框架实现神经网络模型,同时利用容器的隔离性和Kubernetes的资源共享、自动调度、故障恢复等特性,但平台不能支持更多深度学习框架接口。而亚马逊和腾讯云相继推出了面向开发者的公有云服务,能够同时支持多种主流的开源深度学习框架,阿里、金山和小米也即将推出基于GPU的云深度学习服务,还有无数企业在默默地研发内部的机器学习平台和大数据服务。编程
面对如此眼花缭乱的云服务和开源技术,架构师该如何考虑其中的技术细节,从用户的角度又该如何选择这些平台或者服务呢。我将介绍小米云深度学习平台的架构设计与实现细节,但愿能给AI领域的研发人员提供一些思考和启示。后端
云深度学习平台设计api
云深度学习平台(Cloud Machine Learning),就是基于云计算的机器学习和深度学习平台。首先TensorFlow、MXNet是深度学习框架或者深度学习平台,但并非云深度学习平台,它们虽然能够组成一个分布式计算集群进行模型训练,但须要用户在计算服务器上手动启动和管理进程,并没有云计算中任务隔离、资源共享、自动调度、故障恢复以及按需计费等功能。所以咱们须要区分深度学习类库以及深度学习平台之间的关系,而这些类库实现的随机梯度降低和反向传播等算法倒是深度学习应用所必须的,这是一种全新的编程范式,须要咱们已有的基础架构去支持。数组
云计算和大数据发展超过了整整十年,在业界催生很是多优秀的开源工具,如实现了相似AWS IaaS功能的OpenStack项目,还有Hadoop、Spark、Hive等大数据存储和处理框架,以及近年很火的Docker、Kubernetes等容器项目,这些都是构建现代云计算服务的基石。安全
这些云服务有共同的特色,例如咱们使用HDFS进行数据存储,用户不须要手动申请物理资源就能够作到开箱即用,用户数据保存在几乎无限制的公共资源池中,而且经过租户隔离保证数据安全,集群在节点故障或者水平扩容时自动触发Failover且不会影响用户业务。虽然Spark经过MLib接口提供部分机器学习算法功能,但毫不能替代TensorFlow、Caffe等深度学习框架的做用,所以咱们仍须要实现Cloud Machine Learning服务,而且确保实现云服务的基本特性服务器
总结为下面几条:网络
相比于MapReduce或者Spark任务,深度学习的模型训练时间周期长,并且须要调优的超参数更多,平台设计还须要考虑如下几点:架构
这是我我的对云深度学习平台的需求理解,也是小米在实现cloud-ml服务时的基本设计原则。虽然涉及到高可用、分布式等颇具实现难度的问题,但借助目前比较成熟的云计算框架和开源技术,咱们的架构和实现基本知足了前面全部的需求
云深度学习平台架构
遵循前面的平台设计原则,咱们的系统架构也越发清晰明了,为了知足小米内部的全部深度学习和机器学习需求:
计算机领域有句名言“任何计算机问题均可以经过增长一个中间层来解决”。不管是AWS、OpenStack、Hadoop、Spark仍是TCP/IP都是这样作的,经过增长一个抽象层来屏蔽底层资源,对上层提供更易用或者更可靠的访问接口。小米的cloud-ml平台也须要实现对底层物理资源的屏蔽,尤为是对GPU资源的抽象和调度,但咱们不须要从新实现,由于社区已经有了不少成熟的分布式解决方案,如OpenStack、Yarn和Kubernetes。目前OpenStack和Yarn对GPU调度支持有所欠缺,虚拟机也存在启动速度慢、性能overhead较大等问题,而容器方案中的Kubernetes和Mesos发展迅速,支持GPU调度等功能,是目前最值得推荐的架构选型之一。
进一步简化了整个云深度学习平台的使用流程,总体架构设计以下图:
云深度学习平台实现
前面提到咱们后端使用Kubernetes编排系统,经过API Server实现受权认证和Quota配额功能。因为云深度学习服务是一个计算服务,和我之前作过的分布式存储服务有着本质的区别,计算服务离线运算时间较长,客户端请求延时要求较低并且吞吐很小,所以咱们的API服务在易用性和高性能上能够选择前者,目前主流的Web服务器均可以知足需求。基于Web服务器咱们能够实现集成内部权限管理系统的业务逻辑,小米生态云提供了相似AWS的AKSK签名认证机制,用户注册登陆后能够自行建立Access key和Secret key,请求时在客户端进行AKSK的签名后发送,这样用户不须要把帐号密码或密钥加到请求中,即便密钥泄露也能够由用户来禁用,请求时即便签名被嗅探也只能重放当前的请求内容,是很是可靠的安全机制。除此以外,咱们参考OpenStack项目的体系架构,实现了多租户和Quota功能,经过认证和受权的请求须要通过Quota配额检查,在高可用数据库中持久化相应的数据,这样平台管理员就能够动态修改每一个租户的Quota,并且用户能够随时查看自身的审计信息。
咱们遵循Google CloudML标准,会自动生成Cluster spec等信息经过环境变量加入到容器的启动任务中。这样不管是单机版训练任务,仍是几个节点的分布式任务,甚至是上百节点的分布式训练任务,cloud-ml平台均可以经过相同的镜像和代码来运行,只是启动时传入的环境变量不一样,在不改变任何外部依赖的状况下优雅地实现了看似复杂的分布式训练功能。
除了训练任务,Cloud Machine Learning平台最好也能集成模型服务、开发环境等功能。
对于模型服务,TensorFlow社区开源了TensorFlow Serving项目,能够加载任意TensorFlow模型而且提供统一的访问接口,
而Caffe社区也提供了Web demo项目方便用户使用。
目前Kubernetes和Mesos都实现了相似Deployment的功能,经过制做TensorFlow Serving等服务的容器镜像,咱们能够很方便地为用户快速启动对应的模型服务。
经过对Kubernetes API的封装,咱们在暴露给用户API时也提供了replicas等参数,这样用户就能够直接经过Kubernetes API来建立多副本的Deployment实例,而且由Kubernetes来实现负载均衡等功能。
除此以外,TensorFlow Serving自己还支持在线模型升级和同时加载多个模型版本等功能,咱们在保证TensorFlow Serving容器正常运行的状况下,容许用户更新分布式对象存储中的模型文件就能够轻易地支持在线模型升级的功能。
对于比较小众但有特定使用场景的深度学习框架,Cloud Macine Learning的开发环境、训练任务和模型服务都支持Bring Your Own Image功能,也就是说用户能够定制本身的Docker镜像并在提交任务时指定使用。这种灵活的设置极大地下降了平台管理者的维护成本,咱们不须要根据每一个用户的需求定制通用的Golden image,事实上也不可能有完美的镜像能够知足全部需求,用户不一样的模型可能有任意的Python或者非Python依赖,甚至是本身实现的私有深度学习框架也能够直接提交到Cloud Machine Learning平台上训练。内测BYOI功能时,咱们还惊喜地发现这个功能对于咱们开发新的深度学习框架支持,以及提早测试镜像升级有很是大的帮助,同时用户本身实现的Caffe模型服务和XGBoost模型服务也能够完美支持。
固然Cloud Machine Learning平台还能够实现不少有意思的功能,例如经过对线上不一样GPU机型打label,经过NodeSelector功能能够容许用户选择具体的GPU型号进行更细粒度的调度,这须要咱们暴露更底层Kubernetes API实现,这在集群测试中也是很是有用的功能。而不管是基于GPU的训练任务仍是模型服务,咱们都制做了对应的CUDA容器镜像,经过Kubernetes调度到对应的GPU计算节点就能够访问本地图像处理硬件进行高性能运算了。
小米cloud-ml还开放了前置命令和后置命令功能,容许用户在启动训练任务前和训练任务结束后执行自定义命令,对于不支持分布式存储的深度学习框架,能够在前置命令中挂载S3 fuse和FDS fuse到本地目录,或者初始化HDFS的Kerberos帐号,灵活的接口能够实现更多用户自定义的功能。
还有超参数自动调优功能,与Google CloudML相似,用户能够提交时指定多组超参数配置,云平台能够自动分配资源起多实例并行计算,为了支持读取用户自定义的指标数据,咱们实现了相似TensorBoard的Python接口直接访问TensorFlow event file数据,并经过命令行返回给用户最优的超参数组合。最后还有TensorFlow Application Template功能,在Cloud Machine Learning平台上用户能够将本身的模型代码公开或者使用官方维护的开源TensorFlow应用,用户提交任务时能够直接指定这些开源模板进行训练,模板已经实现了MLP、CNN、RNN和LR等经典神经网络结构,还能够经过超参数来配置神经网络每一层的节点数和层数,并且能够支持任意稠密和稀疏的数据集,这样不须要编写代码就能够在云平台上训练本身的数据快速生成AI模型了。
在前面的平台设计和平台架构后,要实现完整的云深度学习服务并不困难,尤为是集成了Docker、Etcd、Kubernetes、TensorFlow等优秀开源项目,组件间经过API松耦合地交互,须要的重复工做主要是打通企业内部权限系统和将用户请求转化成Kubernetes等后端请求而已,而支持标准的打包方式还可让业务代码在任意云平台上无缝迁移。
云深度学习平台实践
目前小米云深度学习平台已经在内部各业务部门推广使用,相比于直接使用物理机,云服务拥有超高的资源利用率、快速的启动时间、近乎“无限”的计算资源、自动的故障迁移、支持分布式训练和超参数自动调优等优势,相信能够获得更好的推广和应用。
管理GPU资源和排查GPU调度问题也是至关繁琐的,尤为是须要管理不一样GPU设备和不一样CUDA版本的异构集群,咱们统一规范了CUDA的安装方式,保证Kubernetes调度的容器能够正常访问宿主机的GPU设备。固然对于GPU资源的调度和释放,咱们有完善的测试文档能够保证每个GPU均可以正常使用,根据测试需求实现的NodeSelector功能也帮忙咱们更快地定位问题。
因为已经支持几十个功能和十几个深度学习框架,每次升级均可能影响已有服务的功能,所以咱们会在多节点的分布式staging集群进行上线演习和测试,而且实现smoke test脚本进行完整的功能性测试。服务升级须要更新代码,可是为了保证不影响线上业务,不管是Kubernetes仍是咱们实现的API Server都有多副本提供服务,经过高可用技术先迁移服务进行滚动升级,对于一些单机运行的脚本也经过Etcd实现了高可用的抢主机制,保证全部组件没有单点故障。