背景介绍

上图是一个GPU上的图架构的简单表示。硬件层来说GPU上的全局内存与主机内存相通,可以进行数据传输;GPU上有许多流多处理器(SM),每个流多处理器上有自己若干个核和自己的片上缓存,是相对独立的单元。软件层次上,程序员启动核函数(grid),其中包括多个block,每个block上又有若干warp。Block是依赖于流多处理器的,每个block只会运行于一个流多处理器。值得一提的是,每个warp中包含32个线程,这32个线程是按照严格单指令多线程的形式运行的,是严格的同步关系,因而warp内部线程在运行代码遇到分支或者循环结构时的线程发散会导致warp内部分线程的空闲,并且warp内线程执行的任务量的不均衡会导致很严重的线程发散,因为所有线程都在等待运行时间最长的线程结束。
线程发散是我们试图寻找更好的任务分配方式的初衷,更好的任务分配方式能够保证更少的线程发散,从而提升整体性能。
例子:
首先我们会以三角形计数为例子,讲解什么是更好的任务分配方式。论文1: GPU-based Graph Traversal on Compressed Graphs
SIGMOD 2019
本文设计了一个GCGT的图处理系统,针对的是大规模图中的并行算法,并且算法中包含“扩张—过滤—压缩”的过程。
上图算法一中给出了一个直观的算法,每个线程负责处理一个点的邻接表,直接扩展这个邻接表中的所有节点。跟例子中介绍的直观三角形计数算法影响,由于图的power-law的性质,线程之间会存在比较明显的工作量负载不均衡的情况。


论文2: High Performance and Scalable GPU Graph Traversal
TOPC 2015
本文中使用到任务动态分配的部分,也仅仅是从邻接表中收集邻居的部分。详细来说,对于一个BFS过程,这个算法仅仅从一系列邻接表中读进来所有的邻居,并且加载进本地存储或寄存器中。接下来我们比较几种实现。
1. 顺序读取
每个线程获取一个邻接表的起始和终止范围,然后负责记载这个邻接表中的所有元素。很显然,这是一个非常naïve的想法,线程的负载均衡会很差。
2. 粗粒度的,warp协同的方法
下图算法5中展示了warp协同的方法,warp中的线程竞争warp的控制权,竞争的胜利者将自己的任务广播给warp中所有的线程,大家一起完成该任务,然后重复“竞争-广播-协作”的过程。
此方法中,warp内每个线程的工作都是由整个warp内所有的线程协同完成的,比较好地均衡分配了任务。
3. 细粒度的,基于scan的方法
下图展示了基于scan的方法的算法流程。这个方法中,将一个block中所有的线程获得的邻接表都拼接到一起,然后所有block中的线程协作处理这个拼接完成后的表。这个算法比上一个算法更好的地方在于协调了整个block内线程的工作负载,但是也有额外的拼接代价。
4. Scan+warp 协调+block协调的方式。
1) 邻接表长度非常大的线程首先竞争整个block的控制权,整个block的运算资源都一起处理这个邻接表。
2) 剩下的线程中,邻接表长度适中的,线程竞争warp控制权,整个warp协作处理。
3) 最后剩下工作量比较小的线程,所有的任务拼接到一起,由整个block协作完成。
这个算法很好地协调了整个block内的工作负载的均衡性,又减少了大量拼接的代价,是最优的解决方案。从下面的三个性能指标中也能看出来,上面几种算法的性能,以及跟最优性能之间的差异。论文3:Update on Triangle Counting on GPU
HPEC 2019
这篇文章研究的是GPU上的三角形计数算法,其中naïve的三角形计数的任务分配在前面已经介绍过了,使用一个线程处理一条边。下面的算法1就是这种实现的伪代码。
总结
动态任务分配是GPU上进行图计算任务中一种比较好的任务分配方式,可以使线程之间的工作量更加均衡,很好解决图的不规则形带来的问题,并且能够减少线程的发散,实际上也有更好的合并访存效果。这种方法也不是完美的,动态计算需要额外的计算开销,以便得到线程各自的任务。当然这种负面影响完全可以被所带来的性能提升抵消。综合而言,这种方法还是非常值得我们学习和借鉴。参考文献
[1] J. Fox, O. Green, K. Gabert, X. An, and D. A. Bader. Fast and adaptive list intersections on the gpu. In 2018 IEEE High Performance extreme Computing Conference (HPEC), pages 1–7. IEEE, 2018. [2] O. Green, J. Fox, A. Watkins, A. Tripathy, K. Gabert, E. Kim, X. An, K. Aatish, and D. A. Bader. Logarithmic radix binning and vectorized triangle counting. In 2018 IEEE High Performance extreme Computing Conference (HPEC), pages 1–7. IEEE, 2018.[3] Sha M, Li Y, Tan K, et al. GPU-based Graph Traversal on Compressed Graphs[C]. international conference on management of data, 2019: 775-792.[4] Duane Merrill, Michael Garland, and Andrew Grimshaw. 2015. High-Performance and Scalable GPU Graph Traversal. ACM Trans. Parallel Comput. 1, 2, Article 14 (January 2015), 30 pages.[5] C. Pearson et al., "Update on Triangle Counting on GPU," 2019 IEEE High Performance Extreme Computing Conference (HPEC), Waltham, MA, USA, 2019, pp. 1-7, doi: 10.1109/HPEC.2019.8916547.