家好,我是Echa。
工作流(Workflow),是对工作流程及其各操作步骤之间业务规则的抽象、概括描述。 工作流建模,即将工作流程中的工作如何前后组织在一起的逻辑和规则,在计算机中以恰当的模型表達并对其实施计算。 工作流要解决的主要问题是:为实现某个业务目标,利用计算机在多个参与者之间按某种预定规则自动传递文档、信息或者任务。
设置供应商发票工作流
工作流是业务流的一部分,而流程引擎就是驱动业务按照公司设定的固定流程去流转,在复杂多变的业务情况下,使用既定的流程能够提高工作效率,降低设计业务成本,保证业务执行的准确性;
从代码层面上来说,工作流是对业务逻辑代码的按照指定的流程格式化。即原来可以用代码直接完成的任务流程,借助工作流工具来进行标准格式化、视图化。
数据工作流
工作流程的价值
工作流程的价值流图
说到这里又有好学的粉丝们又会问道,工作流程能解决什么问题呢?小编从两个维度来解答:
工作流分析活动的重要性
借此机会,今天小编给大家推荐20个精选的开源免费的工作流系统,值得学习收藏,希望对粉丝们有所帮助。同时祝福大家万事如意,心想事成,身体健康,笑容常开,愿大家的生活更加美好,愿大家的未来更加光明。接下来小编给大家介绍一些开源免费的工作流系统,喜欢的小伙们记得点个赞和收藏。
Github:https://github.com/apache/airflow
介绍
Apache Airflow 是一个能够开发、调度和监控工作流的编排平台。在 Shopify,我们已经在生产中运行了两年多的 Airflow,用于各种工作流,包括数据提取、机器学习模型训练、Apache Iceberg 表维护和 DBT 驱动的数据建模。在撰写本文时,我们正通过 Celery 执行器和 MySQL 8 在 Kubernetes 上来运行 Airflow 2.2。
Shopify 在 Airflow 上的应用规模在过去两年中急剧扩大。在我们最大的应用场景中,我们使用了 10000 多个 DAG,代表了大量不同的工作负载。在这个场景中,平均有 400 多项任务正在进行,并且每天的运行次数超过 14 万次。由于 Shopify 的内部采用率越来越高,我们的 Airflow 部署将会产生更多的负载。因为这样的迅速增长,我们所面临的困难包括:文件存取速度太慢、对 DAG(Directed acyclic graph,有向无环图)能力的控制不足、流量水平的不规则、工作负载之间的资源争用等等。
airflow工作流管理平台基于四个重要原则构建。
系统截图
Github:https://gitee.com/agile-bpm
介绍
AgileBPM 工作流 低代码 快速开发平台,基于 JDK17、Activiti7、Vue3、TS、Vite、ElementPlus 的 全新版本,全新的技术栈,全新的体验。
AgileBPM 流程实施推荐通过三步来,
系统截图
Gitee:https://gitee.com/shenzhanwang/RuoYi-activiti
介绍
基于Activiti6.0,集流程设计、流程部署、流程执行、任务办理、流程监控于一体的开源工作流开发平台。
若依是有名的开源权限管理系统,集权限管理和代码快速生成于一体,将其作为基础开发平台集成activiti框架完成工作流引擎开发,打造集流程设计、流程部署、流程执行、任务办理、流程监控于一体的强大工作流平台。
系统截图
Github:https://github.com/tony2y/RuoYi-flowable
介绍
基于RuoYi-vue + flowable 6.x 的工作流管理平台,提供流程管理、流程监控和任务调度等功能。具有易于集成、高度可定制和扩展性强的特点。
内置功能
系统截图
Github:https://github.com/yubaolee/OpenAuth.Core
介绍
.Net权限管理及快速开发框架、最好用的权限工作流系统。源于Martin Fowler企业级应用开发思想及最新技术组合(SqlSugar、EF、Quartz、AutoFac、WebAPI、Swagger、Mock、NUnit、Vue2/3、Element-ui/plus、IdentityServer等)。包括:角色授权、代码生成、打印设计、表单设计、工作流等。架构易扩展,是中小企业的首选。
特点
系统截图
Gitee:https://gitee.com/opencc/JFlow
介绍
国外有activiti,国内有JFlow, Java版驰骋BPM=表单引擎+流程引擎+权限控制,方便集成,配置灵活,功能强大,适合中国国情的工作流引擎.
产品特色
系统截图
Gitee:https://gitee.com/willianfu/jw-workflow-engine
介绍
wflow-web 是 wflow工作流 项目的前端设计器,免费且开源,本设计器包含表单设计,审批流程设计。
区别于传统Bpmn自带流程设计器,传统设计器晦涩难懂,对于普通企业用户使用门槛偏高,没有经过专业培训根本无从下手,需要相关专业人员辅助来创建流程。而本设计器界面简单,符合普通大众的思维逻辑,易于理解和上手使用。
系统截图
Gitee:https://gitee.com/calvinhwang123/RuoYi-Process
介绍
闲鹿工作流是一款基于 RuoYi 4.x + Activiti 6.x + Spring Boot 2.x + Thymeleaf 3.x 的开源工作流管理系统~
作为技术小菜鸟的我,一直对学习 Activiti 工作流框架求之不得,断断续续入门入了三次。这次能够写出这个项目主要归功于 ? 的《Activiti 实战》。这本书给予了我很大的帮助。最后但仍然重要的,我要感谢若依框架,她让我实现快速集成工作流 WEB 应用。—— 一只闲鹿
系统截图
Github:https://github.com/lanyulei/ferry
介绍
本系统是集工单统计、任务钩子、权限管理、灵活配置流程与模版等等于一身的开源工单系统,当然也可以称之为工作流引擎。 致力于减少跨部门之间的沟通,自动任务的执行,提升工作效率与工作质量,减少不必要的工作量与人为出错率。
通过灵活的配置流程、模版等数据,非常快速方便的生成工单流程,通过对流程进行任务绑定,实现流程中的钩子操作,目前支持绑定邮件来通知处理,当然为兼容更多的通知方式,也可以自己写任务脚本来进行任务通知,可根据自己的需求定制。
兼容了多种处理情况,包括串行处理、并行处理以及根据条件判断进行节点跳转。
可通过变量设置处理人,例如:直接负责人、部门负责人、HRBP等变量数据。
基于casbin的RBAC权限控制,借鉴了go-admin项目的前端权限管理,可以在页面对API、菜单、页面按钮等操作,进行灵活且简单的配置。
功能介绍
工单系统相关功能:
权限管理相关功能,使用casbin实现接口权限控制:
Github:https://github.com/KonBAI-Q/RuoYi-Flowable-Plus
介绍
本项目基于 RuoYi-Vue-Plus 进行二次开发扩展Flowable工作流功能,支持在线表单设计和丰富的工作流程设计能力。
系统截图
Gitee:https://gitee.com/jehc/jehc-workflow
介绍
JEHC-2.0开源平台单工程工作流版本, 采用技术为: spring,springMVC,Mybatis,Activiti5.22,(Activiti可视化设计器基于IE,火狐,谷歌,360等浏览器),Solr4.10,Mysql,Redis,Ehcache,服务器监控模块,tk压缩,BootStrap,Junit单元测试,Logback,数据库读写分离,MQ消息中间件等技术
本开发团队重点打造医疗(专攻医学软件Web方向,病历云,影像学,实验室检验等等),IOT方向,工作流Workflow等开源平台
技术栈
后端
Spring, SpringBoot2.0, Mybatis, PageHelper, Solr全文检索, Redis, Ehcache, JWT, Oauth2, 数据库读写分离, Activity5.22工作流, 客户端负载均衡Rule, Sentinel限流体系, Nacos注册中心 配置中心, Gateway网关, Junit, Netty, Quartz调度器, FTP, ES全文检索, Openoffice, Onvif摄像头, OpenCV, Mqtt, ffmpeg
前端
可视化流程设计器, VUE, Bootstrap4+, ElementUI, perfect-scrollbar, fontawesome, jstree, Jquery2, DataTables, Mxgraph, PDFJS, ZTree, SVGEditor, VTK, ITK, video等
开发工具
eclipse-jee-mars-1、eclipse-jee-mars-2、eclipse-juno、STS、IDEA
软件架构
授权中心数据结构
系统截图
Gitee:https://gitee.com/junyue/cxygzl
介绍
现在开源的工作流引擎,基本都是以BPMN.js为基础的,导致使用门槛过高,非专业人员无法驾驭。本工作流借鉴钉钉/飞书的方式,以低代码方式降低用户使用门槛,即使是普通企业用户也可以几分钟内就能搭建自己的工作流引擎。
前端管理后台框架使用的是 vue3-element-admin,流程图使用的是Workflow-Vue3。在此特别感谢两个产品的作者无私奉献,让我抄了个近道,特别感谢。
系统截图
Gitee:https://gitee.com/ccflow/jfinal-jflow
介绍
系统截图
Github:https://github.com/aizuda/flowlong
介绍
飞龙工作流 FlowLong 真正的国产工作流引擎、json 格式实例模型、仿飞书钉钉审批流程设计器、为中国特色审批匠心打造?
中国特色流程操作概念
支持功能 | 功能描述 | 完成程度 |
顺序会签 | 指同一个审批节点设置多个人,如A、B、C三人,三人按顺序依次收到待办,即A先审批,A提交后B才能审批,需全部同意之后,审批才可到下一审批节点。 | ? |
并行会签 | 指同一个审批节点设置多个人,如A、B、C三人,三人会同时收到待办任务,需全部同意之后,审批才可到下一审批节点。 | ? |
或签 | 一个流程审批节点里有多个处理人,任意一个人处理后就能进入下一个节点 | ? |
票签 | 指同一个审批节点设置多个人,如A、B、C三人,分别定义不同的权重,当投票权重比例大于 50% 就能进入下一个节点 | ? |
抄送 | 将审批结果通知给抄送列表对应的人,同一个流程实例默认不重复抄送给同一人 | ? |
驳回 | 将审批重置发送给某节点,重新审批。驳回也叫退回,也可以分退回申请人、退回上一步、任意退回等 | ? |
分配 | 允许用户自行决定任务转办、委派、主办 及其它 | ? |
转办 | A转给其B审批,B审批后,进入下一节点 | ? |
委派 | A转给其B审批,B审批后,转给A,A审批后进入下一节点 | ? |
跳转 | 可以将当前流程实例跳转到任意办理节点 | ? |
拿回 | 在当前办理人尚未处理文件前,允许上一节点提交人员执行拿回 | ? |
撤销 | 流程发起者可以对流程进行撤销处理 | ? |
加签 | 允许当前办理人根据需要自行增加当前办理节点的办理人员 | ? |
减签 | 在当前办理人操作之前减少办理人 | ? |
认领 | 公共任务认领 | ? |
已阅 | 任务是否查看状态显示 | ? |
催办 | 通知当前活动任务处理人办理任务 | ? |
沟通 | 与当前活动任务处理人沟通 | ? |
终止 | 在任意节点终止流程实例 | ? |
系统截图
Gitee:https://gitee.com/agile-bpm
介绍
科技部门通过快速迭代支撑业务不断的创新、发展,最终构建出完善的、高效的业务线从而提高产品竞争力、行业壁垒。
AgileBPM 是一个快速开发平台,与众多开发平台不一样的地方是,他支持低代码、在线开发、且无感知的、跨应用的进行业务流程的实施,助力企业快速、轻松的构建业务流。
优点
架构图
Gitee:https://gitee.com/opencc/ccflow
介绍
ccflow包含表单引擎+流程引擎+权限控制,方便集成,配置灵活,功能强大,适合中国国情的工作流引擎
特点
系统截图
Gitee:https://gitee.com/52itstyle/BPMN
介绍
找一个好用的画图工具真心不容易,Activiti 工作流自带的 Web 版画图工具,外表挺华丽,其实使用起来各种拧巴;Eclipse 的 Activiti 画图插件,对于相对复杂的流程也是很不友好。
功能模块
这是一个Python版本,Java版本功能已经基本开发完毕,需要进行功能迁移。
系统截图
Github:https://github.com/huangxianyuan/hxyFrame-activiti-boot
介绍
hxyFrame-activiti-boot是一个快速开发工作流系统框架,采用流行的框架springBoot+mybatis+shiro+redis开发,实现了权限管理(菜单权限、数据权限),activiti工作流程引擎。
项目功能
技术选型:
软件环境
Gitee:https://gitee.com/cangjingge/sunFlow
介绍
sunFlow基于是基于camunda开发的工作流web系统。设计理念是易用,简单,美观,高效。 尤其注重对开发友好; 项目设计之初就考虑了前后端分离的vue开发模式。角色和路由之间的绑定跟角色和数据权限之间是不耦合的。
前端开发只需要开发路由组件, 后端开发只需要开发 数据api接口。从菜单配置界面上分前端做的是左边的部分,后端是开发右边的部分,当然如果你不用工作流只用后台权限管理本框架也是一个绝佳的选择
软件架构
软件架构说明:目前项目分三个模块,camunda(工作流相关服务),upms-server(后台权限管理模块),webApp(前端模块)
系统为了降低上手成本,和自由度,各个模块之间依赖尽量降低,而且对组件依赖也很低,有些都是可选的,比如redis组件你就可以选择不用,而且仅仅通过一个spring注解就可以控制
介绍
Github:https://github.com/camunda
介绍
Camunda是一个免费的开源工作流管理工具,允许企业通过自动化工具和高效工作流的力量实现数字化转型。Camunda建立在设计、自动化和改进的三个基本原则基础上,确保设计工作流程的过程变得更简单,负担更少。工作流管理系统的设想是确保能够灵活地处理各种组织的复杂工作流程。该平台基于Java应用程序接口(API)技术栈构建,功能强大且易于扩展。
Camunda的特征
系统截图
一行代码,可能会创造出下一个让人惊叹的产品;
一个创新,可能会开启一个全新的科技时代;
一份初心,可能会影响到无数人的生活;
无论是在大公司工作,还是在小团队奋斗;
无论是资深的程序员,还是刚刚入行的新手;
每个人的代码,都有力量改变世界。
创作不易,喜欢的老铁们加个关注,点个赞,打个赏,后面会不定期更新干货和技术相关的资讯,速速收藏,谢谢!你们的一个小小举动就是对小编的认可,更是创作的动力。
创作文章的初心是:沉淀、分享和利他。既想写给现在的你,也想贪心写给 10 年、20 年后的工程师们,现在的你站在浪潮之巅,面对魔幻的互联网世界,很容易把一条河流看成整片大海。未来的读者已经知道了这段技术的发展历史,但难免会忽略一些细节。如果未来的工程师们真的创造出了时间旅行机器,可以让你回到现在。那么小编的创作就是你和当年工程师们的接头暗号,你能感知到他们在这个时代的键盘上留下的余温。
#文章首发挑战赛#
js2flowchart 是一个可视化库,可将任何JavaScript代码转换为漂亮的SVG流程图。你可以轻松地利用它学习其他代码、设计你的代码、重构代码、解释代码。这样一个强大的神器,真的值得你拥有,看下面截图就知道了,有没有很强大。
https://github.com/Bogdan-Lyashenko/js-code-to-svg-flowchart
yarn add js2flowchart
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>fly测试</title> </head> <body> <div style="width:50%;float:left"> <p id="svgImage"></p> </div> <div style="width:50%;float:left"> <textarea name="" id="jsContent" style="width: 90%;height:900px" oninput="createSVG()"> </textarea> </div> <script src="./node_modules/js2flowchart/dist/js2flowchart.js"></script> <script src="./index.js"></script> </body> </html>
index.js
createSVG=()=> { document.getElementById("svgImage").innerHTML=null; let code=document.getElementById("jsContent").value; const { createFlowTreeBuilder, createSVGRender }=js2flowchart; const flowTreeBuilder=createFlowTreeBuilder(), svgRender=createSVGRender(); const flowTree=flowTreeBuilder.build(code), shapesTree=svgRender.buildShapesTree(flowTree); const svg=shapesTree.print(); document.getElementById("svgImage").innerHTML=svg; }; createSVG();
我们直接在文本域中输入自己的代码,如下,左边会直接生成流程图,这只是一个简单的示例:
js2flowchart获取您的JS代码并返回SVG流程图,适用于客户端/服务器,支持ES6。
主要特点:
用例场景:
以上所有功能可以直接到github上详细了解,用法太多,这里就不在介绍了!
这么强大的东西,有人肯定说如果在开发的时候实时看到流程图有助于理解代码,官网提供了插件(我在最新版中测试失效了,不知道是否是我使用的有问题还是插件本身的问题),如果感兴趣的可以到扩展商店搜索code-flowchart。如果测试成功,欢迎到评论区分享。以下是我vscode版本和官网的插件使用截图。
如果利用好这个插件,可以开发出Chrome插件,以及其他JavaScript编辑器或者IDEA的插件,由于官方github已经几个月没更新了,所以还不知道未来会不会支持!
js2flowchart是一个比较实用的Javascript插件,可以用来做很多事情,不管是自己写代码。还是阅读别人的代码,都无疑是一大助力,能够帮助我们提升我们的代码能力,更容易的阅读代码,这样学习起来就快了,希望对你有所帮助!如果有什么好的建议,也可以到评论区分享!
器之心发布
机器之心编辑部
要想炼丹爽得飞起,就要选择一个顺手的炉子。作为 AI 工程师日常必不可缺的「炼丹炉」,「PyTorch 还是 TensorFlow?」已成为知乎、Reddit 等炼丹师出没之地每年都会讨论的热门话题。
业界流传一种说法:PyTorch 适合学术界,TensorFlow 适合工业界。毕竟,PyTorch 是用户最喜欢的框架,API 非常友好,Eager 模式让模型搭建和调试过程变得更加容易,不过,它的静态图编译和部署体验还不令人满意。TensorFlow 恰恰相反,静态编译和部署功能很完备,不过其调试体验让人欲哭无泪。
那么问题来了:鱼和熊掌真的不可兼得吗?未必,来自北京的一流科技团队推出的开源深度学习框架 OneFlow 已经做到了。
等等,OneFlow 一直主打分布式和高性能,易用性也能和 PyTorch一样吗?听说过 OneFlow 的人一定会发出这样的疑问。
没错,从 2016 年底立项之日起,OneFlow 就是为大规模分布式而生,特色之一就是静态图机制,2020 年 7 月在 GitHub 上开源时还不支持动态图。不过,OneFlow 团队用一年多时间自研了动态图引擎, OneFlow 0.7 版本已支持和 PyTorch 一模一样的 Eager 体验,也就是说,OneFlow 实现了同时支持动态图和静态图。不仅如此,OneFlow 编程 API 完全和 PyTorch 兼容,常见深度学习模型只需修改一行 import oneflow as torch 就可以把 PyTorch 写的模型在 OneFlow 上跑起来。
不妨先到 OneFlow 视觉模型库 flowvision 看一看:https://github.com/Oneflow-Inc/vision ,这个模型库已经支持计算机视觉领域图像分类、分割和检测等方向的经典 SOTA 模型 (见下表),这些模型都可以通过 import torch as flow 或 import oneflow as torch 实现自由切换。
OneFlow 和 PyTorch 兼容之后,用户可以像使用 PyTorch 一样来使用 OneFlow ,对模型效果比较满意之后,可以继续使用 OneFlow 扩展到大规模分布式或使用静态图部署模型。听上去是不是 too good to be true?
在下面的案例中,一家头部通信公司基于 PyTorch 的业务模型快速方便地迁移成 OneFlow 的模型,并进行大幅度的训练/推理性能优化、部署上线,短短几天时间就让业务得以按时上线部署,且各项性能指标均大幅超出预期!
他们究竟是是如何做到的?先从项目背景说起。
为什么选择 OneFlow?
因业务发展需求,这家通信公司近期将上线一款基于深度学习的图像识别应用,该项目的业务需求有如下五个特点:
用户基于市面上最流行的深度学习框架 PyTorch 搭建了业务模型,且跑通了正常训练流程,但是训练/推理都很慢,远远达不到目标(离上线 QPS 有 20 倍的差距),随着交付日期临近,整个团队深陷焦虑。
用户尝试了各种方案(基于已有实现进行优化)都无济于事,于是调研了其他深度学习框架,如 TensorFlow、OneFlow 等,发现 OneFlow (https://github.com/OneFlow-Inc/oneflow) 是加速 PyTorch 风格代码的最平滑框架。
具体而言,用户选择试用 OneFlow的理由主要有三点:
1、OneFlow 是众多深度学习框架中,API 与 PyTorch 兼容性最高的,这样方便工程师用最少的时间/人力成本,对已有项目代码进行迁移,减少学习成本。
2、OneFlow 动静转换十分方便,动态图(Eager)模式的代码简单改动几行就能转换为静态图(nn.Graph)模式。
3、OneFlow 在框架层面做了大量优化,nn.Graph 提供了简洁、丰富的性能优化选项,如算子融合(Kernel Fusion)、自动混合精度训练 (Auto Mixed Precision Training) 等。
于是,用户就开始尝试将已有代码迁移至 OneFlow,没想到,不到半天就搞定并跑起来了,迁移过程非常丝滑。
在 OneFlow 官方文档(https://docs.oneflow.org/master/index.html) 以及 OneFlow 研发团队的大力支持下,用户开展了以下工作:
迁移调优过程
1. 一键迁移 PyTorch 模型转 OneFlow 模型:只需 import oneflow as torch 就够了
OneFlow 最新发布的 0.7.0 版本对 PyTorch 接口的兼容性有了进一步的完善。OneFlow 对已经支持的算子都能保证和 PyTorch 的接口在语义和结果上一致。于是用户就尝试了一下迁移模型脚本到 OneFlow。由于业务模型的主干网络是 resnet101,在迁移过程中,用户参考了官方文档(https://docs.oneflow.org/master/cookies/torch2flow.html)来迁移 ,发现只需要模型文件中与 torch 相关的 import 修改为 import oneflow as torch,就完成了模型代码的迁移工作。
在模型脚本迁移完毕之后,还需要验证模型迁移的正确性,看看精度是不是对齐了。
1)用户首先做了推理精度的验证,就是直接加载 PyTorch 训练好的模型然后验证推理精度,由于 OneFlow 对齐了 PyTorch 的接口,所以加载 PyTorch 的模型也非常方便,只需数行代码即可完成:
import torchvision.models as models_torch
import flowvision.models as models_flow
resnet101_torch=models_torch.resnet101(pretrained=True)
resnet101_flow=models_flow.resnet101()
state_dict_torch=resnet101_torch.state_dict()
state_dict_numpy={key: value.detach().cpu().numpy() for key, value in state_dict_torch.items()}
resnet101_flow.load_state_dict(state_dict_numpy)
2)在验证完推理精度后接着就是验证训练流程,在对齐训练超参数之后,使用 OneFlow 训练模型的 loss 曲线和 PyTorch 的收敛曲线也一致,在小数据集上的精度完全一致。
2. 使用 OneFlow 的 nn.Graph 加速模型训练与推理性能
在验证完算法正确性后,就需要考虑如何加速执行了。如果使用现有的动态图模型直接部署,在现有的机器资源和时间限制内,使用最原始的代码实现还差约 20 倍的性能,短期内是一个不可能完成的任务。
用户决定双管齐下,在基于 PyTorch 做加速优化时,并行地使用 OneFlow 进行加速。最终结合「动态转静态、算法逻辑约减、提高并行度、静态编译优化」这四类技巧,最终单机执行达到了 25 倍以上的加速效果。
2.1 动态转静态
动态图转静态图执行后,得到了约 25% 的性能加速。
OneFlow 有个 ResNet50 的开源项目( https://github.com/Oneflow-Inc/models/tree/main/Vision/classification/image/resnet50 ),了解到单卡的执行效率已经做得很高,照猫画虎,这些优化技巧都可以用在 ResNet101 上。
OneFlow ResNet50 下做模型加速使用的是静态图 nn.Graph,类似 PyTorch 的 TorchScript。但OneFlow的优化功能做的更全面一些,运行时也是一个特有的服务于加速的 Actor Runtime。
nn.Graph 是一个面向对象风格的静态图类,它代表一个完整的静态计算图。对于预测任务,nn.Graph 可以只包括前向计算;对于训练任务,还可以包括后向计算和模型更新。
nn.Graph 的基础接口和 nn.Module 的行为比较类似,比如添加子 Module,自定义算法执行逻辑,调用以执行一次计算,保存模型等。被添加进入 nn.Graph 的 nn.Module 对象,在 nn.Graph 里执行时,就会采用静态图模式执行,如此动态图下的计算逻辑就可以被静态图直接复用,这样就实现了动静执行的切换。特殊一点的是,Optimizer 也可以添加进入静态图,这样前向、后向、模型更新可以被加入一个完整的静态图做联合优化。
下面的步骤把动态执行的 ResNet101Module 变成静态执行,使用方式和 nn.Module 类似,只需要声明、实例化、调用三个基本步骤。
1)声明一个静态图:主要包括两部分,先在初始化函数中添加要静态化的 nn.Module 和 Optimizer;然后在 build 函数中构图。
class ResNet101Graph(oneflow.nn.Graph):
def __init__(self, input_shape, input_dtype=oneflow.float32):
super().__init__()
# 添加 ResNet101 nn.Module
self.model=ResNet101Module(input_shape, input_dtype)
self.loss_fn=ResNet101_loss_fn
# 添加 对应的 Optimizer
of_sgd=torch.optim.SGD(self.model.parameters(), lr=1.0, momentum=0.0)
self.add_optimizer(of_sgd)
# 配置静态图的自动优化选项
_config_graph(self)
def build(self, input):
# 类似 nn.Module 的 forward 方法,这里是构图,包括了构建后向图,所以叫 build
out=self.model(input)
loss=self.loss_fn(out)
# build 里面支持构建后向图
loss.backward()
return loss
2)实例化静态图:按普通的 Python Class 使用习惯去做初始化就好。
resnet101_graph=ResNet101Graph((args.batch_size, 3, img_shape[1], img_shape[0]))
3)调用静态图:类似 nn.Module 的调用方式,注意第一次调用会触发编译,所以第一次调用比后面的时间要长。
for i in range(m):
loss=resnet101_graph(images)
把 ResNet101 的 nn.Module 的实例加入 nn.Graph 执行后,对比得到约 25% 的加速。
2.2 算法层次的优化
用户在把动态图代码迁移到静态图代码的过程中,因为需要考虑哪些部分要做静态化,所以对模型做了模块化的重构,但发现本任务中有些计算是做实验时遗留的,在部署时并不必要,顺便做了算法逻辑的约减:
总体而言,算法层次方面累积加速了 2.33 倍,事实证明,算法逻辑本身具有很大的优化空间,代码做好模块化,可以比较容易找到算法逻辑上的优化点。当然,这部分改善也适用于PyTorch。
2.3 提高并行度
这个思路也比较直接,在做完优化的基础上,用户观察到 GPU 的利用率只有 30%。此时 batch_size 为 1( BN 的某些参数和 batch 大小有关,原先用户担心扩大 batch_size 可能影响计算结果,事后证明这个担心是多余的,从理论推导和实验结果都证实,扩大 batch_size 并不影响计算结果),单进程,提高数据并行度是很值得尝试的方案。因此,用户尝试了提高 batch_size 和 多进程方案:
提高并行度的累积加速是 4.6 倍。增加并行度以充分利用多核、多设备,带来了最明显的加速效果。当然,这里的优化效果是用户迁移到 OneFlow 后实现的,在 PyTorch 上也可以做到。
2.4 静态编译优化
做到以上优化后,GPU 利用率已经能比较稳定的保持在 90%,一般来说,已经没有太大优化空间了。但是,OneFlow nn.Graph 下还有一些自动的编译优化技术可以尝试。
比如利用自动混合精度做低精度计算、利用算子融合来减少访存开销等,这里最终带来了 64% 的加速,速度到了原来最好性能的 1.56 倍。
此前示例中提到的 _config_graph 函数就是在配置这些优化选项,具体如下:
def _config_graph(graph):
if args.fp16:
# 打开 nn.Graph 的自动混合精度执行
graph.config.enable_amp(True)
if args.conv_try_run:
# 打开 nn.Graph 的卷积的试跑优化
graph.config.enable_cudnn_conv_heuristic_search_algo(False)
if args.fuse_add_to_output:
# 打开 nn.Graph 的add算子的融合
graph.config.allow_fuse_add_to_output(True)
if args.fuse_pad_to_conv:
# 打开 nn.Graph 的pad算子的融合
graph.config.allow_fuse_pad_to_conv(True)
对于 ResNet101,batch_size 设置为 16,在 nn.Graph 无优化选项打开的基础上:
自动混合精度训练,自动将网络中的合适的算子由 FP32 单精度计算转换成 FP16 半精度浮点进行计算,不仅可以减少 GPU 显存占用,而且可以提升整体性能,在支持 Tensor Core 的 GPU 设备上还会使用 Tensor Core 进一步加速训练。
cudnn 的 convolution 算子包含多种算法,例如前向的算法(https://docs.nvidia.com/deeplearning/cudnn/api/index.html#cudnnConvolutionFwdAlgo_t)。不同的 input 和 filter 大小在不同的算法下有不同的性能表现,为了选择最佳算法,在调用 cudnn convolution 算子接口前,需要先调用 cudnn convolution searching algorithm 的接口。cudnn 提供了2种搜索模式:启发式搜索(https://docs.nvidia.com/deeplearning/cudnn/api/index.html#cudnnGetConvolutionForwardAlgorithm_v7)和试运行搜索(cudnnFindConvolutionForwardAlgorithm)(https://docs.nvidia.com/deeplearning/cudnn/api/index.html#cudnnFindConvolutionForwardAlgorithm)。
启发式搜索是通过一种「查表」的方式来搜寻最佳算法,cudnn 对不同的参数配置对应的最佳算法进行了预先定义,然后每次搜索时进行匹配得到结果。试运行搜索会传入实际的张量进行多次试运行,然后返回运行结果。搜索算法返回的结果都是不同算法的元信息及其所需耗时。
启发式搜索在搜索阶段不需额外分配内存,且能更快得到结果;而试运行搜索能得到更为全面和精确的结果,也即通常能更精确地找到最佳算法。启发式搜索在常见情形下可以得到与试运行搜索一致的结果,但在一些特殊参数配置下无法得到最佳结果。OneFlow 中默认启动了启发式搜索,但可通过 graph.config.enable_cudnn_conv_heuristic_search_algo(False) 接口关闭,关闭后使用的就是试运行搜索。
在 CNN 网络 Backbone 中有很多 convolution + pad 的组合,convolution 算子自身支持 pad 操作,自动将 pad 算子 fuse 到 convolution 算子上,可以省掉 pad 算子的开销,提升网络整体性能。
自动将网络中常见的访存密集型算子 Elementwise add 算子和上游的算子 fuse 起来,可以减少带宽使用,从而提升性能。对于 Elementwise add 算子来说,将其 fuse 到上一个算子,可以减少一次数据读写,有约 2/3 的性能提升。
另外 nn.Graph 可以很方便地支持使用 TensorRT 。本优化对象没有更新模型的需求,所以也适合使用 TensorRT 做加速。在 nn.Graph 无优化选项基础上, batch_size 设置为 16,新增自动混合精度、NHWC、使用 TensorRT 后端,可以提速 48%。
在这个模型里,只使用 TensorRT 后端比只使用 OneFlow 的静态图优化还差一点,可能的原因是, TensorRT 下的一些优化在 nn.Graph 里已经做了,所以没有带来额外收益。不过其实验起来还比较方便,编译一下带 TensorRT 的 OneFlow,再在 nn.Graph 下打开开关就可以,列出来作为参考:
def _config_graph(graph):
if args.tensorrt:
# 使用 TensorRT 后端执行
graph.config.enable_tensorrt(True)
2.5 加速优化总结
以上记录了加速的主要过程,动态转静态加速约 1.25 倍、算法逻辑约减加速约 2.33 倍、提高并行度加速约 4.6 倍、静态编译优化加速约 1.6 倍,累积加速约 21 倍。中间有些小的优化点没有完全记录,实际累积的加速效果达到了 25 倍以上,超过了项目部署的 20 倍加速需求。
nn.Graph 的进一步的使用可以参考:
3. 使用 OneFlow-Serving,轻松将训练好的模型部署上线
当用户完成训练,得到最终的模型之后,接下来的一步就是模型部署。不同于模型训练时需要进行权重更新,部署时的权重固定不变,所以可以进行更激进的速度优化,例如 int8 量化、更广泛的 kernel fusion、constant folding 等等。
用户参考 OneFlow v0.7.0 提供了官方的 Serving 模块(https://github.com/Oneflow-Inc/serving),它是一个 NVIDIA Triton 的后端,集成了 OneFlow 内置的 XRT 模块,并提供了开箱即用的用户接口。只需使用下述方法就将训练好的 OneFlow 模型快速高效的部署起来:
为了将模型用于推理,在使用 nn.Graph 训练完成之后,需要构造一个只包含前向的 ResNet101InferenceGraph:
class ResNet101InferenceGraph(oneflow.nn.Graph):
def __init__(self):
super().__init__()
self.model=resnet101_graph.model
def build(self, input):
return self.model(input)
inference_graph=ResNet101InferenceGraph()
并以一个样例输入运行 inference_graph,触发 inference_graph 的计算图构建:
unused_output=inference_graph(flow.zeros(1, 3, 224, 224))
接下来就可以运行 flow.save 将 inference_graph 的计算图结构以及权重均保存在 "model" 文件夹下,以供部署使用:
flow.save(inference_graph, "model")
然后只需要运行
docker run --rm --runtime=nvidia --network=host -v$(pwd)/model:/models/resnet101/1 \
oneflowinc/oneflow-serving:nightly
由此可以启动一个部署着 ResNet101 模型的 Docker 容器。这里的 -v 很重要,它表示将当前目录下的 model 文件夹映射到容器内的 "/models/resnet101/1" 目录,其中 /models 是 Triton 读取模型的默认目录,Triton 会以该目录下的一级目录名("resnet101")作为模型名称,二级目录名("1")作为模型版本。
如果将启动命令调整为
docker run --rm --runtime=nvidia --network=host -v$(pwd)/model:/models/resnet101/1 \
oneflowinc/oneflow-serving:nightly oneflow-serving --model-store /models --enable-tensorrt resnet101
模型就会通过 OneFlow 的 XRT 模块自动使用 TensorRT 进行推理,此外 OneFlow Serving 还支持类似的 “--enable-openvino”。
启动 Docker 容器后,运行下面的命令,就可以查看服务状态:
curl -v localhost:8000/v2/health/ready
返回值为 HTTP/1.1 200 OK,表示服务正在正常工作。
接下来就可以使用 Triton 的 C++ 或 Python SDK 实现向服务端发送请求并获取结果的逻辑了,例如一个最简单的客户端:
#/usr/bin/env python3
import numpy as np
import tritonclient.http as httpclient
from PIL import Image
triton_client=httpclient.InferenceServerClient(url='127.0.0.1:8000')
image=Image.open("image.jpg")
image=image.resize((224, 224))
image=np.asarray(image)
image=image / 255
image=np.expand_dims(image, axis=0)
# Transpose NHWC to NCHW
image=np.transpose(image, axes=[0, 3, 1, 2])
image=image.astype(np.float32)
input=httpclient.InferInput('INPUT_0', image.shape, "FP32")
input.set_data_from_numpy(image, binary_data=True)
output_placeholder=httpclient.InferRequestedOutput('OUTPUT_0', binary_data=True, class_count=1)
output=triton_client.infer("resnet101", inputs=[input], outputs=[output_placeholder]).as_numpy('OUTPUT_0')
print(output)
试着运行一下,可以发现它成功的打印出了推理结果:
$ python3 triton_client.py
[b'3.630257:499'] # class id 为 499,值为 3.630257
写在最后
在上述案例中,用户因时间紧迫没法做充分调研,抱着试试看的想法选择了 OneFlow,幸运的是,终于在极限压缩的项目周期里顺利完成了任务。
基于 OneFlow v0.7.0 ,用户轻松地将之前开发的 PyTorch 的业务模型代码一键迁移成 OneFlow 的模型代码,再经过简单加工就转成 OneFlow 的静态图 nn.Graph 模式,并利用 nn.Graph 丰富、高效、简洁的优化开关来快速大幅提升模型的训练速度,利用完善的周边工具链如 OneFlow-Serving 方便的进行线上部署。值得一提的是,用户还可以使用 OneFlow-ONNX 工具将 OneFlow 高效训练好的模型转成 ONNX 格式导入到其他框架中使用。
本文只介绍了借助和 PyTorch 的兼容性 OneFlow 帮助用户实现模型加速和部署的例子。OneFlow 原来的杀手锏功能“大规模分布式”还没有体现出来,未来,我们将进一步介绍 OneFlow 如何帮助习惯 PyTorch 的用户便捷地实现大规模预训练 Transformer 模型和搜索推荐广告领域需要的大规模 embedding 模型。
*请认真填写需求信息,我们会在24小时内与您取得联系。