本文从分布式系统的角度对目前的一些机器学习平台进行了研究,总结了这些平台使用的架构设计,分析了通信和控制瓶颈、容错性和开发难度进行了分析比较,并对未来分布式机器学习平台的研究工作提出了一些建议。本文中的工作由MuratDemirbas教授与他的研究生KuoZhang和SalemAlqahtani共同完成。机器学习,尤其是深度学习,在语音识别、图像识别和自然语言处理方面取得了革命性的成功,最近在推荐和搜索引擎等领域取得了革命性的成功。这些技术在无人驾驶、数字医疗系统、CRM、广告、物联网等领域具有良好的应用前景。当然,正是资助和推动技术的加速进步让我们看到一些机器学习平台在不久的将来推出。考虑到训练涉及的数据集和模型规模庞大,机器学习平台通常是分布式平台,部署数十个甚至上百个并行运行的计算节点来训练模型。估计在不久的将来,数据中心的大部分任务都是机器学习任务。我来自分布式系统研究领域,所以我们考虑从分布式系统的角度对这些机器学习平台进行研究,分析这些平台的通信和控制瓶颈。我们还考虑了这些平台的容错性和易编程性。我们从设计方法上将机器学习平台分为三个基本类别,即:基本数据流、参数服务器模型和高级数据流。下面我们将简要介绍每一类方法,以ApacheSpark为例介绍基本数据流,以PMLS(Petuum)为例介绍参数服务器模型,以高级数据流为例介绍TensorFlow和MXNet。我们对比了以上平台的性能,给出了一系列的评测结果。有关详细的评估结果,请参阅我们的论文。不幸的是,作为一个小型研究团队,我们无法进行大规模评估。在这篇博文的最后,我给出了一些结论,并为未来在分布式机器学习平台上的研究工作提出了一些建议。已经对这些分布式机器学习平台有一定了解的读者可以直接跳到本文末尾。在Spark中,计算被建模为有向无环图(DAG),其中图中的每个顶点代表一个RDD,每条边代表对RDD的操作。RDD是由一系列分区对象(Partition)组成的。这些分区对象存储在内存中并完成计算,在Shuffle过程中也会溢出(Overflow)到磁盘。在DAG中,从顶点A到B的有向边E的一条直线表示RDDB是对RDDA执行操作E的结果。操作分为两类:Transformation和Action。转换操作(例如map、filter和join)应用于RDD,转换操作的输出是一个新的RDD。Spark用户将计算建模为DAG,代表在RDD上执行的转换和操作。然后DAG被编译成多个阶段。每个Stage作为一系列并行运行的任务(Tasks)执行,每个分区(Partition)对应一个任务。这里,Narrowdependencies将有利于计算的高效执行,而Widedependencies将引入瓶颈,因为这种依赖会引入通信密集型Shuffle操作,从而中断操作流程。Spark的分布式执行是通过将DAGStage划分到不同的计算节点来实现的。上图清楚地展示了这种“主(master)-工人(worker)”的架构。驱动程序(Driver)包含两个调度器(Scheduler)组件,分别是DAG调度器和任务调度器。调度程序将任务分配给工作人员并协调工作人员。Spark专为一般数据处理而设计,并非专门用于机器学习任务。要在Spark上运行机器学习任务,您可以使用MLlibforSpark。通过Spark的基本设置,模型参数存储在驱动程序节点上,并且在每次迭代后通过工作程序与驱动程序通信更新参数。如果大规模部署机器学习任务,驱动程序可能无法存储所有模型参数。在这种情况下,就需要使用RDD来容纳所有的参数。这将引入大量开销,因为需要在每次迭代中创建新的RDD以容纳更新的模型参数。更新模型涉及机器和磁盘之间的数据混洗,这限制了Spark的可扩展性。这就是基本数据流模型(即DAG)的不足之处。Spark不支持机器学习中的迭代操作。PMLSPMLS专为机器学习任务而设计。它引入了一个称为参数服务器(PS)的抽象来支持迭代密集型训练过程。PS(图中绿框所示)作为分布式key-value数据表存在于内存中,可复制,可分片。每个节点(node)是模型中一个分片的主节点(参数空间),作为其他分片的从节点或副本节点。这样PS在节点数量上的扩展性就很好。PS节点存储和更新模型参数并响应工作人员的请求。工作人员从他们的本地PS副本请求最新的模型参数,并对分配给他们的数据集分区执行计算。PMLS也采用了SSP(StaleSynchronousParallelism)模型。与BSP(BulkSynchronousParellism)模型相比,SSP放宽了每次迭代结束时每台机器都需要同步的要求。为了实现同步,SSP允许worker之间存在一定程度的异步,并确保最快的worker不会领先最慢的worker超过s次迭代。这种非严格一致性模型仍然适用于机器学习,因为处理在允许的误差范围内。我曾经发表过一篇专门讨论这种机制的博文。TensorFlowGoogle提出了一个基于名为“DistBelief”的分布式机器学习平台的参数服务器模型(这里是我对DistBelief论文的评论)。据我所知,对DistBelief的主要不满是它需要在编写机器学习应用程序时混合一些低级代码。谷歌希望让任何不精通分布式执行的员工都可以编写机器学习代码。出于同样的原因,Google编写了用于大数据处理的MapReduce框架。TensorFlow正是为此而设计的平台。它采用了更先进的数据流处理范式,其中表示计算的图不再需要是DAG,图可以包含循环,并支持可变状态。我认为TensorFlow的设计在某种程度上受到了Naiad的设计理念的影响。TensorFlow将计算表示为节点和边的有向图。节点表示计算操作或可变状态(如Variable),边表示节点之间通信的多维数组。这种多维数据被称为“张量”。TensorFlow需要用户静态声明逻辑计算图,通过将图重写和划分到机器上来实现分布式计算。需要注意的是,MXNet,尤其是DyNet,使用了动态定义的图。这简化了编程并增加了编程灵活性。如上图所示,在TensorFlow中,分布式机器学习训练采用了参数服务器的方式。在TensorFlow中使用PS抽象时,使用参数-服务器和数据并行性。TensorFlow声称能够完成更复杂的任务,但这需要用户编写通往那些未探索领域的代码。MXNetMXNet是由2015年出现的CXXNet、Minverva、Purines等深度学习项目衍生而来的协作开源项目。与TensorFlow类似,MXNet也是一个数据流系统,支持状态可变的循环计算图,支持训练计算使用参数服务器模型。同样,MXNet也对多CPU/GPU上的数据并行性提供了良好的支持,并实现了模型并行性。MXNet支持同步和异步训练计算。下图显示了MXNet的主要组件。其中,运行时依赖引擎分析计算过程中的依赖关系,对不存在相互依赖关系的计算进行并行处理。MXNet在依赖于运行时的引擎之上提供了一个中间层,用于优化计算图和内存。MXNet使用检查点机制来支持基本的容错,并提供对模型的保存和加载操作。save操作将模型参数写入checkpoint文件,load操作从checkpoint文件中读取模型参数。MXNet使用描述性编程语言将计算表达为有向图,也支持一些命令式编程来定义张量的计算和控制流程。MXNet提供用多种语言(如C++、Python、R和Scala等)编写的客户端API。和TensorFlow一样,MXNet的后台核心引擎库也是用C++编写的。一些评估结果在我们的实验中,使用了AmazonEC2m4.xlarge实例。每个实例都有4个vCPU,由IntelXeonE5-2676v3、16GB内存和750Mbps的EBS带宽提供支持。我们对两种常见的机器学习任务进行了实验,即二元逻辑回归和使用多层神经网络的图像分类。本文只给出了部分结果图,更多实验结果可以查看我们的论文。应该指出的是,我们的实验有一些局限性。首先,我们使用的机器数量少,无法测试可扩展性。其次,我们只使用了CPU计算,没有测试GPU的使用情况。该图显示了每个平台的逻辑回归计算速度。PMLS和MXNet是最快的两个系统,TensorFlow最慢,Spark介于两者之间。对此,我们分析是多方面原因造成的。首先,相对于Spark和TensorFlow,PMLS是一个用高性能C++编程语言实现的轻量级系统,而Spark是用运行在JVM上的Scala语言编写的。其次,PMLS包含的抽象较少,而TensorFlow包含的抽象过多。抽象增加了系统的复杂性并导致运行时开销。该图显示了DNN在各种平台上的速度。与单层神经网络相比,当发展到两层神经网络时,由于需要更多的迭代计算,Spark的性能有所下降。我们将模型参数存储在Spark的驱动程序中,因为驱动程序可以保存它们。但是如果我们用RDD来保持参数,每次迭代后更新,结果可能会更差。该图显示了平台的CPU使用率。Spark应用程序的CPU使用率似乎很高,这主要是由于序列化开销。之前的一些工作也指出了同样的问题。结论和未来研究方向机器学习和深度学习应用都具有高度可并行性,但从并发算法的角度来看,并不是那么容易做到。可以说,参数服务器方法最适合分布式机器学习平台的训练任务。考虑到瓶颈,网络仍然是分布式机器学习应用的瓶颈。比更先进的通用数据流平台更重要的是提出更好的数据和模型的组织和参与机制。数据和模型应该被视为一等公民。此外,还有其他因素对平台产生微妙的影响。对于Spark,CPU开销成为比网络限制更严重的瓶颈。Spark使用的编程语言是Scala等JVM语言,它对Spark的性能影响很大。因此,分布式机器学习平台需要更好的监控工具和性能预测。最近出现了Ernest、CherryPick等工具,解决了Spark数据处理应用中的一些问题。对于支持机器学习的运行时分布式系统,还存在一些未解决的问题,例如资源调度和运行时性能提升。考虑到应用程序运行时监控和性能分析,下一代分布式机器学习平台应该为平台上运行的任务提供计算、内存和网络资源的运行时弹性配置和调度。在编程和软件工程支持方面也存在未解决的问题。什么是适合机器学习应用程序的分布式编程抽象?这些问题需要对分布式机器学习应用程序进行进一步研究、检查和验证,例如使用特定问题输入测试DNN。
