并行计算框架

概念

框架与引擎

处理框架和处理引擎负责对数据系统中的数据进行计算。虽然“引擎”和“框架”之间的区别没有什么权威的定义,但大部分时候可以将前者定义为实际负责处理数据操作的组件,后者则可定义为承担类似作用的一系列组件。例如Apache Hadoop可以看作一种以MapReduce作为默认处理引擎的处理框架。引擎和框架通常可以相互替换或同时使用。例如另一个框架Apache Spark可以纳入Hadoop并取代MapReduce。

批处理框架

批处理主要操作大容量静态数据集,并在计算过程完成后返回结果。批处理模式中使用的数据集特征:

  • 有界:批处理数据集代表数据的有限集合
  • 持久:数据通常始终存储在某种类型的持久存储位置中
  • 大量:批处理操作通常是处理极为海量数据集的唯一方法

批处理非常适合需要访问全套记录才能完成的计算工作。例如在计算总数和平均数时,必须将数据集作为一个整体加以处理,而不能将其视作多条记录的集合。这些操作要求在计算进行过程中数据维持自己的状态。大量数据的处理需要付出大量时间,因此批处理不适合对处理时间要求较高的场合。

批处理框架应用:Apache Hadoop

流处理框架

流处理会对随时进入系统的数据进行计算。相比批处理模式,这是一种截然不同的处理方式。流处理方式无需针对整个数据集执行操作,而是对通过系统传输的每个数据项执行操作。

流处理中的数据集是“无边界”的,这就产生了几个重要的影响:

  • 完整数据集只能代表截至目前已经进入到系统中的数据总量。
  • 工作数据集也许更相关,在特定时间只能代表某个单一数据项。
  • 处理工作是基于事件的,除非明确停止否则没有“尽头”。处理结果立刻可用,并会随着新数据的抵达继续更新。

流处理系统可以处理几乎无限量的数据,但同一时间只能处理一条(真正的流处理)或很少量(微批处理,Micro-batch Processing)数据,不同记录间只维持最少量的状态。虽然大部分系统提供了用于维持某些状态的方法,但流处理主要针对副作用更少,更加功能性的处理(Functional processing)进行优化。

功能性操作主要侧重于状态或副作用有限的离散步骤。有近实时处理需求的任务很适合使用流处理模式。分析、服务器或应用程序错误日志,以及其他基于时间的衡量指标是最适合的类型,因为对这些领域的数据变化做出响应对于业务职能来说是极为关键的。流处理很适合用来处理必须对变动或峰值做出响应,并且关注一段时间内变化趋势的数据。

流处理框架应用:Apache Storm,Apache Samza

扫描二维码关注公众号,回复: 4070822 查看本文章

混合处理框架

一些处理框架可同时处理批处理和流处理工作负载。这些框架可以用相同或相关的组件和API处理两种类型的数据,借此让不同的处理需求得以简化。

虽然侧重于某一种处理类型的项目会更好地满足具体用例的要求,但混合框架意在提供一种数据处理的通用解决方案。这种框架不仅可以提供处理数据所需的方法,而且提供了自己的集成项、库、工具,可胜任图形分析、机器学习、交互式查询等多种任务。

混合处理框架应用:Apache Spark,Apache Flink

MapReduce

MapReduce是Google提出的一个软件架构,用于大规模数据集的并行运算。

MapReduce的处理过程分为两个步骤:map(映射)和reduce(归纳)。每个阶段的输入输出都是key-value的形式,类型可以自行指定。map阶段对切分好的数据进行并行处理,处理结果传输给reduce,由reduce函数完成最后的汇总。Reduce又可以作为一个Map为下一级Reduce作准备,以此迭代。

MapReduce进程间的通信纯粹是用文件去联系的,每个进程做的事情就是去读取上一级进程生成的数据,然后处理后写入磁盘让下一级进程进行读取。这个特性使得MapReduce有着良好的容错性,当某一级的某一个进程出错了,JobMaster会重新调度这个进程到另外一个机器上重新运行。坏处是每当Map-Reduce的某一个步骤运行完后,需要重新调度下一级任务,调度产生的开销会非常的大(网络传输,文件读写磁盘IO)。

MapReduce通过把对数据集的大规模操作分发给网络上的每个节点实现可靠性;每个节点会周期性的把完成的工作和状态的更新报告回来。如果一个节点保持沉默超过一个预设的时间间隔,主节点记录下这个节点状态为死亡,并把分配给这个节点的数据发到别的节点。每个操作使用命名文件的不可分割操作以确保不会发生并行线程间的冲突;当文件被改名的时候,系统可能会把他们复制到任务名以外的另一个名字上去。(避免副作用)。

归纳操作工作方式很类似,但是由于归纳操作在并行能力较差,主节点会尽量把归纳操作调度在一个节点上,或者离需要操作的数据尽可能近的节点上了。

Hadoop

Apache Hadoop是一款支持数据密集型分布式应用程序的开源批处理框架,包含多个组件,即多个层,通过配合使用可处理批数据:

  • HDFS:(Hadoop Distributed File System分布式文件系统层)可对集群节点间的存储和复制进行协调。HDFS确保了无法避免的节点故障发生后数据依然可用,可将其用作数据来源,可用于存储中间态的处理结果,并可存储计算的最终结果。
  • YARN:(Yet Another Resource Negotiator另一个资源管理器)可充当Hadoop堆栈的集群协调组件。该组件负责协调并管理底层资源和调度作业的运行。通过充当集群资源的接口,YARN使得用户能在Hadoop集群中使用比以往的迭代方式运行更多类型的工作负载。
  • MapReduce:Hadoop的原生批处理引擎。

基本处理过程

  • 从HDFS文件系统读取数据集
  • 将数据集拆分成小块并分配给所有可用节点
  • 针对每个节点上的数据子集进行计算(计算的中间态结果会重新写入HDFS)
  • 重新分配中间态结果并按照键进行分组
  • 通过对每个节点计算的结果进行汇总和组合对每个键的值进行“Reducing”
  • 将计算而来的最终结果重新写入 HDFS

优势和局限

由于每个任务需要多次执行读取和写入操作,因此速度相对较慢。但另一方面由于磁盘空间通常是服务器上最丰富的资源,这意味着MapReduce可以处理非常海量的数据集。同时也意味着相比其他类似技术,Hadoop的MapReduce通常可以在廉价硬件上运行,因为该技术并不需要将一切都存储在内存中。MapReduce具备极高的缩放潜力,生产环境中曾经出现过包含数万个节点的应用。与其他框架和引擎的兼容与集成能力使得Hadoop可以成为使用不同技术的多种工作负载处理平台的底层基础。

Spark

Apache Spark是一种包含流处理能力的下一代批处理框架。与Hadoop的MapReduce引擎基于各种相同原则开发而来的Spark主要侧重于通过完善的内存计算和处理优化机制加快批处理工作负载的运行速度。Spark可作为独立集群部署(需要相应存储层的配合),或可与Hadoop集成并取代MapReduce引擎。

Spark的批处理模式

与MapReduce不同,Spark的数据处理工作全部在内存中进行,只在一开始将数据读入内存,以及将最终结果持久存储时需要与存储层交互。所有中间态的处理结果均存储在内存中。

虽然内存中处理方式可大幅改善性能,Spark在处理与磁盘有关的任务时速度也有很大提升,因为通过提前对整个任务集进行分析可以实现更完善的整体式优化。为此Spark可创建代表所需执行的全部操作,需要操作的数据,以及操作和数据之间关系的Directed Acyclic Graph(有向无环图),即DAG,借此处理器可以对任务进行更智能的协调。

为了实现内存中批计算,Spark会使用一种名为Resilient Distributed Dataset(弹性分布式数据集),即RDD的模型来处理数据。这是一种代表数据集,只位于内存中,永恒不变的结构。针对RDD执行的操作可生成新的RDD。每个RDD可通过世系(Lineage)回溯至父级RDD,并最终回溯至磁盘上的数据。Spark可通过RDD在无需将每个操作的结果写回磁盘的前提下实现容错。

Spark的流处理模式

流处理能力是由Spark Streaming实现的。Spark本身在设计上主要面向批处理工作负载,为了弥补引擎设计和流处理工作负载特征方面的差异,Spark实现了一种叫做微批(Micro-batch)*的概念。在具体策略方面该技术可以将数据流视作一系列非常小的“批”,借此即可通过批处理引擎的原生语义进行处理。

Spark Streaming会以亚秒级增量对流进行缓冲,随后这些缓冲会作为小规模的固定数据集进行批处理。这种方式的实际效果非常好,但相比真正的流处理框架在性能方面依然存在不足。

优势和局限

使用Spark而非Hadoop MapReduce的主要原因是速度。在内存计算策略和先进的DAG调度等机制的帮助下,Spark可以用更快速度处理相同的数据集。

Spark的另一个重要优势在于多样性。既可作为独立集群部署,亦可与现有Hadoop集群集成,可运行批处理和流处理,运行一个集群即可处理不同类型的任务。

