处理框架和处理引擎负责对数据系统中的数据进行计算。虽然“引擎”和“框架”之间的区别没有什么权威的定义,但大部分时候可以将前者定义为实际负责处理数据操作的组件,后者则可定义为承担类似作用的一系列组件。例如Apache Hadoop可以看作一种以MapReduce作为默认处理引擎的处理框架。引擎和框架通常可以相互替换或同时使用。例如另一个框架Apache Spark可以纳入Hadoop并取代MapReduce。
批处理主要操作大容量静态数据集,并在计算过程完成后返回结果。批处理模式中使用的数据集特征:
批处理非常适合需要访问全套记录才能完成的计算工作。例如在计算总数和平均数时,必须将数据集作为一个整体加以处理,而不能将其视作多条记录的集合。这些操作要求在计算进行过程中数据维持自己的状态。大量数据的处理需要付出大量时间,因此批处理不适合对处理时间要求较高的场合。
批处理框架应用:Apache Hadoop
流处理会对随时进入系统的数据进行计算。相比批处理模式,这是一种截然不同的处理方式。流处理方式无需针对整个数据集执行操作,而是对通过系统传输的每个数据项执行操作。
流处理中的数据集是“无边界”的,这就产生了几个重要的影响:
流处理系统可以处理几乎无限量的数据,但同一时间只能处理一条(真正的流处理)或很少量(微批处理,Micro-batch Processing)数据,不同记录间只维持最少量的状态。虽然大部分系统提供了用于维持某些状态的方法,但流处理主要针对副作用更少,更加功能性的处理(Functional processing)进行优化。
功能性操作主要侧重于状态或副作用有限的离散步骤。有近实时处理需求的任务很适合使用流处理模式。分析、服务器或应用程序错误日志,以及其他基于时间的衡量指标是最适合的类型,因为对这些领域的数据变化做出响应对于业务职能来说是极为关键的。流处理很适合用来处理必须对变动或峰值做出响应,并且关注一段时间内变化趋势的数据。
流处理框架应用:Apache Storm,Apache Samza
一些处理框架可同时处理批处理和流处理工作负载。这些框架可以用相同或相关的组件和API处理两种类型的数据,借此让不同的处理需求得以简化。
虽然侧重于某一种处理类型的项目会更好地满足具体用例的要求,但混合框架意在提供一种数据处理的通用解决方案。这种框架不仅可以提供处理数据所需的方法,而且提供了自己的集成项、库、工具,可胜任图形分析、机器学习、交互式查询等多种任务。
混合处理框架应用:Apache Spark,Apache Flink
MapReduce是Google提出的一个软件架构,用于大规模数据集的并行运算。
MapReduce的处理过程分为两个步骤:map(映射)和reduce(归纳)。每个阶段的输入输出都是key-value的形式,类型可以自行指定。map阶段对切分好的数据进行并行处理,处理结果传输给reduce,由reduce函数完成最后的汇总。Reduce又可以作为一个Map为下一级Reduce作准备,以此迭代。
MapReduce进程间的通信纯粹是用文件去联系的,每个进程做的事情就是去读取上一级进程生成的数据,然后处理后写入磁盘让下一级进程进行读取。这个特性使得MapReduce有着良好的容错性,当某一级的某一个进程出错了,JobMaster会重新调度这个进程到另外一个机器上重新运行。坏处是每当Map-Reduce的某一个步骤运行完后,需要重新调度下一级任务,调度产生的开销会非常的大(网络传输,文件读写磁盘IO)。
MapReduce通过把对数据集的大规模操作分发给网络上的每个节点实现可靠性;每个节点会周期性的把完成的工作和状态的更新报告回来。如果一个节点保持沉默超过一个预设的时间间隔,主节点记录下这个节点状态为死亡,并把分配给这个节点的数据发到别的节点。每个操作使用命名文件的不可分割操作以确保不会发生并行线程间的冲突;当文件被改名的时候,系统可能会把他们复制到任务名以外的另一个名字上去。(避免副作用)。
归纳操作工作方式很类似,但是由于归纳操作在并行能力较差,主节点会尽量把归纳操作调度在一个节点上,或者离需要操作的数据尽可能近的节点上了。
Apache Hadoop是一款支持数据密集型分布式应用程序的开源批处理框架,包含多个组件,即多个层,通过配合使用可处理批数据:
由于每个任务需要多次执行读取和写入操作,因此速度相对较慢。但另一方面由于磁盘空间通常是服务器上最丰富的资源,这意味着MapReduce可以处理非常海量的数据集。同时也意味着相比其他类似技术,Hadoop的MapReduce通常可以在廉价硬件上运行,因为该技术并不需要将一切都存储在内存中。MapReduce具备极高的缩放潜力,生产环境中曾经出现过包含数万个节点的应用。与其他框架和引擎的兼容与集成能力使得Hadoop可以成为使用不同技术的多种工作负载处理平台的底层基础。
Apache Spark是一种包含流处理能力的下一代批处理框架。与Hadoop的MapReduce引擎基于各种相同原则开发而来的Spark主要侧重于通过完善的内存计算和处理优化机制加快批处理工作负载的运行速度。Spark可作为独立集群部署(需要相应存储层的配合),或可与Hadoop集成并取代MapReduce引擎。
与MapReduce不同,Spark的数据处理工作全部在内存中进行,只在一开始将数据读入内存,以及将最终结果持久存储时需要与存储层交互。所有中间态的处理结果均存储在内存中。
虽然内存中处理方式可大幅改善性能,Spark在处理与磁盘有关的任务时速度也有很大提升,因为通过提前对整个任务集进行分析可以实现更完善的整体式优化。为此Spark可创建代表所需执行的全部操作,需要操作的数据,以及操作和数据之间关系的Directed Acyclic Graph(有向无环图),即DAG,借此处理器可以对任务进行更智能的协调。
为了实现内存中批计算,Spark会使用一种名为Resilient Distributed Dataset(弹性分布式数据集),即RDD的模型来处理数据。这是一种代表数据集,只位于内存中,永恒不变的结构。针对RDD执行的操作可生成新的RDD。每个RDD可通过世系(Lineage)回溯至父级RDD,并最终回溯至磁盘上的数据。Spark可通过RDD在无需将每个操作的结果写回磁盘的前提下实现容错。
流处理能力是由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(Message Passing Interface 消息传递接口)。是一个跨语言的并行计算接口,可以被fortran,c,c++等调用,常在超级电脑、电脑簇等分布式内存环境应用。MPI的目标是高性能,大规模性,和可移植性。目前MPI的实现非常多,开源的有Open MPI和MPICH。
OpenMp是线程级别的,是针对单主机上多核/多CPU并行计算而设计的工具,支持目前所有平台上的c,fortran等的共享内存式并行计算:
主线程(顺序的执行指令)生成一系列的子线程,并将任务划分给这些子线程进行执行。这些子线程并行的运行,由运行时环境将线程分配给不同的处理器。
OpenMp比较简单,修改现有的大段代码也容易。基本上OpenMp只要在已有程序基础上根据需要加并行语句即可。而MPI有时甚至需要从基本设计思路上重写整个程序,调试也困难得多,涉及到局域网通信这一不确定的因素。不过,OpenMp虽然简单却只能用于单机多CPU/多核并行,MPI才是用于多主机超级计算机集群的强悍工具,当然复杂。
CUDA(Compute Unified Device Architecture)是一种由NVIDIA推出的通用并行计算架构,该架构使GPU能够解决复杂的计算问题。它包含了CUDA指令集架构(ISA)以及GPU内部的并行计算引擎。
CPU擅长处理不规则数据结构和不可预测的存取模式,以及递归算法、分支密集型代码和单线程程序。这类程序任务拥有复杂的指令调度、循环、分支、逻辑判断以及执行等步骤。例如,操作系统、文字处理、交互性应用的除错、通用计算、系统控制和虚拟化技术等系统软件和通用应用程序等等。
GPU擅于处理规则数据结构和可预测存取模式。例如,光影处理、3D 坐标变换、油气勘探、金融分析、医疗成像、有限元、基因分析和地理信息系统以及科学计算等方面的应用。显示芯片通常具有更大的内存带宽。具有更大量的执行单元。和高阶 CPU 相比,显卡的价格较为低廉。
目前设计GPU+CPU架构平台的指导思想是:让CPU的更多资源用于缓存,GPU的更多资源用于数据计算。
当代CPU的微架构是按照兼顾“指令并行执行”和“数据并行运算”的思路而设计,就是要兼顾程序执行和数据运算的并行性、通用性以及它们的平衡性。CPU的微架构偏重于程序执行的效率,不会一味追求某种运算极致速度而牺牲程序执行的效率。
GPU的微架构就是面向适合于矩阵类型的数值计算而设计的,大量重复设计的计算单元,这类计算可以分成众多独立的数值计算——大量数值运算的线程,而且数据之间没有像程序执行的那种逻辑关联性。
CUDA 是 NVIDIA 的 GPGPU 模型,它使用 C 语言为基础,可以直接以大多数人熟悉的 C 语言,写出在显示芯片上执行的程序,而不需要去学习特定的显示芯片的指令或是特殊的结构。
从CUDA体系结构的组成来说,包含了三个部分:开发库、运行期环境和驱动:
在 CUDA 的架构下,一个程序分为两个部份:host 端和 device 端。Host 端是指在 CPU 上执行的部份,而 device 端则是在显示芯片上执行的部份。Device 端的程序又称为 “kernel”。通常 host 端程序会将数据准备好后,复制到显卡的内存中,再由显示芯片执行 device 端程序,完成后再由 host 端程序将结果从显卡的内存中取回。
一般的机器学习类算法有以下两个特性:
而当前被广泛使用的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 的出现不是对MapReduce 算法的替代,相反,GraphLab 借鉴了MapReduce 的思想,将MapReduce 并行计算模型推广到了对数据重叠性、数据依赖性和迭代型算法适用的领域。本质上,GraphLab 填补了高度抽象的MapReduce 并行计算模型和底层消息传递、多线程模型(如MPI 和PThread)之间的空隙。
GraphLab 模拟了MapReduce 中的抽象过程:
GraphLab将数据抽象成Graph结构,将算法的执行过程抽象成Gather、Apply、Scatter三个步骤。其并行的核心思想是对顶点的切分。
每个顶点每一轮迭代经过gather->apple->scatter三个阶段。
在执行模型中,graphlab通过控制三个阶段的读写权限来达到互斥的目的。在gather阶段只读,apply对顶点只写,scatter对边只写。并行计算的同步通过master和mirror来实现,mirror相当于每个顶点对外的一个接口人,将复杂的数据通信抽象成顶点的行为。