1 主流深度學習架構對比
當今的軟體開發基本都是分層化和子產品化的,應用層開發會基于架構層。比如開發Linux Driver會基于Linux kernel,開發Android app會基于Android Framework。深度學習也不例外,架構層為上層模型開發提供了強大的多語言接口、穩定的運作時、高效的算子,以及完備的通信層和裝置層管理層。是以,各大公司早早的就開始了深度學習架構的研發,以便能占領市場。目前的架構有數十種之多,主流的如下(截止到2018年11月)

顯然TensorFlow是獨一無二的王者。第二名Keras,它是對TensorFlow或Theano接口的二次封裝,嚴格意義上并不是一個獨立的深度學習架構。TensorFlow目前也已經內建了Keras,使得安裝了TensorFlow的使用者就可以直接使用Keras了。
TensorFlow之是以能夠從數十種架構中脫穎而出,主要優點有
- 出身高貴,是谷歌出品的。但其他很多架構出身也不差,例如PyTorch之于Facebook,MXNET之于Amazon
- 2015年就開源了,比較早的俘獲了一大批開發者。這個确實是tf的一大先發優勢,但PyTorch的前身Caffe,以及MXNET開源時間都不晚,而且Caffe流行時間比tf早,後來才被趕超的。更有Theano這樣的絕對老前輩。由此可見,軟體開源是多麼重要。目前流行的深度學習架構也基本都開源了。
- 支援的開發語言多,支援Python Java Go C++等多種流行語言。相比某些架構,确實是優勢很大。相比MXNET則小巫見大巫了。MXNET早期發展的一個主要方向就是前端多語言的支援,連MATLAB R Julia等語言都支援了。
- 運作效率高。早期的時候,其實tf的運作效率比很多架構都要低一些的。
- 安裝容易,使用者上手快,文檔齊全,社群活躍。這個是tf的一個較大優勢,特别是社群方面,也就是我們常說的生态優勢。網際網路頭部集中效應十分明顯,展現在開源軟體上也是一樣。這也是我認為最大的一個優勢。
總結起來,TensorFlow雖然每個方面都不是絕對領先的優勢,但貴在每個方面都做的不錯,是以最終能夠一騎絕塵,獨領風騷。
學習Tensorflow架構核心,可以了解前端接口語言的支援,session生命周期,graph的建構、分裂和執行,operation的注冊和運作,子產品間資料通信,本地運作和分布式運作模式,以及CPU GPU TPU等異構裝置的封裝支援等。學習這些,對于模型的壓縮 加速 優化等都是大有裨益的。
2 TensorFlow系統架構
TensorFlow設計十分精巧,基于分層和子產品化的設計思想進行開發的。架構如下圖
整個架構以C API為界,分為前端和後端兩大部分。
- 前端:提供程式設計模型,多語言的接口支援,比如Python Java C++等。通過C API建立前後端的連接配接,後面詳細講解。
- 後端:提供運作環境,完成計算圖的執行。進一步分為4層
- 運作時:分為分布式運作時和本地運作時,負責計算圖的接收,構造,編排等。
- 計算層:提供各op算子的核心實作,例如conv2d, relu等
- 通信層:實作元件間資料通信,基于GRPC和RDMA兩種通信方式
- 裝置層:提供多種異構裝置的支援,如CPU GPU TPU FPGA等
模型構造和執行流程
TensorFlow的一大特點是,圖的構造和執行相分離。使用者添加完算子,建構好整圖後,才開始進行訓練和執行,也就是圖的執行。大體流程如下
- 圖建構:使用者在client中基于TensorFlow的多語言程式設計接口,添加算子,完成計算圖的構造。
- 圖傳遞:client開啟session,通過它建立和master之間的連接配接。執行session.run()時,将構造好的graph序列化為graphDef後,以protobuf的格式傳遞給master。
- 圖剪枝:master根據session.run()傳遞的fetches和feeds清單,反向周遊全圖full graph,實施剪枝,得到最小依賴子圖
- 圖分裂:master将最小子圖分裂為多個Graph Partition,并注冊到多個worker上。一個worker對應一個Graph Partition。
- 圖二次分裂:worker根據目前可用硬體資源,如CPU GPU,将Graph Partition按照op算子裝置限制規範(例如tf.device('/cpu:0'),二次分裂到不同裝置上。每個計算裝置對應一個Graph Partition。
- 圖運作:對于每一個計算裝置,worker依照op在kernel中的實作,完成op的運算。裝置間資料通信可以使用send/recv節點,而worker間通信,則使用GRPC或RDMA協定。
3 前端多語言實作 - swig包裝器
TensorFlow提供了很多種語言的前端接口,使得使用者可以通過多種語言來完成模型的訓練和推斷。其中Python支援得最好。這也是TensorFlow之是以受歡迎的一大原因。前端多語言是怎麼實作的呢?這要歸功于swig包裝器。
swig是個幫助使用C或者C++編寫的軟體能與其它各種進階程式設計語言進行嵌入聯接的開發工具。在TensorFlow使用bazel編譯時,swig會生成兩個wrapper檔案
- pywrap_tensorflow_internal.py:對接上層Python調用
- pywrap_tensorflow_internal.cc:對接底層C API調用。
pywrap_tensorflow_internal.py 子產品被導入時,會加載_pywrap_tensorflow_internal.so動态連結庫,它裡面包含了所有運作時接口的符号。而pywrap_tensorflow_internal.cc中,則注冊了一個函數符号表,實作Python接口和C接口的映射。運作時,就可以通過映射表,找到Python接口在C層的實作了。
4 tensorflow 源碼結構
TensorFlow源碼基本也是按照架構分層來組織檔案的。如下
其中core為tf的核心,它的源碼結構如下
5 總結
TensorFlow架構設計精巧,代碼量也很大,我們可以從以下部分逐漸學習
- TensorFlow核心架構和源碼結構。先從全局上對架構進行了解。
- 前後端連接配接的橋梁--Session,重點了解session的生命周期,并通過相關源碼可以加深了解Python前端如何調用底層C實作。
- TensorFlow核心對象—Graph。圖graph是TensorFlow最核心的對象,基本都是圍繞着它來進行的。graph的節點為算子operation,邊為資料tensor。
- TensorFlow圖的節點 -- Operation。operation是圖graph的節點,承載了計算算子。
- TensorFlow圖的邊 -- Tensor。Tensor是圖graph的邊,承載了計算的資料。
- TensorFlow本地運作時。
- TensorFlow分布式運作時。和本地運作時有一些共用的接口,但差別也很大。
- TensorFlow裝置層。主要了解裝置層的定義規範,以及實作。
- TensorFlow隊列和并行運算。
- TensorFlow斷點檢查checkpoint,模型儲存Saver,以及可視化tensorboard。這三個為TensorFlow主要的工具。