Graphiler系列(三):论文背景及现有系统问题
1、GNNs 消息传递范式
GNN消息传递范式三个阶段:(同质图)
-
消息创建: 每个边通过将一个摆振倾角消息函数φ应用到自己的特征以及两个端点的特征中产生一条消息。
-
消息聚合: 每个节点使用聚合函数ρ对来自传入边的消息进行聚合。
-
特征更新: 每个节点使用逐节点更新函数ψ更新其特征。
扩展到异构图:(具有多种点和边类型)eg.对引文网络建模
-
定义:
-
两种类型的节点:作者和论文
-
两种类型的边:
-
在一个作者节点和一个论文节点之间代表作者身份;
-
在一对论文节点之间代表引文
-
-
-
异构图的消息传递范式:
2、两个运行实例:GAT和HGT
图注意力网络(GAT)和它的异构GNN对应的异构图转换器(HGT)
-
两种模型的主要区别在于消息创建阶段:
-
GAT和HGT共享相同的消息聚合函数,每个节点接收来自传入边的消息并产生一个聚合结果r:
-
在特征更新阶段,每个节点的特征通过一个激活函数σ进行更新;为了便于阐述,我们省略了在HGT中执行的复杂更新。
3、当前GNN系统的性能问题
图1 ( a )给出了GAT和HGT在DGL的UDF接口中的简化实现,其中每一行代码都与§ 2.2中的一个方程相关联。其他框架如PyG采用了类似的设计。
3.1 消息创建中的冗余
-
消息创建过程中产生数据冗余。
-
在真实图中,当许多节点共享相同类型(即| A | < < | V |),而节点具有较高的度(即| V | < < | E |)时,这种数据冗余更严重。
在第10行代码中,edge.src[ ’ h ']从存储所有节点表示的节点张量中查找每条边的源节点表示。同样,边srctype[‘Wk’]根据每条边的源节点类型聚集权重矩阵,如图1 ( b )所示。
图1 ( b )显示了不同源数据使用不同颜色产生的消息,并说明了产生的数据冗余。
这种冗余在真实图中可能非常严重,因为许多节点可能共享相同类型的(即| A | < < | V |),而节点可能具有较高的度(即| V | < < | E |)。
3.2 消息聚合中的碎片化计算
产生碎片化的原因:
-
节点具有不同的度,他们可以接收不同数量的消息,使得聚合过程中批处理变得困难。
- “装桶”策略,将消息张量分解为多个片段,每个片段将接收相同数量消息的节点分组在一起
-
异构GNN,需要对不同节点类型的消息进行不同的聚合
- 系统进一步根据目的节点类型对消息张量进行切分并循环
消息聚合UDF聚合函数(图1 ( a ),第19 - 24行)为用户提供了以节点为中心的视图。用户可以访问由消息创建UDF计算的消息以及使用节点参数的节点表示。由于节点可能具有不同的度,它们可以接收不同数量的消息,这使得聚合过程中的批处理变得困难。为了解决这个问题,DGL在内部将消息张量分解成多个片段,每个片段将接收相同数量消息的节点分组在一起。这种"装桶"策略使得在聚合UDF中应用任意张量操作成为可能。然后系统调用每个消息张量片上的聚合函数来获得所有节点的聚合消息。在异构GNN中,如果用户希望对不同节点类型的消息进行不同的聚合,系统会进一步根据目的节点类型对消息张量进行切分并循环。然而,切分消息张量会导致计算碎片化,并导致GPU利用率低、内核启动开销大等性能问题。
3.3 为了性能而牺牲表现力
为了规避性能问题,当前所有GNN框架都不同程度的限制其表达能力。例如:
-
PyG禁止使用聚合UDF,从而避免了碎片化计算的问题;
-
DGL推荐用一组内置的消息创建和聚合原语来表达模型;如果消息创建和聚合函数都从内置集合中选择,DGL将两个阶段进行融合,完全绕过任何消息创建。
产生问题:
-
DGL的方法需要大量的内置原语来实现良好的模型覆盖率,所需的工程量在实际中往往是不可行的。
-
即使在可行的情况下对一个模型在现有的原语中进行编程,用户需要理解并使用原语是困难的。
图2展示了DGL开发人员如何构建无UDF的GAT模型以获得更好的性能。
通过与图1 ( a )的对比,我们可以观察到用户需要谨慎地管理与同一范围内节点和边相关的数据,并额外地将熟悉的张量算子(例如concat和softmax)分解为高效但非直观的原语。
3.4 论文方法产生动机和核心思想
产生动机:
-
UDFs提供了高度的表现力和良好的面向用户接口 —— 灵活性
-
内置原语是针对系统性能的一种良好的低级接口 —— 性能
-
因此,我们构建了Graphiler作为编译器栈来搭建桥,从而提供两者的好处。
核心思想和算法问题:
Graphiler设计中的一个关键见解是,GNN计算中最需要计算的部分,即消息收集和聚合,可以与数据存储类型的变化相关联,我们称之为数据驻留。例如:例如,edge.src[ ’ h ']将概念上在节点的表示转换为在边上的消息,而edge.srctype[ ’ Wk ']将驻留在节点类型中的权重转换为边上的消息。类似地,消息聚合将边上的消息转换为新的节点表示。
因此,Graphiler关注的主要算法问题是 检测数据驻留变化,并根据变化推导优化。