家好,我是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小時內與您取得聯系。