假如問在深度學習實踐中,最難的部分是什麼?猜想80%的開發者都會說:html
「固然是調參啊。」python
爲何難呢?由於調參就像廚師根據食材找到了料理配方,藥劑師根據藥材找到了藥方,充滿了玄幻色彩。git
可是,掌握了調參,頂多算深度學習的絕學掌握了一半。而另外一半就是「模型部署」。github
模型部署有什麼難的?舉個例子:前面這位大廚在培訓學校,通過各類訓練掌握了不少料理配方,終於要到酒店上任了,卻發現酒店的廚房環境和訓練時不同,就餐高峯時手忙腳亂,客戶等了1個小時還沒上菜,結果第一天上崗就被投訴了。數組
雖然比喻略有誇張,卻也道出了深度學習模型訓練和推理部署的關係。服務器
咱們知道,深度學習通常分爲訓練和推理兩個部分,訓練是神經網絡「學習」的過程,主要關注如何搜索和求解模型參數,發現訓練數據中的規律。網絡
有了訓練好的模型以後,就要在線上環境中應用模型,實現對未知數據作出預測,這個過程在AI領域叫作推理。架構
在實際應用中,推理階段可能會面臨和訓練時徹底不同的硬件環境,固然也對應着不同的計算性能要求。咱們訓練獲得的模型,須要能在具體生產環境中正確、高效地實現推理功能,完成上線部署。框架
因此,當咱們千辛萬苦訓練好模型,終於要上線了,但這個時候可能會遇到各類問題,好比:dom
對工業級部署而言,要求的條件每每很是繁多並且苛刻,不是每一個深度學習框架都對實際生產部署上能有良好的支持。一款對推理支持完善的的框架,會讓你的模型上線工做事半功倍。
飛槳做爲源於產業實踐的深度學習框架,在推理部署能力上有特別深厚的積累和打磨,提供了性能強勁、上手簡單的服務器端推理庫Paddle Inference,幫助用戶擺脫各類上線部署的煩惱。
飛槳框架的推理部署能力通過多個版本的升級迭代,造成了完善的推理庫Paddle Inference。Paddle Inference功能特性豐富,性能優異,針對不一樣平臺不一樣的應用場景進行了深度的適配優化,作到高吞吐、低時延,保證了飛槳模型在服務器端即訓即用,快速部署。
在推理初始化階段,對模型中的OP輸出Tensor 進行依賴分析,將兩兩互不依賴的Tensor在內存/顯存空間上進行復用,進而增大計算並行量,提高服務吞吐量。
在推理初始化階段,按照已有的融合模式將模型中的多個OP融合成一個OP,減小了模型的計算量的同時,也減小了 Kernel Launch的次數,從而能提高推理性能。目前Paddle Inference支持的融合模式多達幾十個。
內置同Intel、Nvidia共同打造的高性能kernel,保證了模型推理高性能的執行。
Paddle Inference採用子圖的形式集成TensorRT,針對GPU推理場景,TensorRT可對一些子圖進行優化,包括OP的橫向和縱向融合,過濾冗餘的OP,併爲OP自動選擇最優的kernel,加快推理速度。
Paddle Lite 是飛槳深度學習框架的一款輕量級、低框架開銷的推理引擎,除了在移動端應用外,還可使用服務器進行 Paddle Lite 推理。Paddle Inference採用子圖的形式集成 Paddle Lite,以方便用戶在服務器推理原有方式上稍加改動,便可開啓 Paddle Lite 的推理能力,獲得更快的推理速度。而且,使用 Paddle Lite 可支持在百度崑崙等高性能AI芯片上執行推理計算。
PaddleSlim是飛槳深度學習模型壓縮工具,Paddle Inference可聯動PaddleSlim,支持加載量化、裁剪和蒸餾後的模型並部署,由此減少模型存儲空間、減小計算佔用內存、加快模型推理速度。其中在模型量化方面,Paddle Inference在X86 CPU上作了深度優化,常見分類模型的單線程性能可提高近3倍,ERNIE模型的單線程性能可提高2.68倍。
【性能測一測】經過比較resnet50和bert模型的訓練前向耗時和推理耗時,能夠觀測到Paddle Inference有顯著的加速效果。
說明:測試耗時的方法,使用相同的輸入數據先空跑1000次,循環運行1000次,每次記錄模型運行的耗時,最後計算出模型運行的平均耗時。
支持服務器端X86 CPU、NVIDIA GPU芯片,兼容Linux/Mac/Windows系統。支持全部飛槳訓練產出的模型,徹底作到即訓即用。
支持C++, Python, C, Go和R語言API, 接口簡單靈活,20行代碼便可完成部署。對於其餘語言,提供了ABI穩定的C API, 用戶能夠很方便地擴展。
下面咱們一塊兒來看看如何使用飛槳完成服務器端推理部署。
飛槳框架提供了一個內置函數 save_inference_model, 將模型保存爲推理用的模型格式。save_inference_model能夠根據推理須要的輸入和輸出, 對訓練模型進行剪枝, 去除和推理無關部分, 獲得的模型相比訓練時更加精簡, 適合進一步優化和部署。
from paddle import fluid place = fluid.CPUPlace() executor = fluid.Executor(place) image = fluid.data(name="image", shape=[None, 28, 28], dtype="float32") label = fluid.data(name="label", shape=[None, 1], dtype="int64") feeder = fluid.DataFeeder(feed_list=[image, label], place=place) predict = fluid.layers.fc(input=image, size=10, act='softmax') loss = fluid.layers.cross_entropy(input=predict, label=label) avg_loss = fluid.layers.mean(loss) executor.run(fluid.default_startup_program()) # 保存模型到model目錄中, 只保存與輸入image和輸出與推理相關的部分網絡 fluid.io.save_inference_model("model", feed_var_names=["image"], target_vars=[predict]. executor=executor)
保存推理模型以後, 就可使用推理庫了, Paddle Inference提供了 AnalysisConfig 用於管理推理部署的各類設置,好比設置在CPU仍是GPU部署、加載模型路徑、開啓/關閉計算圖分析優化、使用MKLDNN/TensorRT進行部署的加速等,用戶能夠根據本身的上線環境, 打開所需優化配置。同時,可配置採用zero copy的方式管理輸入和輸出, 推理執行時可跳過feed op和fetch op,減小多餘的數據拷貝,提升推理性能。
from paddle.fluid.core import AnalysisConfig # 建立配置對象 config = AnalysisConfig("./model") # 配置採用zero copy的方式 config.switch_use_feed_fetch_ops(False) config.switch_specify_input_names(True)
定義好部署的配置後,就能夠建立預測器了。Paddle Inference提供了多項圖優化的方式,建立預測器時將會加載推理模型並自動進行圖優化,以加強推理性能。
# 建立預測器 from paddle.fluid.core import create_paddle_predictor predictor = create_paddle_predictor(config)
建立好預測器以後,只須要傳入數據就能夠運行推理計算預測結果了。這裏假設咱們已經將輸入數據讀入了一個numpy.ndarray數組中,飛槳提供了簡單易用的API來管理輸入和輸出。
# 獲取並傳入數據 input_names = predictor.get_input_names() input_tensor = predictor.get_input_tensor(input_names[0]) input_tensor.copy_from_cpu(input_data.reshape([1, 28, 28]).astype("float32")) # 運行預測器, 這裏將會執行真正的預測 predictor.zero_copy_run() # 輸出預測結果 ouput_names = predictor.get_output_names() output_tensor = predictor.get_output_tensor(output_names[0]) output_data = output_tensor.copy_to_cpu()
接下來以一個完整的Python API的實例,來實踐一下使用飛槳部署模型的全流程。咱們以在P4 GPU服務器上部署resnet模型爲例。
能夠參考官網下載並安裝PaddlePaddle。
wget http://paddle-inference-dist.bj.bcebos.com/resnet50_model.tar.gz && tar -xzf resnet50_model.tar.gz
import argparse import argparse import numpy as np from paddle.fluid.core import AnalysisConfig from paddle.fluid.core import create_paddle_predictor def main(): args = parse_args() # 設置AnalysisConfig config = set_config(args) # 建立PaddlePredictor predictor = create_paddle_predictor(config) # 獲取輸入的名稱 input_names = predictor.get_input_names() input_tensor = predictor.get_input_tensor(input_names[0]) # 設置輸入 fake_input = np.random.randn(args.batch_size, 3, 318, 318).astype("float32") input_tensor.reshape([args.batch_size, 3, 318, 318]) input_tensor.copy_from_cpu(fake_input) # 運行predictor predictor.zero_copy_run() # 獲取輸出 output_names = predictor.get_output_names() output_tensor = predictor.get_output_tensor(output_names[0]) output_data = output_tensor.copy_to_cpu() # numpy.ndarray類型 for i in range(args.batch_size): print(np.argmax(output_data[i])) def parse_args(): # 模型路徑配置 parser = argparse.ArgumentParser() parser.add_argument("--model_file", type=str, help="model filename") parser.add_argument("--params_file", type=str, help="parameter filename") parser.add_argument("--batch_size", type=int, default=1, help="batch size") return parser.parse_args() def set_config(args): config = AnalysisConfig(args.model_file, args.params_file) config.enable_use_gpu(100, 0) config.switch_use_feed_fetch_ops(False) config.switch_specify_input_names(True) return config if __name__ == "__main__": main()
# model爲模型存儲路徑 python3 infer_resnet.py --model_file=model/model --params_file=model/params
以上就是使用Paddle Inference的Python API進行模型部署的完整流程,可從官網獲取代碼。若是想了解C++部署,能夠參考官網提供的C++示例。
Python示例:
C++示例:
到這裏已經完成一個基本的推理服務,是否能夠交差了?對於精益求精的開發者們來講顯然還不夠,飛槳還可經過下面這些方法,幫助用戶進一步提升推理性能:
在X86 CPU上, 若硬件支持, 能夠打開DNNL (Deep Neural Network Library, 原名MKLDNN) 優化, 這是一個Intel開源的高性能計算庫, 用於Intel架構的處理器和圖形處理器上的神經網絡優化, 飛槳可自動調用,只須要在配置選項中打開便可。
config.enable_mkldnn()
若須要使用NVIDIA GPU,只需一行配置,就可自動切換到GPU上。
# 在 GPU 0 上初始化 100 MB 顯存。這只是一個初始值,實際顯存可能會動態變化。 config.enable_use_gpu(100, 0)
TensorRT是一個高性能的深度學習推理加速庫,可爲GPU上的深度學習推理應用程序提供低延遲和高吞吐量的優化服務。Paddle Inference採用子圖的形式對TensorRT 進行了集成。在已經配置使用 GPU 推理的基礎上, 只須要一行配置就能夠開啓 Paddle TensorRT加速推理:
config.enable_tensorrt_engine(workspace_size=1 << 30, max_batch_size=1, min_subgraph_size=3, precision_mode=AnalysisConfig.Precision.Float32, use_static=False, use_calib_mode=False)
針對一些計算量較小,實際推理耗時不多的小模型,若是直接使用Paddle Inference,框架耗時可能與模型耗時在同一量級,此時可選用Paddle Lite子圖的方式來運行以減小框架耗時。Paddle Inference採用子圖的形式集成 Paddle Lite,只須要添加一行配置便可開啓 Paddle Lite 的推理加速引擎。
config.enable_lite_engine(precision_mode=AnalysisConfig.Precision.Float32)
工業級部署可能面臨多樣化的部署環境,針對不一樣應用場景,飛槳提供了三種推理部署方案:
更多介紹可訪問以下飛槳項目地址,一塊兒探索飛槳強大的工業部署實踐能力。
飛槳Paddle Inference項目地址:
https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/fluid/inference
飛槳Paddle Lite項目地址:https://github.com/PaddlePaddle/Paddle-Lite
飛槳Paddle Serving項目地址:https://github.com/PaddlePaddle/Serving
飛槳PaddleSlim項目地址:https://github.com/PaddlePaddle/PaddleSlim
若是您加入官方QQ羣,您將趕上大批志同道合的深度學習同窗。
官方QQ羣:703252161。
若是您想詳細瞭解更多飛槳的相關內容,請參閱如下文檔。
官網地址:https://www.paddlepaddle.org.cn
飛槳核心框架項目地址: