模型部署
一、Pytorch 模型部署
1. 模型保存
1.1. 使用torch.save()保存
-
保存和加載state_dict,即只保存模型參數(shù)
保存:
torch.save(model.state_dict(), SAVE_PATH)
加載:
model = ModelClass(*args, **kwargs) model.load_state_dict(torch.load(SAVE_PATH)) model.eval()
-
保存完整的模型文件
保存:
torch.save(model, SAVE_PATH)
加載:
model = torch.load(SAVE_PATH) model.eval()
-
保存模型并恢復(fù)訓(xùn)練狀態(tài),斷點(diǎn)重訓(xùn)
# 保存 state = { 'epoch': epoch, 'state_dict': model.state_dict(), 'optimizer': optimizer.state_dict(), ... } torch.save(state, filepath) # 模型與參數(shù)加載 model.load_state_dict(state['state_dict']) optimizer.load_state_dict(state['optimizer'])
1.2. 使用torch.jit.save()保存
用于保存編譯過后的模型,跨平臺(tái)使用,模型中只能使用pytorch的函數(shù),可以使用被加載到C ++ API torch::jit::load(filename)
或與Python的API torch.jit.load
torch.jit.save支持保存script類型和trace類型的模為TorchScript,其中script為全量模型,trace為僅保存運(yùn)行過的路徑。
什么是JIT?TorchScript?
JIT(just-in-time compilation,即時(shí)編譯)模式選擇了構(gòu)建well-defined IR的方式。這樣帶來的好處有:
- 將python runtime和計(jì)算圖(model graph)解耦
- 獲得C++相比帶GIL的Python的收益
- 獲得整個(gè)程序,拿到全局信息,來進(jìn)行優(yōu)化
- 將易于調(diào)試的模式和易于部署/優(yōu)化的模式進(jìn)行切分(算法調(diào)參和算法部署各司其職)
TorchScript是JIT模式的具體形式,是一種從PyTorch代碼創(chuàng)建可序列化和可優(yōu)化模型的方法。任何TorchScript程序都可以從Python進(jìn)程中保存,并加載到?jīng)]有Python依賴的進(jìn)程中。
trace和script的區(qū)別?
1、trace只記錄走過的tensor和對(duì)tensor的操作,不會(huì)記錄任何控制流信息,如if條件句和循環(huán)。因?yàn)闆]有記錄控制流的另外的路,也沒辦法對(duì)其進(jìn)行優(yōu)化。好處是trace深度嵌入python語言,復(fù)用了所有python的語法,在計(jì)算流中記錄數(shù)據(jù)流。
2、script會(huì)去理解所有的code,真正像一個(gè)編譯器一樣去進(jìn)行l(wèi)exer、parser、Semantic analusis的分析「也就是詞法分析語法分析句法分析,形成AST樹,最后再將AST樹線性化」。script相當(dāng)于一個(gè)嵌入在Python/Pytorch的DSL,其語法只是pytorch語法的子集,這意味著存在一些op和語法script不支持,這樣在編譯的時(shí)候就會(huì)遇到問題。此外,script的編譯優(yōu)化方式更像是CPU上的傳統(tǒng)編譯優(yōu)化,重點(diǎn)對(duì)于圖進(jìn)行硬件無關(guān)優(yōu)化,并對(duì)IF、loop這樣的statement進(jìn)行優(yōu)化。
【Pytorch部署】TorchScript
PyTorch系列「一」PyTorch JIT —— trace/ script的代碼組織和優(yōu)化方法
2. 模型部署 or 模型編譯
什么是模型編譯?深度學(xué)習(xí)編譯器?
傳統(tǒng)的編譯器是以高層語言作為輸入,避免直接去寫匯編,機(jī)器碼;而深度學(xué)習(xí)編譯器作用相仿,其輸入是高度抽象的計(jì)算圖,輸出包括CPU或者GPU等硬件平臺(tái)是哪個(gè)的底層代碼和執(zhí)行引擎,即深度學(xué)習(xí)編譯器將不同框架描述的深度學(xué)習(xí)模型為某個(gè)硬件平臺(tái)生成優(yōu)化的代碼。AOT(ahead-of-time compliation)

深度學(xué)習(xí)編譯器普遍采用的設(shè)計(jì)架構(gòu):

這類編譯器的通用設(shè)計(jì)體系結(jié)構(gòu)主要包含兩部分:編譯器前端和編譯器后端。 中間表示(IR)橫貫前端和后端。 通常IR是程序的抽象,用于程序優(yōu)化。 具體而言,深度學(xué)習(xí)模型在編譯器中轉(zhuǎn)換為多級(jí)IR,其中高級(jí)IR駐留在前端,而低級(jí)IR駐留在后端。 基于高級(jí)IR,編譯器前端負(fù)責(zé)獨(dú)立于硬件的轉(zhuǎn)換和優(yōu)化。 基于低級(jí)IR,編譯器后端負(fù)責(zé)特定于硬件的優(yōu)化、代碼生成和編譯。
2.1. TorchScript部署
參見上文
2.2. TensorRT部署
tensorrt 部署 pth:
- 使用pytorch訓(xùn)練得到pt文件;
- 將pt文件轉(zhuǎn)換為onnx中間件;
- 使用onnxsim.simplify對(duì)轉(zhuǎn)換后的onnx進(jìn)行簡化;
- 解析onnx文件構(gòu)建trt推理引擎;
cd tensorrt_path/bin && ./trtexec --onnx=*.onnx --saveEngine=*.trt
- 導(dǎo)出網(wǎng)絡(luò)定義以及相關(guān)權(quán)重;
- 解析網(wǎng)絡(luò)定義以及相關(guān)權(quán)重;
- 根據(jù)顯卡算子構(gòu)造出最優(yōu)執(zhí)行計(jì)劃;
- 將執(zhí)行計(jì)劃序列化存儲(chǔ);
- 反序列化執(zhí)行計(jì)劃;
- 進(jìn)行推理
pytorch中使用TensorRT
2.3. TVM部署
模型在使用 TVM 編譯器框架進(jìn)行轉(zhuǎn)換時(shí)所采取的步驟。
-
從Tensorflow、PyTorch或Onnx等框架導(dǎo)入模型。
TVM 導(dǎo)入層是從其他框架(如 Tensorflow、PyTorch 或 ONNX)導(dǎo)入模型,如果在將模型導(dǎo)入 TVM 時(shí)遇到問題,想嘗試將其轉(zhuǎn)換為 ONNX(更適配)。
-
將導(dǎo)入的模型翻譯成TVM 的高級(jí)模型語言Relay。
已導(dǎo)入 TVM 的模型在 Relay 中表示。Relay 是模型的中間表示 (Intermediate representation, IR)。支持:
- 傳統(tǒng)數(shù)據(jù)流表示
- Functional-style scoping, let-binding which makes it a fully featured differentiable language
- 允許混合兩種編程風(fēng)格的能力
Relay 應(yīng)用圖級(jí)優(yōu)化傳遞來優(yōu)化模型。
-
Lower到Tensor expression(TE) 表示。
Lower是指將高級(jí)表示轉(zhuǎn)換為低級(jí)表示。在應(yīng)用高級(jí)優(yōu)化后,Relay 運(yùn)行 FuseOps pass 將模型劃分為許多小子圖,并將子圖降低為 TE 表示。張量表達(dá)式 (TE) 是一種用于描述張量計(jì)算的domain-specific語言。TE 還提供了幾個(gè)schedule來指定low-level loop優(yōu)化,例如tiling、vectorization、parallelization、unrolling和fusion。為了幫助將Relay representation轉(zhuǎn)換為 TE represention的過程,TVM 包括一個(gè)張量運(yùn)算符清單 (Tensor Operator Inventory, TOPI),它具有預(yù)定義的常用張量運(yùn)算符模板(例如,conv2d、轉(zhuǎn)置)。
-
使用auto-tuning模塊AutoTVM或AutoScheduler搜索最佳schedule。
schedule為 TE 中定義的運(yùn)算符或子圖指定的低級(jí)循環(huán)進(jìn)行優(yōu)化。auto-tuning模塊搜索最佳schedule并將其與cost model和on-device measurement進(jìn)行比較。TVM 中有兩個(gè)auto-tuning模塊。
- AutoTVM:基于模板的自動(dòng)調(diào)整模塊。它運(yùn)行搜索算法來找到最佳值。對(duì)于常用的算子,TOPI 中已經(jīng)提供了模板。
- AutoScheduler(又名 Ansor):一個(gè)無模板的自動(dòng)調(diào)整模塊。它不需要預(yù)定義的schedule模板。相反,它通過分析計(jì)算定義自動(dòng)生成搜索空間。然后它在生成的搜索空間中搜索最佳schedule。
-
選擇模型編譯的最佳配置。
調(diào)優(yōu)后,自動(dòng)調(diào)優(yōu)模塊會(huì)生成JSON格式的調(diào)優(yōu)記錄。此步驟為每個(gè)子圖選擇最佳schedule。
-
Lower to Tensor Intermediate Representation (TIR),TVM 的低級(jí)中間表示。
在根據(jù)調(diào)整步驟選擇最佳配置后,每個(gè) TE 子圖都降低到 TIR 并通過低級(jí)優(yōu)化通道進(jìn)行優(yōu)化。接下來,將優(yōu)化后的 TIR 降低到硬件平臺(tái)的目標(biāo)編譯器。這是生成可部署到生產(chǎn)中的優(yōu)化模型的最終代碼生成階段。TVM 支持多種不同的編譯器后端,包括:
- LLVM,它可以針對(duì)任意微處理器架構(gòu),包括標(biāo)準(zhǔn) x86 和 ARM 處理器、AMDGPU 和 NVPTX 代碼生成,以及 LLVM 支持的任何其他平臺(tái)。
- 專用編譯器,例如 NVCC,NVIDIA 的編譯器。
- 嵌入式和專用目標(biāo),通過 TVM 的Bring Your Own Codegen (BYOC) 框架實(shí)現(xiàn)。
-
編譯成機(jī)器代碼。
在此過程結(jié)束時(shí),特定于編譯器的生成代碼可以lower為機(jī)器代碼。
TVM 可以將模型編譯為可鏈接的對(duì)象模塊,然后使用輕量級(jí) TVM runtime 提供的 C API 來動(dòng)態(tài)加載模型然后運(yùn)行,以及使用其他語言(如 Python 和 Rust)的接口。TVM 還可以構(gòu)建捆綁部署,其中runtime與模型結(jié)合在一個(gè)包中。文章來源:http://www.zghlxwxcb.cn/news/detail-633415.html
使用tvmc的python API文章來源地址http://www.zghlxwxcb.cn/news/detail-633415.html
- TVM 實(shí)戰(zhàn)練習(xí):
[模型部署]:TVM模型部署實(shí)戰(zhàn)
2.4. Laser部署
到了這里,關(guān)于[模型部署]:深度學(xué)習(xí)模型部署(已更Pytorch篇)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!