APP下载

一种适合Tegra K1架构的Top-k查询优化算法

2020-02-02李靓琦黄玉龙谢绍国

电子技术与软件工程 2020年17期
关键词:下界数组线程

李靓琦 黄玉龙 谢绍国

(1.吉安职业技术学院机械与电子工程学院 江西省吉安市 343000)

(2.新余学院数学与计算机学院 江西省新余市 338004 3.安庆师范大学计算机与信息学院 安徽省安庆市 246133)

1 引言

在当今移动互联网时代,NVIDIA 推出了拥有192 个CUDA[1]核心的嵌入式GPU — Tegra K1 来提升移动应用性能。禁止随机访问的Top-k 查询为信息检索领域的典型问题,在移动应用中得到了广泛使用。作为禁止随机读的代表性算法--NRA 算法[2]使用分值上下界逐次逼近策略,算法可在未获取所有对象的准确聚合分值前获得最终结果。为了减少计算代价,Guntzer 以及Mamoulis 等分别提出了SC 算法[3]及LARA 算法[4]。为了充分利用台式GPU 的计算性能,黄玉龙等提出了分段Top-k 查询算法[5]。然而,由于嵌入式硬件GPU 与CPU 共享运行内存等特点,这些算法均不能适应在Tegra TK1 上运行。为此,本文提出了一种适合Tegra K1 架构的查询优化算法。

2 共享内存的CUDA模型

在CUDA 编程模型中,通常需将CPU 看作是主机,将GPU看作是设备。为此,可将程序分为两类:一种是运行在CPU 上的宿主代码,另一种为GPU 执行的设备代码。由于CPU 和GPU 在硬件架构上存在差异,这两类代码可访问的资源是不一样的。

与传统架构不同,嵌入式GPGPU 与CPU 共享运行内存,即:基于嵌入式GPGPU 算法的执行时间T= Th+Td。其中,Th表示host端执行时间,而Td为device 端执行时间。

3 查询优化算法

由文献[1]可知:Top-k 查询就是在规模为m 的空间中找出聚合分值最高的k 个对象。其中,每个对象由n 个属性组成且所有对象在属性i 下的得分降序保存到一规模为m 的列表Li。其中,每个存储位的结构为(id,score)。由于CUDA 适合处理线性结构,在此将输入数据数组合并为一个m*n 的一维数组L。为了存储候选结果,算法执行前需分配一个长度为k 的对象集合Ck。集合中每个元素的结构为(oID,w,b,visited)。其中,oID 为标识符,b 和w 分别表示分值上下界,visited 位图则记录对象的访问状况。此外,为记录集合Ck外的已访问对象,还需分配一个变长对象数组Ck。同理,在此将集合Ck与Ck合并为集合C。为了尽可能地利用Tegra K1 的线程资源,我们的算法还采用分段执行策略。即,一次执行有序列表STRIDE个层次。基于以上定义,下面分两个阶段阐述查询优化算法。

3.1 扩展阶段

开始时,数组C 为空,在此仅需将读到的数组L 中的元素简单插入集合C 即可,具体流程为:循环批量读取L 中元素及下标。在此,可将读取到的元素分为两类:一类是从未读取过。对于此类元素,直接将其插入数组C 即可。另一类元素是数组C 保存对象的属性值。对于此类元素,需要更新相关对象的访问状况并且更新其分值下界b,直至数组C 的长度大于等于k 为止。此阶段的具体思想如下:

For each tid∈[0,STRIDE ) parallel do item ←L[tid].id; //tid 为线程编号if(item.id ≠obj.oID)// obj 为数组C 中的对象obj.oID=item.id;obj.w=item.score;将obj 追加到数组C 末尾;else obj.w=obj.w+item.score;//更新对象obj 的分值下界end if更新obj 的visited 位图;End parallel for使用thrust 库[5]中的sort_by_key 原语排序数组C;

此时,在host 端将当前阈值T 与数组C 末尾对象的分值下界进行比较,如大于等于,则算法进入下一阶段。否则,继续批量访问数组L,直至数组C 末尾对象的分值下界大于等于当前阈值为止。