除了引擎自身的能力外,围绕Spark还建立了包含各种库的生态系统,可为机器学习、交互式查询等任务提供更好的支持。相比MapReduce,Spark任务更是“众所周知”地易于编写,因此可大幅提高生产力。

为流处理系统采用批处理的方法,需要对进入系统的数据进行缓冲。缓冲机制使得该技术可以处理非常大量的传入数据,提高整体吞吐率,但等待缓冲区清空也会导致延迟增高。这意味着Spark Streaming可能不适合处理对延迟有较高要求的工作负载。

由于内存通常比磁盘空间更贵,因此相比基于磁盘的系统,Spark成本更高。然而处理速度的提升意味着可以更快速完成任务,在需要按照小时数为资源付费的环境中,这一特性通常可以抵消增加的成本。

Spark内存计算这一设计的另一个后果是,如果部署在共享的集群中可能会遇到资源不足的问题。相比Hadoop MapReduce,Spark的资源消耗更大,可能会对需要在同一时间使用集群的其他任务产生影响。

总结

Spark是多样化工作负载处理任务的最佳选择。Spark批处理能力以更高内存占用为代价提供了无与伦比的速度优势。对于重视吞吐率而非延迟的工作负载,则比较适合使用Spark Streaming作为流处理解决方案。

MPI

MPI(Message Passing Interface 消息传递接口)。是一个跨语言的并行计算接口,可以被fortran,c,c++等调用,常在超级电脑、电脑簇等分布式内存环境应用。MPI的目标是高性能,大规模性,和可移植性。目前MPI的实现非常多,开源的有Open MPI和MPICH。

MPI的优点

  • 允许静态任务调度,程序的调度是一次性的,就是比如开始申请了50个进程,那这50个进程就会一起跑,同生同死。
  • MPI的封装,让并发数据更操作变得非常的方便,显示并行提供了良好的性能和移植性。
  • 由于MPI是基于消息的,划分计算任务,将任务映射到分布式进程集合中进行计算时,既可进行任务划分,也可进行数据划分,没有任何限制。
  • 用 MPI 编写的程序可直接在多核集群上运行。集群的各节点之间可以采用 MPI 编程模型进行程序设计,每个节点都有自己的内存,可以对本地的指令和数据直接进行访问,各节点之间通过互联网络进行消息传递。具有很好的可移植性,完备的异步通信功能,较强的可扩展性。

MPI的缺点

  • MPI都没有提供GFS系统,这个让大文件的存放,读取都成了一个问题,如果底层有一个GFS,再在上面搭一个MPI的系统,使用起来会非常的舒服。
  • MPI的容错性一般不容易做,因为程序是同生同死的,某一个进程挂了,整个任务就挂了。
  • 并行化改进需要大量地修改原有的串行代码,调试难度比较大。
  • 通信会造成很大的开销,为了最小化延迟,通常需要大的代码粒度,细粒度的并行会引发大量的通信。
  • 动态负载平衡困难。

OpenMP

OpenMp是线程级别的,是针对单主机上多核/多CPU并行计算而设计的工具,支持目前所有平台上的c,fortran等的共享内存式并行计算:
主线程(顺序的执行指令)生成一系列的子线程,并将任务划分给这些子线程进行执行。这些子线程并行的运行,由运行时环境将线程分配给不同的处理器。

OpenMp比较简单,修改现有的大段代码也容易。基本上OpenMp只要在已有程序基础上根据需要加并行语句即可。而MPI有时甚至需要从基本设计思路上重写整个程序,调试也困难得多,涉及到局域网通信这一不确定的因素。不过,OpenMp虽然简单却只能用于单机多CPU/多核并行,MPI才是用于多主机超级计算机集群的强悍工具,当然复杂。

CUDA

CUDA(Compute Unified Device Architecture)是一种由NVIDIA推出的通用并行计算架构,该架构使GPU能够解决复杂的计算问题。它包含了CUDA指令集架构(ISA)以及GPU内部的并行计算引擎。

Cpu与Gpu

CPU擅长处理不规则数据结构和不可预测的存取模式,以及递归算法、分支密集型代码和单线程程序。这类程序任务拥有复杂的指令调度、循环、分支、逻辑判断以及执行等步骤。例如,操作系统、文字处理、交互性应用的除错、通用计算、系统控制和虚拟化技术等系统软件和通用应用程序等等。

GPU擅于处理规则数据结构和可预测存取模式。例如,光影处理、3D 坐标变换、油气勘探、金融分析、医疗成像、有限元、基因分析和地理信息系统以及科学计算等方面的应用。显示芯片通常具有更大的内存带宽。具有更大量的执行单元。和高阶 CPU 相比,显卡的价格较为低廉。

