一种残膜回收机防缠绕挑膜装置的制 一种秧草收获机用电力驱动行走机构

用于最短路径图搜索的向量化的队列的制作方法

2022-11-12 21:21:41 来源:中国专利 TAG:


1.本发明涉及查询图数据库数据,并且更具体而言涉及使用向量化的操作在图数据库数据内执行最短路径图搜索,以及执行高效的基于向量的数据移动。


背景技术:

2.图处理是用于数据分析的重要工具。具体而言,数据实体之间的细粒度关系在图数据库中被具体化为图节点(或简称为“节点”)之间的图边(或简称为“边”)。可以查询和分析由节点表示的关于实体的信息以及由边表示的关于实体之间的关系的信息以获得对所表示的数据的洞察。
3.图处理包括两种主要方法:(a)分析/算法,和(b)模式匹配查询。图算法(诸如pagerank)迭代地探索图数据以识别图中编码的信息,并且可以聚合识别出的信息。相比之下,模式匹配查询为图的交互式探索提供接口,类似于结构化查询语言(sql)为关系数据库提供的接口,重点是探索数据中的联系。为简单起见,本文的术语“图查询”是指图查询和模式匹配。虽然对图分析进行了大量研究,但图查询引起的关注却少得多。尽管如此,图查询对于工业来说是个非常重要的工具,正如大量可用的图查询引擎和语言所指示的那样。
4.图查询是具有挑战性的工作量,因为它们专注于图数据中的连接。寻找图数据中从一个或多个源节点到一个或多个目的地节点的(一条或多条)最短路径(本文称为最短路径图搜索或最短路径问题)是图论中的关键问题。这是计算和存储器昂贵的问题,并且在如图数据库、搜索引擎或社交网络等各种各样的系统中有许多应用。一些用例包括道路网络中的寻路、欺诈检测或计算机网络中的路由。在此类应用中使用的最短路径图搜索技术的效率极大地影响了应用本身的效率。
5.最短路径问题有多种变体。最短路径可以或者构成1)从源节点到目的地节点的边最少的路径-即,它具有最小的跳距(在由边直接连接的两个节点之间执行跳);或2)路径的边的权重之和最小的路径-即,所谓的“最便宜的路径”。图1描绘了具有节点a-f和表示节点之间关系的边(与权重相关联)的示例图数据100。在图1中,从节点a到节点b的最短路径(跳数最少)是a-d-b,而从节点a到节点b的最便宜的路径是a-e-d-b。
6.关于源节点和目的地节点的数量还有进一步的变化。单对最短路径问题涉及单对节点(如上面解释的从节点a到节点b的最短路径搜索),涉及从一个源节点到一个目的地节点的最短路径。单源最短路径问题涉及图中从一个源节点到多个目的地节点中的每一个(直至所有其它节点)的最短路径。单目的地最短路径问题涉及从图的多个源节点(直至所有节点)中的每一个到一个目的地节点的最短路径。全对最短路径问题涉及从图的多个源节点中的每一个(直至所有节点)到图的多个目的地节点中的每一个(直至到所有其它节点)的最短路径。最短路径问题通过多种图分析普遍存在,照此,最短路径问题的已实现的解决方案的有效性极大地影响了相关联的图分析是否被高执行。
7.最短路径图搜索算法基于图的物理表示而存在显著差异。图可以经由邻接矩阵或经由邻接列表来表示。在邻接矩阵类型的图表示中,矩阵的每个元素表示所表示图中的关
联节点对是否相邻(或是邻居),即,通过一跳连接。矩阵表示对于不随时间改变的密集图工作良好。但是,矩阵类型的图表示一般用于表示相对小的图数据集,因为邻接矩阵的存储器消耗是基于所表示图中节点数的二次方。因此,矩阵样式的图表示对于甚至中型图数据集一般就是不切实际的,更不用说对于大型图形数据集,因为中型到大型数据集的邻接矩阵的存储器需求一般超过可用存储器。
8.在邻接列表类型的图表示中,对于所表示图中的每个节点,表示给定图的一个或多个邻接列表包括相应节点的邻居节点的相应子列表。邻接列表类型的图表示的存储器需求是线性的,基于所表示图中的节点数。照此,对于大型图数据集,列表类型图表示使用的存储器比矩阵类型图表示所需的存储器少。
9.一般而言,广度优先遍历策略被用于解决最短路径问题。这种技术迭代地扩展可以从源节点到达的已知节点集,直到或者(a)到达目的地节点,或者(b)源节点可到达的节点集无法进一步扩展。在后一种情况下,图数据中没有从源节点到目的地节点的路径。
10.此类策略的实施方式一般维护散列表来记录哪些节点已经被访问过。此类实施方式一般还维护两个队列;一个队列记录在当前迭代中被扩展的节点集,而另一个队列记录将在下一次迭代中被扩展的节点集。
11.以下伪代码1说明了最短路径图搜索的标量实施方式:
12.[0013][0014]
伪代码1:标量shortest_path()
[0015]
在伪代码1的第1-2行中,函数graph::shortest_path将源节点(node0)和目的地节点(node1)以及状态对象(vs)作为输入参数。状态对象保存函数所需的数据结构(即,队列,以及无序集,一般被实现为散列表)并被用于避免在每次调用函数时创建和销毁这些数据结构。在第4-5行,如果给定节点作为源节点和目的地节点被传递,那么函数返回距离0。在第6-8行,无序集和两个队列被指派给变量visited、cur_queue和next_queue。所有这三个数据结构在函数开始时都是空的。在第9行,保持距离的变量dist最初设置为0,并将起始节点添加到下一个队列。
[0016]
此后,在第13-40行,伪代码1在外循环中迭代,直到或者找到目的地节点(第27-29行),或者下一个队列为空(第13行)。在后一种情况下,没有从源节点到结束节点的路径并且返回-1(第43行)。在外循环的每次迭代中,距离增加一(第17行),并交换cur_queue和next_queue的内容,即,通过将next_queue的所有节点指派给cur_queue,从而清空next_queue(第15行)。此后,获取cur_queue的节点(第20行),并且伪代码1在内循环中在所获取的节点的所有邻居节点上迭代(第19-39行)。在第22行,获取的节点从cur_queue被删除。在内循环中,伪代码1检查每个邻居节点是否是目的地节点-在这种情况下返回dist并终止函数(第27-29行)-如果不是,那么探测该节点是否已经在visited散列中表(第32行)。如果节点之前没有被访问过,那么伪代码1将邻居节点添加到next_queue和visited散列表中(第33-38行)。
[0017]
此类标量最短路径图搜索要求检查每个节点是否是目的地节点以及该节点之前
是否被访问过。这些功能要求多次触摸队列中的每个节点,这可以是耗时的。此外,最短路径图搜索的标量实施方式包括不可预测的条件,这些条件限制了指令级并行性和高速缓存预取。这些是在使用时提供巨大的性能优势的现代cpu的两个重要特征。
[0018]
向量化已经以一些有限的方式被使用,以减少用于最短路径图搜索的每个所需操作都接触每个节点的需要。但是,向量化的最短路径图算法一般被配置为对邻接矩阵起作用(即,它们依赖于距离矩阵作为输入)。如上面所指示的,基于邻接矩阵的图数据的表示不能很好地扩展,照此,不太适合大型图数据集。将最短路径图数据搜索向量化以用于邻接列表类型的图表示以更好地促进对大型数据集的高效最短路径图搜索将是有益的。
[0019]
本节中描述的方法是可以采用的方法,但不一定是先前已经设想或采用的方法。因此,除非另有说明,否则不应仅由于将本节中所述的任何方法包括在本节中而认为本节中的任何方法有资格作为现有技术。另外,不应当假设本节中描述的任何方法仅因其包括在本节中就是易于理解的、例行的或常规的。
附图说明
[0020]
在附图中:
[0021]
图1描绘了由图数据库管理系统维护的示例图数据,带有节点和边。
[0022]
图2是描绘用于图数据库管理系统的示例布置的框图。
[0023]
图3描绘了用于将值插入向量中的流程图。
[0024]
图4a-图4c描绘了向量和对该向量执行的示例向量化的比较操作。
[0025]
图5描绘了将值插入向量中的向量化的操作的集合。
[0026]
图6描绘了在八个步骤中填充单个向量的向量化的操作的集合。
[0027]
图7描绘了用于增加特定散列表的桶的基数以产生扩展散列表的流程图。
[0028]
图8a-图8b描绘了向量和将该向量的内容拆分到两个向量中的向量化的操作的集合。
[0029]
图9a-图9c描绘了散列表从一个桶增长到两个桶、从两个桶增长到四个桶,以及从四个桶增长到八个桶。
[0030]
图10描绘了用于执行三阶段最短路径图搜索的流程图。
[0031]
图11描绘了由图数据库管理系统维护的示例图数据,带有节点和边。
[0032]
图12描绘了用于执行基于向量的数据复制的流程图。
[0033]
图13描绘了执行从示例邻接列表到当前队列的基于向量的数据复制的向量化的操作的集合。
[0034]
图14a-图14b描绘了用于实验的数据集的特点,以及通过本文描述的向量化的最短路径技术实现的针对各种数据集的加速。
[0035]
图15描绘了可以在其上实现实施例的计算机系统的框图。
[0036]
图16描绘了可以用其实现实施例的软件系统。
具体实施方式
[0037]
在以下描述中,为了解释的目的,阐述许多具体细节以提供对本发明的透彻理解。但是,明显可以在没有这些具体细节的情况下实践本发明。在其它情况下,众所周知的结构
和设备以框图形式示出以避免不必要地混淆本发明。
[0038]
总体概述
[0039]
本文描述的技术用于利用向量化的队列的三阶段最短路径图搜索技术,其针对图处理进行了优化并且具有低初始化成本。本文描述的向量化的操作是使用向量化的指令执行的,每条指令基本上同时对给定向量中的所有值执行一个或多个操作(其中向量是存储在地址空间内的连续存储器地址中,或连续存储在寄存器内的值的集合)。例如,应用于特定向量的向量化的相加指令基本上同时将特定值与特定向量的所有值相加,而不需要对向量的值进行迭代。
[0040]
根据实施例,向量化的队列还具有低实施方式复杂性,因为向量的实施方式重用已知的向量数据结构(例如,c 标准模板库(stl)的)或来自另一个源的可比较的数据结构。向量化的队列从基本数据结构继承“clear”和“swap”函数。另外,向量化的队列可以集成到图引擎的现有队列数据结构中。根据实施例,向量化的队列实现向量化的“contains”函数,该函数快速确定给定值是否包含在队列中。本文描述的向量化的队列技术适用于对图数据执行的各种任务(诸如未加权和加权的最短路径搜索、广度优先搜索、最小生成树搜索、拓扑排序等),支持16位、32位和64位节点标识符,适用于任意向量宽度k,并且根据实施例,针对avx-512指令集进行了优化。
[0041]
此外,本文描述了用于对使用基于邻接列表的表示来表示的图进行向量化的最短路径图搜索的技术,其可容纳在现实世界应用中常见的大型图数据集。这些技术将最短路径图搜索所需的扩展和探测迭代拆分成三个阶段。在第一阶段,使用向量化的指令获取下一个队列中的节点的邻居节点并将其写入当前队列。在第二阶段,经由向量化的指令确定是否在当前队列中获取的邻居节点内找到了目的地节点。在检查这些节点是否已被访问(在第三阶段执行)之前在当前队列中搜索目的地节点避免了对节点是否已被访问的不必要检查,即,在其中在获取的邻居当中找到目的地节点的最后一次搜索迭代中。在第三阶段,获取的尚未被访问的邻居节点被放入下一个队列。
[0042]
将主循环拆分成多个阶段显著提高了指令级并行性,因为每个阶段具有较少不可预测的分支。具体而言,现代cpu常常一次执行多个指令(而不是一次一个),这大大地提高了利用这个特征的应用的性能。这种并行执行与向量级并行性类似,但是,代替在多个数据元素上运行一个指令,指令级并行性并行地运行指令。指令级并行性可以大大地有利于循环的实施方式,但如果循环中包括不可预测的条件,那么常常无法使用。
[0043]
根据实施例,上述向量化的队列(以保持当前和下一组图节点)与向量化的最短路径图搜索技术结合使用。
[0044]
根据实施例,向量化的复制操作使用向量化的加载和存储指令来执行基于向量的数据复制。具体而言,为了将目标数据的一个或多个非连续部分从源复制到目的地,数据的向量从源复制到目的地。在源处存储目标数据的非连续部分,在目标数据部分之间存储非目标数据。
[0045]
当目标数据的第一部分的尺寸不是向量宽度k的倍数时,复制到目的地的目标数据的第一部分的最后一个向量包括不是目标数据的第一部分的一部分的无效数据的一部分。当目标数据的第二部分从源复制到目的地时,目标数据的第二部分的第一向量被覆写在目标数据的第一部分之后存储在目的地处的无效数据上。因此,目标数据的各个部分被
写到目的地,而在有效数据当中没有剩余无效数据。根据实施例,在目标数据的最后部分被复制到目的地之后,随机数数据的向量被复制到在目标数据的最后部分之后被复制到目的地的任何无效数据上,其中随机数数据不可解释为有效数据。例如,如果有效数据包括非负整数,那么随机数据可以包括
“‑
1”值。根据实施例,这种基于向量的数据复制被用于本文描述的最短路径图搜索技术,以将邻居节点标识符从邻接列表复制到用于搜索的当前队列。
[0046]
数据库系统概述
[0047]
本文的实施例是在图2的数据库系统200的上下文中描述的,包括在单个设备(即,单节点数据库系统)上运行的单个数据库服务器实例。不过,本文描述的技术可以由数据库系统的任何实施方式执行,例如,在包括访问相同共享存储装置的多个数据库服务器实例的多节点共享存储器数据库系统上,在在多个数据库服务器实例之间不共享的磁盘上维护数据库数据的多节点无共享数据库系统上,在包含为多个不同数据库提供服务的单个数据库服务器实例的多租户数据库系统上等。
[0048]
图2描绘了示例数据库系统200,其包括在计算设备210的易失性存储器212中运行的数据库服务器实例214。实例214在持久存储装置220中维护数据库数据222。图数据库实施方式的示例包括并行图分析(pgx)。(有关pgx的更多信息可以在“oracle spatial and graph:property graph developer's guide”,18c,e84313-01,2018年2月中找到,其全部内容并入本文,就像在本文完整阐述一样。)
[0049]
本文的实施例描述了由数据库系统200使用avx-512指令集执行的操作,其使用每条指令十六个32位整数值起作用,即,向量宽度k=16。但是,本文描述的用于向量化的图搜索的技术可以用其它向量指令集来实现。例如,本文描述的技术可以针对avx-512上的其它向量宽度运行,例如,针对每条指令具有八个或四个32位整数值的avx-512vl,或者针对每条指令容纳32或64个值的指令集,本文描述的技术还可以针对容纳其它值宽度的指令集运行,诸如64位值、128位值等。此外,使用c 风格的伪代码描述技术,但是可以在允许使用向量化的指令的任何系统中实现技术,如本文所述。
[0050]
本文的示例是使用基于单指令、多数据(simd)的指令来描述的,诸如avx-512指令集的指令。simd体系架构的存在允许具有多个处理元件的计算机同时对多个数据点执行相同的操作。simd体系架构可以主要执行“垂直”操作,其中单独操作数中的对应元素被并行和独立地操作。与垂直simd指令不同,水平simd指令跨simd寄存器的元素被执行。simd指令允许一次相同操作对多个数据元素的执行对准。
[0051]
向量化的散列表
[0052]
根据实施例,向量化的散列表根据需要使用向量化的操作高效地插入值并使表增长。图3描绘了根据实施例的用于将值插入向量中的流程图300。具体而言,在步骤302处,特定值被插入到包括多个值的向量中,其中多个值被连续地存储在向量的第一极端处。例如,计算设备210在易失性存储器212中维护具有单个桶400(图4a)的向量化的散列表,其中散列表的每个桶包括值的向量。本文使用整数值来描述实施例。但是,根据实施例,向量的值可以表示任何种类的信息。根据实施例,将特定值插入向量包括流程图300的步骤304-306。
[0053]
下面的伪代码2说明了实现向量化的散列表的实施例的simdhashset类。在本文描述的非限制性示例中,示例向量化的散列表是使用伪代码2实现的。
[0054][0055]
伪代码2:simdhashset
[0056]
伪代码2中描绘的实施例非常适合许多应用,包括下面更详细描述的最短路径图搜索。simdhashset类似于stl的c 无序集合容器。但是,实施例可以基于来自其它源的其它集合容器类型结构。本文描述的实施例支持整数数据类型,例如,64位、32位和16位整数值。但是,根据一个或多个实施例,也可以支持其它数据类型;根据实施例,向量的值可以表示任何种类的信息。
[0057]
伪代码2说明了类simdhashset的示例成员函数和变量。具体而言,类simdhashset包括以下成员变量:
[0058]
·
变量idx保持用于在插入新值时对桶中的值进行混洗的掩码,如本文中进一步详细描述的。
[0059]
·
变量mem保持用于桶的存储器。
[0060]
·
变量n_buckets保持当前使用的桶数。
[0061]
·
变量lsbits_mask保持用于获得用于给定值的散列值的掩码,其中散列值被用
于识别用于给定值的桶。
[0062]
构造函数分配用于桶的存储器并调用clear函数(如下所述)来初始化所有其它成员变量。所分配的存储器与向量尺寸对准,例如,在使用512位向量指令(例如,来自avx-512)时对准到64字节。当simdhashset实例被销毁时,析构函数释放所分配的存储器。
[0063]
下面的伪代码3描述了simdhashset的clear函数,它丢弃容器的所有值,从而有效地重新初始化simdhashset实例的成员变量。
[0064][0065]
伪代码3:clear()
[0066]
clear函数允许将向量化的散列表的实例重用于后续图搜索操作,即,避免为每个单独的图搜索创建和销毁向量化的散列表。
[0067]
如上面所指示的,clear函数重新初始化simdhashset的已建立的实例。初始状态包括其中没有值的单个桶。根据实施例,空槽指示符值(其是不包括在向量化的散列表的可能有效值(例如,正整数)的集合中的值,诸如“0”)填充桶的空槽。以这种方式标记空槽消除了维护指示存储在桶中的值的数量的任何计数器的需要。当空槽指示符值为“0”时,内在函数_mm512_setzero_si512被用于经由单条指令用“0”值填充第一个桶,其中内在函数是包括在由cpu(例如,设备210的cpu)实现的指令集中的函数。用于未来的桶的存储器不在clear函数中被初始化,因为这些桶在散列表增长时被初始化,如下文进一步详细描述的。
[0068]
向量化的插入操作
[0069]
根据实施例,向量化的散列表支持向量化的插入操作,如果值还不存在于散列表中,那么该操作将值插入到散列表的桶中。为了说明,下面的伪代码4描绘了类simdhashset的插入函数的实施例,其中插入函数对要插入的值进行散列,加载与散列结果对应的桶,并在桶尚未包含该值插入时将值插入到加载的桶中。
[0070][0071]
伪代码4:insert()
[0072]
图4a描绘了具有单个桶400的示例散列表,例如,其由设备210在易失性存储器212中维护。本文包括桶400的向量的描绘示出了具有k=8的向量宽度以简化说明,尽管本文表示的示例伪代码利用容纳k=16且地址为64字节对准的指令,
[0073]
在图4a的示例中,具有单个桶400的散列表被配置为存储非负整数,并且“0”是空槽指示符值。在这个实施例中,所有有效值在插入散列表中之前都递增一以允许有效值“0”的表示,即,在散列表中表示为“1”,同时使用“0”作为空槽指示符值。因此,只有空槽具有空槽指示符值“0”。如图4a中所示,向量中存储的值连续存储到桶400的左极端,并且存储到桶400右极端的空槽填充有“0”值。根据实施例,虽然本文的示例向量图示了将值压缩到向量表示的左极端,但是可以将值连续地存储到向量的右极端。
[0074]
对值进行散列并加载桶
[0075]
返回到对流程图300(图3)的步骤302的讨论,设备210确定将值“6”插入到桶400中。例如,值“6”是结合下面详细描述的最短路径搜索识别出的图节点的节点标识符。在准备将这个值插入到桶400中时,它递增一,即,从“6”到“7”。
[0076]
设备210对修改后的值“7”进行散列以确定与该值相关联的桶标识符(或b
id
)。根据实施例,散列函数是将要插入的值除以散列表的尺寸所得的余数,即,b
id
=(n
id
1)mod t
size
,其中t
size
是散列表的尺寸(伪代码4,第6-7行)。在图4a的示例中,散列表的尺寸为一,并且任何数模“1”都等于“0”。因此,插入到具有单个桶400的散列表中的所有值都映射到桶
400。为了进一步说明,对于要插入具有八个桶的散列表中的值“14”,值“14”递增到“15”并且,因为“15”mod“8”=“7”,所以该值插入到散列表的第七个桶中。
[0077]
根据伪代码4的第6-7行中描述的实施例,模运算是经由与lsbits_mask按位and实现的,以避免代价高昂的除法指令。掩码lsbits_mask为尺寸为2n的散列表设置了n个最低有效位,例如,对于具有八个桶的散列表它是111
(2)
,并且对于具有一个桶的散列表它是000
(2)
,等等。在伪代码4的第8-9行,加载与识别出的桶标识符对应的桶。
[0078]
确定对应的桶是否包含要插入的值
[0079]
设备210还确定要插入的值是否已经存在于桶400中。根据图4b中描绘的实施例,要插入的值经由指令_mm512_set1_epi32被复制到向量410(val_vec)的所有元素(伪代码4,第4-5行)。
[0080]
然后将向量410与存储在桶400中的向量进行比较。在伪代码4的第10行中,经由指令_mm512_cmpeq_epi32_mask执行比较,该指令对两个向量的值进行逐元素比较并返回位掩码。除了在被比较的向量当中对应值相等的位置(在这种情况下,对应的位被设置为1)之外,结果所得的位掩码的位被设置为0。为了使用图4b进行说明,存储在桶400中的向量和被复制的值向量410经由simd比较指令进行比较,该指令产生所有位都被设置为“0”的结果掩码420。所有位都未设置的结果掩码420指示要插入的值尚未在桶400中。
[0081]
在伪代码4第10行中,位掩码经由_mm512_mask2int转换成标量值430。标量值被用于控制是否将值插入到桶中的分支(第10-30行)。因为从结果掩码420计算出的标量值430是“0”,所以确定值“7”不在桶400中并且需要插入,下面将更详细地描述该操作。
[0082]
图4c进一步图示了与4b中相同的检查,但与将值“17”(递增到“18”)插入到桶400中有关。在图4c中,存储在桶400中的向量中和复制的值向量440(存储“18”)中的第三个位置处的两个值相等。结果所得的位掩码450是100
(
2)(省略前导零),它表示“4”的标量值460。因此,如由非零标量值460所指示的,值“17”已经在桶400中被表示并且不需要插入。在这种情况下,伪代码4第10行的条件将评估为false,并且该函数将返回false。
[0083]
确定桶是否满
[0084]
在确定要插入的值尚未在散列表中的情况下,如图4b中所示,确定识别出的桶中是否有空间可以插入该值。返回到流程图300(图3)的讨论,在步骤304处,确定向量中是否有一个或多个空槽。例如,设备210通过确定识别出的桶400是否包括任何空槽指示符值(例如,“0”)来确定识别出的其中值“7”应当被插入的桶400是否具有任何空槽。
[0085]
根据实施例,确定桶400是否包括任何空槽指示符值是经由simd比较来执行的,如上文结合检查要插入的特定值是否已经在给定桶中所述。具体而言,给定空槽指示符值“0”,在伪代码4的第12-13行,经由_mm512_setzero_si512创建其中复制了“0”的向量。如伪代码4的这些行中所示,在经由_mm512_cmpeq_epi32_mask比较零填充的向量与桶向量后,结果所得的位掩码经由_mm512_mask2int被转换成标量值。当桶中没有空槽时该标量值为零,而当至少有一个空槽时该标量值大于零。
[0086]
在伪代码4的第11-20行,如果桶中没有为要插入的值识别出的空槽,那么散列表增长以容纳该值,如下面进一步详细描述的。根据实施例,使用指数增长策略,其中散列表的尺寸在其增长的任何时候加倍。如下面结合伪代码5所描述的,在需要时调用私有成员增长函数以将散列表的尺寸加倍。增长函数使用先前描述的散列函数重新分配来自原始散列
表的桶的值。
[0087]
在伪代码4的第16-17行,在散列表已经增长到产生扩展散列表之后,映射到要插入的值的桶的桶标识符被重新计算。具体而言,散列表中值的位置可能已改变,因为散列函数基于扩展散列表的尺寸。例如,对于尺寸为四的散列表,值“7”被插入到第四个桶中(b
id
=3),而对于尺寸为八的散列表,它被插入到第八个桶中(b
id
=7)。在第18-19行,在计算出更新后的桶标识符之后,识别出的桶经由_mm512_load_epi32加载到向量桶中并且,返回到第12-13行,检查识别出的桶是否包含空槽。具体而言,在使散列表增长之后,散列表中的值的重新分配并不能保证之前已满的桶在增长操作之后会有空槽。因此,散列表继续进行增长操作,直到映射到要插入的值的桶至少有一个空槽。
[0088]
值插入
[0089]
一旦确定应当将值插入到散列表中,并且该表已经增长以容纳该值(如果需要),那么使用基于向量的指令将该值插入到由散列表中映射到该值的桶存储的向量中。再次返回到流程图300的讨论,在步骤306处,响应于确定向量中有一个或多个空槽,执行单个simd指令以执行:至少基于置换掩码,将向量中的多个值朝着向量的第二极端移位,并且至少部分地基于填充有特定值的值向量,将该特定值插入到向量的第一极端处。例如,设备210根据伪代码4的第21-23行将值“7”插入到桶400(图4a)中。在伪代码4中描绘的实施例中,使用单个simd指令_mm512_mask_permutexvar_epi32来移位识别出的桶中的值并将该值插入到桶中。
[0090]
图5描绘了_mm512_mask_permutexvar_epi32将值插入向量的功能,即,将“7”插入存储在桶400中的值的向量中。使用单个simd指令移位识别出的桶中的值并将值插入桶中优雅地解决了在桶中寻找下一个空闲槽的问题。具体而言,技术(a)不要求保持向量的尺寸的变量,而(b)要求恒定数量的指令,该指令数量与向量中的值的数量无关。
[0091]
根据实施例,向量中的所有值被一个接一个地(即,连续地)连续存储,随后是向量中的所有空槽。因此,向量中的有效值之间没有空槽。当在向量中插入值时,以及在散列表的情况下当在使散列表增长的同时重新分配值时,确保这个特性。具体而言,为了将值插入到向量中,所有的值在向量中移位一个位置,即,向量中第一个位置处的值移动到第二个位置,向量中第二个位置处的值移动到第三个位置,以此类推。移动值可以经由水平移位指令或混洗指令等来完成。因为在确定向量至少有一个空闲槽之后执行插入,所以只有空槽指示符值被移出向量并且没有大量值由于移位而丢失。在移位值之后,要插入的值被写入向量中的第一个槽。
[0092]
这种用于将值插入向量的技术消除了搜索空槽的任何需要。例如,因为空槽连续存储到向量的右极端,所以可以通过将向量中的值向右移位一个槽来确定性地创建用于新值的空槽。这些操作成本低廉,尤其是在使用向量化的指令执行时。
[0093]
如上面所指示的,伪代码4采用内在函数_mm512_mask_permutexvar_epi32来执行到向量中的值插入。内在函数采用四个参数:带值的向量(val_vec)、位掩码(_mm512_int2mask(0xfffe))、置换向量(idx,它是如上所述的类simdhashset的变量),以及第二个带值的向量(bucket)。位掩码控制从两个输入向量中的哪一个获取输出向量的给定值。如果从这个向量中选择值,那么置换向量控制采用第二个值向量的哪个值。
[0094]
图5图示了如何通过_mm256_mask_permutexvar_epi32将单个值插入到桶400中,
这是_mm512_mask_permutexvar_epi32的8通道版本(即,k=8)。在图5中,插入掩码502是用于从两个输入向量中的哪个输入向量中选择输出向量(更新后的桶510)中的值的位掩码,复制的值向量504是保持要添加到桶的复制的值的向量(伪代码4中的val_vec),置换向量506指示来自第二个向量的哪些值将被放置在输出向量中的哪些位置,而桶400表示要插入值的原始向量。
[0095]
如上面所指示的,桶400存储值“15”、“1”、“18”、“6”、“5”和“11”,并且在将值“7”添加到桶的操作的发起之前有两个空槽。插入掩码502是11111110
(2)
并且指示输出向量(即,更新后的桶510)的第一个值应当从向量504中获取。所有其它位都设置为“1”,这意味着输出向量的第二个到第八个值应当经由置换向量从保持桶400的值的向量中“获取”。例如,置换向量506的第二个值是“0”(使用基于0的计数),这意味着更新后的桶510的第二个值应当包含桶400的第一个值。类似地,置换向量的第三个值是“1”,这意味着更新后的桶510的第三个值应当包含桶400的第二个值,依此类推。在完成向量化的插入操作之后,更新后的桶510保持值“7”、“15”、“1”、“18”、“6”、“5”和“11”,剩余一个空槽。来自复制的值向量504和桶400向量的值加下划线以说明哪些值构成更新后的桶510的值。
[0096]
图6图示了如何在8个步骤中填充单个桶(k=8)。具体而言,第一插入操作602将值“7”插入到桶中的值的向量中。在操作602之前,桶不包含任何值。通过操作602,标记空点的零全部向右移一个到下一个向量槽。如以前一样,在每个插入操作完成之后属于桶的一部分的值都带有下划线。当对值“2”的操作604开始时,桶仅包含值“7”,该值与零一起向右移动一个到下一个向量槽。在操作604之后,桶包含值“2”和“7”。类似地,通过操作606将值“11”插入到桶中。尽管图6中未示出这些操作,但接下来的四个值以类似的方式插入到值的向量中。操作616将值“15”插入桶中,此时桶已满。每次插入时,一个空槽指示符值从向量中移出,并在向量的第一个位置插入新的有效(或实质性)值。
[0097]
向量化的生长操作
[0098]
如果散列表的映射到要插入的值的桶中没有空槽,那么使用向量化的指令使散列表增长以容纳该值。本文描述的向量化的增长技术使用向量化的指令仅对散列表的每个桶迭代一次以处置散列表中的所有值。根据实施例,每当值应当被插入到已满的桶中时,就调用增长函数,诸如下面伪代码5中的增长函数。根据实施例,散列表就地增长,使得将新桶添加到散列表的现有桶以产生扩展散列表,使得在为了增长操作而移动值时不需要附加的存储器。
[0099][0100]
伪代码5:grow()
[0101]
在第2-3行,伪代码5中描绘的增长操作创建向量split_bit_vec,用于将一个桶的值分区到两个桶中。在第5-18行,伪代码5在散列表的所有桶上迭代并将每个桶的值分区到新的扩展散列表的两个桶中。第13-17行中使用的内在函数_mm512_maskz_compress_epi32是向量化的指令,其计算用于扩展散列表中的新桶的值的向量。对于原始表的每个桶,这个向量化的指令的两个实例分别被用于生成(a)用于扩展表的“上”桶的值的向量和(b)用于扩展表的“下”桶的值的向量。基于是否设置了相应值的第m位,将输入桶的值在下桶和上桶之间划分,其中m=log2(n)和n表示扩展散列表中的桶的数量。
[0102]
更具体而言,_mm512_maskz_compress_epi32将输入向量和位掩码作为参数,并返回包括来自由位掩码选择的输入向量的值的向量(即,返回向量中的值是输入向量中与位掩码中的设置位对应的值)。返回向量中的值被连续存储并且返回向量的其余元素被设置为零,这是示例空槽指示符值。注意的是,将值在相应桶的极端处连续存储在结果所得的下桶和上桶中促进对上面详细描述的值进行向量化的插入。
[0103]
在伪代码5的第20行,变量n_buckets的值被加倍,并且在第21-22行,计算新的散列掩码(lsbits_mask)。注意的是,n_buckets保持散列表中的桶的数量,其中鉴于散列表的桶的数量n始终是2的幂,因此这个值的二进制版本仅将第m位设置为1。
[0104]
图7描绘了根据实施例的用于增加特定散列表的桶的基数的流程图700,该特定散列表包括桶集合,以通过对于桶集合的每个桶执行步骤702-710来产生扩展散列表。在步骤702处,基于用于扩展散列表的散列函数,第一simd指令实例被执行以产生用于相应桶的拆分掩码。为了说明,计算设备210在易失性存储器212中维护具有单个完整桶800(图8a)的向量化的散列表,该桶包含值“15”、“1”、“18”、“6”、“5”、“11”、“2”和“7”。设备210尝试将值插入散列表并发现桶800已满。因而,如图8b中所示,设备210将散列表从单个桶800增长到两个桶(上桶820和下桶830)。
[0105]
结合这个增长操作,设备210基于关于扩展散列表的散列函数计算拆分掩码,根据
实施例,该散列函数基于扩展散列表的尺寸。使用上面的伪代码5的示例散列函数,基于相应值的第m位是否被设置,输入桶800的值在下桶822和上桶820之间划分,其中m=log2(n)和n表示扩展散列表中的桶的数量。在示例散列表增长到两个桶的情况下,基于是否设置了相应值的第1位来划分值,其中1=log2(2)。换句话说,桶800的可以被2整除而没有余数的值(偶数值)被放在上桶820中,而其它(奇数)值被放在下桶822中。
[0106]
根据图8b中描绘的示例实施方式,拆分位向量810填充有在被扩展之前散列表的桶的数量(“1”值)。拆分位掩码812基于桶800中的哪些值在与拆分位向量810的对应值相同的位置处具有设置位来确定。因为散列表的尺寸是或者“1”或者“2”的倍数,所以在填充拆分位向量810的散列表尺寸值中始终只有一位被设置。因此,使用桶800的值和拆分位向量810,simd测试指令_mm512_test_epi32_mask产生拆分位掩码812(11001101
(2)
),这指示桶800的第3、第4和第7个值在被除以“1”时没有余数,而桶800的其它值在除以“1”时还有余数。
[0107]
在流程图700的步骤704处,至少部分地基于拆分掩码,执行第二simd指令实例,以识别相应桶中的多个值的第一值集合。另外,在步骤706处,用第一值集合填充扩展散列表的第一导出桶。例如,在伪代码5的第13-15行,simd压缩指令_mm512_maskz_compress_epi32的第一个实例使用否定的拆分位掩码814(其基于拆分位掩码812)产生包括来自桶800的与否定拆分位掩码814中的设置位对应的值(即,偶数值)的向量。该指令将所选择的值填充到扩展散列表的上桶820中数据的向量的左极端的连续槽中。
[0108]
在流程图700的步骤708处,至少部分地基于拆分掩码执行第三simd指令实例以识别多个值中的第二值集合。在步骤710处,用第二值集合填充扩展散列表的第二导出桶。例如,在伪代码5的第16-17行,simd压缩指令_mm512_maskz_compress_epi32的第二个实例使用拆分位掩码812产生包括来自桶800的与拆分位掩码812中的设置位对应的值(即,奇数值)的第二个向量。该指令将所选择的值填充到扩展散列表的下桶822中数据的向量的左极端的连续槽中。
[0109]
simd压缩指令_mm512_maskz_compress_epi32用空槽指示符值(例如,“0”)填充所产生的向量的空槽。
[0110]
图9a-图9c描绘了散列表900从一个桶增长到两个桶(图9a)、从两个桶增长到四个桶(图9b)以及从四个桶增长到八个桶(图9c)。如图9a中所示,表900的原始桶具有桶标识符“0”并且没有用于附加值的空槽。对表900执行增长操作以产生扩展表910。在扩展表910中,原始桶(现在只有原始值中的一些)保留桶标识符“0”,而新桶(具有原始桶的其余原始值)具有桶标识符“1”。来自表900的桶“0”的值基于值的相应最后位在扩展表910中被分区到桶“0”和“1”中,这实际上基于它们是奇数还是偶数来对值进行分区。因此,值“18”、“6”和“2”留在桶“0”中,而值“15”、“1”、“5”、“11”和“7”移入桶“1”。
[0111]
图9b描绘了已经被填充到桶“0”不再具有用于附加值的容量的点的散列表910。为了为当前映射到桶“0”的值腾出空间,将表910扩展为具有四个桶的表920。具体而言,基于值的倒数第二位(即,基于模4),表910的两个桶中的每一个被拆分成两个相应的导出桶。表910中桶“0”的值或者留在表920中的桶“0”中或者移动到表920中的桶“2”,而表910中的桶“1”的值或者留在表920中的桶“1”中或者移动到表920中的桶“3”。
[0112]
在对值进行分区之后,表920的桶“0”包含node
id mod 4(扩展表920中的桶的数量)
=0的所有值,表920的桶“1”包含node
id mod4=1的所有值,以此类推。在拆分之后,桶“0”包含值“12”、“28”和“8”;桶“1”包含值“1”和“5”;桶“2”包含值“18”、“6”、“2”、“22”和“14”;并且桶“3”包含“15”、“11”、“7”和“3”。
[0113]
图9c描绘了已经被填充到桶“0”和“3”不再具有用于附加值的容量的点的散列表920。为了添加当前映射到桶“0”或“3”中的任一个的值,表920被扩展为具有八个桶的表930。具体而言,基于值的倒数第三位(即,基于模8),表920的四个桶中的每一个被拆分成两个相应的桶。具体而言,表920中的桶“0”的值或者留在表930中的桶“0”中或者被移动到表930中的桶“4”,表920中的桶“1”的值或者留在表930中的桶“1”中或者被移动到表930中的桶“5”,依此类推。在对值进行分区之后,桶“0”包含node
id mod 8(表930中的桶的数量)=0的所有值,桶“1”包含node
id mod 8=1的所有值,桶“2”包含node
id mod 8=2的所有值,依此类推。在拆分之后,桶“0”包含值“8”、“32”和“48”;桶“1”包含值“1”、“33”和“9”;桶“2”包含值“18”和“2”;桶“3”包含值“11”、“3”、“35”和“27”;桶“4”包含值“12”、“28”、“4”、“60”和“20”;桶“5”包含值“5”和“21”;桶“6”包含值“6”、“22”和“14”;并且桶“7”包含值“15”、“7”、“3”、“63”和“23”。
[0114]
向量化的队列
[0115]
根据实施例,向量化的队列(诸如下面伪代码6中定义的simdvisitorqueue)包括促进最短路径图搜索的特征,如下文进一步详细描述的。在由simdvisitorqueue所示的实施例中,向量化的队列类似于stl的c std::queue容器,但是,根据实施例,向量化的队列可以类似于来自另一个源的另一个队列类型数据结构。虽然simdvisitorqueue支持整数数据类型,例如64位、32位和16位整数值,但根据实施例,支持其它数据类型。
[0116]
根据实施例,向量化的队列具有调整尺寸功能,其在恒定时间内从队列中移除所有值。根据实施例,通过将值直接复制到保持队列的值的底层存储器阵列来将值添加到向量化的队列(而不是实现推送和弹出技术)。
[0117]
根据实施例,向量化的队列具有contains_end_node函数,该函数执行检查特定元素(诸如下面描述的最短路径搜索技术中的目的地节点)是否在队列内的向量化的搜索。另外,根据实施例,向量化的队列具有恒定时间init函数,该函数允许重用队列,例如,用于多个独立的最短路径搜索。
[0118]
以下的伪代码6说明了类simdvisitorqueue,它是向量化的队列的示例实施方式。
[0119]
[0120][0121]
伪代码6:simdvisitorqueue
[0122]
在伪代码6中,simdvisitorqueue继承自std::vector,从中派生出用于在向量化的队列中存储值的功能。类simdvisitorqueue具有构造函数、一个私有方法和三个公共方法。私有方法n_vec返回在队列中存储值所需的向量的数量;n_vec使用std:vector的底层size方法来确定队列中值的数量。simdvisitorqueue的构造函数初始化底层std::vector并为队列将保持的最大数量的值max_n_nodes保留空间。当向量化的队列用于最短路径搜索时,max_n_nodes的这个值取决于进行搜索的图的尺寸。simdvisitorqueue的resize方法通过修改底层std::vector的内部变量在恒定时间内改变队列的尺寸。在所示实施例中,这个方法在队列增长时不初始化值(在队列使用的存储器块中),也不在队列收缩时覆写值。
[0123]
为了促进最短路径搜索,simdvisitorqueue的方法init设置向量end_node_vec,它在其所有槽中保持目的地节点(或端节点)。注意的是,init函数与构造函数是分开的,因为队列只构造一次,但被配置为可重用于多个应用,诸如多个最短路径搜索。
[0124]
而且为了促进最短路径搜索,contains_end_node方法检查队列是否包含目的地节点,其中该方法在存储在队列中的所有值向量上迭代,用向量化的指令检查用于目的地
节点的每个向量,使得该技术不需要迭代通过向量的值。具体而言,在每次迭代中(伪代码6的第28-36行),contains_end_node从队列数组中检索值的向量vec,并经由向量化的指令_mm512_cmpeq_epi32_mask(第30-31行)将vec与向量end_node_vec进行比较,如上面结合图4b和图4c详细描述的。
[0125]
如果目的地节点存在于向量vec中,那么由_mm512_cmpeq_epi32_mask返回的位掩码包含设置为一的位,而如果目的地节点不存在于vec中,那么包含全零。掩码具有_mm512_mask2int被转换成标量值,当掩码包含设置为一的位时返回大于零的标量值,否则返回零。如果标量值大于零,那么在队列中找到了目的地节点,并且contains_end_node方法返回true(第32-33行)。否则,循环(第28-36行)继续。如果循环在将存储在队列中的所有值向量与向量end_node_vec进行比较之后结束,并且尚未找到目的地节点,那么该方法返回false(第37-38行)。
[0126]
最短路径图搜索
[0127]
根据实施例,向量化的最短路径图搜索识别源图节点和目的地图节点之间的图路径,在该路径中具有最少的跳数。但是,本文描述的用于最短路径图搜索的技术也适用于寻找源和目的地图节点之间的路径的问题,边缘权重的总和最小。此外,虽然技术是在单对最短路径问题的上下文中描述的,但所描述的技术也适用于最短路径问题的其它变体,包括单源最短路径问题、单目的地最短路径问题问题,以及所有对最短路径问题。
[0128]
类似于标量技术(在上面的伪代码1中描述),本文描述的向量化的最短路径搜索技术使用广度优先搜索策略来找到最短路径。具体而言,这些技术迭代地扩展可以从源节点到达的节点的集合,直到找到目的地节点,或确定目的地节点不在可从源节点到达的节点的集合中。但是,与标量技术不同,本文描述的搜索技术使用本文描述的向量化的队列以及根据一个或多个实施例使用本文还描述的向量化的散列表来执行高效的向量化的最短路径图搜索。
[0129]
如下面进一步详细描述的,向量化的最短路径图搜索将可到达节点的集合的广度优先搜索扩展(结合寻找节点之间的最短路径来执行)的每次迭代拆分为三个阶段:
[0130]
·
在第一阶段,使用向量化的指令,例如下面更详细描述的伪代码7的方法fetch_neighbors,获取下一个队列中节点的邻居节点并将其写入当前队列。
[0131]
·
在第二阶段,经由向量化的指令,诸如上述向量化的队列的contains_end_node方法的向量化的指令,确定在当前队列中获取的邻居节点中是否已经找到目的地节点。在检查这些节点是否已被访问(在第三阶段中执行)之前在当前队列中搜索目的地节点避免了对节点是否已被访问的不必要检查,即,在其中在获取的邻居当中找到目的地节点的最后一次扩展迭代中。
[0132]
·
在第三阶段,将获取到的尚未访问的邻居节点放入下一个队列。
[0133]
图10描绘了根据实施例的用于在图数据库中识别包括源节点和目的地节点的一对节点之间的路径的流程图1000。例如,设备210接收要求在图数据库数据222中搜索特定源节点和特定目的地节点之间的最短路径的图查询。因而,实例214发起对图数据库数据222的最短路径图搜索。
[0134]
以下伪代码7描绘实现上述三阶段最短路径搜索技术的实施例的示例shortest_path方法:
[0135][0136]
伪代码7:shortest_path()
[0137]
伪代码7中的shortest_path方法具有三个参数:访问者状态vs保持一个或多个向量化的数据结构,以及源节点node0和目的地节点node1。类似于顺序版本(参见上面的伪代码1),在伪代码7的第2-4行中,当源节点与目的地节点相同时,shortest_path方法返回“0”。在第10行,通过调用init方法使用目的地节点初始化当前队列,上面描述了其示例。需要用目的地节点的标识符初始化当前队列,以便能够在迭代增加可达节点的集合的同时调用contains_end_node。在第11行,源节点被添加到下一个队列next_queue,并且在第12行,在迭代广度优先搜索开始之前,距离dist被设置为“0”(参见第13-31行)。
[0138]
如前面所提到的,第13-31行的主循环分三个阶段工作:1)第一阶段:获取下一个队列中所有节点的邻居节点,例如,通过调用下面详细描述的fetch_neighbors(第17-18行);2)通过调用contains_end_node来确定在获取的邻居节点当中是否已找到目的地节点,并且如果找到目的地节点则返回(第19-21行);3)将当前队列中先前未访问过的那些节点添加到下一个队列(第22-30行),例如,经由调用push_back将节点标识符推回到下一个队列(第26-28行)。根据实施例,结合第三阶段,通过调用向量化的散列表的插入方法(第24-25行)来执行检查节点是否已被访问。如上所述,插入方法尝试将节点标识符插入向量化的散列表中。如果节点标识符被成功插入到散列表中,即,因为它还不在散列表中,那么插入方法返回“1”或true,否则返回“0”或false。在第32-33行,如果扩展迭代之后下一个队
列为空,那么无法从源节点到达目的地节点并且shortest_path方法返回
“‑
1”。
[0139]
返回到流程图1000的讨论,在步骤1002处,通过在图数据库中识别下一个队列中的节点的一个或多个邻居节点来执行第一阶段。例如,设备210基于由设备210维护的图数据库数据222中表示的节点的邻接列表来识别下一个队列中的节点的邻居节点。具体而言,数据222的邻接列表包括图数据库数据222中每个节点的相应的特定于节点的邻接列表。每个特定于节点的邻接列表中的节点标识符被连续存储,使得在邻接列表中,给定节点的邻居的节点标识符一个接一个地列出,直到列出所有邻居节点。随后在邻接列表数据中,连续列出第二节点的所有邻居节点的标识符,依此类推。根据实施例,对在列表或向量中包括节点的引用是指在列表或向量中包括节点的标识符。
[0140]
根据实施例,设备210基于将给定节点的节点标识符映射到数据222中的邻接列表中存储给定节点的特定于节点的邻接列表的位置的映射数据来识别下一个队列中给定节点的邻居节点。根据实施例,映射数据还指示特定于节点的邻接列表的长度。
[0141]
为了说明与最短路径图搜索的第一阶段相关的识别邻居节点,数据库服务器实例214(图2)执行接收到的图查询,该查询要求在维护在图数据库数据222中的图11中描绘的图数据库1100中在源节点f和目的地节点b之间进行最短路径图搜索。根据遵循伪代码7中的shortest_path方法的模式的实施例,实例214用目的地节点b初始化当前队列232并将源节点f推送到下一个队列234,其中当前队列232和下一个队列234是如本文所述的向量化的队列。对于下一个队列234中的源节点f,实例214通过执行步骤1002中描述的第一阶段通过将节点f的所有邻居节点[g,a,e,j]提取到当前队列232中来开始广度优先节点扩展的第一次迭代。
[0142]
返回到流程图1000的讨论,在步骤1004处,通过确定目的地节点是否包括在一个或多个邻居节点中来执行第二阶段。例如,在执行广度优先节点扩展的当前迭代的第二阶段,实例214确定目的地节点b是否在当前队列232中(当前保持[g,a,e,j]),例如,使用向量化的队列的contains_end_node方法。因而,实例214确定目的地节点b不在当前队列232中。
[0143]
在步骤1006处,响应于确定目的地节点不包括在一个或多个邻居节点中,对于一个或多个邻居节点中的每个节点执行第三阶段:确定相应节点是否具有之前被访问过,并且响应于确定相应节点之前没有被访问过,在下一个队列中包括相应节点。例如,在确定目的地节点b不在当前队列232中后,实例214将当前队列232中在当前最短路径搜索期间没有被先前访问过的那些节点添加到下一个队列234。
[0144]
根据实施例,实例214通过尝试将当前队列232中的每个节点插入到散列表230中来确定当前队列232中的每个节点是否之前已经被访问过,散列表230被实现为如本文详细描述的向量化的散列表。如果插入散列表230的节点尚未被访问过,那么插入函数插入节点标识符并返回“1”或true。如果节点已被访问过,那么插入函数返回“0”或false。仅将当前队列232中尚未访问过的节点的标识符写入下一个队列234。
[0145]
继续上面的示例,基于实例214确定这些节点之前都没有被访问过,将[g,a,e,j]的所有节点标识符写入下一个队列234。节点扩展的迭代一直持续到或者源节点f和目的地节点b之间的路径已经被识别,或者确定节点之间没有路径。为了说明,在广度优先节点扩展的第二次迭代的第一阶段,实例214将[g,a,e,j]的邻居(下一个队列234的内容)加载到当前队列232中。具体而言,g的邻居[f,h]、a的邻居[f、e、d、h]、e的邻居[f、j、i、b、d、a]、j的
邻居[f,e]被加载到当前队列232中,使得在第一阶段之后,当前队列232存储节点[f,h,f,e,d,h,f,j,i,b,d,a,f,e]。在广度优先节点扩展的第二次迭代的第二阶段中,实例214确定目的地节点b是否包括在当前队列232中。因为b的标识符在当前队列232中,所以实例214返回计算出的距离“2”并结束最短路径搜索。在广度优先节点扩展的第二次迭代中,实例214通过将潜在探测延迟到广度优先节点扩展的第二次迭代的第二阶段完成之后来避免对散列表230的不必要的探测。
[0146]
本文描述的向量化的最短路径图搜索技术也适用于从起始节点和目的地节点开始的双重广度优先最短路径搜索。具体而言,在搜索期间维护被访问节点的两个集合而不是被访问节点的一个集合。一旦在另一个集合中找到来自一个集合的节点,就找到了最短路径。
[0147]
基于向量的邻居节点到当前队列的复制
[0148]
根据实施例,设备210使用向量化的指令来执行节点的基于向量的复制,例如,结合最短路径搜索扩展的第一阶段。数据的基于向量的复制包括将数据向量直接从源(例如,邻接列表)复制到底层存储器阵列(例如,其保持队列的值)。图12描绘了根据实施例的用于执行数据的基于向量的复制的流程图1200。在步骤1202处,在数据源中识别数据的第一部分。例如,在广度优先节点扩展的迭代的第一阶段,如上所述,实例214将节点x、y和z的邻居加载到当前队列232中。具体而言,实例214基于将每个节点的节点标识符映射到图数据的邻接列表中的相应位置的映射数据来识别节点x、y和z中的每个节点的特定于节点的邻接列表。
[0149]
图13描绘了示例邻接表1300,其例如被存储为图数据库数据222(图2)的一部分并且结合上面最短路径图搜索的执行被加载到易失性存储器212中。如图13中所描绘的,邻接列表1300中用于节点x的特定于节点的邻接列表开始于位置1342并且包括40个邻居节点标识符。另外,邻接列表1300中用于节点y的特定于节点的邻接列表开始于位置1344并且包括10个邻居节点标识符,邻接列表1300中用于节点z的特定于节点的邻接列表开始于位置1346并且包括27个邻居节点标识符。
[0150]
在流程图1200的步骤1204处,通过第一复制操作,数据的第一部分通过向量被复制到数据目的地,其中第一复制操作的执行导致位于数据源中数据的第一部分之后的数据的第二部分被复制到数据目的地。例如,实例214使用一个或多个向量化的指令将邻接列表1300中的位置1342处的用于节点x的特定于节点的邻接列表复制到当前队列232中。
[0151]
图13描绘了第一示例复制操作1310,通过该操作,实例214通过宽度k=16的向量将用于节点x的特定于节点的邻接列表复制到用于当前队列232的存储器阵列。用于节点x的特定于节点的邻接列表的长度是40个节点标识符,这要求三个向量化的加载和三个向量化的存储操作以复制到用于当前队列232的存储器。因为所需数据的长度不能被所使用的向量的宽度完全整除,所以将48个节点标识符从邻接列表1300复制到用于当前队列232的存储器阵列,其中不是用于节点x的邻接列表的一部分的8个节点标识符(描绘为无效数据1312)在有效的被复制数据结束之后被复制到当前队列232。
[0152]
在步骤1206处,在数据源中识别数据的第三部分。例如,实例214使用映射数据来识别用于节点y的特定于节点的邻接列表,该邻接列表开始于邻接列表1300中的位置1344并且包括10个邻居节点标识符。
[0153]
在步骤1208处,通过第二复制操作,将数据的第三部分通过向量复制到数据目的地,其中第二复制操作的执行覆写数据的第二部分。例如,实例214使用一个向量化的加载指令和一个向量化的存储指令将16个节点标识符,包括用于节点y的邻接列表,从邻接列表1300中的位置1344复制到用于当前队列232的存储器阵列中。
[0154]
图13进一步描绘了第二复制操作1320,通过该操作,实例214通过宽度k=16的向量将用于节点y的邻接列表复制到用于当前队列232的存储器阵列。代替将用于节点y的邻接列表复制到先前复制数据的末尾,实例214用用于节点y的特定于节点的邻接列表覆写无效数据1312,使得在第二次复制操作1320之后,在当前队列232中的两个特定于节点的邻接列表之间没有无效数据剩余。但是,因为用于节点y的特定于节点的邻接列表的长度是10个节点标识符,这不能被所使用的向量的宽度完全整除,所以不属于用于节点y的特定于节点的邻接列表的六个节点标识符(被描绘为无效数据1322)在有效的被复制数据结束之后被复制到用于当前队列232的存储器阵列。
[0155]
还如图13中所描绘的,在第三复制操作1330处,实例214使用一个或多个向量化的指令将邻接列表1300中的位置1346处的用于节点z的特定于节点的邻接列表复制到用于当前队列232的存储器阵列中。更具体而言,通过第三复制操作1330,通过宽度k=16的向量,实例214使用两个向量化的加载指令和两个向量化的存储指令将来自邻接列表1300的32个节点标识符,包括用于节点z的27个邻居节点标识符,复制到用于当前队列232的存储器阵列。代替将用于节点z的邻接列表复制到先前复制的数据的末尾,实例214用用于节点z的特定于节点的邻接列表覆写无效数据1322,使得在第三复制操作1330之后在当前队列232中的任何邻接列表之间都没有无效数据剩余。再次,因为用于节点z的特定于节点的邻接列表的长度是27个节点标识符,这不能被所使用的向量的宽度完全整除,所以不属于用于节点z的特定于节点的邻接列表的五个节点标识符(被描绘为无效数据1332)在有效的被复制数据结束之后被复制到用于当前队列232的存储器阵列。
[0156]
很多时候,在将所有邻接列表数据复制到当前队列232之后,在复制的有效数据之后在当前队列232中仍然存在无效数据(例如,无效数据1332)的一部分。根据实施例,实例214用随机数数据(即,与有效数据可区分的数据)覆写无效数据的剩余部分。在其中存储在邻接列表1300中的节点标识符是非负整数的实施例中,随机数数据的示例是
“‑
1”值。
[0157]
为了说明,在执行第三复制操作1330之后,实例214执行操作1350以覆写无效数据1322,通过该操作,实例214将向量1352