3.2 剪枝阶段

此阶段,数组L 的对象个数将维持不变。访问中,如遇到上阶段从未访问的对象,则不予处理。为了减少比较次数,在此使用类似SC 算法策略,仅维护分值上界即可。为了充分利用GPU 的性能,在此亦采用相似批量处理策略循环执行。同样地,此阶段一次遍历数组L 中STRIDE 个元素且每次遍历的流程如下:

(1)并行获取L 中从第 j 到 j + STRIDE 层所有元素及下标;//j为上阶段访问的层次。

(2)更新数组C 中相关对象的分值下界及访问状况visited 位图;

图1:算法执行时间

图2:算法的加速比

(3)如果数组C 存在k 个或以上对象的聚合分值完全确定,则执行步骤4;

(4)并行获取数组C 中已确定聚合分值的对象到临时数组tmp;

(5)并行删除数组C 中相应位置对象;

(6)使用thrust[5]库中的sort_by_key 原语排序tmp 以及C 数组;

(7)如果tmp[k-1]的分值score 大于等于C[0]的分值上界b,则算法结束,tmp 数组前k 个对象即为查询结果;否则,重复执行步骤1~6,直至算法结束。

由此可知,本文提出的算法在综合LARA 及SC 算法的优点基础上,充分利用了Tegra K1 GPU 强大的线程资源,可快速获得查询结果。与此同时,考虑到Tegra K1 与CPU 共享内存的特点,使用位图结构记录对象访问状态,从而可处理更大规模的查询。

4 性能分析

为了验证本文算法的有效性,在嵌入式开发板Jetson-TK1 上进行了实验。开发板硬件配置为:CPU 为 ARM Cortex-A15,主频为1.3GHz;GPU 为拥有192 个CUDA 核心的Tegra K1,每个核心主频为0.825GHz。CPU 与GPU 共享2GB 运行内存;操作系统为Ubuntu14.04,CUDA 工具包为6.5 版本。实验数据集为随机生成的均匀分布数据,其中,每个对象的属性分值都服从(0,1)分布。基于此,随机生成了1M、2M、4M、6M、8M 以及10M 规模的实验数据,每个对象包含了4 个属性。算法返回的对象数量100;分值计算函数为∑ ui(0 ≤i<m),m 为有序列表数量。STRIDE 步长为100。根据上述规定,下面给出了算法的具体执行时间以及算法的加速比,分别如图1 和2所示。

由图1 可知,在一次访问100 个输入元素基础上,我们的算法在10M 规模数据集上执行top-100 查询,可在2 秒内完成,这样的性能非常适合在大规模集合上执行top-k 查询。从图2 中可以得知,与单线程CPU 算法比较,我们的算法可以获得2.7 至3.8 倍的加速比,这主要因为虽然Tegra K1 的计算核心数量众多,但工作频率低且算法中存在多处线程同步,需要消耗大量通信代价。

5 结论

作为信息检索的一个经典问题,Top-k 查询在移动应用中得到了广泛使用。为了提高移动应用的查询性能,NVIDIA 公司推出了一个拥有192 个计算核心的Tegra K1 GPU。为此,本文研究了一种适合Tegra K1 架构的分段查询算法。结合LARA 以及SC 算法的优势,本文的算法在10M 规模对象中查找出100 个最高分值对象的过程可在2 秒钟内完成。与单线程CPU 算法比较,本文的算法有着显著的性能提升。

猜你喜欢

下界数组线程
JAVA稀疏矩阵算法
JAVA玩转数学之二维数组排序
Lower bound estimation of the maximum allowable initial error and its numerical calculation
Excel数组公式在林业多条件求和中的应用
浅谈linux多线程协作
寻找勾股数组的历程
矩阵Hadamard积的上下界序列
最大度为10的边染色临界图边数的新下界
常维码的一个构造性下界
基于上下文定界的Fork/Join并行性的并发程序可达性分析*