近年来,深度学习发展非常迅速。在雅虎,我们发现为了从海量数据中获得洞察力,我们需要部署分布式深度学习。现有的深度学习框架通常需要单独的集群来进行深度学习,这迫使我们为一个机器学习管道创建多个程序(见下图1)。建立独立的集群需要我们传输大型数据集,引入不必要的系统复杂性和端到端的学习延迟。去年,我们通过开发和发布CaffeOnSpark解决了横向扩展问题,CaffeOnSpark是我们的开源框架,支持在同一Spark和Hadoop集群上进行分布式深度学习和大数据处理。我们在Yahoo内部使用CaffeOnSpark来改进我们的NSFW图像检测,自动从现场镜头中识别电子竞技比赛剪辑,等等。凭借来自社区的大量宝贵反馈和贡献,CaffeOnSpark已更新为支持LSTM、新数据层、交错训练和测试、PythonAPI和Docker容器部署。这些都改善了我们的用户体验。但是那些使用TensorFlow框架的人呢?于是我们按照之前的做法,开发了TensorFlowOnSpark。TensorFlow公开后,谷歌于2016年4月开放了带有分布式学习的增强版TensorFlow。2016年10月,TensorFlow开始支持HDFS。然而,在谷歌云之外,用户仍然需要一个专门用于TensorFlow应用程序的集群。TensorFlow程序无法部署在现有的大数据集群上,因此想要大规模使用这项技术的人需要花费更多的成本和时间。为了克服这个限制,一些社区项目将TensorFlow连接到Spark集群。SparkNet使Spark执行器能够运行TensorFlow网络。DataBricks提出了用于使用TensorFlow程序操纵ApacheSpark的数据帧的张量框架。虽然这些方法是朝着正确方向迈出的一步,但我们检查了他们的代码,发现我们不能让多个TensorFlow进程直接相互通信,我们不能实现异步分布式学习,我们需要迁移现有的花费很多在tensorflow程序上的努力。TensorFlowOnSpark我们的新框架TensorFlowOnSpark(TFoS)支持在Spark和Hadoop上分布式执行TensorFlow。如上图(图2)所示,TFoS与SparkSQL、MLlib和其他Spark库一起运行在一个项目或管道中。TFoS支持所有类型的TensorFlow程序,支持同步和异步训练和推理。并支持模型和数据的并行处理,以及Spark集群上的TensorFlow工具(如TensorBoard)。任何TensorFlow程序都可以轻松修改以在TFoS上运行。通常,需要修改的Python代码少于10行。许多在雅虎平台上使用TensorFlow的开发者已经很容易地将TensorFlow项目转移到TFoS上执行。TFoS支持在TensorFlow处理过程中(计算节点和参数服务节点)张量(tensor)信息的直接通信。进程到进程的直接通信机制使TFoS项目可以轻松地扩展到其他机器上。如图3所示,TFoS不需要Spark驱动程序参与张量通信,因此它具有与独立TensorFlow集群相同的可扩展性。TFoS提供了两种不同的模式来“吞噬”数据进行训练和推理:1.TensorFlowQueueRunners:TFoS使用TensorFlow的文件读取器和QueueRunners直接从HDFS文件中读取数据。Spark不需要参与数据获取过程。2.Sparkfeed:SparkRDD数据会被传送给各个Spark执行器,Spark执行器会进一步将数据传递给TensorFlowgraph(通过feed_dict参数)。图4显示了如何通过简单的QueueRunners设置在TFoS中扩展Inception图像分类网络中的并发分布式训练:每个计算节点设置为1个GPU,一个读取器,批次数为32。运行四个TFoS任务同时进行100k步的训练。两天多后,当这些任务完成时,top-5准确率分别为0.730、0.814、0.854和0.879。0.730的精度需要单计算节点运行46小时,双计算节点需要22.5小时。4个计算节点13小时,8个计算节点7.5小时。在Inception模型训练上,TFoS几乎可以做到线性扩展。这是令人鼓舞的,尽管TFoS的缩放比例因不同的模型和超参数而异。RDMAforDistributedTensorFlow在雅虎的Hadoop集群上,GPU节点通过以太网和无线宽带相互连接。无线宽带提供高速连接并支持直接访问RDMA中其他服务器的存储。然而,目前TensorFlow仅支持在以太网上使用“gRPC”进行分布式学习。为了加速分布式学习,我们增强了TensorFlowC++层以在无线宽带上实施RDMA。为了配合我们发布的TFoS,除了默认的“gRPC”协议之外,我们还引入了一个新的TensorFlow服务器协议。任何分布式tensorflow程序都可以通过在tf.train.ServerDef()或tf.train.Server()中指定protocol="grpc_rdma"来使用我们的增强版TensorFlow。使用这个新协议,需要一个RDMA会合管理器来确保张量直接写入远程服务器的内存。我们尽量减少张量缓冲区的创建:张量缓冲区在开始时分配一次,然后在TensorFlowworker的所有训练步骤中重复使用。从我们对大型模型(例如VGG-19)的早期实验开始,我们已经证明,与现有的gRPC相比,我们的RDMA实现显着加快了训练时间。由于RDMA支持的高性能要求(请参阅TensorFlow问题#2916),我们决定将我们当前的实现作为预览提供给TensorFlow社区。在接下来的几周内,我们将进一步优化我们的RDMA实施并分享一些基准测试结果细节。简单的CLI和APITFoS程序通过标准的ApacheSpark命令spark-submit运行。如下图,用户可以在CLI中指定Spark执行器的数量,每个执行器使用的GPU数量,以及参数服务节点的数量。用户还可以表明他们更喜欢使用TensorBoard(–tensorboard)还是RDMA(–rdma)。spark-submit–master${MASTER}\${TFoS_HOME}/examples/slim/train_image_classifier.py\–model_nameinception_v3\–train_dirhdfs://default/slim_train\–dataset_dirhdfs://default/data/imagenet\–dataset_nameimagenet\–dataset_split_nametrain\–cluster_size${NUM_EXEC}\–num_gpus${NUM_GPU}\–num_ps_tasks${NUM_PS}\–sync_replicas\–replicas_to_aggregate${NUM_WORKERS}\–tensorboard\–rdmaTFoS提供了高级PythonAPI(在Python笔记本中示例显示在):TFCluster.reserve()...从Spark执行器TFCluster.start()...构建TensorFlow集群TFCluster.start()...在执行器TFCluster.train()或TFCluster.inference()上加载TensorFlow程序...RDD数据是传入TensorFlow处理TFCluster.shutdown()...结束TensorFlow在executor中的运行。示例程序(包括MNIST、Cifar10、Inception和VGG)来说明TensorFlow程序到TensorFlowOnspar的转换过程,并利用RDMA。地址:https://github.com/yahoo/TensorFlowOnSpark/tree/master/examples提供了在AWSEC2上应用TensorFlowOnSpark的亚马逊机器镜像。然后像CaffeOnSpark一样,我们再推进TensorFlowOnSpark。地址:https://github.com/yahoo/TensorFlowOnSpark/wiki/GetStarted_EC2【本文为专栏机器心原创文章,微信公众号“机器心(id:almosthuman2014)”】点此查看作者更多好文章
