GNNAdvisor: GPU 上 GNN 加速的自适应高效运行时系统 [Paper] [Slides] [Code]
OSDI’21
提出了 GNNAdvisor, 一个用于加速 GPU 平台上各种 GNN 工作负载的自适应高效运行时系统.
GNN 突出特点: 在聚合阶段的图操作(scatter-and-gather) 和在更新阶段的神经网络(NN)操作(矩阵乘法)交错执行.
最先进的 GNN 框架遵循一刀切(one-size-fits-all, 通用适配)的实现方案.
先前 GNN 系统的不足:
提出了 GNNAdvisor, 一个用于 GPU 上 GNN 加速的自适应高效运行时系统.
单 GPU 系统; 前端: Pytorch; 底层: C++/CUDA 构建, 使用 Pytorch Wrapper 与 Pytorch 集成.
本文贡献:
基于第 k k k 层( k ≤ 0 k\leq 0 k≤0)的嵌入信息计算第 k + 1 k +1 k+1 层结点 v v v 特征向量的公式:
a v ( k + 1 ) = Aggregate ( k + 1 ) ( h u ( k ) ∣ u ∈ N ( v ) ∪ h v ( k ) ) h v ( k + 1 ) = Update ( k + 1 ) ( a v ( k + 1 ) ) \begin{aligned} &a_v^{(k+1)}=\textbf{Aggregate}^{(k+1)}(h_u^{(k)}|u\in\textbf{N}(v)\cup h_v^{(k)})\\ &h_v^{(k+1)}=\textbf{Update}^{(k+1)}(a_v^{(k+1)}) \end{aligned} av(k+1)=Aggregate(k+1)(hu(k)∣u∈N(v)∪hv(k))hv(k+1)=Update(k+1)(av(k+1))
扩展图处理系统支持 GNN 计算的挑战:
缺乏对 GNN 中的非欧几里德数据(如图)的支持. 扩展 NN 框架以支持作为输入的 GNN 的挑战:
GNN 两类主流聚合方法:
结点度数和嵌入维数:
工作负载大小如果由邻结点数量(如结点度数较大)主导, 可以定制能同时处理更多邻居的设计, 以增加邻居间的计算并行性; 如果由结点嵌入大小(如高维结点嵌入)主导, 可以考虑沿结点嵌入维度提高计算并行性.
图社区(Graph Community):
描述了一小组结点倾向于保持"强"组内连接(许多边), 同时与图的其余部分保持"弱"连接(更少的边).
在结点嵌入大小很大的 GNN 计算中, 以结点为中心的加载会触发大量不必要的内存访问, 因为重复邻居加载的开销占主导地位而不会被每个结点的并行性所抵消.
在 GPU 上利用图社区的关键: 通过利用 L1 缓存来有效地利用线程之间的数据局部性.
首先捕获图社区, 然后将此类局部性从输入级别(结点 ID 相邻)映射到底层 GPU 内核(线程/wrap/线程块 ID 相邻).
GNN 工作负载在两个主要维度上增长: 邻居数量和嵌入维度大小.
旨在解决: 结点间工作负载不平衡和冗余原子操作.
将结点的邻居分解为一组大小相等的邻居分组, 并将每个邻居分组(neighbor group, NG)的聚合工作负载作为调度的基本工作负载单位.
两个组件:
优点:
来沿嵌入维度进一步分配邻居分组的工作负载, 以提高聚合性能.
每个线程独立管理一维的聚合; 维度大小大于工作线程数则需多次迭代.
依据:
优点:
通过通过轻量级结点重编号重新排列结点 ID, 以改进 GNN 聚合期间的时间/空间局部性.
何时应用:
对于形状更不规则的图, 而非邻接矩阵已近似块对角模式的图, 重排序可以带来显著的性能改进.
确定图重排序是否有益的度量标准: 平均边跨度(Average Edge Span, AES):
AES = 1 # E ∑ ( s r c i d , t r g i d ) ∈ E ∣ s r c i d − t r g i d ∣ \textbf{AES}=\frac{1}{\#E}\sum\limits_{(src_{id},trg_{id})\in E}|src_{id}-trg_{id}| AES=#E1(srcid,trgid)∈E∑∣srcid−trgid∣
当 A E S > ⌊ # N 100 ⌋ \sqrt{AES}>\lfloor\frac{\sqrt{\#N}}{100}\rfloor AES>⌊100#N⌋ 时结点重编号更可能提高运行时性能.
如何应用:
利用 Rabbit Reordering, 一种完全并行且低开销的图重排序技术.
以 warp 为中心的共享内存优化技术. 根据块级 warp 的组织模式定制共享内存布局, 以显着减少原子操作和全局内存访问的数量.
(注: 算法 11 行和 14 行的 l o c a l _ c n t local\_cnt local_cnt 笔者认为更可能是 l o c a l _ c n t × D i m local\_cnt\times Dim local_cnt×Dim, 因为每个 warp 计算的中间结果大小为嵌入维度 D i m Dim Dim.)
每个 warp (在 w a r p P t r warpPtr warpPtr 中维护) 具有三个属性: n o d e S h a r e d A d d r nodeSharedAddr nodeSharedAddr (邻居分组聚合结果的共享内存地址)、 n o d e I D nodeID nodeID (目标结点ID)、和 l e a d e r leader leader (布尔标志, 指示当前 warp 是否为leader warp).
分析建模:
每线程工作负载(workload per thread, WPT)和每线程块共享内存使用率(shared memory usage per block, SMEM):
WPT = n g s × D i m d w , SMEM = t p b t p w × D i m × F l o a t S \textbf{WPT}=ngs\times \frac{Dim}{dw},\quad \textbf{SMEM}=\frac{tpb}{tpw}\times Dim\times FloatS WPT=ngs×dwDim,SMEM=tpwtpb×Dim×FloatS
参数自动选择:
各种优化的性能提升: Figure 12
额外研究: Figure 13, Figure 14
本文的核心在于通过探索 GNN 输入信息, 提出了包括 2D 工作负载管理和 GPU 上的专用内存定制的一组 GNN 定制的系统优化, ; 并结合了分析建模和参数自动选择.