TensorFlow白皮書閱讀筆記
Martín Abadi, Ashish Agarwal, Paul Barham, Eugene Brevdo, Zhifeng Chen, Craig Citro, Gregory S. Corrado, Andy Davis,Jeffrey Dean, Matthieu Devin, Sanjay Ghemawat, Ian J. Goodfellow, Andrew Harp, Geoffrey Irving, Michael Isard,Yangqing Jia, Rafal Józefowicz, Lukasz Kaiser, Manjunath Kudlur, Josh Levenberg, Dan Mané, Rajat Monga, Sherry Moore,Derek Gordon Murray, Chris Olah, Mike Schuster, Jonathon Shlens, Benoit Steiner, Ilya Sutskever, Kunal Talwar, Paul A. Tucker, Vincent Vanhoucke, Vijay Vasudevan, Fernanda B. Viégas, Oriol Vinyals, Pete Warden, Martin Wattenberg, Martin Wicke, Yuan Yu, Xiaoqiang Zheng:
編程模型與基本概念
TensorFlow的計算過程采用一張有向圖(DAG)來描述,有向圖由許多節點(nodes)構成,圖代表了一個數據流(dataflow)計算過程,用戶通常用某種前端語言(C++/Python)建立一個計算圖,來執行某個過程。
在TensorFlow圖中,每個節點(node)可以有任意個輸入,任意個輸出,代表了一個操作的實例化,流過圖中正常的邊(edge)(從輸出到輸入)的值(Values)稱為張量(Tensor),可以理解為任意維的array。有一些特殊的邊,稱為控制依賴(control dependencies),沒有數據流過,表示節點與節點之間一種序關系,也即happens-before關系。
- 操作(Operation):一個操作代表一次抽象計算,有一個名字,還能有一個屬性,所有的屬性必須給定或者能夠在圖建立的時候就推斷出來,屬性的作用主要就是是操作在不同的張量類型上保持多態(?)
- 核(Kernel):操作的特殊實現,可以運行在一個特定設備上。
- 會話(Session):用戶與TensorFlow系統交互的客戶端程序,提供許多操作。主要是Run,即獲取需要計算的輸出,以及fed進來的輸入,運行一次整個流圖的計算,得到結果填入輸出中。一般是對一個圖啟動一個Session,然后執行多次。
- 變量(Variable):大多數情況下,圖是執行多次的,大多數的Tensor在一次執行后不會繼續存活,然而變量(Variable)是一種特殊的操作,它返回一個到持久化可變張量(persistent mutable tensor)的句柄,就是說它的生命周期是整個圖的計算過程。這樣可以保證許多機器學習任務中參數的持續迭代改變。
- 設備(device):設備是TensorFlow的計算核心,每個worker負責一到多個設備,每個設備有一個名字,設備通常指的就是某個CPU或者GPU,它的命名方式有一定講究,比如 /job:localhost/device:cpu:0 等。
- 張量(Tensor):一種有類型的多維數組,元素類型包括大小為從 8 bit 到 64 bit 的帶符號和無符號整型,IEEE 浮點數和雙精度類型、復數類型和字符串類型(任意長的字節數組)。通過一個分配器來管理其后臺存儲(backing store),且維持一個引用計數,在沒有引用時釋放。
Implementation
單設備執行
單設備執行不用說了,一切都在本地,每個節點維護一個依賴計數,表示該節點的先序節點還有多少個沒有執行,如果該計數為0,則將該節點放入準備隊列ReadyQueue等待執行。
多設備執行
多設備執行中,主要有兩個復雜性:
- 如何分配哪個節點在哪臺設備上計算?
- 管理跨設備的數據通信
節點置放
現在有一張計算圖,TensorFlow需要將這些節點的計算放置到可用給的設備上,如何分配每個節點到具體的設備是要解決的問題。
此版本的TensorFlow采用了一種模擬執行過程的啟發式的cost model,即先模擬一遍圖的執行過程,采用啟發式貪心策略來分配。首先設備需要滿足能夠執行該node所需的操作,然后再談分配的問題,在備選的設備中選取一個預計執行時間最小的設備,放置,然后進行下面的分配,當然在有控制依賴的時候還需要加以考慮。目前來說, 置放算法還在進一步地研究優化 。
設備間通信
TensorFlow采用Send節點和Receive節點來實現跨設備的數據交換。將設備A中a節點到設備B中b節點之間的邊用send和recv的節點隔開,如圖所示。
這使得我們將Send和Receive內部的通信機制與節點與節點之間的通信隔離開來。而且這種方式下,master只需要提出“任務”(通過Run)給workers,而無需管理workers之間的通信,這就相當于去中心化(decentralized)了,大大減小了master的負載。
要注意的是,如果一臺設備上的兩個或多個tensor都依賴于另一臺設備的某一個tensor,TensorFlow只使用一個Recv節點,參看上圖右邊的b,c。
分布式執行
分布式執行非常像多設備執行,之中要解決容錯的問題。
錯誤主要發生在:
- Send/Recv的通信錯誤
- 周期性的保活檢查(keep-alive)時
如果發生了錯誤,那么整個圖會終止執行,并重啟。如果簡單地這樣處理的話,那些正確計算好的節點就得重新計算,不高效,所以TensorFlow支持在重啟過程中一致的檢查點和狀態恢復。
怎么實現的呢?
每個節點有一個到Save節點的連接,也被一個Restore節點所連接,周期性地執行Save,持久化變量到比如分布式文件系統等存儲上。類似的,Restore節點負責在重啟后的第一個迭代中恢復變量的值(或狀態?)
擴展
TensorFlow內嵌地支持自動梯度計算。
在存儲管理(memory management),TensorFlow的作者們也在尋求提升的方法。一些可能的選項包括:
- 使用更加復雜的啟發式算法來決定圖的執行順序
- 重新計算tensor而不用把他們保持在主存
- 將長久存在的tensor從GPU memory中交換到更加豐富的主機CPU
TensorFlow支持圖的部分計算,如圖:
顯然,支持條件與循環會導致更加精確和高效地表示機器學習算法,TensorFlow提供了一些控制流操作原語包括Switch,Merge,Enter,Leave,NextIteration等。
每輪迭代由一個唯一的tag標識,執行狀態由一個frame來表示,一個輸入只要可用就可以進入一個迭代過程,因此,多個迭代可以并發地執行。
盡管輸入數據可以通過feed節點提供,另一個典型的訓練大規模機器學習模型的機制是在圖中采用特殊的輸入操作節點(input operation nodes),節點通過文件名配置,這使得工作節點可以直接從存儲系統中將數據拿到內存。
隊列是很有用的一個特性,允許圖的不同部分亦不知悉,按照不同的節奏通過Enqueue和Dequeue來處理數據。隊列的一個用途是允許輸入數據提前從文件中取出,此時并不耽誤前一批數據的處理,更有效率。TensorFlow不僅實現了基本的FIFO隊列,還實現了一個shuffling隊列,可以隨機shuffle一個大型內存buffer中的元素。
容器是用來管理長期存在的可變狀態的機制。默認的話,容器一直保持到進程結束。
優化
本部分描述了TensorFlow的實現過程中所做的一些優化,提升性能并且提高了資源的重用率。
這些優化包括:
- 消除公共子表達式
- 控制數據通信與內存使用,調度優化是必要的且有效的
- 異步核(?)
- 核實現的優化庫,cuDNN,cuda-convnet,cuBLAS等
- 有損壓縮。為了減少通信量,將一些浮點數的位數壓縮,比如32位浮點數壓縮到16位,通過損失一定精度換來跨機通信的高效。
一些經驗
本部分介紹了作者們在移植/遷移機器學習模型(從一個系統到另一個系統)中的一些經驗教訓。
包括:
- 對參數的個數有一個洞察
- 從小(模型)開始逐步擴展
- 保證目標函數的正確性
- 先單機,再分布式
- 防備數值錯誤/誤差
- 分析網絡,理解數值誤差的量級和容忍度。可以同時在兩個系統中跑,看結果是否一致來判斷有無數值誤差/錯誤
數據并行,模型并行與并發步
TensorFlow關心的一大領域就是加速計算密集型的大規模神經網絡的訓練。本部分描述了一些方法。
數據并行
數據并行分為同步數據并行和異步數據并行。見圖:
數據并行的意思是,用很多的模型副本,每個副本運行在不同的數據上,然后同時訓練,更新模型。通過更新模型的方式不同,可以分為同步和異步,同步的方式是一個用戶線程驅動整個大循環,如圖上部,等到所有的$\Delta P$都算出來后,將它們相加去更新模型。而異步的方式不同,每個模型副本自己異步地對模型參數進行更新,不用等到所有的梯度算出來再更新,每個模型副本有一個用戶線程。見圖下部。
模型并行和并發步(concurrent steps)
模型并行的意思是,對于同樣一批數據,模型計算的不同部分分散在不同的計算設備上同時進行。如圖是一個循環深度LSTM用來做序列到序列學習的例子。(?)
并發步是另一種通常的做法,即通過在同樣的設備集合中運行少數的并發步來將同一設備中的模型計算流水線化。(?)
工具
TensorBoard用來對計算圖,總結信息和訓練過程等進行可視化,方便觀察訓練過程。
性能追蹤(performance tracing),了解哪些地方是瓶頸時間。EEG。
未來工作
未來工作包括:
- 子圖的重用,像函數一般
- 置放算法與節點的調度,可能采用DNN和強化學習相結合來學習置放
- just-in-time compiler
- 跨操作動態編譯框架(cross-operation dynamic compilation framework)
- 等等。。。
來自:http://whatbeg.com/2017/01/11/tensorflowwhitepaper.html