以便了解如何选择最适合特定数据科学用例的框架。
Spark是由Matei Zaharia于2009年在加州大学伯克利分校的AMPLab启动的。这个项目的主要目的是加快分布式大数据任务的执行,在那个时候,这些任务是由Hadoop MapReduce处理的。MapReduce在设计时考虑到了可扩展性和可靠性,但性能和易用性一直不是它的强项。MapReduce需要不断将中间结果存储到磁盘,这是Spark要克服的关键障碍。Spark通过引入弹性分布式数据集(RDD)范式,并利用内存缓存和惰性计算的优势,能够比MapReduce减少几个数量级的延迟。这使Spark确立了其作为大规模、容错、并行化数据处理的事实标准的主导地位。该项目通过添加GraphX(用于分布式图形处理)、MLlib(用于机器学习)、SparkSQL(用于结构化和半结构化数据)等功能得到进一步加强。 值得注意的是,Spark是用Scala编写的,后来又增加了对Python/ target=_blank class=infotextkey>Python和R的支持,因此与它互动一般不会有Pythonic的感觉。理解RDD范式和Spark中的工作方式需要一点时间来适应,但这对任何熟悉Hadoop生态系统的人来说通常不是问题。
Dask是一个用于并行计算的开源库,它在2015年发布,所以与Spark相比,它相对较新。该框架最初是由Continuum Analytics(现在的Anaconda Inc.)开发的,他们是许多其他开源Python包的创造者,包括流行的Anaconda Python发行。Dask的最初目的只是为了将NumPy并行化,这样它就可以利用具有多个CPU和核心的工作站计算机。与Spark不同,Dask开发中采用的最初设计原则之一是 "无发明"。这一决定背后的想法是,使用Dask的工作应该让使用Python进行数据分析的开发者感到熟悉,而且升级时间应该最小。根据其创造者的说法,Dask的设计原则经过多年的发展,现在正被开发成一个用于并行计算的通用库。
最初围绕并行NumPy的想法得到进一步发展,包括一个完整而轻量级的任务调度器,可以跟踪依赖关系,并支持大型多维数组和矩阵的并行化。后来又增加了对Pandas DataFrames和scikit-learn并行化的支持。这使该框架能够缓解Scikit中的一些主要痛点,如计算量大的网格搜索和太大无法完全容纳在内存中的工作流程。最初的单机并行化目标后来被分布式调度器的引入所超越,这使Dask能够在多机多TB的问题空间中舒适地运行。
Ray是加州大学伯克利分校的另一个项目,其使命是 "简化分布式计算"。Ray由两个主要部分组成--Ray Core,它是一个分布式计算框架,而Ray Ecosystem,广义上讲是一些与Ray打包的特定任务库(例如Ray Tune--一个超参数优化框架,RaySGD用于分布式深度学习,RayRLib用于强化学习,等等)。
Ray与Dask类似,它让用户能够以并行的方式在多台机器上运行Python代码。然而,与Dask不同的是,Ray并不模仿NumPy和Pandas的API--它的主要设计目标不是为数据科学工作做一个落地的替代品,而是为Python代码的并行化提供一个通用的低层次框架。Ray更像是一个通用的集群和并行化框架,可以用来构建和运行任何类型的分布式应用。由于Ray Core的架构方式,它经常被认为是一个构建框架的框架。也有越来越多的项目与Ray集成,以利用加速的GPU和并行计算。 spaCy、Hugging Face和XGBoost都是引入Ray互操作性的第三方库的例子。
这里没有简单明了的方法来选择 "最佳 "框架,就像每个复杂的问题一样,答案在很大程度上取决于我们具体工作流程中的背景和许多其他因素。我们需要逐个看看这三个框架,分析它们的优劣势,同时考虑到各种常见的使用情况进行选择。
优点:
成熟稳定:Spark 的原始版本发布于2014年5月,是比较成熟的技术。 商业支持:大量的公司提供商业支持/服务。 处理大数据集:适用于针对大型数据集进行数据工程/ ETL 类型的任务。 提供高级 SQL 抽象层(Spark SQL)。 弊端:
需要学习新的执行模型和API,学习曲线陡峭。 调试困难。 复杂的架构,仅靠IT部门很难维护,因为适当的维护需要了解计算范式和Spark的内部运作(如内存分配)。 缺少丰富的数据可视化生态系统。 没有内置的GPU加速,需要RAPIDS加速器来访问GPU资源。
优点:
纯Python框架,非常容易上手。 直接支持Pandas DataFrames和NumPy数组。 通过Datashader轻松实现对数十亿行的探索性数据分析。 提供Dask Bags--它是PySpark RDD的Python版本,具有map、filter、groupby等功能。 Dask能够带来令人印象深刻的性能改进。 2020年6月,Nvidia使用RAPIDS、Dask和UCX在16个DGX A100系统(128个A100 GPU)上进行TPCx-BB测试,取得了惊人的结果。但是,需要谨慎对待,因为2021年1月,TPC强制Nvidia将该结果下架,因为它们违反了TPC的公平使用政策。 弊端:
缺乏商业支持(但有几家公司已开始在此领域的工作,例如Coiled和QuanSight)。 没有内置的GPU支持,依赖于RAPIDS进行GPU加速。
优点:
最小的集群配置 最适合于计算密集型工作负载。已经有证据表明,Ray在某些机器学习任务上的表现优于Spark和Dask,如NLP、文本规范化和其他。此外,Ray的工作速度比Python标准多处理快10%左右,即使是在单节点上也是如此。 因为Ray正被越来越多地用于扩展不同的ML库,所以你可以以可扩展的、并行的方式一起使用所有的ML库。另一方面,Spark将你限制在它的生态系统中可用的框架数量明显减少。 独特的基于actor的抽象,多个任务可以在同一个集群上异步工作,从而实现更好的利用率(相比之下,Spark的计算模型不太灵活,基于并行任务的同步执行)。 弊端:
相对较新(2017年5月首次发布)。 不太适合分布式数据处理。Ray没有用于分区数据的内置原语。该项目刚刚引入了Ray Datasets,但这是一个全新的补充,仍然非常新且基础。 对GPU的支持仅限于调度和预留。由远程函数来实际利用GPU(通常通过外部库,如TensorFlow和PyTorch)。 从这三个框架的优缺点出发,我们可以提炼出以下选择标准:
如果工作负载是以数据为中心的,主要是ETL/预处理方面的工作,那么我们最好选择Spark。特别是如果该组织拥有Spark API的机构知识。 Dask/Ray的选择并不那么明确,但一般的规则是,Ray旨在加速任何类型的Python代码,而Dask是面向数据科学特定的工作流程。 为了让事情变得更加复杂,还有Dask-on-Ray项目,它允许你在不使用Dask分布式调度器的情况下运行Dask工作流。 为了更好地理解Dask-on-Ray试图填补的空白,我们需要看一下Dask框架的核心组件。这些是集合抽象(DataFrames,数组等),任务图(DAG,表示类似于Apache Spark DAG的操作集合),以及调度器(负责执行Dask图)。分布式调度器是Dask中可用的调度器之一,它负责协调分布在多台机器上的若干工作进程的行动。这个调度器很好,因为它设置简单,保持最小的延迟,允许点对点的数据共享,并支持比简单的map-reduce链复杂得多的工作流。另一方面,分布式调度程序并非没有缺点,它的缺点包括:
它是一个单点故障--分布式调度器没有高可用性机制,因此如果它发生故障,整个集群需要重置,所有正在进行的任务都会丢失。 它是用Python编写的,这使得它易于安装和调试,但也会引入通常与Python搭配使用的标准性能考虑因素。 Client API是为数据科学家设计的,并不适合从高可用性的生产基础设施中调用(例如,它假定客户是长期存在的,可能从Jupyter会话中与集群一起工作)。 它对有状态执行提供的支持很少,所以很难实现容错的流水线。 它可能会成为瓶颈,并且不能本地扩展。 相比之下,容错和性能是深深嵌入Ray调度器设计中的原则。它是完全分散的(没有瓶颈),提供更快的数据共享(通过Apache Plasma),各个调度器是无状态的(容错),支持有状态的Actor等。这使得在Ray集群上运行Dask任务的吸引力非常明显,也是Dask-on-Ray调度器存在的理由。
现在我们已经看过了Spark、Dask和Ray的优缺点--并简要讨论了Dask-on-Ray混合解决方案,很明显这不是“一刀切”的情况。这三个框架从一开始就有不同的设计目标,试图把根本不同的工作流程硬塞到其中一个框架中不是最明智的选择。更好的方法是以灵活性为基础设计数据科学流程和相应的基础架构,最好能够让您启动并使用适合工作的正确工具。一个典型的流程可能涉及在Spark中进行一些类似ETL的数据处理,然后在Ray中执行机器学习工作流。提供自由度以控制、容错和按需方式运行两个框架,使数据科学团队能够利用两个框架的优势。
从Spark(DataFrames)到Ray(分布式训练)再返回到Spark(Transformer)的流程的高级概述。Ray Estimator在Spark Estimator接口中封装了这种复杂性。
混合使用框架的重要性已经显而易见,因为出现了使这种跨框架通信更加简化的集成库。例如,Spark on Ray正是这样做的--它 "结合了你的Spark和Ray集群,使你可以轻松地使用PySpark API进行大规模数据处理,并无缝地使用这些数据来使用TensorFlow和PyTorch训练你的模型。"还有Ray on Spark项目,它允许我们在Apache Hadoop/YARN上运行Ray程序。这种方法也已经成功地在实际生产工作负载中得到了测试。例如,Uber的机器学习平台Michelangelo定义了一个Ray Estimator API,该API抽象了终端用户在Spark和Ray之间移动的过程。Uber工程公司最近的出版物中详细介绍了这一点,该出版物涵盖了涉及Spark和XGBoost在Ray上的分布式训练的架构。
在这文中,我们介绍了三种最流行的并行计算框架。我们讨论了它们的优缺,并给出了一些关于如何为手头的任务选择正确框架的一般性指导。推荐的方法不是寻找适合所有可能的需求或用例的终极框架,而是理解它们如何适合各种工作流程,并拥有一个灵活的数据科学基础架构,使该基础设施允许采用混合和匹配方法。