1. tensorflow工作流程
如官網所示:
根據整體架構或者代碼功能可以分為:

圖1.1 tensorflow架構
如圖所示,一層C的api接口將底層的核運行時部分與頂層的多語言接口分離開。
而根據整個的工作流程,又可以分為:

圖1.2 不同系統組件之間的交互
而圖1.2也是tensorflow整個工作的流程,其中主要分為四個部分:
1.1. 客戶端client
- 將整個計算過程轉義成一個數據流graph
- 通過session,將graph傳遞給master執行
ps:假設我們使用的是python作為客戶端,則其中session文件在Anaconda3/lib/python3.6/site-packages/tensorflow/python/client/session.py
1.2. 分布式主節點Distributed Master
- 基於用戶傳遞給Session.run()中的參數來進行修剪整個完整的graph,提取其中特定subgraph;
- 將上述subgraph划分成不同部分,並將其對應不同的進程和devices中;
- 將上述划分的部分分布到worker services上;
- 每個worker services執行其收到的graph塊
1.3. 工作節點的服務Worker Services (one for each task)
- 使用可用的硬件kernel(如cpu,gpu)計划執行接收到的graph塊表示的計算部分;
- 與其他work services相互發送和接收計算結果
1.4. 核的實現Kernel Implementations
- 執行graph操作的計算部分
現在回到圖1.2。其中的"/job:worker/task:0" 和"/job:ps/task:0" ,都是worker services上執行的任務。
- "PS"表示parameter server:一個task負責存儲和更新模型的參數
- 其他worker會發送他們迭代優化的參數給PS。
當然如果在單機環境下,上述PS和worker不是必須的,不過如果是分布式訓練,這種模式就很常見了。而且上述的 "Distributed Master","Worker Service"只存在於分布式tensorflow中,對於單進程的tensorflow(也就是單機版),一個特定的session就負責了Distributed Master的任何事情,且其自己負責本機的多進程或者說多devices之間的數據交互。
下面,通過一個graph例子詳細的介紹下tensorflow的核心模塊。
2 client
用戶負責在client端編寫tensorflow代碼,以此行程一個計算graph。該程序可以直接通過底層API組成(如自己寫每一層,每一個激活函數),或者使用google提供的如Estimators API等高階API來完成整個NN的搭建。同時Tensorflow支持多種client端的語言,如Python,CPP。當然隨着tensorflow本身的趨於完善,CPP的接口也會越來越多,用於提供更快速的執行效率,當然python接口還是最全的。
client創建一個session,該會話會將graph的定義通過一個tf.GraphDef的protocol buffer 發送給distributed master。當在run中指定了某個graph中的node或者某些nodes,該函數會觸發distributed master 去執行所需要的計算。
假如我們的graph如圖2.1,就是一個$$s+= wx+b$$

圖2.1 基於client端建立的graph
ps:tf.Session
3 Distributed master
該部分的主要工作為:
- 基於client在run中指定的節點,從整個完整的graph中截取所需要的subgraph;
- 將subgraph進一步划分成多個pieces,使其可以將每個piece映射到不同的執行設備上;
- 將划分好的pieces緩存起來,以備后面的其他run的觸發。
因為一旦到了master的部分,master可以總攬整個graph,所以它可以使用標准的優化方法去做優化,如公共子表達式消除(common subexpression elimination )和常量的綁定。然后給優化后的subgraphs或者說pieces定義不同的坐標,每個坐標對應了不同的執行設備如"/job:worker/task:0" 和"/job:ps/task:0"

圖3.1 client通過運行run,將graph發送給master

圖3.2 master將所需要執行的subgraph划分成參數更新和迭代優化兩部分

圖3.1 master在划分好的subgraph上添加所需要的發送和接收接口,為真實任務分發做准備

圖3.1 master將每個piece通過分布式task分發到真實的節點去運行
Ps:MasterService API definition
Master interface
4 Worker Service
在每個task中,該部分負責:
- 處理從master發來的請求;
- 基於接收到的subgraph,規划所需要執行的kernels;
- 與其他task直接進行消息交換
google優化了該部分,使其就算面對large graph,其負載也很低。當前的版本可以執行每秒上萬個subgraphs,這使得大量副本可以進行快速的,細粒度的訓練。該部分會將所需要執行的kernels指派給本地的devices,並盡可能的並行執行kernels。例如使用多CPU核或者多GPU流。
該部分還負責具體化源和目標device的Send和Recv操作:
- 使用cudaMemcpAsync()來進行本地CPU和GPU設備之間的數據傳輸操作;
- 使用點對點的DMA進行GPU之間的傳輸,以避免需要通過host CPU主內存進行數據傳輸的高代價
為了在tasks之間進行傳輸,tensorflow使用多種協議:
- 基於TCP的gRPC;
- 基於Converged Ethernet的RDMA
同時tensorflow也支持NVIDIA的NCCL庫來為多GPU之間進行數據交互(tf.contrib.nccl)

圖4.1 worker端接收到的piece;對應的接收發送接口;task之間的交互
ps:WorkerService API definition
Worker interface
Remote rendezvous (for Send and Recv implementations)
5 Kernel Implementations
該運行時包含了超過200個標准操作,其中涉及數學,數組,控制流,和狀態管理等操作。每個操作都有對應不同devices的優化后的實現。其中許多kernel是通過使用了CPP的模版的Eigen:Tensor去實現的,主要是為了能生成可以在多CPU和多GPU上運行的高效並行代碼。不過如果cuDNN中已經實現了一些kernel,那么就用cuDNN的接口。同時google還實現了quantization,可以更快速的基於移動設備和高吞吐量的數據中心應用進行inference,並且可以使用低精確度的gemmlowp用於加速量化計算。
如果用戶發現很難去將子計算組合成一個大計算,或者說組合后發現效率很低,那么用戶可以通過注冊額外的cpp編寫的kernel來提供一個新的接口。例如,可以自己將一些性能敏感的操作如ReLU和Sigmoid等函數(或者其對應的梯度等)進行融合。XLA提供了一個實驗性質的自動kernel融合實現
參考資料:
