Closed jasperzhong closed 11 months ago
HetG可以理解为是a collection of graphs,每一个relation是一个graph. 传统的做法是将HomoGNN模型如GCN用于每个HetG decomposed出来的homo subgraph上. 比如DGL的RGAT可以分解成多个GAT.
# homogeneous model
conv = nn.GATConv(...)
# heterogeneous model
convs = nn.HeteroGraphConv({
'paper_cite_paper': nn.GATConv(...),
'author_write_paper': nn.GATConv(...),
}, aggregate=’sum’)
现有的系统把HomoGNN layers当作HetGNN的building blocks. 有两个问题
于是他们提出了HGL,将HomoGNN和HetGNN用Holistic Intermediate Representation (HIR)来表示,用HIR来表示HomoGNN/HetGNN的计算图DAG后,又用tailored optimizations: graph stitching, operator fusion和operator bundling来进行优化. HIR只包括了forward computation.
HIR这个描述有点抽象. 看代码可能更直接一些.
HGL中DGLGraph如何表示?调用dgl.DGLGraph.adj_external(),对每个etype转成csr. HomoGraph只有一个CSR,HeteGraph每个relation有一个CSR.
tracer很有意思,继承了torch tensor,然后实现了__torch_function__()
.
https://pytorch.org/docs/stable/notes/extending.html#subclassing-torch-tensor
这种写法是每次调用pytorch tensor operation的时候,都会执行这一段,有点像一个wrapper. 这个tracer在这里面记录了function name, args, kwargs等等信息,然后用做一次forward pass,得到一个DAG. 然后walk这个DAG,转成他们自己的IR,这个IR除了包括一些常见的op (add/sub/mul etc),还包括tensor, graph, OpVertFunc, OpEdgeFunc. 这个IR和普通DNN的IR最重要区别是多了几个GNN的概念: OpVertFunc/OpEdgeFunc的输入是一个HomoGraph,HeteGraph在IR里面是拆成了多个HomoGraph.
这个IR怎么执行,就是walk一边这个DAG,遇到什么op就执行对应的kernel(可能是pytorch的,可能是他自己写的fused kernel)
有了HIR后就做了三件事:
另一个省略掉copy_u步骤,比如DGL的GCN的message passing先有一个copy_u('h', 'm'),然后aggregate_sum('m', 'v'),这里fuse起来就是跳过copy_u这一步,直接aggregate_sum.
后面ablation study显示,vertical fusion非常有用,horizontal fusion效果不显著.
这里不太明白为什么不直接全部fuse,而是分成多个bin fuse?为了给后面留一点优化空间?
cublasSgemmStridedBatched
这个API. (为啥Table VI显示R-GCN也能用这个优化?)
实验
HomoGNN也是有一些收益的,不是很大. HeteGNN收益非常显著,但都是在很小KG图上跑的.
这个ablation study也很重要. 可以看到主要收益来自于graph stitching和vertical fusion.
换成ogbn-mag效果还能有多少?
结果是容易OOM....
https://dl.acm.org/doi/abs/10.5555/3571885.3571980
https://github.com/ytgui/HGL-proto/tree/master