GraphScope项目教程:如何编写自定义图算法

GraphScope项目教程:如何编写自定义图算法

GraphScope 🔨 🍇 💻 🚀 GraphScope: A One-Stop Large-Scale Graph Computing System from Alibaba | 一站式图计算系统 GraphScope 项目地址: https://gitcode.com/gh_mirrors/gr/GraphScope

前言

GraphScope是阿里巴巴开源的一款分布式图计算系统,其分析引擎基于GRAPE(一种在SIGMOD-2017上提出的图处理系统)。GRAPE的独特之处在于能够将顺序图算法作为一个整体进行并行化处理。本教程将详细介绍如何在GraphScope中使用PIE和Pregel两种编程模型来编写自定义图算法。

环境准备

首先需要安装GraphScope包:

!pip3 install graphscope

PIE模型算法开发

基本概念

PIE(Parallel Incremental Evaluator)模型是GRAPE的核心编程模型,它允许开发者通过实现三个关键方法将顺序算法轻松并行化:

  1. Init:初始化顶点数据和消息传递策略
  2. PEval:初始计算(Partial Evaluation)
  3. IncEval:增量计算(Incremental Evaluation)

算法框架

我们以单源最短路径(SSSP)算法为例:

from graphscope.framework.app import AppAssets
from graphscope.analytical.udf.decorators import pie

@pie(vd_type="double", md_type="double")
class SSSP_PIE(AppAssets):
    @staticmethod
    def Init(frag, context):
        pass
    
    @staticmethod
    def PEval(frag, context):
        pass
    
    @staticmethod
    def IncEval(frag, context):
        pass

@pie装饰器中的vd_typemd_type分别指定顶点数据类型和消息类型,支持intdoublestring三种类型。

实现Init方法

Init方法负责三件事:

  1. 设置顶点初始值
  2. 定义消息传递策略
  3. 指定消息聚合器
@staticmethod
def Init(frag, context):
    v_label_num = frag.vertex_label_num()
    for v_label_id in range(v_label_num):
        nodes = frag.nodes(v_label_id)
        context.init_value(
            nodes, v_label_id, 1000000000.0, PIEAggregateType.kMinAggregate
        )
        context.register_sync_buffer(v_label_id, MessageStrategy.kSyncOnOuterVertex)

对于SSSP算法,我们使用kMinAggregate作为聚合器,因为需要找出最短路径。其他可用的聚合器包括kMaxAggregatekSumAggregate等。

实现PEval方法

PEval方法处理包含源节点的分片:

@staticmethod
def PEval(frag, context):
    src = int(context.get_config(b"src"))
    graphscope.declare(graphscope.Vertex, source)
    native_source = False
    v_label_num = frag.vertex_label_num()
    for v_label_id in range(v_label_num):
        if frag.get_inner_node(v_label_id, src, source):
            native_source = True
            break
    if native_source:
        context.set_node_value(source, 0)
    else:
        return
    e_label_num = frag.edge_label_num()
    for e_label_id in range(e_label_num):
        edges = frag.get_outgoing_edges(source, e_label_id)
        for e in edges:
            dst = e.neighbor()
            distv = e.get_int(2)
            if context.get_node_value(dst) > distv:
                context.set_node_value(dst, distv)

实现IncEval方法

IncEval方法在所有分片上执行:

@staticmethod
def IncEval(frag, context):
    v_label_num = frag.vertex_label_num()
    e_label_num = frag.edge_label_num()
    for v_label_id in range(v_label_num):
        iv = frag.inner_nodes(v_label_id)
        for v in iv:
            v_dist = context.get_node_value(v)
            for e_label_id in range(e_label_num):
                es = frag.get_outgoing_edges(v, e_label_id)
                for e in es:
                    u = e.neighbor()
                    u_dist = v_dist + e.get_int(2)
                    if context.get_node_value(u) > u_dist:
                        context.set_node_value(u, u_dist)

运行算法

加载P2P网络数据集并执行算法:

from graphscope.dataset import load_p2p_network

graph = load_p2p_network(directed=False, generate_eid=False)
sssp = SSSP_PIE()
ctx = sssp(graph, src=6)

查看结果:

r1 = (
    ctx.to_dataframe({"node": "v:host.id", "r": "r:host"})
    .sort_values(by=["node"])
    .to_numpy(dtype=float)
)

算法持久化

可以将算法保存为GAR文件供以后使用:

import os
dump_path = os.path.expanduser("~/sssp_pie.gar")
SSSP_PIE.to_gar(dump_path)

加载保存的算法:

from graphscope.framework.app import load_app
sssp2 = load_app(os.path.expanduser("~/sssp_pie.gar"))

Pregel模型算法开发

基本概念

Pregel是Google提出的顶点中心计算模型,GraphScope也提供了对Pregel模型的支持。

算法框架

from graphscope.analytical.udf.decorators import pregel

@pregel(vd_type="double", md_type="double")
class SSSP_Pregel(AppAssets):
    @staticmethod
    def Init(v, context):
        pass
    
    @staticmethod
    def Compute(messages, v, context):
        pass

实现Init方法

@staticmethod
def Init(v, context):
    v.set_value(1000000000.0)

实现Compute方法

@staticmethod
def Compute(messages, v, context):
    src_id = context.get_config(b"src")
    cur_dist = v.value()
    new_dist = 1000000000.0
    if v.id() == src_id:
        new_dist = 0
    for message in messages:
        new_dist = min(message, new_dist)
    if new_dist < cur_dist:
        v.set_value(new_dist)
        for e_label_id in range(context.edge_label_num()):
            edges = v.outgoing_edges(e_label_id)
            for e in edges:
                v.send(e.vertex(), new_dist + e.get_int(2))
    v.vote_to_halt()

总结

本教程详细介绍了在GraphScope中开发自定义图算法的两种方式:

  1. PIE模型:基于分片的编程模型,适合复杂图算法
  2. Pregel模型:顶点中心计算模型,实现简单直观

开发者可以根据算法特性和个人偏好选择合适的编程模型。GraphScope的强大之处在于能够将顺序算法轻松并行化,同时保持代码的简洁性。

GraphScope 🔨 🍇 💻 🚀 GraphScope: A One-Stop Large-Scale Graph Computing System from Alibaba | 一站式图计算系统 GraphScope 项目地址: https://gitcode.com/gh_mirrors/gr/GraphScope

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

劳泉文Luna

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值