目前设计GPU+CPU架构平台的指导思想是:让CPU的更多资源用于缓存,GPU的更多资源用于数据计算。

当代CPU的微架构是按照兼顾“指令并行执行”和“数据并行运算”的思路而设计,就是要兼顾程序执行和数据运算的并行性、通用性以及它们的平衡性。CPU的微架构偏重于程序执行的效率,不会一味追求某种运算极致速度而牺牲程序执行的效率。

GPU的微架构就是面向适合于矩阵类型的数值计算而设计的,大量重复设计的计算单元,这类计算可以分成众多独立的数值计算——大量数值运算的线程,而且数据之间没有像程序执行的那种逻辑关联性。

CUDA框架

CUDA 是 NVIDIA 的 GPGPU 模型,它使用 C 语言为基础,可以直接以大多数人熟悉的 C 语言,写出在显示芯片上执行的程序,而不需要去学习特定的显示芯片的指令或是特殊的结构。

从CUDA体系结构的组成来说,包含了三个部分:开发库、运行期环境和驱动:

  • 开发库是基于CUDA技术所提供的应用开发库。
  • 运行期环境提供了应用开发接口和运行期组件,包括基本数据类型的定义和各类计算、类型转换、内存管理、设备访问和执行调度等函数。
  • 驱动部分基本上可以理解为是CUDA-enable的GPU的设备抽象层,提供硬件设备的抽象访问接口。
  • 应用领域例如游戏、高清视频、卫星成像等数据规模庞大的场景。

在 CUDA 的架构下,一个程序分为两个部份:host 端和 device 端。Host 端是指在 CPU 上执行的部份,而 device 端则是在显示芯片上执行的部份。Device 端的程序又称为 “kernel”。通常 host 端程序会将数据准备好后,复制到显卡的内存中,再由显示芯片执行 device 端程序,完成后再由 host 端程序将结果从显卡的内存中取回。

GraphLab

一般的机器学习类算法有以下两个特性:

  • 数据依赖性很强。运算过程中参与计算的各个机器之间经常需要交换大量的数据。
  • 流处理复杂。主要表现在整个处理过程需要反复地迭代计算,数据处理分支很多,很难实现真正的并行。

而当前被广泛使用的MapReduce 计算框架,Map阶段集群的各台机器各自完成负载较重的计算过程,数据并行度高,适合完成类似矩阵运算、数据统计等数据独立性强的计算,任务执行期间不需要相互之间进行数据通信,所以MapReduce 不适合数据依赖性强的任务,而且MapReduce 并行计算模型也不能高效表达迭代型算法。这种计算模型在处理如日志分析、数据统计等数据独立性的任务时具有明显的优势,但是在机器学习领域,MapReduce框架并不能很好地满足机器学习计算任务。

另一个并行实现方案就是采用纯MPI(Native MPI)的方式。纯MPI实现通过精细的设计将并行任务按照MPI协议分配到集群机器上,并根据具体应用,在计算过程中进行机器间的数据通信和同步。纯MPI的优点是,可以针对具体的应用,进行深度优化,从而达到很高的并行性能。但纯MPI存在的问题是,针对不同的机器学习算法,需要重写其数据分配、通信等实现细节,代码重用率低,机器拓展性能差,对编程开发人员的要求高,而且优化和调试成本高。因而,纯MPI不适合敏捷的互联网应用。

为解决机器学习的流处理,Google提出了Pregel框架,Pregel是严格的BSP模型(Bulk Synchronous Parallel,整体同步并行计算模型),采用“计算-通信-同步”的模式完成机器学习的数据同步和算法迭代。Goolge曾称其80%的程序使用MapReduce完成,20%的程序使用Pregel实现。因而,Pregel是很成熟的机器学习流处理框架,但Google一直没有将Pregel的具体实现开源,外界对Pregel的模仿实现在性能和稳定性方面都未能达到工业级应用的标准。

2010年,CMU的Select实验室提出了GraphLab框架,GraphLab 是一个基于图像处理模型的开源图计算框架,框架使用C++语言开发实现。该框架是面向机器学习(ML)的流处理并行计算框架,可以运行在多处理机的单机系统、集群等多种环境下。

GraphLab 自成立以来就是一个发展很迅速的开源项目,GraphLab的设计目标是,像MapReduce一样高度抽象,可以高效执行与机器学习相关的、具有稀疏的计算依赖特性的迭代性算法,并且保证计算过程中数据的高度一致性和高效的并行计算性能。该框架最初是为处理大规模机器学习任务而开发的,但是该框架也同样适用于许多数据挖掘方面的计算任务。在并行图计算领域,该框架在性能上高出很多其他并行计算框架(例如,MapReduce、Mahout)几个数量级。

