最新發布的飛槳開源深度學習框架1.7版本,帶來多項重要更新。很是值得關注的是,飛槳「動態圖」能力有了重大升級,不但編程體驗極大提高,並且訓練性能已媲美「靜態圖」,部署能力也有全面強化。php
下載安裝命令
## CPU版本安裝命令
pip install -f https://paddlepaddle.org.cn/pip/oschina/cpu paddlepaddle
## GPU版本安裝命令
pip install -f https://paddlepaddle.org.cn/pip/oschina/gpu paddlepaddle-gpu
有過深度學習框架編程體驗的開發者都知道,目前主要有聲明式和命令式兩種編程範式,通常被稱爲靜態圖模式和動態圖模式。相對於靜態圖模式,動態圖類採用「define-by-run」的執行方式,寫一行代碼便可即時得到結果,在編程體驗、調試便捷性等方面有絕佳的優點;而靜態圖採用先編譯後執行的方式,事先定義好總體網絡結構再執行,可以對全局編譯優化,更有利於性能的提高,也有利於模型的保存和部署。python
飛槳做爲源於產業實踐的深度學習框架,並致力於讓深度學習技術的創新與應用更簡單,目前同時支持動態圖和靜態圖,兼顧開發的靈活性和高性能。c++
飛槳開源深度學習框架自1.3版增長動態圖功能,1.5版本發佈動態圖編程範式預覽版,通過多個版本的持續完善,目前已經在易用性、運行效率、模型部署能力等方面有很大的加強。飛槳將持續強化編程開發靈活性易用性的同時,保持更強勁的性能優點和全面的部署能力,助力開發者快速實現AI想法、快速上線AI業務。git
下面咱們就來看看,本次飛槳在動態圖方面帶來哪些新升級:github
深度效率優化,媲美靜態圖的訓練性能
訓練性能表現對一個深度學習框架而言很是重要,尤爲是在工業生產應用場景中。動態圖模式在帶來了編程體驗提高的同時,也讓不少人顧慮它的性能損失問題。飛槳在對動態圖支持的實現上,特別考慮到執行效率的優化問題。在1.6版本中,對於不少任務模型,動態圖的執行性能已經能和靜態圖模式相接近。在1.7版本中,進一步對Python與C++交互效率、C++端運行效率等方面作了深度優化,總體訓練性能已和靜態圖圖相媲美。即便對於RNN一類的動態圖的性能短板任務,飛槳動態圖也達到了極高的速度水平。編程
咱們能夠看到,在P40環境下,基於LSTM實現的語言模型任務,當下的訓練速度相比1.6版本有近三倍的提高。網絡
下面來看一下,本次升級對應的關鍵技術點:數據結構
-
提高Python與 C++交互效率框架
咱們知道,爲了保證運行效率,框架底層的運算邏輯都是使用C++實現的,而爲了編程的便利性,框架的用戶編程接口爲Python。在動態圖模式下,每個OP執行時,都須要進行一次Python與C++交互,即將Python端的對象傳遞給C++端,這相對於靜態圖模式是一種顯著的額外開銷。新版本中,優化了Python與C++交互的數據結構,傳遞的結構更加精簡,大大提高了執行效率。dom
在1.6版本的實現中,動態圖的VarBase對象包含在Variable對象當中的,python與c++交互處理的是Variable對象,可是在Python的底層,這種對象保護關係是經過map進行實現的,咱們獲取或者修改包含的元素,性能都很是的差,在1.7中,咱們從新設計了動態圖的VarBase對象,python與c++直接傳遞VarBase對象,節省map的查找和修改開銷,從而提升性能。
-
優化C++端運行效率
動態圖模式下,每一個OP執行時,均須要作一次數據構造,OP運行結束以後進行析構。因爲Op中包含了複雜的map等結構,這種結構的構造和析構會都帶來很大的開銷,在1.7版本中,咱們經過框架的優化,移除了這種map的構造和析構。簡化數據結構,下降構造開銷,由此提高執行效率。
-
【提高運行效率】優化DataLoader,提高總體性能
DataLoader雖然不算是動態圖核心功能,但倒是影響任務總體訓練性能的重要因素。因爲動態圖執行模式下的差別性,對應的DataLoader的設計和實現須要有不一樣於靜態圖模式的更多考量。動態圖模式下若每一個op執行時,都申請python的全局鎖(Global Interpreter Lock),會致使異步DataLoader中數據處理的線程效率受到很大影響,若是訓練時每一個batch的數據量比較大,DataLoader的性能就不如靜態圖模式下那麼高效。爲此,飛槳新版本的動態圖模式在原來的基礎上引入了multi-processing進行數據處理,這種進程間的處理不受全局鎖的影響,進而提高執行效率。在resnet,se_resnext等任務上,總體性能提高約30%。
-
優化反向計算策略,刪除冗餘Tensor空間,下降顯存佔用。
針對部分OP,在執行反向計算時不依賴正向Tensor值,只依賴Tensor shape的狀況,引入策略,刪除不須要的Tensor空間,只保留須要的Tensor shape信息,以下降顯存佔用。在Resnet等任務上,同一個硬件設備上,可以設置最大batch size 提高了20%左右。
強化部署能力,追求極佳產業應用實踐
在工業界,深度學習模型的部署是技術落地很是關鍵的部分。動態圖模式採用命令式執行,並使用python原生語法來構建網絡的形式,帶來靈活性和便利性的同時,對於模型在C++端的自動部署產生了巨大的挑戰。由於動態圖模式下,沒有一個總體的靜態的網絡結構內部表達,須要將python語法自動映射到C++端。
飛槳在推出動態圖編程模式的同時,周密考慮了對訓練後部署的支持。針對網絡中不包含依賴數據的控制流的模型, 咱們提供了基於TracedLayer的方案來將動態圖模型轉換爲靜態圖的方案,完成自動部署的功能;對於網絡中存在依賴數據的控制流模型,飛槳實現了基於python語法解析和重構的技術,能夠將python的控制流解釋爲飛槳控制流op,總體映射爲靜態圖圖表達,這種方案將支持絕大部分任務完成推理部署功能,會在下個版本發佈。
TracedLayer 使用方法以下:
import paddle.fluid as fluid from paddle.fluid.dygraph import Linear, to_variable, TracedLayer import numpy as np #自動一個Layer class ExampleLayer(fluid.dygraph.Layer): def __init__(self): super(ExampleLayer, self).__init__() self._fc = Linear(3, 10) # 包含一個Linear層 def forward(self, input): return self._fc(input) with fluid.dygraph.guard(): layer = ExampleLayer() in_np = np.random.random([2, 3]).astype('float32') # 須要一個fake的數據 in_var = to_variable(in_np) #調用trace方法 out_dygraph, static_layer = TracedLayer.trace(layer, inputs=[in_var]) # 內部使用Executor運行靜態圖模型 out_static_graph = static_layer([in_var]) print(len(out_static_graph)) # 1 print(out_static_graph[0].shape) # (2, 10) # 將靜態圖模型保存爲預測模型 static_layer.save_inference_model(dirname='./saved_infer_model')
對於上述操做保存的文件,能夠直接使用靜態圖的C++部署方案,進行部署上線。
提高易用性,追求極致編碼體驗
在追求框架極限性能和部署能力的同時,飛槳也一直持續優化框架的易用性,在編程接口和模塊使用上不斷的打磨,精益求精,努力讓你們的使用成本最低。在1.7版本中經過優化反向自動剪枝策略,在提高執行效率的同時,對於沒有反向的op輸出,不用顯式設置stop_gradient的屬性;Layer的構造函數中移除了name_scope,減小參數的傳遞;並移除Layer中的 build_once接口,方便你們更方便的進行參數的初始化、模型預測等;增長了一系列容器,包含Sequencial,LayerList,ParameterList,更加方便Layer和參數的管理,並可以下降你們使用時出錯的機率。關於新版本的功能優化接口升級的細節可查看官網。
咱們來看一個demo示例,針對上述一系列的改動,模型的代碼會更加簡潔。
# 1.6版本示例 class MyLayer(fluid.Layer): def __init__(self): ... # 在1.6中相似的Layer須要單獨定義 self.conv2d1 = Conv2D("conv1", 3, 5) self.conv2d2 = Conv2D("conv2", 3, 5) self.conv2d3 = Conv2D("conv3":, 3, 5) self.layer_list = [TestLayer(shapes[i]) for i in range(10)] # 1.6中 列表中的Layer須要單獨調用 add_sublayer, 增長使用成本 # 並且add_sublayer的第一個參數必須惟一,惟一出錯 for i, layer in enumerate(self.layer_list): self.add_sublayer("layer_" + str(i), layer) def forward(self, x, y): # 使用的時候,須要單獨調用 y = self.conv2d1(x) y = self.conv2d2(y) y = self.conv2d3(y) for layer in self.layer_list: x, y = layer(x, y) return x, y # 1.7版本示例 class MyLayer(fluid.Layer): def __init__(self): ... # 在1.7中,Layer能夠統一放入Sequencial容器進行管理 # Sequencial中的Layer必須是單輸入、單輸出的 self.sequential = Sequential([ Conv2D(3, 3, 5), # Conv2D的構造再也不須要name_scope Conv2D(5, 3, 5), Conv2D(5, 3, 5)]) # 在1.7中,多個Layer能夠經過LayerList統一管理,不在調度調用 add_sublayer # 因爲這個Layer的輸入和輸出都是兩個,不能放入Sequencial中 self.layer_list = fluid.dygraph.LayerList( [TestLayer(shapes[i]) for i in range(10)]) def forward(self, x, y): # Sequencial的對象在調用時,內部包含的Layer會依次執行,沒必要單獨調用 y = self.sequential(x) for layer in self.layer_list: x, y = layer(x, y) return x, y
目前動態圖功能已趨於完善,接口也趨於穩定,在後續新版本會最大可能保持前向兼容,飛槳將持續爲廣大開發者提供靈活高效的產業級深度學習框架。
若是您加入官方QQ羣,您將趕上大批志同道合的深度學習同窗。官方QQ羣:703252161。
若是您想詳細瞭解更多飛槳的相關內容,請參閱如下文檔。
下載安裝命令
## CPU版本安裝命令
pip install -f https://paddlepaddle.org.cn/pip/oschina/cpu paddlepaddle
## GPU版本安裝命令
pip install -f https://paddlepaddle.org.cn/pip/oschina/gpu paddlepaddle-gpu
官網地址:
https://www.paddlepaddle.org.cn
飛槳PGL項目地址:
https://github.com/PaddlePaddle/PGL
飛槳開源框架項目地址:
GitHub: https://github.com/PaddlePaddle/Paddle
Gitee: https://gitee.com/paddlepaddle/Paddle
>> 訪問 PaddlePaddle 官網,瞭解更多相關內容。