本申请要求于2008年11月7日提交的美国专利申请序列号12/267,142的优先权,该申请是于2007年10月1日提交的美国专利申请序列号11/906,293的部分继续申请,通过参考而将二者在此并入。
具体实施方式
针对并行计算的早期研究关注于在顺序应用中自动检测并行性。例如,工程师研发出计算机架构中的技术,诸如乱序缓冲区,其被设计用来检测指令间的依赖性并以并行方式调度独立的指令。这些技术仅仅检查在顺序编程语言中编码的代码段,并不能发掘应用级的并行性。因此,这些技术限制了可被发掘的并行性数量。
一大类应用(尤其是数据密集型批处理应用)在数据级具有明显的并行性。然而,实现并行应用存在若干技术挑战。在设计并行应用时,程序员必须解决与机器和处理器之间的通信、协调和同步有关的重要问题。与顺序程序完全不同,鉴于并行程序固有的异步性,程序员必须参与到并行程序配置中所有机器之间的所有可能交互。而且,并不存在用于并行应用和配置开发的有效调试工具。例如,单步调试某些代码可能难以在配置具有运行在很多机器上的很多线程的环境中执行。而且,归因于导致并行应用的复杂交互,程序员标识事实上作为瞬象被观察到并且很难再现的很多错误。实现并行化应用的程序员所面临的技术挑战直接转化成更高的研发成本和更长的研发周期。另外,程序员通常不能将并行化方案移植或复制到其他实现。
程序员认识到数据库系统非常适合于分析应用。不幸的是,数据库系统至少归结于两个原因而不能针对较大数据集进行升级。首先,数据库系统给出了高级SQL(结构化查询语言),其目标在于隐藏实现细节。尽管SQL相对容易使用,但是从并行化的角度看,此类高级语言的特性迫使用户按照导致处理低效执行的方式来表达计算。与利用低级语言(例如,C++)(其中并行化处理一次只读取一个数据集)编程相反,以SQL表达的同一处理可能导致执行若干读取。即使已经研发出了自动优化查询处理的技术,但是通过使用低级语言来实现并行化计算所达到的性能仍然远远超过诸如SQL的高级语言的性能。第二,数据库系统的I/O架构限制了分布式并行化实现的可升级性,因为数据库假设将通过分布式文件系统或者SAN(存储区域网络)硬件而经由网络上的公共逻辑存储单元进行数据访问。数据库并不利用数据的逻辑到物理映射,并且因此没有利用数据位置或数据的物理地点。即使存在成熟的高速缓存机制,数据库通常也通过不必要地遍历网络和消耗宝贵网络带宽的方式来访问数据。
分析应用在若干方面与web应用不同。分析应用通常处理结构化数据,相反,web应用频繁地处理非结构化数据。分析应用通常需要交叉参考来自于不同来源(例如,不同数据库表)的信息。与web应用相比,分析应用通常关注于更少的统计。例如,单词计数应用需要词汇表中所有单词的统计,相反,分析应用可以仅对所销售产品的数量感兴趣。
GridBatch提供了基础运算符,其可以用于分析应用或其他应用。详细的并行化应用实现可以表达为由GridBatch提供的基本运算符的组合。GridBatch在实现和调试方面为程序员节约了可观的时间,因为GridBatch为程序员解决了并行编程方面的问题。利用GridBatch,程序员确定所期待的运算符组合、顺序运算符和部署每个运算符的最少编程。
尽管将描述GridBatch的特定组件,但是按照GridBatch的方法、系统和产品可以包括附加的组件或者不同的组件。例如,处理器可以实现为微处理器、微控制器、专用集成电路(ASIC)、离散逻辑,或其他类型电路或逻辑的组合。类似地,存储器可以是DRAM、SRAM、闪存或任何其他类型存储器。用来实现下述处理和程序的逻辑可以存储(例如,作为计算机可读指令)在诸如光盘或磁盘或其他存储器的计算机可读介质上。备选地或附加地,该逻辑可以实现在可在实体间传送的电磁或光信号中。标志、数据、数据库、表和其他数据结构可以单独存储和管理、可并入单个存储器或数据库、可被分布,或可用很多不同方式在逻辑上和物理上进行组织。程序可以是单个程序的部分、单独的程序或者可分布在若干存储器和处理器上。此外,程序或程序的任何部分可以替代地在硬件中实现。
以下描述一个示例,其中基于web的零售商销售诸如PC和打印机的计算机设备。该零售商使用为了跟踪大量数据和信息而使用需要千兆字节存储的若干表,可以使用多个表(包括交易表;客户表和经销商表)来利用这些数据和信息得到分析信息。交易表存储用于每个所销售物品的产品id和购买者的客户id的记录。客户表存储每个客户的客户信息,经销商表存储关于与零售商做生意的每个经销商的信息。零售商可以使用GridBatch来分析很多分析,某些分析包括简单计数统计(例如,特定产品已销售多少,并标识带来利润的前十大客户)。零售商可以使用GridBatch来分析更加复杂化的分析,其涉及多个表和复杂的计算。例如,零售商可以使用GridBatch来确定在地理上邻近零售商的分销设施之一的客户数量,以便测量分销网络的效率。
GridBatch基础架构运行在处理节点集群(“多个节点”)上。运行在GridBatch集群环境中的两个软件组件名称为文件系统管理器和作业调度器。文件系统管理器在集群中的所有计算节点上管理文件并存储文件。文件系统管理器可以将大型文件分段成较小组块(chunk),并将每个组块存储在单独节点上。在该集群中的所有节点中,GridBatch可以指定例如一个节点作为命名节点,而所有其他节点作为数据节点。
数据节点保有大型文件的组块。在一个实现中,取决于集群中节点数量和其他配置考虑,数据节点可以保有大型文件的不止一个组块。数据节点对针对读取指派给该数据节点的组块或向其写入的客户端请求作出响应。命名节点保有文件系统的命名空间。命名节点维护大型文件到组块列表的映射、指派给每个组块的数据节点和每个数据节点的物理位置和逻辑位置。命名节点还对来自客户端请求的针对文件位置的查询作出响应,并将大型文件的组块分配到数据节点。在一个实现中,GridBatch利用节点的IP地址来引用节点,所以GridBatch可以直接访问节点。主节点还维护物理网络拓扑,其跟踪哪些节点是直接连接的。物理网络拓扑可以由管理员手动填充和/或通过自动拓扑发现算法来发现。网络拓扑信息可以通过指示为了减小网络带宽消耗而可以发送和/或取回中间结果的附近邻居从节点,而改善递归运算符的性能。以下讨论拓扑及其在促进递归运算符执行中的使用的简洁描述。
GridBatch文件系统在很多节点上分布大文件,并将每个组块的位置通知给作业调度器,使得作业调度器可以在容纳将被处理的组块的节点上调度任务。GridBatch将大型数据分析问题(诸如,数据仓库)作为目标,其中需要处理大量结构化数据。文件通常存储具有相同模式(例如,对象所有者、或结构或对象族)的数据记录大型集合。对于结构化数据,GridBatch使用数据划分来将数据分段为更小的片,类似于数据库划分。GridBatch文件系统存储固定数量的组块,每个组块具有组块id(CID)。程序员可以与文件系统中的其他组块相独立地访问任何组块。
在一个实现中,程序员可以规定GridBatch可以指派的组块数量。在另一实现中,GridBatch管理员规定GridBatch可以指派的组块数量,和/或GridBatch基于可用的节点数量和/或其他系统配置资源考虑来确定GridBatch可以指派的组块数量。在一个实现中,GridBatch将最高可指派CID设置得比集群中节点数目N大得多。GridBatch使用系统级查找表来指示从CID到N翻译的映射。该翻译提供了对集群大小动态改变的支持,使得当配置停用节点以及附加节点加入集群时,GridBatch文件系统能够自动地重新平衡存储和工作负荷。换言之,文件系统维护CID到数据节点的映射,并当CID到数据节点映射改变时(例如,当数据节点加入和/或离开GridBatch集群102时),将数据自动移动到不同节点。
在一个实现中,GridBatch处理两种数据集,向量和索引向量(indexed vector)。类似于数据库表的记录,向量包括GridBatch认为彼此独立的记录集。向量中的记录可以遵守相同的模式,并且每个记录可以包括若干字段(类似于数据库栏)。与向量相反,但是类似于索引数据库表,索引向量中的每个记录还具有相关联的索引。例如,索引向量中记录的字段之一可以是索引向量的相关联索引,而索引可以是任何数据类型(例如,字符串或整数)。
当使用索引向量时,程序员定义应如何通过划分函数在组块上对数据进行划分。当需要写入新的数据记录时,文件系统调用划分函数来确定组块id,并将该新的数据记录追加至对应于该组块id的组块末端。在一个实现中,用户定义的划分函数采用如下形式:int[]partitionFunc(index X),其中X代表将被写入的记录的索引,而int[]指示整数数组。划分函数应用散列函数,以便将索引转换成在1到CID范围内的一个或多个整数,其中该CID指示数据记录将被存储的指派组块id(或多个id)。在另一实现中,划分函数可以采取如下形式:int[]partitionFunc(distributionkey X),其中X代表用于将被写入以代表要使用的优选处理器和/或处理器组的记录的分布关键字指示符。
在一个实现中,当用户请求创建用于新索引向量的新文件时,用户向文件系统管理器提供用户定义的散列函数,其形式为int[]hashFunc(distributionkey X)。散列函数接受分布关键字作为输入,并产生从1到CID范围内的一个或多个整数。当写入新记录时,文件系统管理器调用散列函数,以确定将该新记录写入哪个划分。其结果是,GridBatch将索引向量进行划分,因为新记录是由文件系统管理器处理的。
作业调度系统包括主节点和多个从节点。主节点可使用主节点逻辑来实现主节点功能。从节点管理由主节点指派到从节点的任务的执行。主节点可使用主节点逻辑来将作业(例如,计算)细分成由程序员在程序中表达的很多较小任务。在一个实现中,主节点逻辑在集群中的从节点间分布任务,并监控这些任务以确保所有这些任务成功完成。在一个实现中,GridBatch将数据节点指定为从节点。因此,当主节点调度任务时,主节点可以在还保有将被处理的数据组块的那个节点上调度任务。GridBatch通过减小网络带宽依赖性而提高了计算性能,该网络带宽依赖性的减小是由于GridBatch将数据传输最小化并在节点本地对节点执行数据处理。
GridBatch提供通常使用的原语集,这些原语称为运算符,程序员可以用该原语来实现计算并行化。运算符处理将工作分布到多个节点的细节,由此避免了程序员解决与实现并行编程方案相关联的复杂问题的负担。程序员以类似于编写传统顺序程序的方式将运算符集引入程序。
GridBatch提供了五种运算符:分布、联接、卷积、递归和映射。分布运算符将源向量或源索引向量转换成具有目的索引的目的索引向量。转换涉及将数据从源数据节点传输到目的数据节点。分布运算符采取如下形式:Vector Distribute(vector V,FuncnewPartitionFunc),其中V代表将被转换的数据所在的向量,而newPartitionFunc代表划分函数,其指示GridBatch将在其处生成新向量的目的数据节点。在一个实现中,用户定义的划分函数采用int[]newPartitionFunc(index X)形式,其中X代表记录的索引,而int[]指示整数数组。用户定义的划分函数返回与目的数据节点的列表相对应的数字列表。在一个实现中,分布运算符可以在所有节点上复制向量,使得每个节点具有准确拷贝以方便的进行本地处理。在所有节点上复制向量可以在newPartionFunc返回作为目的节点的所有数据节点的列表时发生。
联接运算符取得两个索引向量,并在索引字段匹配的情况下合并对应的记录。GridBatch识别具有匹配索引的对应记录并调用用户定义的联接函数。用户定义的联接函数可以简单地合并两个记录(例如,类似于数据库联接),但是通常可以实现任何期待的功能。联接运算符采用以下形式:Vector Join(Vector X,Vector Y,FuncjoinFunc),其中X和Y代表将要联接的索引向量,而joinFunc表示用户定义的将要应用于索引向量中对应记录的联接函数。联接运算符产生新的向量,其包括应用用户定义的函数的结果。用户定义的联接函数采用如下形式:Record joinFunc(Record Z,Record K),其中Z和K分别代表向量X和Y的记录。当GridBatch调用用户定义的函数时,GridBatch可以确保用于记录Z和K的索引相匹配。
GridBatch可以在执行联接操作之前执行分布操作,使得GridBatch通过在联接随后将使用的同一索引字段上使用划分函数来对向量X和Y进行划分。联接运算符在每个节点本地执行联接,而不用确定GridBatch是否将数据分布或取回至每个节点。在一个实现中,联接运算符在执行联接之前会自动执行分布运算符。
联接运算符可以在当索引字段中存在准确匹配时使用。然而,当程序员期待识别联接运算符的相反结果(例如,识别不匹配记录)时,针对每个记录K检查每个记录Z。卷积运算符识别匹配的Z和K记录,并将用户定义的函数应用于每个匹配。卷积运算符提供了附加能力,并将更多的计算选项提供给程序员。在一个实现中,涉及两个向量的所有计算操作可以通过卷积运算符来完成。卷积运算符可以使用任何向量字段针对非索引的向量和索引向量执行联接函数,即使当联接将非索引字段用于联接时也是如此。卷积运算符采用以下形式:vector Convolution(vector X,vector Y,func convFunc),其中X和Y代表两个输入向量,而convFunc代表程序员提供的用户定义的卷积函数。作为结果,卷积运算符产生新的向量。用户定义的函数采用以下形式:Record convFunc(record Z,record K),其中Z和K分别代表向量X和Y的记录。convFunc函数确定是否应该采取任何行动(例如,确定记录Z是否匹配记录K),并随后执行对应的动作。
GridBatch可以在执行卷积运算符之前执行分布运算符,使得GridBatch在卷积随后可以使用的同一索引字段上对向量X和Y进行划分。卷积运算符在每个节点本地执行计算,而不用确定GridBatch是否将数据分布或取回到每个节点。在其他实现中,卷积运算符在执行卷积之前自动执行分布运算符。
作为一个示例,程序员可能希望确定零售商的经销商附近的客户数量。GridBatch文件系统将生成客户向量和经销商向量,其中客户向量包括指示每个客户物理位置的物理位置字段,而经销商向量包括指示每个经销商物理位置的物理位置字段。程序员可以使用GridBatch,以基于客户向量和经销商向量的物理位置字段而合并客户向量和经销商向量。程序员可以使用convFunc,以基于程序员指定的相邻性来评价每个客户和每个经销商之间的物理距离,并将符合该相邻性的每个记录存储在结果向量中。
在一个实现中,GridBatch递归运算符执行归约运算,其取得向量的所有记录并将它们合并至单个结果。针对向量的记录执行的实际逻辑运算是由用户定义的函数定义的。加法是归约运算(reduceoperation)的示例,其中向量的所有记录相加在一起。排序是归约运算的另一示例,其中向量的所有记录都针对彼此进行检查,以产生期待的顺序。递归运算符在很多节点间扩展该归约运算。Web应用通常频繁地执行归约操作(例如,数字计数,其中每个单词需要归约操作以将出现次数相加),这与很少执行归约运算的大多数分析应用相反。大多数分析应用的归约运算符成为瓶颈,并当程序员仅仅需要排序后的输出以供报告或少量统计时限制了应用的升级性。很多归约运算表现出了可交换和可结合特性,并且可以独立于顺序来执行。
例如,对事件出现次数进行计数涉及公知为加法的可交换和可结合运算符。加法出现的顺序不会影响最后的结果。类似地,排序可以独立于顺序。GridBatch递归运算符执行顺序独立的归约运算并采取以下形式:Record Recurse(Vector X,Func recurseFunc),其中X代表要归约的输入向量,而recurseFunc代表要应用的用户定义递归函数。递归运算符将向量合并至单个记录。用户定义的函数recurseFunc采用以下形式:Record recurseFunc(Record Z1,RecordZ2),其中Z1和Z2代表来自于向量X的两个子部分合并的部分结果。recurseFunc函数规定如何进一步合并两个部分结果。
例如,在向量X代表整数的向量,以及程序员希望计算整数的和的情况下,则程序员将加法函数用作用户定义的recurseFunc函数,表示为:Record addition(Record Z 1,Record Z 2){return new Record(Z1.value()+Z2.value());}。GridBatch对向量X的记录递归地应用加法函数,以最终计算向量中整数的总和。
在另一示例中,向量X包括代表字符串的排序后列表的记录,而程序员希望对字符串进行排序以供最终报告。表1示出了GridBatch可如何实现用于排序字符串的用户定义函数。用户定义的函数将字符串的两个排序后的列表合并成一个排序后的字串,并当程序员实现将被递归调用的用户定义函数时,用户定义的函数实现合并排序算法。
表1-用于排序的用户定义函数 |
Record mergeSort(Record Z 1,Record Z2){new Record Z;//来自记录Z1的下一字符串String a=Z 1.next();//来自记录Z2的下一字符串 |
String b=Z2.next();do{if(a<b){Z.append(a);a=Z 1.next();}else{Z.append(b);b=Z2.next();}}while(!Z1.empty()&&!Z2.empty());return x;} |
递归在很多节点上将归约运算并行化。另外,递归将需要部分结果的操作的网络业务最小化。例如,在程序员需要识别带来利润的前十大客户的情况下,每个节点计算本地的前十大客户,并将结果(例如,部分结果)转发到相邻节点,这些相邻节点接着将这些部分结果与接收节点的本地结果合并,以产生前十大。每个节点仅将前十大记录传递到特定相邻节点,而不是将每个节点的每个记录传递到执行归约操作的单个节点。因此,递归运算符避免较大带宽需求和不期待的网络业务,并提供了较高的计算性能。
映射运算符将用户定义的映射函数应用到向量的所有记录。该映射运算符采用如下形式:Vector Map(vector V,Func mapFunc),其中V代表向量,更具体地,代表向量该mapFunc将被应用于其上的记录。用户定义的映射函数可以采取如下形式:RecordmapFunc(Record X)。用户定义的函数mapFunc接受输入向量的一个记录作为变元,并产生用于结果向量的新记录。
块运算符通过将用户定义的bloFunc函数应用于向量组块的记录,来利用块级别的并行性。块运算符采用以下形式:Vector BLO(vector X,Func bloFunc),其中X是输入向量,而bloFunc是用户定义的函数。用户定义的函数bloFunc可以采用以下形式:bloFunc(Iterator records)。用户定义的函数bloFunc接受记录的列表(例如,Iterator)作为变元,用户定义的函数将对其应用。记录列表中的记录用于给定划分(例如,向量组块)。bloFunc可以以记录写入划分(例如,向量组块)的顺序相同的顺序返回向量X的记录,使得可以为划分的记录确定有序序列(例如,排名)。用户定义的bloFunc函数应用于输入Iterator中记录的列表,以便获得用于新向量Z的块函数评价记录。
在一个实现中,GridBatch通过在从节点不能完成任务时重新执行任务来容忍从节点失败和错误。向量的每个向量组块在指定为备份节点的X个不同从节点上复制X次,其中X是用户可以指定的和/或GridBatch可以基于配置、可用资源和/或历史观察确定的常数。在任何运算符计算期间,如果从节点在完成所指派任务之前失效,则主节点被通知,并且该主节点在保有该向量组块的备份拷贝的从节点上开始另一过程。当没有从从节点接收到周期性心跳时,主节点将从节点标识为失效从节点。
图1示出了GridBatch系统配置100(GridBatch),其包括GridBatch集群102、应用104和用户接口106。GridBatch 100组件通过网络108(例如,互联网、局域网、广域网或任何其他网络)通信。GridBatch集群102包括多个节点(例如,主节点116和从节点120)。每个从节点120可以包括通信接口113和存储器118。GridBatch100指明主节点116,将其余节点指定为从节点(例如,从节点120)。GridBatch 100可以将从节点指定为数据节点(例如,数据节点134),以下进一步描述。从节点120使用从节点逻辑160来管理主节点116指派给从节点120的从任务158的执行。
图2示出了示例性主节点116。主节点116可以包括通信接口211和存储器215。GridBatch 100使用文件系统管理器逻辑222来在GridBatch集群102中所有节点上管理并存储文件。在一个实现中,文件系统管理器逻辑222将大型文件分段为较小组块,并将这些组块在从节点间存储。文件系统管理器逻辑222维护CID到数据节点的映射,并当CID到数据节点映射改变时(例如,当数据节点加入和/或离开GridBatch集群102时)自动将数据移动到不同节点。GridBatch 100使用作业调度器逻辑230来协调GridBatch集群102中所有节点之间的操作。
在GridBatch集群102中所有节点间,GridBatch 100可以将主节点116指定为命名节点232,以及指定所有其他节点充当数据节点(例如,数据节点134)。命名节点232保有文件系统240的命名空间238。命名节点232维护文件到对应向量组块的列表的向量映射242、指派给每个组块的数据节点,和每个数据节点的物理和逻辑位置。命名节点232还对针对文件位置的任务请求244进行响应。在一个实现中,命名节点232将大型文件的组块分配至数据节点。
主节点116将程序员在程序中表达的任务252(例如,计算)细分成作业调度器逻辑230在从节点间分布的从任务(例如,从任务158)。在一个实现中,主节点116在GridBatch集群102中的从节点间分布从任务,并监控这些从任务以确保所有任务成功完成。因此,当主节点116调度任务252时,主节点116可以在还保有待处理的数据组块的从节点上的从任务(例如,从任务158)。例如,在待处理的数据驻留在向量组块本地的情况下,主节点116可以将任务252分解成对应于从节点的从任务,使得GridBatch 100通过减小网络带宽依赖性来增大计算性能,其中减小网络带宽依赖性是通过将数据传输最小化以及在节点本地对数据执行数据处理而实现的。
在一个实现中,GridBatch 100在主节点116上实现主节点逻辑260,其协调GridBatch集群102、应用104和用户接口106之间的通信和交互。主节点逻辑260可以协调并控制文件系统管理器逻辑222和作业调度逻辑230。主节点逻辑260可以维护GridBatch软件库262,其包括分布运算符逻辑264、联接运算符逻辑266、卷积运算符逻辑268、递归运算符逻辑270、映射运算符逻辑278和块运算符逻辑280。主节点116可以接收任务请求244,并通过从节点和从节点逻辑160协调任务请求244的执行。
图3示出了在处理分布函数调用300(例如,任务请求244)并实施分布运算符逻辑264期间的GridBatch 100。在一个实现中,主节点116接收分布函数调用300,以执行具有参数的分布运算符,其中这些参数包括第一向量标识符272,其标识将被重新分布以获得在节点集中重新分布的重新分布向量组块的第一向量。例如,第一向量可以代表具有在节点集(例如,分别为从节点1328、从节点3330和从节点6332)上分布的向量组块V1C 1308、V1C2310和V1C3312的之前分布的向量。向量组块V 1C 1308、V 1C2310和V1C3312分别包括对应的向量组块记录V1C 1R1-V1C 1RX 322、V1C2R1-V1C2RY 324和V1C3R1-V1C3RZ。
主节点逻辑260通过在具有第一向量组块的每个节点集(例如,分别为从节点1328、从节点3330和从节点6332)上产生划分任务334来发起执行。箭头336代表节点状态的转变,其中具有第一向量组块的每个节点运行划分任务334。第一向量组块的每个向量组块V1C1308、V1C2310和V1C3312的记录可以由对应的划分任务334来评价,以便确定目的向量组块指派。例如,每个划分任务334可以评价驻留在对应从节点上的第一向量组块记录,以便确定目的向量组块位置,从而重新分布每个第一向量组块记录。在将要重新分布第一向量组块记录的情况下,每个划分任务334可以在用于每个目的向量组块位置(例如,目的向量组块指派)的对应从节点上创建目的向量组块指派文件(例如,V1C1F1338、V1C2F1-V 1C2F4-V1C2F3-V1C2F6340和V1C3F1-V1C3F2-V1C3F5-V1C3F6342)。
主节点116可以在每个划分任务334完成时从每个划分任务334接收完成通知。主节点116通过在每个从节点(例如从节点1328、从节点3330、从节点4346、从节点5348、从节点6332和从节点8350)上产生重新分布任务334而发起执行重新分布任务。箭头346代表节点状态的转变,其中对应于目的向量组块的每个节点运行重新分布任务334。目的地向量块(例如,V1C1352、V1C2354、V1C3356、V1C4358、V1C5360以及V 1C6362)通过由向量块指派文件(例如,V1C1F1338、V1C2F1-V1C2F4-V1C2F3-V1C2F6340以及V1C3F1-V1C3F2-V1C3F5-V1C3F6342)标识的向量块位置来指示。重新分布任务344发起向量组块指派文件到对应的目的从节点的远程拷贝,以便将向量组块指派文件配置在对应于指派给从节点的向量组块(例如,V1C1F1-V1C3F1-V1C2F1364、V1C3F2368、V1C2F3370、V1C2F4372、V1C3F5374和V1C3F6-V1C3F6376)的从节点上。
重新分布任务344发起位于对应于特定目的向量组块的每个向量组块指派文件中的记录(例如,V1C1R1-V1C1RX 382、V1C2R1-V1C2RY 384、V1C3R1-V1C3RZ 386、V1C4R1-V1C4RQ 388、V1C5R1-V1C5RS 390和V1C6R1-V1C6RT 392)的合并378。箭头380表示节点状态的转变,其中对应于目的向量组块的每个节点执行合并378。合并378导致在节点集中重新分布的第一向量的重新分布的向量组块。每个从节点的从节点逻辑160向主节点116发送完成通知,该通知指示合并378的完成状态。
图4示出了在处理联接函数调用400(例如,任务请求244)和实施联接运算符逻辑266期间的GridBatch 100。在一个实现中,主节点116接收具有参数的联接函数调用400,这些参数包括第一向量标识符272和第二向量标识符274以及用户定义的联接函数(例如,用户定义的函数276)。第一向量标识符272和第二向量标识符274标识划分成第一向量组块(例如,V1C 1404、V 1C2406和V1C3408)和第二向量组块(例如,V2C 1410、V2C2412和V2C3414)的第一向量和第二向量。第一向量组块和第二向量组块分别包括第一向量组块记录(例如,V1C1R1-V1C1RZ 416、V1C2R8-V1C2RJ 418和V1C3R4-V1C3RL 420)和第二向量组块记录(例如,V2C1R3-V2C1RY422、V2C2R7-V2C2RK 424和V2C3R4-V2C3RM 426)。
主节点116在对应于第一向量组块和第二向量组块的位置的节点集(例如,从节点1428,从节点4430和从节点6432)本地发起排序任务(例如,从任务158),以便对节点集的每一个,对第二向量的第二向量组块和第一向量组块的每一个进行排序。在一个实现中,排序任务434根据分别出现在第一向量的每个第一向量记录(例如,V1C1R1IF-V1C1RZIF 438、V1C2R8IF-V1C2RJIF 440和V1C3R4IF-V 1C3RLIF 442)中的联接索引字段的索引值和第二向量的每个第二向量记录(例如,V2C1R3IF-V2C1RYIF 444、V2C2R7-V2C2RKIF 446和V2C3R4-V2C3RMIF 448)的联接索引字段的索引值,对第一向量记录和第二向量记录进行排序。箭头436表示节点状态的转变,其中具有向量组块的每个节点运行排序任务434。
在一个实现中,排序任务434将第一向量记录中出现的索引字段的索引值与第二向量记录中出现的索引字段的索引值相比较,以确定包括匹配索引值的第一向量记录和第二向量记录,并将用户定义的函数276(例如,用户定义的联接函数)应用于具有匹配索引字段值的第一向量记录和第二向量记录。排序任务434执行匹配任务450,其将第一向量记录的索引字段的索引字段值与第二向量记录的索引字段的索引字段值进行比较。箭头452代表节点状态的转变,其中具有向量组块的每个节点运行匹配任务450。匹配任务450将用户定义的函数276(例如,用户定义的联接函数)应用于具有用于对应向量组块(例如,V1C2RBIF 454和V2C2RPIF 456、和V1C2RBIF458和V2C2RPIF 460)的匹配索引字段值的第一向量记录和第二向量记录,以获得联接函数组块结果(例如,“无JFC1R”462、JFC2R464和JFC3R 466)。当用于对应向量组块的索引字段值不匹配时(例如,V1C1RXIF 468和V2C1RYIF 470),匹配任务450不将用户定义的联接函数应用于第一向量记录和第二向量记录。
联接函数组块从联接函数向量结果产生,其识别包括从联接函数组块结果(例如,JFC2R 464和JFC3R 466)获得的联接函数向量组块记录(JFVC1RT 480和JFVC2R3-JFVC2RN 482)的联接函数向量组块(例如,JFVC 1476和JFVC2478)。在一个实现中,每个从节点的从节点逻辑160向主节点116发送完成通知,其指示排序任务434的完成状态。
例如,在一个实现中,程序员可以使用GridBatch 100来索引两个向量,即,由产品id字段(例如,索引字段V1C1R1IF-V1C 1RZIF438、V1C2R8IF-V1C2RJIF 440和V1C3R4IF-V1C3RLIF 442)索引的产品向量(例如,由第一向量标识符272标识的第一向量)和由客户id字段(例如,索引字段V2C1R3IF-V2C1RYIF 444、V2C2R7-V2C2RKIF 446和V2C3R4-V2C3RMIF 448)索引的客户向量(例如,由第二向量标识符274标识的第二向量)。产品向量包括产品id和对应于所购买产品(例如,索引字段值)的客户id。客户向量保有客户id和客户的人口统计学信息(例如,索引字段值,诸如年龄、地址、性别)。如果程序员想要知道购买特定产品的每个年龄组中有多少人,则程序员利用产品向量和客户向量作为参数调用联接函数调用,以获得将产品ID信息与客户人口统计学信息联系在一起的联接结果。在一个实现中,为了确保GridBatch 100在基于客户id字段(例如,索引字段)处理产品向量和客户向量的联接函数调用400中获得最高性能,程序员调用分布函数调用300来用客户id索引产品向量,而不是产品id。分布函数调用确保GridBatch 100根据客户id字段将产品向量的记录分布至GridBatch集群102中的节点。在产品向量和客户向量的客户id字段值相等以获得联接函数向量结果的情况下,GridBatch 100随后可以将用户定义的函数276(例如,用户定义的联接函数)应用于产品向量和客户向量的每个记录。
图5示出了在处理卷积函数调用500(例如,任务请求244)和实施卷积运算符逻辑268期间的GridBatch 100。在一个实现中,主节点116接收具有参数的卷积函数调用500,这些参数包括第一向量标识符272和第二向量标识符274和用户定义的卷积函数(例如,用户定义的函数276)。第一向量标识符272和第二向量标识符274标识被划分成第一向量组块(例如,V1C1504和V1C2506)和第二向量组块(例如,V2C1508和V2C2510)的第一向量和第二向量,这些组块对应于在GridBatch集群102的节点间分布的划分向量块。第一向量组块和第二向量组块分别包括第一向量组块记录(例如,V1C1R1-V1C1RZ 512和V1C3R4-V1C3RL 514)和第二向量组块记录(例如,V2C1R3-V2C1RY 516和V2C3R4-V2C3RM 518)。
主节点116在对应于第一向量组块和第二向量组块的位置的节点集(例如,从节点1520和从节点8522)本地发起卷积任务524(例如,从任务158)的产生。箭头526表示用于每个节点的节点状态的转变,其中主节点116产生卷积任务524。卷积任务524在本地将用户定义的函数276(例如,用户定义的卷积函数)应用于第一向量组块记录和第二向量组块记录的置换(permutation)(例如,528和530)。用户定义的卷积函数评价对应第一向量组块记录和第二向量组块记录(例如,528和530)的每个置换,以获得卷积函数评价结果(例如,536、538、540和542)。箭头534代表用于每个节点的节点状态的转变,其中用户定义的卷积函数评价对应第一向量组块记录和第二向量组块记录的每个置换。卷积函数评价结果可以指示相应的第一向量组块记录和第二向量组块记录的置换何时产生卷积函数组块结果记录(例如,CFC1R1-CFC1R3-CFC1R4-CFC1RZ 536和CFC2R3-CFC2RK 540)。卷积函数评价结果可以指示对应第一向量组块记录和第二向量组块记录的置换何时产生无卷积函数组块结果记录(例如,“无CFC 1RX”538和“无CFC2RY”542)。用户定义的卷积函数可以将卷积函数结果转换成卷积函数组块结果记录(例如,CFVC1R1-CFVC1R3-CFVC1R4-CFVC1RZ 548和CFVC2R3-CFVC2RK 550),以获得用于每个节点(例如,从节点1520和从节点8522)的卷积函数结果。
例如,在一个实现中,程序员可以调用卷积函数调用500来确定位于零售商的经销商附近的客户数量。文件系统管理器逻辑222可以包括客户向量(例如,由第一向量标识符272标识的第一向量)和经销商向量(例如,由第二向量标识符274标识的第二向量),其中所述客户向量包括指示每个客户的物理位置的物理位置字段,所述经销商向量包括指示每个经销商的物理位置的物理位置字段。程序员可以调用卷积函数调用500,来基于物理位置字段将用户定义的卷积函数(例如,用户定义的函数276)应用于客户向量和经销商向量,以评价每个客户和每个经销商之间的物理距离并获得卷积函数结果向量。在一个实现中,用户定义的卷积函数可以表示为convFunc。在卷积调用前,客户向量可以划分成客户向量组块(例如,第一向量块V1C1504和V1C2506),这些组块根据出现在每个客户向量记录中的物理位置字段(例如,索引字段)在GridBatch集群102的节点上划分。经销商向量组块(例如,第二向量组块V2C1508和V2C2510)可以拷贝到集群的所有节点中。这可以通过提供总是将所有节点列表返回分布运算符的划分函数来实现。用户定义的卷积函数评价驻留在对应从节点上的客户向量记录和经销商向量记录的置换,以获得卷积函数组块结果记录。换言之,在客户向量组块具有Z个记录而经销商向量组块具有K个记录的情况下,用户定义的卷积函数可以评价Z×K个置换,其中对于客户向量组块中从1到Z的每个记录,GridBatch 100将用于定义的卷积函数应用于经销商向量组块的从1到K的每个记录。GridBatch集群102的每个从节点执行的卷积函数调用的结果产生了对应卷积函数向量组块,以便获得用于每个节点(例如,从节点1520和从节点8522)的卷积函数结果。
图6示出了在处理递归函数调用600(例如,任务请求244)和实施递归运算符逻辑270期间的GridBatch 100。在一个实现中,主节点116接收具有参数的递归函数调用600,这些参数包括第一向量标识符272和用户定义的卷积函数(例如,用户定义的函数276)。第一向量标识符272标识被划分成第一向量组块(例如,V1C1604、V1C2 606和V1C3 610)的第一向量,这些组块对应于在GridBatch集群102的节点间分布的划分向量块。第一向量组块包括第一向量组块记录(例如,V1C1R1-V1C1RX 616、V1C1R3-V1C1RJ 618、V1C2R1-V1C2RY 620、V1C2RK-V1C2RN 622、V1C3R4-V1C3RZ 624和V1C3RG-V1C3RM 626)。
主节点116在对应于第一向量组块的位置的节点集(例如,从节点1628、从节点4630和从节点6632)本地发起递归任务634(例如,从任务158)的产生。箭头636表示节点状态的转变,其中具有第一向量组块的每个节点运行递归任务634。递归任务634最初将用户定义的递归函数应用于第一向量组块记录,以产生用于每个第一向量组块(例如,IRV1C1R1638、IRV1C1R2640、IRV1C2R1642、IRV1C2R2644、IRV1C3R1646和IRV1C3R2648)的中间递归向量组块结果。递归任务对中间递归向量组块结果调用用户定义递归函数,以产生中间递归从节点结果(例如,IRSN1R 650、IRSN4R 652和IRSN6R 654)。
递归任务将中间递归从节点结果(例如,IRSN1R 650)传达至节点集的子集(例如,从节点4630),并且递归任务在中间结果(例如,IRSN1R 650和IRSN4R 652)上迭代调取用户定义的递归函数,以产生越来越少的中间从节点结果(例如,IFIRSN4R 660)。递归任务将越来越少的中间结果的子集(就例如,IFIRSN4R 660)传达至越来越小的节点集的子集(例如,从节点6632),直到GridBatch100在节点集中的最终节点上获得最终递归结果(例如,FRR 668)为止。
在一个实现中,递归任务传达至节点集的子集的中间结果的子集包括产生越来越少中间结果的子集的中间结果的二分之一。类似地,随后由递归任务传达至节点集的子集的越来越少的中间结果的每个子集包括越来越少的中间结果的二分之一。在一个实现中,递归运算符逻辑270使用网络拓扑信息,通过识别为了减少网络带宽消耗可以发送和/或取回中间结果的附近邻居从节点,来改进递归运算符的计算性能。程序员、用户和/或GridBatch 100可以定义确定从节点是否构成另一从节点的附近邻居从节点的因素。可以用来确定从节点是否被指定为附近邻居从节点的因素可以包括从节点之间的数据传输时间、从节点之间的网络跳数(例如,网络路由器的数量),或者数据传输时间与网络跳数的组合。
图6示出了GridBatch递归运算符逻辑270在GridBatch集群102的从节点间如何分布中间结果。从节点可以计算本地中间递归结果(例如,IRSN1R 650、IRSN4R 652和IRSN6R 654)。从节点的子集(例如,从节点1628)可以将本地中间递归结果(例如,IRSN1R650)传输至从节点的子集(例如,从节点4630)。从其他从节点接收中间递归结果的从节点可以迭代地将传输的中间结果(例如,IRSN1R 650)应用于本地中间结果(例如,IRSN4R 652)。在单个从节点(例如,从节点6632)产生最终递归结果(例如,FRR 688)之前,迭代地从节点的子集(例如,二分之一)将中间结果传送至具有本地中间结果(例如,将传输的中间结果放入本地中间结果)的另一半节点。在一个实现中,主节点确定用于将中间结果递送到节点集中从节点的机制、以及产生最终递归结果(例如,FRR 668)所需的放入迭代次数。
图7示出了GridBatch 100可以用来执行分布运算符的逻辑流。在一个实现中,主节点116接收分布函数调用300以执行分布运算符。在一个实现中,分布函数调用300可以表示为Distribute(vectorV,func newPartitionfunc)。向量V表示源向量,newPartitionfunc表示为向量V中数据确定新节点位置的函数。图7和此处的讨论使用向量U以利用符号帮助解释向量V中数据的分布。向量V与向量U包含相同的数据。分布函数调用300的结果是剩下一个向量,其可能划分成可以重新分布在不同节点集中的新组块。主节点逻辑260产生对应于向量V的每个向量组块的从任务(例如,从任务158)(702)。在一个实现中,从任务的数量等于向量V的向量组块的数量。从任务驻留在对应的向量组块所驻留的从节点上(704)。将从任务定位于对应的向量组块所驻留的从节点将数据传输最小化,并避免了网络带宽升级问题。从节点调用从节点逻辑212,以生成对应于向量U的向量组块的输出文件,其中GridBatch 100将重新分布向量V的记录(706)。从节点逻辑160评价V的对应向量组块的每个记录,以确定向量U的组块标识符,其中GridBatch 100将重新分布该记录。从节点逻辑160将记录写入对应于向量U的向量组块的输出文件,其中GridBatch 100将重新分布向量V的记录。
随着每个从任务完成了V的对应向量组块的记录的评价,每个从任务将从任务的完成状态和对应于向量U的向量组块的输出文件的位置通知给住节点逻辑260(708)。主节点逻辑260在从节点上产生新的从任务,GridBatch 100将向量V的向量组块重新分布至向量U的向量组块(710)。每个从任务接收输出文件的位置的列表,其包括对应于与从任务相对应的从节点的U的向量组块;并将输出文件取回至从节点(例如,使用远程拷贝操作或其他文件传输)。每个从任务将输出文件合并到U的对应向量组块中,并将从任务的完成状态通知给主节点逻辑260(712)。在一个实现中,分布函数调用300将第一向量的所有记录分布至所有可用的从节点。例如,表示为Distribute(vector V,func newPartitionfunc)的分布函数调用300的newPartitionfunc可以指引GridBatch 100将向量V的每个记录分布至所有可用的从节点,以在所有可用从节点上复制向量V。
图8示出了GridBatch 100可以用来执行联接运算符的逻辑流。在一个实现中,主节点逻辑260接收联接函数调用400以联接向量X和向量Y。在一个实现中,联接函数调用400可以表示为Vector Join(vector X,vector Y,FuncjoinFunc)(802)。主节点逻辑260产生对应于向量组块号(例如,向量组块id)的从任务,其中文件系统管理器逻辑222将向量X和向量Y划分成等量的向量组块,以及文件系统管理器逻辑222将对应的组块号或向量组块id指派给X的向量组块和Y的向量组块(804)。例如,文件系统管理器逻辑222可以将特定组块id指派给驻留在对应从节点上的X的向量组块和Y的向量组块。在一个实现中,从任务根据索引字段值对驻留在对应从节点上的X的向量组块的记录和Y的向量组块的记录进行排序(806)。从任务调用从节点逻辑160,并评价X的向量组块的记录的索引字段值和Y的向量组块的记录的索引字段值。在X的向量组块的记录的索引字段值和Y的向量组块的记录的索引字段值相等的情况下(808),GridBatch 100调用用户定义的联接函数(例如,用户定义的函数276)。在一个实现中,用户定义的联接函数可以表示为RecordioinFunc(Record Z,Record K),其将X的向量组块的记录和Y的向量组块的记录联接起来(814)。在从节点逻辑160评价X的向量组块的记录Z的索引字段值小于Y的向量组块的记录K的索引字段值时,则从节点逻辑160评价X的向量组块的下一记录Z与Y的向量组块的记录K的索引字段值(810)。在从节点逻辑160评价X的向量组块的记录Z的索引字段值大于Y的向量组块的记录K的索引字段值的情况下,从节点逻辑160评价Y的向量组块的下一记录K与X的向量组块的记录Z的索引字段值(812)。从节点逻辑160评价X的向量组块的每个记录Z与Y的向量组块的记录K(816)。
图9示出了GridBatch 100可以用来执行卷积运算符的逻辑流。在一个实现中,主节点逻辑260接收卷积函数调用500以处理向量X和向量Y(902)。在一个实现中,卷积函数调用500可以表示为Vector Convolution(vector X,vector Y,Func convFunc),其中ConvFunc是用户定义的卷积函数。对于向量X的向量组块的每个记录1-Z,主节点逻辑260将用户定义的卷积函数(例如,用户定义的函数276)(表达为Record convFunc(Record Z,Record K))应用于向量Y的向量组块的记录1-K(904)。换言之,在向量X的向量组块具有Z个记录且向量Y的向量组块具有K个记录时,用户定义的卷积函数评价记录配对的Z×K个置换。从节点逻辑160将用户定义的卷积函数应用于向量Y的每个记录1-K(906)与向量X的每个记录1-Z(908)。
图10示出了GridBatch 100可以用来执行递归运算符的逻辑流。在一个实现中,主节点逻辑260接收对递归向量X的递归函数调用600。在一个实现中,递归函数调用600可以表达为Record Recurse(vector X,Func recurseFunc)。主节点逻辑260产生与驻留在对应从节点上的每个向量组块相对应的递归运算从任务。从任务调用从节点逻辑160以归约(例如,合并)驻留在对应从节点上的向量X的向量组块的第一记录和第二记录。从节点逻辑160存储中间递归(例如,合并器)结果(1004)。从节点逻辑160评价是否存在向量X的向量组块的多个记录(1006),并将向量X的向量组块的下一记录合并至中间合并结果(1008)。一旦从节点逻辑160获得向量X的向量组块的中间合并结果,每个从任务将从任务的完成状态通知给从节点逻辑260(1010)。从任务的子集(例如,二分之一)发送中间合并结果给具有本地中间结果的其余从任务(例如,另外二分之一)。接收中间合并结果的从任务的子集将中间合并任务与本地中间合并结果相合并(1012)。具有中间合并结果的从节点迭代地将中间合并结果放入较少的从节点,直到从节点将越来越少量的中间合并结果并入一个从节点上驻留的最终合并结果(1014)。
图11示出了在处理映射函数调用1100(例如,任务请求244)以及实施映射运算符逻辑278期间的GridBatch 100。映射运算符可以表示为Vector Map(vector V,Func mapFunc),其中V代表向量,更具体地,代表将对其应用mapFunc以获得向量V的映射记录的新向量的向量记录。映射运算符允许用户将用户定义的函数应用于向量的所有记录。在一个实现中,主节点逻辑260接收具有参数的映射函数调用1100,这些参数包括第一向量标识符272和用户定义的映射函数(例如,用户定义的函数276)。第一向量标识符272识别被划分成第一向量组块的第一向量(例如,V1C1 1104、V1C2 1108和V1C3 1110),这些向量组块对应于在GridBatch集群102的节点上分布的已划分向量组块。第一向量组块包括第一向量组块记录(例如,V1C1R1 1116、V1C1RX 1118、V1C2R1 1120、V1C2RY 1122、V1C3R4 1124、和V 1C3RZ 1126)。
主节点116在对应于第一向量组块的节点集(例如,从节点11128、从节点41130和从节点61132)本地发起产生映射任务(例如,从任务158)。箭头1136代表节点状态的转变,其中具有第一向量组块的每个节点运行映射任务1134(例如,并行运行的映射任务1150、1152和1154)。映射任务1134将用户定义的映射函数应用于第一向量组块的每一个,以产生形成向量M的映射后的向量组块的映射后向量组块。箭头1158表示节点状态的转变,其中具有第一向量组块的每个节点包括具有对应的已映射向量组块记录(例如,VMC1R1 1166、VMC1RX 1168、VMC2R1 1170、VMC2RY 1172、VMC3R4 1174、和VMC3RZ 1176)的对应的已映射向量组块(例如,VMC1 1160、VMC2 1162、和VMC3 1164)。
例如,销售记录向量1180可以包括客户ID、产品ID和购买时间字段,以及若干其他字段。然而,对于特定分析,仅对销售记录向量的两个字段(诸如客户ID和产品ID)是感兴趣的。为了高效处理性能,程序员可以调用映射函数调用1100来执行映射运算符,以便只从销售记录向量提取客户ID字段和产品ID字段;映射函数调用1100可以用以下形式表示:Vector newVector=Map(saleRecordVector,chop)。用户定义的chop函数对销售记录向量1180的每个记录进行解析,以产生只包括newVector 1182记录中客户ID字段和产品ID字段的新记录。
图12示出了GridBatch 100可以用来执行映射运算符的逻辑流。主节点逻辑260将映射函数调用1100接收至映射向量V(1202)。主节点逻辑260产生对应于向量V的每个向量组块的从任务(1204)。从任务调用从节点逻辑160来定位指派给对应的从节点的向量V的每个向量组块(1206)。对于向量V的每个向量组块,从节点逻辑160将用户定义的mapFunc应用于每个向量组块记录,以产生形成向量M的映射后的向量组块的映射后的向量组块记录(1208)。一旦从节点逻辑160已经将mapFunc应用到向量V的每个向量组块记录,则每个从任务将从任务的完成状态和M的对应映射后的向量组块的位置通知给主节点逻辑260。映射运算符在从节点向主节点通知所有从任务已完成时成功完成(1210)。向量M的已映射向量组块组合以形成新的向量M。
图13示出了在处理块函数调用1300(例如,任务请求244)实施块运算符逻辑280期间的GridBatch 100。块运算符可以表示为Vector BLO(Vector X,Func bloFunc),其中X代表输入向量,更具体地,代表向量X的记录,bloFunc将对其进行应用以获得块函数评价结果,该结果代表用于形成新向量Z的块函数评价记录的值。块运算符允许用户将用户定义的函数应用于向量组块的所有记录。在一个实现中,主节点逻辑260接收具有参数的块函数调用1300,这些参数包括第一向量标识符272和用户定义的bloFunc函数(例如,用户定义的函数276)。第一向量标识符272识别划分成第一向量组块的第一向量(例如,V1C1 1304、V1C2 1308和V1C3 1310),这些向量组块分布在GridBatch集群102的节点上。第一向量组块包括第一向量组块记录(例如,V1C1R1 1316、V1C1RX 1318、V1C2R1 1320、V1C2RY 1322、V1C3R4 1324、和V1C3RZ 1326)。
主节点136在对应于第一向量组块的节点集(例如,从节点11328、从节点41330和从节点61332)本地发起块任务(例如,从任务158)的产生。箭头1336代表节点状态的转变,其中具有第一向量组块的每个节点运行块任务1334(例如,并行运行的块任务1350、1352和1354)。块任务1334将用户定义的bloFunc函数应用于第一向量组块记录的每一个,以产生用于第一向量组块的每一个的块函数评价结果。块函数评价结果(例如,VBC1 1360、VBC2 1362、和VBC3 1364)代表用于块函数评价记录(例如,VBC1R1 1366、VBC2R1 1368、和VBC3R1 1370)的值,这些记录形成新向量Z。箭头1358表示节点状态的转变,其中具有第一向量组块的每个节点包括具有对应的块函数评价结果(例如,VBC1 1360、VBC2 1362、和VBC3 1364),这些结果是用于向量Z的块函数评价记录(例如,VBC1R1 1366、VBC2R1 1368、和VBC3R1 1370)的值。例如,用户定义的bloFunc函数可以对向量X 1372的每个向量组块的记录数量计数,以形成新向量Z的块函数评价记录1374。
表2示出了GridBatch如何实现用户定义的bloFunc函数以对划分(例如,向量组块)内记录数量进行计数。当程序员实现将被递归调用的用户定义的bloFunc函数(如表2所示)时,用户定义的函数实现计数划分算法。例如,用户定义的bloFunc函数可以接受向量分组的记录的迭代子(iterator)、对输入迭代子中记录数量进行计数,以获得块函数评价结果,以及产生具有用于向量Z的计数值的记录(例如,块函数评价记录)。
表2-用于对划分的记录数量进行计数的用户定义的函数 |
bloFunc(Iterator records)/**向量分组的记录的列表**/int count=0;for each record x in recordscount++EmitResult(Vector Z,count) |
表2中所示用户定义的bloFunc函数对输入迭代子中的记录数量进行计数,并将计数值作为向量Z中的记录包括进来。每个向量分组产生向量分组记录计数值(例如,块函数评价结果)。为了确定向量中记录数量的总计数,可应用递归运算符以将向量Z的块函数评价记录中的所有值(例如,块函数评价结果)相加。用户定义的bloFunc函数可以同时应用于大文件的向量组块。在一个实现中,可以顺序处理驻留在块的同一节点上的向量分组。如果需要,GridBatch可以在执行块运算符之前执行划分运算符和/或分布运算符,以确保向量分组记录的分布(例如,基于每个向量组块记录内感兴趣数据的值的分布、划分和/或节点的数量)。
在一个实现中,可以使用块运算符来优化中值计算。例如,块运算符可以用来在用于大型财务服务公司的数据仓库应用中执行中值计算。具有上千万客户的公司可能对收集并报告关于每个客户的平均和中值账户余额的高层统计感兴趣。统计可以来自于很多不同维度的公司的客户基础(例如,在年龄组20-30岁中、30-40岁中)和/或是跨行业的(例如,零售业和高等教育业)。公司可以对很多维度的组合感兴趣,诸如跨越任一行业内的年龄组,和/或跨越任一地理区域内的工作任期长短。在一个实现中,这种统计的计算涉及具有上千万行的大型事实表,并且每一行保有与特定客户相关的全部信息,包括:账户余额;客户生日;行业;地理;工作任期长短和教育。计算平均值仅需要简单地相加出总和并将其除以计数。然而,计算“中值(median)”更加复杂,因为计算中值涉及顺序处理。一个方法是对所有数据进行排序而后找到中间点。两个步骤在本质上都是顺序的,所以它们需要很长时间才能针对大型数据集而完成。在计算中值是大量中值计算时,其变得更加复杂。
今天,大部分企业经常使用数据库来解决大型数据仓库应用计算,诸如中值计算。例如,一旦将事实表加载至数据库,则针对该事实表执行SQL语句,以计算正好是中值的50%值。尽管该SQL语句编写简单,但是在执行查询之前对数据进行分段是复杂的。例如,为对应于同一年龄组中客户的四个年龄组(例如,20-30岁,30-40岁,40-50岁和50岁及以上)的行计算中值必须在为每个年龄组计算中值之前对其进行归组。一种根据年龄组对行进行归组的方式在于,将条件(例如,where子句)包括在SELECT语句中,其指定客户生日日期的范围,使得随后可以从该组计算出中值。然而,可能需要四个单独的查询,每一个查询用于一个年龄组(例如,20-30岁,30-40岁,40-50岁和50岁及以上),并且数据分四路进行处理,其中每一路都会读取完整数据集。
用来为四个年龄组计算中值的另一方法在于使用GROUP BY子句,来将同一年龄等级中的所有行归组在一起。为了能让GROUP BY工作,年龄范围内的所有行必须具有带有相同值的公共栏。可以使用ETL(提取、变换、加载)工具来添加附加的栏(例如,年龄组栏),其中同意年龄组值被指派给同一年龄组中的所有行。例如,代表年龄在20-30之间的客户的行可以被指派为1的年龄组值,而代表年龄在30-40岁之间的客户的行可以被指派为2的年龄组值。这种方法需要多个三轮通过(pass),其中第一轮读取数据集,第二轮将具有附加栏的已变换数据集写入阶段表,而第三轮为GROUP BY查询读取数据集。然而,第三轮需要为每个年龄组重复。将用于大型数据集的路径数量最小化是关键的,因为从数据库读取数据和向数据库写入数据耗时最多。
利用块运算符,中值计算可以在两轮通过中完成。在一个实现中,块运算符使用三步来计算中值并最小化了通过的次数(例如,记录读取和/或写入)数量、网络和本地带宽使用。
在一个实现中,块运算符逻辑280包括识别代表有序数据划分的分离点(split-point)。识别分离点是为了确保向量分组大小基本上均匀地分布,以便最大化并行性。对于将为其计算中值的值而言,如果分布(例如,账户余额的分布)是已知的,则可以标识分离点。备选地,预处理可被执行以收集感兴趣的值的分布(例如,账户余额)。GridBatch标识分离点,这些分离点确保每个向量组块足够小以适合于存储器。块运算符将输入数据作为迭代子提供至用户定义的函数bloFunc。
GridBatch确保向量组块大小足够小,以便确保bloFunc用户定义的函数能够在存储器中缓存将由bloFunc用户定义的函数处理的所有数据。
在一个实现中,GridBatch根据以下三步为整个数据集计算一个中值(例如,所以客户的中值年龄)。步骤1,GridBatch将记录划分成向量组块,使得用来计算中值的感兴趣的值(例如,客户年龄)位于给定向量组块的两个分离点之间。bloFunc用户定义的函数在向量组块中的所有数据内迭代,以对向量组块中记录的数据进行计数。步骤2,对向量组块的计数聚集。中值的排名是根据从将向量组块的技术相加得到的总数确定的。中值所在的向量组块和中值在该向量组块内的排名是已知的,因为分离点标识了向量组块的顺次次序,并且从而标识了每个向量组块内内阁值的有序排名。例如,在中值被确定位于向量组块c和排名r中的情况下,以及在排名r是向量组块记录的有序顺序中的位置的情况下,中值被标识为排名r处的向量组块的值。步骤3,向量组块c中的数据被排序,并随后识别出第r个数字,其便是中值。
为了确定数据集内的多个中值(例如,多个年龄组20-30岁、30-40岁、40-50岁和50岁及以上的每一个的中值),可以为每个年龄组使用计数器。在以上步骤1和3中,用于每个年龄组的计数器仅在记录属于该计数器的年龄组时增长。GridBatch在步骤1和步骤3中扫描数据一次,以及数据存储在步骤3中一次。
GridBatch计算划分次数一次,并利用已划分的数据结构。预先划分数据的能力使得GridBatch能够提供巨大的性能收益。中值数目的增加增大了GridBatch用来计算多个中值分组和分组划分配置的数目。块运算符处理的中值数据的量增大中值的数量,这与增大行数具有类似的后果。
表3示出了GridBatch可以如何实现用户定义的bloFunc函数来计算划分内的多个年龄等级的中值(例如,多个年龄组的中值)。表3示出了向量X的记录列表属于同一划分(例如,向量组块),使得该划分针对该记录的列表内的所有记录标识一次。
表格3-用于计算多个中值的用户定义的函数 |
bloFunc(list of records X):p=partition(X)for each x in Xfor each bracket bif(x in b)cp,b++/**针对等级b,对划分p中的记录进行计数**/for each bracket bEmitResult(b;p,cp,b) |
表4示出了GridBatch可如何实现用户定义的bloFunc函数以确定划分内多个中值的值。
表4-用于确定中值的用户定义的函数 |
bloFunc(list of records X): |
表4-用于确定中值的用户定义的函数 |
p=partition(X)/**p划分**/sort X by account balancefor each bracket b/**b等级**/if(p==pb)/**划分p的pb等级**/find rbth value in bracket b/**找到等级b内的排名后的值,该值对应于中值**/EmitResult(b,rbth balance) |
图14示出了GridBatch 100可以用来执行块运算符的逻辑流。主节点逻辑260接收块函数调用1400以将用户定义的bloFunc函数应用(例如,计算向量组块中记录的数量)至向量X的向量组块的记录(1402)。主节点逻辑260产生对应于向量X的每个向量组块的从任务(1404)。从任务调用从节点逻辑160以定位指派给对应从节点的向量X的每个向量组块(1406)。对于向量X的每个向量组块,从节点逻辑160将用户定义的bloFunc应用于每个向量组块记录,以获得用于每个向量组块的块函数评价结果(例如,向量组块记录计数),用于形成向量Z的块函数评价记录(1408)。一旦从节点逻辑160已将bloFunc应用于向量X的每个向量组块记录,每个从任务向主节点逻辑260通知从任务的完成状态和Z的对应向量组块的位置。块运算符在从节点向主节点通知所有从任务已完成时成功完成(1410)。向量X的块函数评价结果(例如,每个向量组块的记录计数)用作用于向量Z的块函数评价记录。
GridBatch提供的附加运算符对于并行编程技术产生了意想不到的良好结果。具体地,相比于在应用并行化方面进行尝试的现有技术,每个运算符提供了显著的优势。意想不到的良好结果包括显著附加编程灵活性、效率和适用性,以解决现代企业面临的极难问题,该问题具体上是在现实时间期限内必须处理庞大数据量,从而取得有意义的结果。
MapReduce编程模型实现单一编程结构。具体地,映射函数总是与归约函数配对。另一方面,GridBatch提供多个独立运算符:递归、卷积、联接、分布、映射和块,程序员实际上可以以任何次序或顺序来构建在很多节点上并行执行的复杂应用。此外,GridBatch框架实现了为独立运算符指定的用户定义的函数,程序员可以给予很大程度的自定义功能。这种用户定义的函数包括划分函数,用来确定如何将向量细分成向量组块;散列函数,用来在节点间分布向量组块;联接函数,用来指定如何组合记录;卷积函数,用来支持联接函数;递归函数,其指定如何将递归运算符的部分结果合并;映射函数,用于应用于向量的记录;以及块函数,其规定如何将运算应用于给定划分的记录。
此外,需要注意,系统执行可以代表底层物理对象的数据的电学变换。例如,主节点逻辑、从节点逻辑和分布运算符逻辑通过选择性控制的分布,将离散任务请求变换成多个高度分散的并行任务。主节点逻辑、从节点逻辑、作业调度器逻辑、卷积运算符逻辑、递归运算符逻辑、映射运算符逻辑和块运算符将高度分散的并行化任务转换成离散结果。这些离散结果可代表大量物理对象,仅作为示例包括图像、视频、财务清单(例如,信用卡、银行账户和抵押清单)、电子邮件消息、用于制造的原材料、成品和半成品或者任何其他物理对象。
另外,系统可以实现为特定机器。例如,特定机器可以包括CPU、GPU和用于完成上述主节点逻辑的软件库。特定机器可以包括CPU和具有上述主节点逻辑和从节点逻辑的GPU。将结合主节点逻辑描述的用户定义的函数并入可以包括:将处理上述调度、组合、转换、移位、聚集、映射和分布逻辑的函数调用从软件库构建至应用中。然而,应用可以以其他方式扩展,以便引起与系统的交互。
已经描述了很多实现。不过,应当理解,可以在不脱离本发明精神和范围的前提下,进行各种改进。因此,其他实现落入所附权利要求的范围内。