GraphLab的优点

GraphLab 作为一个基于图处理的并行计算框架,能够高效地执行机器学习相关的数据依赖性强,迭代型算法,其设计具有如下特点和优点。

  • 统一的API 接口。对于多核处理器和分布式环境,采用统一的API 接口,一次编写程序即可高效地运行在共享内存环境或者分布式集群上。
  • 高性能。优化C++执行引擎,在大量多线程操作和同步I/O 操作之间进行了很好的平衡。
  • 可伸缩性强。GraphLab 能够智能地选择存储和计算的节点,原因是GraphLab 对于数据的存储与计算都使用了精心设计的优良算法。
  • 集成HDFS。GraphLab 内置对HDFS 的支持,GraphLab 能够直接从HDFS中读数据或者将计算结果数据直接写入到HDFS 中。
  • 功能强大的机器学习类工具集。GraphLab 在自身提供的API 接口之上实现了大量的开箱即用的工具集。

GraphLab和MapReduce的对比

GraphLab 的出现不是对MapReduce 算法的替代,相反,GraphLab 借鉴了MapReduce 的思想,将MapReduce 并行计算模型推广到了对数据重叠性、数据依赖性和迭代型算法适用的领域。本质上,GraphLab 填补了高度抽象的MapReduce 并行计算模型和底层消息传递、多线程模型(如MPI 和PThread)之间的空隙。

GraphLab 模拟了MapReduce 中的抽象过程:

  • 对MapReduce的map操作,通过称为更新函数(Update Function)的过程进行模拟,更新函数能够读取和修改用户定义的图结构数据集。用户提供的数据图代表了程序在内存中和图的顶点、边相关联的内存状态,更新函数能够递归地触发更新操作,从而使更新操作作用在其他图节点上进行动态的迭代式计算。GraphLab 提供了强大的控制原语,以保证更新函数的执行顺序。
  • 对MapReduce的reduce操作,通过称为同步操作(Sync Operation)的过程进行模拟。同步操作能够在后台计算任务进行的过程中执行合并(Reductions),和GraphLab 提供的更新函数一样,同步操作能够同时并行处理多条记录,这也保证了同步操作能够在大规模独立环境下运行。

GraphLab并行框架

GraphLab将数据抽象成Graph结构,将算法的执行过程抽象成Gather、Apply、Scatter三个步骤。其并行的核心思想是对顶点的切分。

Graph的构造

  • 顶点是其最小并行粒度和通信粒度,边是机器学习算法中数据依赖性的表现方式。
  • 对于某个顶点,其被部署到多台机器,一台机器作为master顶点,其余机器上作为mirror。Master作为所有mirror的管理者,负责给mirror安排具体计算任务;mirror作为该顶点在各台机器上的代理执行者,与master数据的保持同步。
  • 对于某条边,GraphLab将其唯一部署在某一台机器上,而对边关联的顶点进行多份存储,解了边数据量大的问题。
  • 同一台机器上的所有edge和vertex构成local graph,在每台机器上,存在本地id到全局id的映射表。
  • vertex是一个进程上所有线程共享的,在并行计算过程中,各个线程分摊进程中所有顶点的gather->apply->scatter操作。

GraphLab的执行模型

每个顶点每一轮迭代经过gather->apple->scatter三个阶段。

  1. Gather阶段:工作顶点的边 (可能是所有边,也有可能是入边或者出边)从领接顶点和自身收集数据,记为gather_data_i,各个边的数据graphlab会求和,记为sum_data。这一阶段对工作顶点、边都是只读的。
  2. Apply阶段 :Mirror将gather计算的结果sum_data发送给master顶点,master进行汇总为total。Master利用total和上一步的顶点数据,按照业务需求进行进一步的计算,然后更新master的顶点数据,并同步mirror。Apply阶段中,工作顶点可修改,边不可修改。
  3. Scatter阶段:工作顶点更新完成之后,更新边上的数据,并通知对其有依赖的邻结顶点更新状态。这scatter过程中,工作顶点只读,边上数据可写。

在执行模型中,graphlab通过控制三个阶段的读写权限来达到互斥的目的。在gather阶段只读,apply对顶点只写,scatter对边只写。并行计算的同步通过master和mirror来实现,mirror相当于每个顶点对外的一个接口人,将复杂的数据通信抽象成顶点的行为。

猜你喜欢

转载自blog.csdn.net/lk3030/article/details/79685333