需要在数千节点的图上反复求极大独立集,用networkx的实现在 CPU 上慢到不可接受,自己写 Python 循环同样快不起来。这类「逐点删除」的贪心过程其实可以用邻接矩阵上的向量化操作批量完成,在 GPU 上收益尤其明显。
问题现象
需求很简单:输入一个邻接矩阵,输出一个独立集(集合中任意两点之间没有边),不要求最优,近似即可,但要在千级节点规模上跑得快。
networkx.maximal_independent_set是纯 Python 实现,节点规模上千、且需要反复调用时开销明显。具体慢在哪可以量化:它每一轮都要在剩余节点里取最大度,Python 层的属性访问与函数调用叠加起来,千节点图的单次调用就要到百毫秒级;如果一次实验要重复几千次,总时间就无法接受。GPU 版本把一轮删除压缩成几次张量运算,耗时主要取决于 kernel launch 开销。
原因分析
独立集的贪心构造有一条很适合矩阵化的路线:反复删掉度数最大的节点。
- 每一轮计算剩余图中各点的度数,即邻接矩阵按行求和
- 删掉度数最大的若干个点及其对应的行和列
- 直到剩余图中没有任何边
循环结束时,剩余节点之间度数全为 0,即两两不相邻,构成一个独立集。整个过程的每一步都可以表达成矩阵切片与归约,因此能一次性丢给 GPU。
需要注意的是:
- 一轮删多个点(
drop_at_once > 1)能大幅减少迭代