如何实现一个图化框架?代码已开源!

简介: 大家好,我是不会写代码的纯序员——Chunel Feng[3]。俗话说,人生如码,码如人生。人生中,有些事情是可以同时进行的,有些事情又必须是前后依次进行的;有些事情是可以刚开始就做的,有些事情又必须等待某个时机成熟了才可以开始。

大家好,我是不会写代码的纯序员——Chunel Feng[3]。俗话说,人生如码,码如人生。人生中,有些事情是可以同时进行的,有些事情又必须是前后依次进行的;有些事情是可以刚开始就做的,有些事情又必须等待某个时机成熟了才可以开始。


我给大家举个例子:


人必须「出生」后,然后才能「上学」和「工作」。


同样的,「出生」后还可以「恋爱」,然后「结婚」,「生娃」。


你可以「上学」的时候「恋爱」,也可以「工作」的时候再「撩妹」。但是,你必须先完成「上学」之后,才能开始「工作」。


同样的,你必须「恋爱」后,才能「结婚」,然后再「生娃」(好吧,这个顺序,你想咋样我都支持你,哈哈)。


最终,我们都会「被辞退」,我想大概是 35 岁左右吧。


34.png


看上面这个例子,和程序开发中常用的图化框架(比如:TensorFlow)是不是很像。

今天,纯序员给大家提供一种思路,可以轻松实现一套属于自己的轻量级图化框架。


分析


这个问题乍一看很难。但是我们来拆解一下,其实一共只有几步:


1,构建图框架,把node(图中的节点)和node的依赖信息注册到图中2,对图进行分析,找出其中没有任何依赖的node,放入一个queue中3,依次执行queue中的节点,直到queue中所有node被执行完毕4,搜集依赖queue中node执行的节点(称为newNode)5,清空queue,然后将newNode中所有未被运行且依赖的节点均被执行的节点,放入queue中6,重复3、4、5步骤,直到queue中无node插入,则结束


举例


看着看着就晕了?没关系,看举个例子来,就比较容易理解了。


35.png


我们来看上图这个例子,然后对照上面的步骤,开始我们的流程。


•执行 A 的内容,直到全部结束

•执行 B 和 C 节点的内容,直到全部结束

•执行 D 和 E 的内容,直到全部结束

•执行 F 的内容,直到全部结束

•执行 G 的内容


所以说,最终的执行顺序,应该是 A->B->C->E->D->F->G。这样下来,是不是就是比较清楚了。


优化


你以为就这样就结束了?很多朋友应该已经看出来了,上图中 B 和 C 的执行顺序,应该是没有任何先后依赖的。所以,为了加速整体流程,B 和 C 应该并发执行,而不是先执行 B,结束后再执行 C。


再继续看,D、E、F 这三个节点。如果按照上面的说法,应该是 D 和 E 并发执行,都结束后再执行 F。我们假设,D、E、F 的流程的耗时,分别为 D=3s(秒),E=1s,F=2s 。那这个子流程结束,就需要 max(3s,1s)+2s,也就是 5s。但是 F 虽然依赖 E,但是并不依赖 D 啊。


于是,优化点又来了,把 E 和 F 当做一个簇(cluster),簇内部依次执行。同时簇作为一个整体,与 D 并发执行。这样下来,这个子流程的最终耗时就应该是 max(3s, 1s+2s),也就是 3s。


当然了,还有很多优化思路我没有提到,或者我压根不知道的。也欢迎大家来一起讨论。


实现


懂了,但是不知道代码应该如何下手?至于代码实现,纯序员早已贴心的为你写了一套通用组件——CGraph。仅需要自己实现一下节点的功能函数,然后调用一个注册接口,并且设定依赖节点,就可以轻松的 run 起来上面提到的所有功能了。


就以上面画的那个图来举例吧,代码实现一共就这么几句话:


#include "/src/GraphCtrl/GraphInclude.h"class MyNode1 : public GraphNode {public:    CSTATUS run () override {        CSTATUS status = STATUS_OK;        std::cout << "enter node1 run function. sleep for 1 second ... " << std::endl;        this_thread::sleep_for(chrono::milliseconds(1000));        return status;    }};


#include "/src/GraphCtrl/GraphInclude.h"class MyNode2 : public GraphNode {public:    CSTATUS run () override {        CSTATUS status = STATUS_OK;        std::cout << "enter node1 run function. sleep for 2 second ... " << std::endl;        this_thread::sleep_for(chrono::milliseconds(2000));        return status;    }};


#include "MyGraphNode/MyNode1.h"#include "MyGraphNode/MyNode2.h"void graph_demo() {    /* 创建图化 */    Graphic* graphic = new Graphic();    GraphNode* A = nullptr;    GraphNode* B = nullptr;    GraphNode* C = nullptr;    GraphNode* D = nullptr;    GraphNode* E = nullptr;    GraphNode* F = nullptr;    GraphNode* G = nullptr;    /* 注册节点,其中MyNode1和MyNode2必须为GraphNode的子类 */    graphic->registerGraphNode<MyNode1>(&A);               // 注册MyNode1类型的A节点,执行的时候,没有任何依赖信息    graphic->registerGraphNode<MyNode1>(&B, {A});          // B节点执行,依赖A节点执行完毕    graphic->registerGraphNode<MyNode2>(&C, {A});    graphic->registerGraphNode<MyNode1>(&D, {B});          // D节点执行,依赖B节点执行完毕    graphic->registerGraphNode<MyNode2>(&E, {B});    graphic->registerGraphNode<MyNode1>(&F, {E});    graphic->registerGraphNode<MyNode1>(&G, {C, D, F});    // G节点执行,依赖C、E、F节点执行完毕    /* 图信息初始化,准备开始计算 */    graphic->init();    /* 运行图计算。初始化后,支持多次循环计算 */    graphic->run();    /* 图信息逆初始化,准备结束计算 */    graphic->deinit();    delete graphic;}


写在最后


这没有理由说看不懂图计算引擎框架了吧。当然了,CGraph 自身也在不断的迭代和演进过程中,我们也会不断的借(co)鉴(py)行业中比较先进和成熟的一些实现方法。这个过程也需要大家大力的参与、鼓励和拍砖。


目前 CGraph 源码已经开源至 GitHub,地址:https://github.com/ChunelFeng/CGraph


点击阅读原文可直达! 欢迎大家前来帮忙 review,star and fork 哦。如果能帮忙找到几个 bug,或者做一些功能和性能上优化,那当然就更好了,哈哈哈哈!!!!!


引用链接


[1] 一面之猿网: http://www.chunel.cn

[2] CGraph 图计算框架: https://github.com/ChunelFeng/CGraph

[3] Chunel Feng: https://github.com/ChunelFeng


目录
相关文章
|
机器学习/深度学习 人工智能 自然语言处理
AI Compass前沿速览:Qwen3-Max、Mixboard、Qwen3-VL、Audio2Face、Vidu Q2 AI视频生成模型、Qwen3-LiveTranslate-全模态同传大模型
AI Compass前沿速览:Qwen3-Max、Mixboard、Qwen3-VL、Audio2Face、Vidu Q2 AI视频生成模型、Qwen3-LiveTranslate-全模态同传大模型
1437 13
AI Compass前沿速览:Qwen3-Max、Mixboard、Qwen3-VL、Audio2Face、Vidu Q2 AI视频生成模型、Qwen3-LiveTranslate-全模态同传大模型
|
存储 人工智能 数据可视化
从零构建能自我优化的AI Agent:Reflection和Reflexion机制对比详解与实现
AI能否从错误中学习?Reflection与Reflexion Agent通过生成-反思-改进循环,实现自我优化。前者侧重内容精炼,后者结合外部研究提升准确性,二者分别适用于创意优化与知识密集型任务。
2327 9
从零构建能自我优化的AI Agent:Reflection和Reflexion机制对比详解与实现
|
存储 关系型数据库 分布式数据库
【赵渝强老师】HBase的物理存储结构
本文介绍了HBase的存储结构,包括逻辑与物理存储结构。物理存储主要涉及StoreFile、HFile和HLog日志。HFile是HBase数据存储的核心格式,包含Data块、Meta块、File Info块等六部分,支持压缩以优化存储。HLog(预写日志)记录数据变更,确保数据可靠性,并在Region Server故障时用于恢复。最后,文章详细描述了HBase的写数据流程:先写入WAL日志,再写入MemStore,最终通过Flush操作将数据持久化到HFile中。
920 2
|
机器学习/深度学习 人工智能 PyTorch
DeepSeek开源周第四弹之一!DualPipe:训练V3/R1的双向流水线并行技术,计算与训练完全重叠,训练效率提升200%
DeepSeek 开源的 DualPipe 技术通过双向流水线并行设计,显著提升大规模深度学习模型的训练效率,优化计算与通信重叠,降低内存峰值需求,适用于推理加速、多模态数据处理等场景。
1299 1
DeepSeek开源周第四弹之一!DualPipe:训练V3/R1的双向流水线并行技术,计算与训练完全重叠,训练效率提升200%
|
存储 固态存储 索引
DeepSeek 3FS解读与源码分析(3):Storage模块解读
2025年2月28日,DeepSeek 正式开源其颠覆性文件系统Fire-Flyer 3FS(以下简称3FS),重新定义了分布式存储的性能边界。本文将结合代码和design_notes 对storage部分进行分析和探讨。
|
存储 固态存储 文件存储
并行文件存储在大模型训练中的探索与实践
阿里云智能集团存储产品专家何邦剑分享了并行文件存储CPFS在大模型训练中的应用。CPFS针对大模型训练的IO特点,优化性能、降低成本、提升用户体验。它支持多计算平台共享访问,具备数据分层存储、生命周期管理、缓存加速等特性,实现高效的数据处理与管理,显著提升训练效率和资源利用率。尤其在大规模集群中,CPFS提供了高吞吐、低延迟及灵活扩展的能力,助力客户如零一万物实现高性能训练。
|
安全 JavaScript PHP
URL百分号编码
URL百分号编码
1165 0
|
存储 OLAP 数据库
数据仓库作业二:第2章 数据仓库原理
数据仓库作业二:第2章 数据仓库原理
|
数据采集 存储 数据挖掘
Python 爬虫实战之爬拼多多商品并做数据分析
在上面的代码中,我们使用pandas库创建DataFrame存储商品数据,并计算平均价格和平均销量。最后,我们将计算结果打印出来。此外,我们还可以使用pandas库提供的其他函数和方法来进行更复杂的数据分析和处理。 需要注意的是,爬取拼多多商品数据需要遵守拼多多的使用协议和规定,避免过度请求和滥用数据。
|
JSON 自然语言处理 对象存储
通义千问开源模型在PAI灵骏的最佳实践
本文将展示如何基于阿里云PAI灵骏智算服务,在通义千问开源模型之上进行高效分布式继续预训练、指令微调、模型离线推理验证以及在线服务部署。

热门文章

最新文章