C++到Python全搞定,教你如何為FastDeploy貢獻(xiàn)代碼
大家好!今天為大家?guī)淼氖且黄?jīng)驗(yàn)帖文。本次分享的主人公是黑客松比賽參賽者鄭必城,他將為大家?guī)肀荣愴?xiàng)目“No.80瑞芯微RK3588:通過Paddle2ONNX打通5個(gè)飛槳模型的部署中如何為FastDeploy”任務(wù)中的一些心得體會(huì),快來看看他是如何為FastDeploy貢獻(xiàn)代碼的吧!
RKNPU2是瑞芯微Rockchip推出的針對(duì)RK356X/RK3588/RV1103/RV1106的C++推理工具。在參加黑客松比賽時(shí),F(xiàn)astDeploy倉庫[1]還沒有集成RKNPU2的引擎。開發(fā)者需要使用RKNPU2從頭編寫代碼。在參加完黑客松之后,我為FastDeploy倉庫貢獻(xiàn)了RKNPU2的后端推理引擎的代碼,現(xiàn)在能直接使用FastDeploy快速開發(fā)基于RKNPU2的代碼。本次教程將以貢獻(xiàn)SCRFD模型[2]為例,教你如何給FastDeploy貢獻(xiàn)代碼。
Zheng_Bicheng主頁
https://github.com/Zheng-Bicheng
No.80瑞芯微RK3588:通過Paddle2ONNX打通5個(gè)飛槳模型的部署鏈接
https://github.com/PaddlePaddle/Paddle/issues/44068
FastDeploy簡(jiǎn)介
FastDeploy是一款全場(chǎng)景、易用靈活、極致高效的AI推理部署工具,提供開箱即用的云邊端部署體驗(yàn),支持超過150+文本、計(jì)算機(jī)視覺、語音和跨模態(tài)模型,并實(shí)現(xiàn)端到端的推理性能優(yōu)化。其應(yīng)用于圖像分類、物體檢測(cè)、圖像分割、人臉檢測(cè)、人臉識(shí)別、關(guān)鍵點(diǎn)檢測(cè)、摳圖、OCR、NLP、TTS等任務(wù),滿足開發(fā)者多場(chǎng)景、多硬件、多平臺(tái)的產(chǎn)業(yè)部署需求。同時(shí),F(xiàn)astDeploy集成了多種后端推理引擎,其中就包括RKNPU2。開發(fā)者能夠快速基于現(xiàn)有的模型以及后端來進(jìn)行開發(fā)。
很多開發(fā)者可能會(huì)有疑惑,為什么Rockchip提供了RKNPU2和rknn-toolkit2這兩個(gè)分別面向C++和Python的推理引擎,我們還要使用FastDeploy進(jìn)行開發(fā)呢?簡(jiǎn)單來說,RKNPU2和rknn-toolkit2是推理引擎,它們側(cè)重于推理;FastDeploy是推理部署工具側(cè)重于部署。給RKNPU2輸入一張圖片,會(huì)得到一串?dāng)?shù)字。給FastDeploy輸入一張圖片,會(huì)直接得到經(jīng)過后處理后的圖片。這樣就能大大減少開發(fā)者在項(xiàng)目落地過程中的一些困難。
RKNPU2
https://github.com/rockchip-linux/rknpu2
rknn-toolkit2
https://github.com/rockchip-linux/rknn-toolkit2
貢獻(xiàn)步驟
給FastDeploy貢獻(xiàn)代碼,我一般按以下步驟進(jìn)行,當(dāng)然你可以根據(jù)自己的能力制定自己的開發(fā)步驟。
由上圖所示,給FastDeploy貢獻(xiàn)代碼的步驟一般為編寫C++代碼、編寫C++ example、編寫Python代碼、編寫Python example代碼、編寫文檔、提交PR。
貢獻(xiàn)代碼指南
下面我以貢獻(xiàn)SCRFD模型為例子,給大家詳細(xì)介紹每個(gè)貢獻(xiàn)環(huán)節(jié)中的注意事項(xiàng)。
轉(zhuǎn)換模型
不管你是在FastDeploy上開發(fā)C++還是Python的代碼,轉(zhuǎn)換模型都是你首先需要完成的任務(wù)。通常情況下,轉(zhuǎn)換模型的工具一般使用rknn-toolkit2,但是這個(gè)工具API比較多,用起來較為復(fù)雜。為了讓大家能夠更快速的轉(zhuǎn)換模型,在FastDeploy中,我已經(jīng)編寫了轉(zhuǎn)換模型的代碼并且提供了詳細(xì)的文檔。詳情請(qǐng)查看FastDeploy RKNPU2模型轉(zhuǎn)換文檔。這里為了縮短篇幅,直接給出模型轉(zhuǎn)換的配置文件以及模型轉(zhuǎn)換的文檔。大家可以參考這幾個(gè)文檔轉(zhuǎn)換自己的模型。
FastDeploy RKNPU2模型轉(zhuǎn)換文檔
https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/cn/faq/rknpu2/export.md
模型轉(zhuǎn)換的文檔
https://github.com/PaddlePaddle/FastDeploy/tree/develop/examples/vision/facedet/scrfd/rknpu2
編寫C++代碼
上文提到,SCRFD的C++代碼需要在fastdeploy/vision/facedet/contrib這個(gè)目錄下編寫,因此我創(chuàng)建了scrfd.h和scrfd.cc這兩個(gè)文件,實(shí)現(xiàn)模型具體代碼。這里要注意與常見的文件命名形式不同,scrfd.cc這個(gè)C++代碼文件的后綴不是 .cpp而是 .cc ,如果scrfd.cc改為scrfd.cpp將無法成功編譯!
編寫scrfd.h ?
scrfd.h里定義了SCRFD模型的一些基本參數(shù)以及需要重定義的函數(shù)。其中定義的SCRFD模型需要繼承FastDeployModel這個(gè)公共的模型類,為的是繼承FastDeploy的一些公共特性。如下面的代碼所示,在頭文件中,我們需要重寫FastDeployModel中的以下幾個(gè)函數(shù),包括Initialize、Preprocess、Postprocess、Predict、ModelName。分別對(duì)應(yīng)初始化、預(yù)處理、后處理、預(yù)測(cè)、模型名稱。如果你需要完整詳細(xì)的代碼,請(qǐng)?jiān)L問下方鏈接。
scrfd.h
https://github.com/PaddlePaddle/FastDeploy/blob/develop/fastdeploy/vision/facedet/contrib/scrfd.h
編寫scrfd.cc
scrfd.cc負(fù)責(zé)對(duì)在scrfd.h中聲明的函數(shù)進(jìn)行了實(shí)現(xiàn)。在編寫預(yù)處理的過程中要注意,RKNPU2目前僅支持NHWC格式的輸入數(shù)據(jù),因此必須屏蔽Permute操作。我這里使用disable 變量控制Permute操作。此外由于FastDeploy采用的是RKNPU2的零拷貝流程來實(shí)現(xiàn)后端的處理和運(yùn)算,因此可以考慮將Normalize操作放在NPU上來做,提升速度,我這里使用disable 變量控制Normalize的開關(guān)。如果需要詳細(xì)的代碼,請(qǐng)?jiān)L問以下鏈接。
代碼鏈接
https://github.com/PaddlePaddle/FastDeploy/blob/develop/fastdeploy/vision/facedet/contrib/scrfd.cc
在vision.h中添加我們的模型
FastDeploy C++代碼編譯指南
https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/cn/faq/rknpu2/build.md
我們編寫完scrfd的代碼之后,我們還需要讓FastDeploy知道我們已經(jīng)編寫了scrfd代碼,因此我們需要在fastdeploy/vision.h文件中補(bǔ)充scrfd.h頭文件的路徑。
編譯FastDeploy C++ SDK
編寫完C++代碼后,我們需要編譯C++版本的FastDeploy。一是為了測(cè)試我們編寫的代碼是否有程序上的漏洞,二是為了后續(xù)編寫example可以鏈接FastDeploy編譯出來的動(dòng)態(tài)庫。編譯的細(xì)節(jié)詳情請(qǐng)參考FastDeploy C++代碼編譯指南。
這里直接給出編譯時(shí)的命令:
編寫C++ example代碼
為了調(diào)試我們已經(jīng)完成的C++代碼,以及方便用戶使用,在編寫完上述代碼之后,我們需要編寫對(duì)應(yīng)example的代碼來驗(yàn)證我們的想法是否正確。在編寫C++ example時(shí),目錄下的文件一般由infer_model_name.cc以及CMakeLists.txt組成。在CMakeLists.txt中需要對(duì)不同的infer_model_name.cc生成不同的infer_model_name程序。
編寫infer.cc
infer.cc主要負(fù)責(zé)調(diào)用FastDeploy的C++代碼來對(duì)SCRFD進(jìn)行測(cè)試。在上文中,我們提到vision.h可以讓fastdeploy知道我們已經(jīng)編寫了SCRFD模型。因此在編寫example時(shí),我們只需要包含vision.h,即可讓程序知道,我們已經(jīng)聲明了FastDeploy所有已經(jīng)實(shí)現(xiàn)的視覺模型。針對(duì)RKNPU的測(cè)試,其流程一般為初始化模型,然后根據(jù)轉(zhuǎn)換模型時(shí)的配置決定是否需要disable_normalize和disable_permute,隨后輸入測(cè)試圖片,調(diào)用Predict函數(shù)進(jìn)行處理,最后使用對(duì)應(yīng)的可視化函數(shù)進(jìn)行可視化。
編寫CMakeLists.txt
編寫完C++ example的代碼后,我們還需要編寫CMakeLists.txt。CMakeLists.txt相當(dāng)于編譯時(shí)的配置文件,負(fù)責(zé)鏈接infer_model_name.cc和FastDeploy的動(dòng)態(tài)庫,并且把模型推理需要用到的東西集成在install目錄下。
編寫Python代碼
Python代碼的編寫主要包括pybind文件的編寫以及py本體文件的編寫。上文提到,在FastDeploy中,python代碼通過調(diào)用pybind暴露出的C++ API來進(jìn)行工作,因此我們首先需要編寫pybind.cc。
編寫scrfd_pybind.cc
pybind.cc主要負(fù)責(zé)提供可用的API給Python調(diào)用。scrfd_pybind.cc中對(duì)SCRFD C++的代碼進(jìn)行了暴露,代碼如下:
在facedet_pybind.cc中添加聲明
和在vision.h文件中添加聲明一樣,在編寫完pybind代碼之后,我們還需要在fastdeploy/vision/facedet/facedet_pybind.cc中添加聲明。目的是告訴編譯器我們已經(jīng)編寫了pybind的代碼,并且在編譯Python時(shí)請(qǐng)把我們的代碼加上。核心代碼如下:
編寫scrfd.py
編寫完pybind.cc后,我們還需要編寫對(duì)應(yīng)的py文件調(diào)用pybind暴露出來的C++ API。代碼如下:
編譯FastDeploy Python SDK
編寫example之前我們肯定需要編譯Python版本的FastDeploy代碼,請(qǐng)參考FastDeploy RKNPU2編譯指南編譯Python版本的FastDeploy。
FastDeploy RKNPU2編譯指南
https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/cn/faq/rknpu2/build.md
這里給出我經(jīng)常使用的編譯命令:
編寫Python example代碼
為了調(diào)試我們已經(jīng)完成的Python代碼,以及方便用戶使用,在編寫完上述scrfd代碼之后,我們需要編寫對(duì)應(yīng)example的代碼來驗(yàn)證我們的想法是否正確。在編寫Python example時(shí),目錄下的文件一般由infer_model_name.py組成。
編寫infer.py
infer.py 主要負(fù)責(zé)調(diào)用FastDeploy的Python代碼來對(duì)SCRFD的測(cè)試。與C++ example相似,針對(duì)RKNPU的測(cè)試,其流程一般為初始化模型,然后根據(jù)轉(zhuǎn)換模型時(shí)的配置決定是否需要disable_normalize和disable_permute,隨后輸入測(cè)試圖片,調(diào)用Predict函數(shù)進(jìn)行處理,最后使用對(duì)應(yīng)的可視化函數(shù)進(jìn)行可視化。
編寫文檔以及提交pr
請(qǐng)參考SCRFD example編寫模型的轉(zhuǎn)換文檔、模型的cpp example運(yùn)行文檔、模型的python運(yùn)行文檔共三份文檔,然后向FastDeploy的Github倉庫提交PR。待審核過后,你的貢獻(xiàn)就會(huì)被記錄啦。
SCRFD example
https://github.com/PaddlePaddle/FastDeploy/tree/develop/examples/vision/facedet/scrfd/rknpu2
總結(jié)
在飛槳做開源貢獻(xiàn)的體驗(yàn)是無與倫比的,首先能夠快速實(shí)現(xiàn)編程能力提升,在貢獻(xiàn)代碼的過程中,你會(huì)更加深刻的理解書本上的內(nèi)容,掌握行業(yè)前沿的代碼邏輯和編程規(guī)范。同時(shí)在開發(fā)過程中,你還會(huì)認(rèn)識(shí)飛槳研發(fā)團(tuán)隊(duì)的同學(xué)以及很多志同道合的好友,與他們共同創(chuàng)造一些有趣的成果,在修復(fù)bug的過程中體驗(yàn)成就感。歡迎和我一起加入貢獻(xiàn)代碼的行列。
參考文獻(xiàn)
[1]https://github.com/PaddlePaddle/FastDeploy
[2]Guo J , Deng J , Lattas A , et al. Sample and Computation Redistribution for Efficient Face Detection[J]. 2021.