在所有16个槽中填充有随机数(例如,
“‑
1”)值-复制到当前队列232中有效数据直接后面的位置,使得随机数数据与队列232中的有效数据相邻。因为当前队列232中的有效数据后面是随机数数据的完整向量,所以当前队列232中的信息的任何基于向量的分析都将仅包括有效数据,并且可能包括随机数数据,这防止对可能会被错误地解释为有效数据的无效数据的任何分析。如果无效数据没有被覆写,那么经由contains_end_node在队列中的向量化的搜索将需要以不同的方式处置队列中最后一个向量的比较。
[0158]
以下伪代码9描绘类graph的示例向量化的fetch_neighbors方法:
[0159][0160]
伪代码9:fetch_neighbors()
[0161]
伪代码9中的示例fetch_neighbors方法采用类型为simdvisitorstate的一个参数vs,它保持向量化的散列表和队列。该方法首先将访问者状态的队列分别指派给局部变量cur_queue和next_queue。该方法还将指向当前队列的数据或存储器阵列的指针指派给局部变量cur_data。
[0162]
在伪代码9的第7-23行,该方法在下一个队列中的所有节点上迭代。对于每个节点,该方法以向量化的方式将节点的邻居节点复制到当前队列中。具体而言,将邻居节点标识符复制到用于当前队列的存储器阵列中是使用循环完成的,该循环经由向量化的加载指令_mm512_loadu_si512和向量化的存储指令_mm512_storeu_si512一次复制值的一个向量。在进入内循环之前(第16-21行),在第11行,该方法计算要复制多少个向量-包含下一个队列中给定节点的邻居节点。在第12-14行,该方法还计算表示邻居节点的数据需要从何处复制到何处的地址。如上面所讨论的,在处理完下一个队列的所有节点之后,已复制到下一个队列中的邻居节点数据后面可能存在无效数据,即,队列的最后一个向量中的值的一部分。在第24-26行,无效数据经由_mm512_storeu_si512被
“‑
1”值覆盖。最后,在第28-29行,将当前队列的尺寸调整为已复制到当前队列的邻居节点的数量,并将下一个队列的尺寸设置为0。
[0163]
当前队列节点的混合/批处理
[0164]
根据实施例,代替当前队列存储下一个队列中所有节点的所有邻居节点,如上所述,混合搜索技术处理当前队列中的节点的批次。这个实施例减少了上述技术的总体存储
器占用。例如,在广度优先搜索扩展迭代的第一阶段,不是将来自下一个队列234的所有节点的所有邻居节点加载到当前队列232中,而是实例214将来自下一个队列234的节点的邻居加载到当前队列232中直到达到邻居节点的阈值数量,例如1000个节点标识符。邻居节点的这个部分集合在本文中被称为“批次”。实例214对当前队列232中的当前一批节点执行上述向量化的最短路径搜索技术的第二和第三阶段。
[0165]
如果在前一批次中没有找到目的地节点,那么实例214将另一个批次的邻居节点加载到当前队列232中,直到达到存储在下一个队列中的节点234的阈值尺寸,或者直到没有更多邻居节点要加载。与前一批次一样,实例214对当前队列232中的这个附加批次的节点执行上述向量化的最短路径搜索技术的第二和第三阶段。
[0166]
访问者状态
[0167]
以下伪代码8描绘示例类simdvisitorstate,它保持向量化的数据结构,自然上述向量化的最短路径技术所需的那些。
[0168][0169]
伪代码8:simdvisitorstate
[0170]
在上述shortest_path方法的上下文中,simdvisitorstate的实例保持向量化的散列表hashset和两个向量化的队列cur_queue和next_queue。在第7-8行,构造方法和析构
方法分别在创建或销毁状态对象时初始化和销毁向量化的数据结构。在第10-13行,gethashset方法返回指向向量化的散列表的指针。类似地,在第15-22行,方法getcurqueue和getnextqueue分别返回指向相关联的队列的指针。
[0171]
在第24-30行,clear方法将所有数据结构重置为其初始状态。照此,重置simdvisitorstate的实例不要求在任何数据结构中的附加存储器分配,也不要求值的任何覆写;只有少数指针被设置为它们的初始状态,使得该方法具有恒定的计算成本并且只要求几条指令即可完成。
[0172]
查询计划和优化
[0173]
本文为了说明的简单起见,没有描述附加的查询优化,诸如对被探索节点的重新排序。但是,可以结合本文描述的技术根据期望实现附加的查询优化。
[0174]
实验的结果
[0175]
实验表明,本文描述的与用于向量化的散列表和向量化的队列结构结合使用的向量化的最短路径图搜索技术优于标量最短路径图搜索对应物(参见上面的伪代码1)。
[0176]
进行了几个实验,这些实验表明使用向量化的数据结构的向量化的最短路径图技术优于标量最短路径图技术。实验是在包括intel i3-8121u cpu、核心频率高达3.20ghz和8gb主存储器的系统上进行的。cpu支持以下avx-512指令集:avx512f、avx512cd、avx512bw、avx512dq、avx512vl、avx512ifma和avx512vbmi。linux(内核版本4.4.0)被用作操作系统。这些技术是用c 实现的并使用gcc 5.4.0编译。
[0177]
使用本文也描述的向量化的散列表和向量化的队列数据结构,将伪代码1中描绘的标量最短路径技术与本文描述的向量化的最短路径技术进行比较。对于向量化的最短路径技术,使用k=16,即,avx-512指令使用的512位寄存器。实验是在真实世界的数据集上进行的,这些数据集可以在snap.stanford.edu/data/上免费获得。
[0178]
图14a描绘了用于本文描述的实验的数据集的特征。选择具有不同顶点-边比的数据集来说明本文描述的向量化的技术显著提高了独立于数据集特征的性能。当加载到存储器中时,数据集的图形需要50mb到大约0.5gb的主存储器。数据集1产生无向图,而所有其它数据集产生有向图。对于每个数据集,生成了10000对由起始顶点和目的地顶点组成的对-两者都是从数据集的所有顶点中随机选择的。对所有对测量用于执行最短路径搜索的运行时间。每次搜索都依次进行。加载数据集不包括在测得的运行时间中。
[0179]
图14b描绘了当与针对图14a的不同数据集的标量最短路径搜索技术相比时通过本文描述的向量化的最短路径搜索技术实现的加速。因而,对于每个数据集,向量化的最短路径搜索技术比标量最短路径搜索技术快得多。具体而言,实现了从2.5x到4.1x的加速。预计其它数据集也会有类似的结果。
[0180]
一般概述:数据库系统
[0181]
dbms管理数据库。dbms可以包括一个或多个数据库服务器。数据库包括数据库数据和数据库字典,它们被存储在诸如硬盘集合之类的持久性存储器机制上。数据库数据(包括图数据)可以被存储在一个或多个数据容器中。每个容器包含记录。每个记录中的数据被组织到一个或多个字段中。在关系型dbms中,数据容器被称为表,记录被称为行,并且字段被称为列。在面向对象的数据库中,数据容器被称为对象类,记录被称为对象,并且字段被称为属性。其它数据库体系架构可能使用其它术语。
[0182]
用户通过向数据库服务器提交使数据库服务器对存储在数据库中的数据执行操作的命令来与dbms的数据库服务器进行交互。用户可以是在与数据库服务器交互的客户端计算机上运行的一个或多个应用。多个用户在本文中也可以被统称为用户。
[0183]
用户通过向数据库服务器提交命令来与dbms的数据库服务器交互,这些命令使数据库服务器对存储在数据库中的数据执行操作。用户可以是在客户端计算机上运行的一个或多个与数据库服务器交互的应用。多个用户在本文中也可以统称为一个用户。
[0184]
数据库命令可以是符合数据库语言的数据库语句的形式。用于表达图查询的数据库语言是特性图查询语言(pgql),它是语法接近结构化查询语言(sql)的图查询语言。(有关pgql的附加信息可以在oskar van rest等人在grades 2016,2016年6月24日撰写的“pgql:a property graph query language”中找到,其全部内容通过引用并入本文,如同在本文完整阐述一样)。
[0185]
多节点dbms由互连的节点组成,这些节点共享对同一数据库的访问。通常,节点经由网络互连,并在不同程度上共享对共享存储的访问,例如,对盘驱动器集合和存储在其上的数据块的共享访问。多节点数据库系统中的节点可以采用经由网络互连的一组计算机(例如,工作站、个人计算机)的形式。替代地,节点可以是网格的节点,其由与机架上的其它服务器刀片互连的服务器刀片形式的节点组成。
[0186]
多节点数据库系统中的每个节点都托管数据库服务器。服务器(诸如,数据库服务器)是集成软件组件和计算资源(诸如,存储器、节点以及节点上用于在处理器上执行集成软件组件的进程)的分配的组合,软件和计算资源的组合专用于代表一个或多个客户端执行特定功能。
[0187]
来自多节点数据库系统中的多个节点的资源可以被分配给运行特定数据库服务器的软件。软件和来自节点的资源分配的每种组合都是在本文中被称为“服务器实例”或“实例”的服务器。数据库服务器可以包括多个数据库实例,它们中的一些或全部在包括单独的服务器刀片的单独的计算机上运行。
[0188]
散列表
[0189]
许多算法严重依赖散列表,因此散列表函数的效率会极大地影响这些算法的效率。散列表最昂贵的操作之一是使散列表增长以容纳附加的元素,这一般要求为扩展的散列表重新散列所存储的元素。避免代价高昂的增长操作的常用技术是多探测策略,其中元素可以位于散列表中的h个不同位置。这种策略为给定元素提供了在散列表经历增长的代价之前适应散列表的h个不同机会。但是,将元素插入多探测散列表可能要求多达h次不同的插入操作尝试。
[0190]
散列表的向量化的方法一般使用多探测策略并且还假设小散列表尺寸,这导致在散列表扩展以容纳大型数据集时出现问题。对于多探测散列表,向量化已被用于计算用于给定键的h个不同桶的桶标识符,并搜索该键是否在那些桶之一中。
[0191]
而且,向量化已被用于向量化的散列方案,包括线性散列、双重散列和布谷鸟散列,它们利用avx-512指令集的向量化的分散和收集类型指令。但是,当散列表增长到大于cpu高速缓存尺寸时,使用分散和收集类型指令显著限制性能。因此,当散列表达到1mb或更大时,这种向量化的方法的性能一般与标量方法的性能相当,这使得这些方案不适用于大型数据集。
[0192]
此外,现有方法一般不提供高效的增长策略。缺乏高效的增长策略是个大的缺点,因为许多算法所需的散列表尺寸是事先不知道的,并且许多散列方案(包括线性散列、双重散列和布谷鸟散列)在散列表增长时要求昂贵的重新散列。照此,为可以容纳大型数据集的散列表提供高效的插入策略以及高效的增长操作将是有益的。
[0193]
本节中描述的方法是可以采用的方法,但不一定是先前已经设想或采用的方法。因此,除非另有说明,否则不应仅由于将本节中所述的任何方法包括在本节中而认为本节中的任何方法有资格作为现有技术。另外,不应当假设本节中描述的任何方法仅因其包括在本节中就是易于理解的、例行的或常规的。
[0194]
数据库系统配置
[0195]
图2中未描绘的数据库客户端连接到数据库系统200。客户端可以包括在客户端节点上运行的数据库应用。客户端通过提交使实例对存储在数据库中的数据执行操作的命令来与数据库系统200的实例(例如,实例214)交互。例如,命令可以是访问或修改来自数据库的数据、对数据执行操作和/或将数据返回给客户端的请求。
[0196]
通常,数据库系统200可以由单个机器(例如,设备210)来实现,或者可以由通信连接的多个机器来实现。参考图2,在设备210上运行的数据库服务器实例214将数据库数据222维护在持久存储装置220中。
[0197]
根据实施例,设备210可以被称为机器节点,并且运行数据库服务器实例214。数据库服务器实例(或“实例”)是包括软件和来自机器节点的资源分配的组合的服务器。具体而言,服务器(诸如数据库服务器)或任何其它处理是集成的软件组件和计算资源分配的组合,资源诸如是存储器、机器节点(即,计算设备和/或计算设备可访问的存储器),和/或机器节点上用于在处理器上执行集成软件组件的子处理,软件和计算资源的组合专用于代表一个或多个客户端执行特定功能。在图2中所描绘的实施例中,实例214实现了数据库系统200的服务器侧功能。
[0198]
数据库数据222可以驻留在易失性和/或非易失性存储器中,诸如易失性存储器212、持久存储装置220等。实现数据库系统200的每个机器节点可以包括虚拟盘和/或物理盘的集合。附加地或可替代地,数据库数据222可以至少部分地存储在数据库服务器计算设备的主存储器中。
[0199]
根据一个或多个实施例,归属于本文描述的任何处理的功能中的一个或多个可以由图2中可能或可能未描绘的任何其它逻辑实体来执行。在实施例中,本文描述的技术和/或功能中的每一个被自动执行,并且可以使用通用计算机或专用计算机中的任一个中的一个或多个计算机程序、其它软件元素和/或数字逻辑来实现,同时执行涉及与计算机的存储器的物理状态交互和变换其的数据检索、变换和存储操作。
[0200]
硬件概述
[0201]
根据一个实施例,本文描述的技术由一个或多个专用计算设备来实现。专用计算设备可以是硬连线的以执行本技术,或者可以包括被永久性地编程以执行本技术的数字电子设备,诸如一个或多个专用集成电路(asic)或现场可编程门阵列(fpga),或者可以包括被编程为根据固件、存储器、其它存储装置或组合中的程序指令执行本技术的一个或多个通用硬件处理器。这种专用计算设备还可以将定制的硬连线逻辑、asic或fpga与定制的编程组合来实现本技术。专用计算设备可以是台式计算机系统、便携式计算机系统、手持式设
备、联网设备或结合硬连线和/或程序逻辑来实现技术的任何其它设备。
[0202]
例如,图15是图示可以在其上实现本发明的实施例的计算机系统1500的框图。计算机系统1500包括用于传送信息的总线1502或其它通信机制,以及与总线1502耦合用于处理信息的硬件处理器1504。硬件处理器1504可以是例如通用微处理器。
[0203]
计算机系统1500还包括主存储器1506,诸如随机存取存储器(ram)或其它动态存储设备,其耦合到总线1502用于存储信息和要由处理器1504执行的指令。主存储器1506还可以用于在要由处理器1504执行的指令的执行期间存储临时变量或其它中间信息。当此类指令存储在处理器1504可访问的非暂态存储介质中时,将计算机系统1500渲染为被定制以执行指令中指定的操作的专用机器。
[0204]
计算机系统1500还包括只读存储器(rom)1508或耦合到总线1502的其它静态存储设备,用于存储用于处理器1504的静态信息和指令。提供诸如磁盘、光盘或固态驱动器之类的存储设备1510并耦合到总线1502以用于存储信息和指令。
[0205]
计算机系统1500可以经由总线1502耦合到显示器1512(诸如阴极射线管(crt))用于向计算机用户显示信息。包括字母数字键和其它键的输入设备1514耦合到总线1502,用于将信息和命令选择传送到处理器1504。另一种类型的用户输入设备是光标控件1516(诸如鼠标、轨迹球或光标方向键),用于将方向信息和命令选择传送到处理器1504并用于控制显示器1512上的光标移动。这种输入设备通常在两个轴上具有两个自由度,第一轴(例如,x)和第二轴(例如,y),这允许设备指定平面中的位置。
[0206]
计算机系统1500可以使用定制的硬连线逻辑、一个或多个asic或fpga、固件和/或程序逻辑来实现本文描述的技术,这些与计算机系统相结合使计算机系统1500成为特殊目的机器。根据一个实施例,本文的技术由计算机系统1500响应于处理器1504执行包含在主存储器1506中的一条或多条指令的一个或多个序列而执行。此类指令可以从另一个存储介质(诸如存储设备1510)读入主存储器1506。包含在主存储器1506中的指令序列的执行使处理器1504执行本文描述的处理步骤。在替代实施例中,硬连线电路系统可以代替软件指令或与软件指令结合使用。
[0207]
如本文使用的术语“存储介质”是指存储数据和/或指令的任何非暂态介质,这些数据和/或指令使机器以特定方式操作。这种存储介质可以包括非易失性介质和/或易失性介质。非易失性介质包括例如光盘、磁盘或固态驱动器(诸如存储设备1510)。易失性介质包括动态存储器(诸如主存储器1506)。常见形式的存储介质包括例如软盘、柔性盘、硬盘、固态驱动器、磁带或任何其它磁性数据存储介质、cd-rom、任何其它光学数据存储介质、任何具有孔图案的物理介质、ram、prom和eprom、flash-eprom、nvram、任何其它存储芯片或盒式磁带。
[0208]
存储介质不同于传输介质,但可以与传输介质结合使用。传输介质参与在存储介质之间传送信息。例如,传输介质包括同轴电缆、铜线和光纤,包括构成总线1502的电线。传输介质也可以采用声波或光波的形式,诸如在无线电波和红外数据通信期间生成的那些。
[0209]
在将一条或多条指令的一个或多个序列携带到处理器1504以供执行时,可以涉及各种形式的介质。例如,指令最初可以被携带在远程计算机的磁盘或固态驱动器上。远程计算机可以将指令加载到其动态存储器中并使用调制解调器通过电话线发送指令。计算机系统1500本地的调制解调器可以在电话线上接收数据并使用红外发送器将数据转换成红外
信号。红外检测器可以接收红外信号中携带的数据并且适当的电路系统可以将数据放置在总线1502上。总线1502将数据携带到主存储器1506,处理器1504从主存储器1506检索并执行指令。由主存储器1506接收的指令可以可选地在由处理器1504执行之前或之后存储在存储设备1510上。
[0210]
计算机系统1500还包括耦合到总线1502的通信接口1518。通信接口1518提供到连接到本地网络1522的网络链路1520的双向数据通信耦合。例如,通信接口1518可以是综合服务数字网络(isdn)卡、电缆调制解调器、卫星调制解调器或提供到对应类型的电话线的数据通信连接的调制解调器。作为另一个示例,通信接口1518可以是局域网(lan)卡以提供到兼容lan的数据通信连接。也可以实现无线链路。在任何这样的实施方式中,通信接口1518发送和接收携带表示各种类型信息的数字数据流的电、电磁或光信号。
[0211]
网络链路1520通常通过一个或多个网络向其它数据设备提供数据通信。例如,网络链路1520可以提供通过本地网络1522到主机计算机1524或到由互联网服务提供商(isp)1526操作的数据装备的连接。isp 1526进而通过现在通常称为“互联网”1528的全球分组数据通信网络提供数据通信服务。本地网络1522和互联网1528都使用携带数字数据流的电、电磁或光信号。通过各种网络的信号和网络链路1520上的信号以及通过通信接口1518的信号是传输介质的示例形式,它们将数字数据携带到计算机系统1500和从计算机系统1500携带数字数据。
[0212]
计算机系统1500可以通过(一个或多个)网络、网络链路1520和通信接口1518发送消息和接收数据,包括程序代码。在互联网示例中,服务器1530可以通过互联网1528、isp 1526、本地网络1522和通信接口1518传输对应用的请求代码。
[0213]
接收到的代码可以在接收到时由处理器1504执行,和/或存储在存储设备1510或其它非易失性存储器中以供以后执行。
[0214]
软件概述
[0215]
图16是可以用于控制计算机系统1500的操作的基本软件系统1600的框图。软件系统1600及其组件,包括它们的连接、关系和功能,仅仅是示例性的,并且不意味着限制(一个或多个)示例实施例的实现。适于实现(一个或多个)示例实施例的其它软件系统可以具有不同的组件,包括具有不同的连接、关系和功能的组件。
[0216]
提供软件系统1600用于指导计算机系统1500的操作。可以存储在系统存储器(ram)1506和固定存储装置(例如,硬盘或闪存)1510上的软件系统1600包括内核或操作系统(os)1610。
[0217]
os 1610管理计算机操作的低级方面,包括管理进程的执行、存储器分配、文件输入和输出(i/o)以及设备i/o。表示为1602a、1602b、1602c...1602n的一个或多个应用可以被“加载”(例如,从固定存储装置1510传送到存储器1506中)以供系统1600执行。意图在计算机系统1500上使用的应用或其它软件也可以被存储为可下载的计算机可执行指令集,例如,用于从互联网位置(例如,web服务器、app商店或其它在线服务)下载和安装。
[0218]
软件系统1600包括图形用户界面(gui)1615,用于以图形(例如,“点击”或“触摸手势”)方式接收用户命令和数据。进而,这些输入可以由系统1600根据来自操作系统1610和/或(一个或多个)应用1602的指令来操作。gui 1615还用于显示来自os 1610和(一个或多个)应用1602的操作结果,用户可以提供附加的输入或终止会话(例如,注销)。
[0219]
os 1610可以直接在计算机系统1600的裸硬件1620(例如,(一个或多个)处理器1504)上执行。可替代地,管理程序或虚拟机监视器(vmm)1630可以插入在裸硬件1620和os 1610之间。在这个配置中,vmm 1630充当os 1610与计算机系统1500的裸硬件1620之间的软件“缓冲”或虚拟化层。
[0220]
vmm 1630实例化并运行一个或多个虚拟机实例(“访客机”)。每个访客机包括“访客”操作系统(诸如os 1610),以及被设计为在客户操作系统上执行的一个或多个应用(诸如(一个或多个)应用1602)。vmm 1630向访客操作系统呈现虚拟操作平台并管理访客操作系统的执行。
[0221]
在一些情况下,vmm 1630可以允许访客操作系统如同其直接在计算机系统1500的裸硬件1620上运行一样运行。在这些实例中,被配置为直接在裸硬件1620上执行的访客操作系统的相同版本也可以在vmm 1630上执行而无需修改或重新配置。换句话说,vmm 1630可以在一些情况下向访客操作系统提供完全硬件和cpu虚拟化。
[0222]
在其它情况下,访客操作系统可以被专门设计或配置为在vmm1630上执行以提高效率。在这些实例中,访客操作系统“意识到”它在虚拟机监视器上执行。换句话说,vmm 1630可以在某些情况下向客户操作系统提供半虚拟化。
[0223]
计算机系统进程包括硬件处理器时间的分配,以及存储器的分配(物理和/或虚拟)、用于存储由硬件处理器执行的指令的存储器的分配,用于存储由硬件处理器执行指令所生成的数据,和/或用于当计算机系统进程未运行时在硬件处理器时间的分配之间存储硬件处理器状态(例如,寄存器的内容)。计算机系统进程在操作系统的控制下运行,并且可以在计算机系统上执行的其它程序的控制下运行。
[0224]
云计算
[0225]
本文一般地使用术语“云计算”来描述计算模型,该计算模型使得能够按需访问计算资源的共享池,诸如计算机网络、服务器、软件应用和服务,并且允许以最少的管理工作或服务提供商交互来快速提供和释放资源。
[0226]
云计算环境(有时称为云环境或云)可以以各种不同方式实现,以最好地适应不同要求。例如,在公共云环境中,底层计算基础设施由组织拥有,该组织使其云服务可供其它组织或公众使用。相反,私有云环境一般仅供单个组织使用或在单个组织内使用。社区云旨在由社区内的若干组织共享;而混合云包括通过数据和应用可移植性绑定在一起的两种或更多种类型的云(例如,私有、社区或公共)。
[0227]
一般而言,云计算模型使得先前可能由组织自己的信息技术部门提供的那些职责中的一些替代地作为云环境内的服务层来输送,以供消费者使用(根据云的公共/私人性质,在组织内部或外部)。取决于特定实现,由每个云服务层提供或在每个云服务层内提供的组件或特征的精确定义可以有所不同,但常见示例包括:软件即服务(saas),其中消费者使用在云基础设施上运行的软件应用,同时saas提供者管理或控制底层云基础设施和应用。平台即服务(paas),其中消费者可以使用由paas的供应者支持的软件编程语言和开发工具,以开发、部署和以其它方式控制它们自己的应用,同时paas提供者管理或控制云环境的其它方面(即,运行时执行环境下的一切)。基础设施即服务(iaas),其中消费者可以部署和运行任意软件应用,和/或提供进程、存储装置、网络和其它基础计算资源,同时iaas提供者管理或控制底层物理云基础设施(即,操作系统层下面的一切)。数据库即服务(dbaas),
其中消费者使用在云基础设施上运行的数据库服务器或数据库管理系统,同时dbaas提供者管理或控制底层云基础设施、应用和服务器,包括一个或多个数据库服务器。
[0228]
在前面的说明书中,已经参考因实现而异的许多具体细节描述了实施例。因此,说明书和附图应当被认为是说明性的而不是限制性的。本发明的范围的唯一且排他的指标以及申请人预期作为本发明的范围的内容是从本技术中发出的权利要求集合的字面和等同范围,以这种权利要求发出的具体形式,包括任何后续的更正。
再多了解一些

本文用于创业者技术爱好者查询,仅供学习研究,如用于商业用途,请联系技术所有人。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

相关文献