Scaph: Scalable GPU-Accelerated Graph Processing with Value-Driven Differential Scheduling
Scaph: 具有价值驱动差分调度的可扩展 GPU 加速图处理 [Paper] [Slides] [Code]
ATC’20
摘要
提出了 Scaph, 一个 GPU 加速的图系统, 实现了对大规模图的可扩展图处理.
- Scaph 通过减少传输冗余数据(仅有激活结点的邻域信息被使用而传输整个子图)大幅提高了主机-GPU带宽利用率, 从而显著提高了性能.
- Scaph 的关键新颖点是在每次迭代时自适应地分类子图是高价值子图(可能在当前和未来的迭代中被广泛遍历)还是低价值子图(反之).
- Scaph 使用两个图处理引擎调度子图在 GPU 上进行图处理: 一个用于高价值子图, 其将被完全流式传输到 GPU 并反复迭代; 一个用于低价值子图, 只传输其激活结点所需的邻域信息.
1 介绍
目前 GPU 加速的图系统的性能瓶颈是有限的主机-GPU 带宽.
现有图系统总是将激活子图完整地传输到 GPU(即使通常只使用其激活顶点的邻域信息), 导致主机-GPU 带宽利用低下.
本文通过通过提高主机-GPU 带宽的有效利用率来显着提高 GPU 加速架构上大规模图处理的性能.
主要观察: 激活子图的大部分数据(一旦流式传输到 GPU)从未在当前和未来的迭代中被使用.
提出了 Scaph:
- 通过对激活子图采用价值驱动的差分调度实现性能提高
- 关键的新颖点是自适应地将激活子图分类为高价值子图(可能在当前和未来的迭代中被广泛遍历)和低价值子图(反之).
- 使用分别处理高价值子图和低价值子图的两个图处理引擎将激活子图流式传输至 GPU.
- 高价值子图完全转移至 GPU, 多次计算以提前利用其 PUD(potentially useful data, 潜在有用数据) 来加速收敛.
提出了一种 GPU 上下文友好的延迟调度, 以实现 GPU 上跨子图利用 PUD - 低价值子图只传输和调度激活结点的邻域信息一次.
- 高价值子图完全转移至 GPU, 多次计算以提前利用其 PUD(potentially useful data, 潜在有用数据) 来加速收敛.
文章贡献:
- 子图价值表征. 根据当前和未来迭代中使用的 UD(useful data, 有用数据) 和 PUD 自适应地(动态地)量化子图的价值.
- 价值驱动的差分调度. 提出了一种在每次迭代中自适应区分高价值子图和低价值子图并将子图调度到合适图处理引擎加速的调度器.
- 价值驱动的图处理引擎. 引入了两个图处理引擎分别处理高价值子图和低价值子图, 以在每种情况下最大限度有效利用主机-GPU 带宽.
- 评估. Scaph 优于最先进的异构图系统.
2 背景和动机
2.1 主机-GPU 异构架构
2.2 动机研究
现有图异构系统: 使用主机内存存储大规模图(划分为子图) 并完全在 GPU 上加速图分析.
将整个子图传输到 GPU 但仅处理数据中的一小部分, 浪费了大量主机-GPU 带宽, 使所需的数据无法及时到达 GPU 从而限制了 GPU 的性能.
不足的数据提供与 GPU 高速计算之间存在显著差距.
2.3 价值驱动的子图调度
激活结点角度下的三类边数据:
- 有用数据(Useful Data, UD): 与激活结点相连的边数据. 肯定会在当前迭代使用, 必须传输至 GPU.
- 潜在有用数据(Potentially Useful Data, PUD): 与子图未来迭代中所有未来激活结点相连的边数据. 在当前迭代中并未使用, 但可能重复传输至 GPU.
- 从未使用数据(Never Used Data, NUD): 不会再次使用的边数据. 与已收敛的结点相连, 不会被激活.
给定一个子图, 其在不同迭代中计算的 UD、PUD 和 NUD 会动态变化. 只流式传输 UD 不划算, 因为 PUD 不能被同时利用.
提高主机-GPU 带宽有效利用率的关键见解: 不仅考虑当前迭代中的 UD, 还考虑未来迭代中的 PUD.
目标: 在迭代图处理中利用而非丢弃其 PUD.
迭代子图的价值根据其 UD 和 PUD 来衡量.
从子图中精确提取 PUD 是困难的, 因为在当前迭代期间其未来的激活结点尚不清楚.
本文提出根据当前和过去迭代中的 UD 大小预测一次迭代中的 PUD 大小.
3 Scaph 概览
- 价值驱动子图分配器: 子图在给定迭代的价值与其 UD 和 PUD 的数量成正比.
子图分配器自适应地将包含足够数量 UD 和 PUD 的子图分类为高价值子图, 子图将被整体传输至 GPU; 反之, 分类为低价值子图, 仅将子图的 UD 传输至 GPU. - 价值驱动子图调度: Scaph 有两个独立的图处理引擎用于分别处理高价值子图和低价值子图.
- 高价值子图: 使用队列辅助多轮(queue-assisted multi-round)处理引擎, 完全传输到 GPU(如果不在 GPU 内存中), 充分利用其 UD 和 PUD 以实现更快的收敛.
- 低价值子图: 仅将其 UD 传输到 GPU, 在主机上以 NUMA 感知方式提取 UD.
Scaph 是一个混合图系统, 允许在每次同步迭代中对高价值子图乱序计算.
图算法满足最终结点结果对值传播顺序不敏感的正确性条件, 可安全使用 Scaph.
4 价值驱动的子图分配
4.1 量化子图价值
从当前迭代
C
u
r
Cur
Cur 到第
M
A
X
MAX
MAX 迭代, 子图
G
~
\tilde{G}
G~ 的价值:
V
a
l
(
G
~
)
=
∑
i
=
C
u
r
M
A
X
∑
v
∈
G
~
.
S
e
t
O
f
V
e
r
t
i
c
e
s
D
(
v
)
∗
A
i
(
v
)
Val(\tilde{G})=\sum_{i=Cur}^{MAX}\sum_{v\in \tilde{G}.SetOfVertices}D(v)*A^i(v)
Val(G~)=i=Cur∑MAXv∈G~.SetOfVertices∑D(v)∗Ai(v)
表示从当前迭代到收敛
G
~
\tilde{G}
G~ 产生的计算量.
- D ( v ) D(v) D(v): G ~ \tilde{G} G~ 中结点 v v v 的出边数量(出度)
- A i ( v ) ∈ { 0 , 1 } A^i(v)\in\{0,1\} Ai(v)∈{0,1}: 在第 i i i 次迭代时结点 v v v 是否激活
4.2 价值驱动的差分调度
G
~
\tilde{G}
G~ 是高价值子图时, GPU 上处理
G
~
\tilde{G}
G~ 的吞吐量的测量公式:
T
H
V
(
G
~
)
=
∣
U
D
∣
+
λ
∣
P
U
D
∣
∣
G
~
∣
/
B
W
+
t
b
a
r
r
i
e
r
T_{HV}(\tilde{G})=\frac{|UD|+\lambda|PUD|}{|\tilde{G}|/BW+t_{barrier}}
THV(G~)=∣G~∣/BW+tbarrier∣UD∣+λ∣PUD∣
- 分母
∣
G
~
∣
/
B
W
+
t
b
a
r
r
i
e
r
|\tilde{G}|/BW+t_{barrier}
∣G~∣/BW+tbarrier:
G
~
\tilde{G}
G~ 的传输时间, 通过假设 GPU 上数据传输和计算完全重叠来近似处理
G
~
\tilde{G}
G~ 的时间.
- ∣ G ~ ∣ |\tilde{G}| ∣G~∣: G ~ \tilde{G} G~ 被全部传输至 GPU 的数据量
- B W BW BW: 主机-GPU 带宽
- t b a r r i e r t_{barrier} tbarrier: G ~ \tilde{G} G~ 的同步开销(按处理的激活子图数摊销)
- 分子
∣
U
D
∣
+
λ
∣
P
U
D
∣
|UD|+\lambda|PUD|
∣UD∣+λ∣PUD∣:
G
~
\tilde{G}
G~ 在 GPU 上迭代时访问的 UD 和 PUD 的数量.
- 0 ≤ λ ≤ 1 0\leq\lambda\leq1 0≤λ≤1: 平衡因子, 表示实际访问的 PUD 的数量
G
~
\tilde{G}
G~ 是低价值子图时, GPU 上处理
G
~
\tilde{G}
G~ 的吞吐量的测量公式:
T
L
V
(
G
~
)
=
∣
U
D
∣
∣
U
D
∣
/
B
W
+
t
b
a
r
r
i
e
r
T_{LV}(\tilde{G})=\frac{|UD|}{|UD|/BW+t_{barrier}}
TLV(G~)=∣UD∣/BW+tbarrier∣UD∣
若
T
H
V
(
G
~
)
≥
T
L
V
T_{HV}(\tilde{G})\geq T_{LV}
THV(G~)≥TLV (比较高低价值子图传输的吞吐量), 则
G
~
\tilde{G}
G~ 是高价值子图, 反之为低价值子图. 需要分析:
∣
U
D
∣
+
λ
∣
P
U
D
∣
(
1
+
t
b
a
r
r
i
e
r
∣
U
D
∣
/
B
W
)
>
∣
G
~
∣
|UD|+\lambda|PUD|(1+\frac{t_{barrier}}{|UD|/BW})> |\tilde{G}|
∣UD∣+λ∣PUD∣(1+∣UD∣/BWtbarrier)>∣G~∣
关键取决于
∣
P
U
D
∣
|PUD|
∣PUD∣.
在本文工作中, 满足以下两个条件之一则被认为子图具有高价值:
- ∣ U D ∣ / ∣ G ~ ∣ > α |UD|/|\tilde{G}|> \alpha ∣UD∣/∣G~∣>α: UD 在 G ~ \tilde{G} G~ 中占主导地位.
- ∣ U D c u r r e n t ∣ − ∣ U D l a s t ∣ > 0 |UD_{current}|-|UD_{last}|>0 ∣UDcurrent∣−∣UDlast∣>0 且 ∣ U D ∣ / G ~ > β |UD|/\tilde{G}>\beta ∣UD∣/G~>β: UD 保持在中等水平且随着迭代不断增长, 表明潜在的 PUD 增长.
α \alpha α 和 β \beta β 根据经验设置为 50% 和 30%.
价值驱动的差分调度器:
两个图处理引擎 HVSPEngine()
和 LVSPEngine()
独立且并行工作.
5 价值驱动的子图处理
5.1 高价值子图处理
通过跨子图利用外部值(external value)显著提高了 PUD 的利用率.
关键观察: 给定 GPU 内存中的可用子图, 在延迟一段时间后再次调度比重复处理可以更充分地暴露其 PUD. 利用这种 PUD 可以实现更快的收敛.
HVSPEngine()
包含并发执行的两个模块: 子图传输(Subgraph Transferring)和子图调度(Subgraph Scheduling).
队列辅助多轮处理(Queue-Assisted Multi-Round Processing):
使用
k
k
k 级优先队列
(
P
Q
1
,
.
.
.
,
P
Q
k
)
(PQ_1, ..., PQ_k)
(PQ1,...,PQk) 在一段延迟之后重新调度在 GPU 中驻留的子图.
k
k
k 表示当前迭代中处理子图的最大次数, 随迭代而变化.
调度器具有多级优先队列, 确保子图得到公平的调度, 避免太多无用计算, 即结点数据被计算但没有更新.
时间和空间复杂度分析:
k
k
k 受
B
W
′
B
W
\frac{BW'}{BW}
BWBW′ 限制. 其中,
B
W
′
BW'
BW′ 为 GPU 内部带宽,
B
W
BW
BW 为主机-GPU 带宽. 通常
k
≤
20
k\leq20
k≤20.
最差空间复杂度:
O
(
M
e
m
G
P
U
×
s
i
z
e
o
f
(
S
u
b
g
r
a
p
h
I
n
d
e
x
)
∣
G
~
∣
)
O(\frac{Mem_{GPU}\times sizeof(SubgraphIndex)}{|\tilde{G}|})
O(∣G~∣MemGPU×sizeof(SubgraphIndex)). 其中,
M
e
m
G
P
U
Mem_{GPU}
MemGPU 为 GPU 全局内存大小,
∣
G
~
∣
|\tilde{G}|
∣G~∣ 为子图
G
~
\tilde{G}
G~ 的大小.
5.2 低价值子图处理
LVSPEngine()
包含并发执行的三个模块: UD 提取(UD Extraction), 子图传输(Subgraph Transferring), 和子图调度(Subgraph Scheduling). 主要贡献是 NUMA 感知的并行 UD 提取.
UD 提取:
在主机上使用多个 CPU 内核来并行 UD 提取.
子图均匀分布于不同 NUMA 节点.
- NUMA 感知的负载均衡:
为了提高性能和改善节点内负载均衡: 每个子图的 UD 提取在其自己的线程中完成, 该线程绑定到存储该子图的 NUMA 节点.
为了改善节点间负载均衡: 在 NUMA 节点中复制来自其他节点的相同数量的随机选择的子图(如果仍有一些可用内存空间). - 基于位图的 UD 提取:
采用一种简单的基于位图的方法来从子图 G ~ \tilde{G} G~ 中提取 UD. 所有结点存储在 V e r t e x S t a t e s ( G ~ ) . b i t m a p VertexStates(\tilde{G}).bitmap VertexStates(G~).bitmap 中, 1/0 表示结点激活/非激活; 在 GPU 上计算激活结点总数. - 为了减少(经 UD 提取的)不同大小的 UD 诱导子图所带来的碎片, Scaph 将存储子图的每个分块(chunk)进一步划分为更小的分片(tile).
存储子图时, 先尝试存在部分填充分块中的连续分片中, 再寻找空闲分块.
6 评估
性能: Table 3
价值驱动的差分调度带来的性能提升: Figure 13
扩展性: Figure 14
额外运行时开销: Figure 15
局限: 子图划分策略(贪婪的结点切割的划分); 基于磁盘(需要图能放入主机内存); 性能收益(不支持激活结点集不会随着计算缩小的算法).
笔者总结
本文的核心在于通过在迭代时将子图分类为高价值子图和低价值子图, 对两种价值的子图进行差分调度和处理(高价值子图完全传输到 GPU 并反复迭代, 低价值子图只传输其激活结点所需的邻域信息), 从而提高了主机-GPU 带宽的有效利用率.
Scaph 属于单机 GPU 图计算系统.