[toc]html
本目錄包括了運行時分佈式TensorFlow的實現,其底層使用了gRPC 做爲進程內通訊的支持庫。node
首先,須要構建一個TensorFlow的服務端可執行版本(grpc_tensorflow_server
) 以及一個基於gRPC的客戶端。目前只能基於源代碼進行自構建, 可是會包含在將來發布的二進制版本中。可使用以下命令進行構建:python
# CPU-only build. $ bazel build -c opt //tensorflow/core/distributed_runtime/rpc:grpc_tensorflow_server # GPU build. $ bazel build -c opt --config=cuda //tensorflow/core/distributed_runtime/rpc:grpc_tensorflow_server
若是是從最新的源代碼建立的Python依賴包,它會自動包含一個基於gRPC的客戶端。若是使用的是一個以前發佈的二進制版本,須要根據這個安裝說明來從新編譯安裝。在你成功地構建了分佈式的TensorFlow組件以後,能夠經過以下方式來啓動服務器而且判斷你的安裝是否成功:git
# Start a TensorFlow server as a single-process "cluster". $ bazel-bin/tensorflow/core/distributed_runtime/rpc/grpc_tensorflow_server \ --cluster_spec='local|localhost:2222' --job_name=local --task_index=0 &
而後啓動Python的交互器而且啓動一個Session:github
$ python >>> import tensorflow as tf >>> c = tf.constant("Hello, distributed TensorFlow!") >>> sess = tf.Session("grpc://localhost:2222") >>> sess.run(c) 'Hello, distributed TensorFlow!'
命令行參數 grpc_tensorflow_server
定義了集羣之間的關係. 參數 --cluster_spec
決定了集羣中工做對象的多少, 譬若有一系列的 jobs, 而每一個jobs又包含了多個task 終端。 全部集羣中的處理過程都必須設置相同的 --cluster_spec
參數, 例子以下:shell
--cluster_spec='...' |
Available tasks | ||
---|---|---|---|
`local\ | localhost:2222` | /job:local/task:0 |
|
`local\ | localhost:2222;localhost:2223` | /job:local/task:0 `/job:local/task:1` |
|
`worker\ | worker0:2222;worker1:2222;worker2:2222,``ps\ | ps0:2222;ps1:2222` | /job:worker/task:0 `/job:worker/task:1/job:worker/task:2 /job:ps/task:0`/job:ps/task:1 |
還有 --job_name
與 --task_index
標誌位指明瞭哪些任務會運行在當前處理過程上。 具體而言,--job_name=local --task_index=0
意思就是該過程會被標誌爲/job:local/task:0
, 而後全部在該過程上的TensorFlow的設備都會使用這個前綴。api
N.B.
手動來指明這些運行參數多是很是冗長的,特別是對一個大型集羣而言。咱們正在研發能夠程式化啓動的工具,譬如使用一些相似於Kubernetes集羣管理器。若是有啥集羣管理工具你以爲挺好的但願加入進來,能夠在GitHub issue上提出你的建議。服務器
爲了將某個操做放在某個特殊的處理過程上,在分佈式環境下依然可使用tf.device()
函數,以前是用來指明是放在CPU仍是GPU上的。譬如:網絡
with tf.device("/job:ps/task:0"): weights_1 = tf.Variable(...) biases_1 = tf.Variable(...) with tf.device("/job:ps/task:1"): weights_2 = tf.Variable(...) biases_2 = tf.Variable(...) with tf.device("/job:worker/task:7"): input, labels = ... layer_1 = tf.nn.relu(tf.matmul(input, weights_1) + biases_1) logits = tf.nn.relu(tf.matmul(layer_1, weights_2) + biases_2) # ... train_op = ... with tf.Session("grpc://worker7:2222") as sess: for _ in range(10000): sess.run(train_op)
在上面的例子中,Variables在job ps
的兩個task上被建立,而後計算密集型的部分建立在job work
上。TensorFlow會自動地在不一樣的job之間傳輸數據。(從job
到work
是前向傳遞,而從worker
到ps
是梯度應用)。分佈式
一個常見的訓練配置(數據並行訓練)包含了job ps
上共享參數以及job work
上的多個任務來訓練相同的模型。每一個task通常會運行在不一樣的機器上。如今仍是有不少辦法能夠在TensorFlow中來實現這一種結構的,咱們將來也會提供更簡單的實現方式,主要途徑有:
構建單一的包含了一系列參數的圖(in tf.Variable
nodes pinned to /job:ps
), 而且建立多個模型的副原本映射到/job:worker
中的不一樣tasks。每一個model的副本有一個不一樣的train_op
,而且對於每一個worker i
而言一個或者多個的客戶端線程能夠調用sess.run(train_ops[i])
。這種方法使用了單一的tf.Session
,它的工做目標是集羣中的某個workers。
As above, but where the gradients from all workers are averaged. See the
CIFAR-10 multi-GPU trainer
for an example of this form of replication. The implements synchronous training
另外一種分佈式訓練器的方法使用多張圖,一張圖對應一個worker,而且每張圖都包含了一系列的參數的集合(/job:ps
)和一份模型的賦值。而容器的機制就是在不一樣的圖之間共享變量:一旦某個變量構造完成,可選的container
參數會由圖中每份複製的相同值來決定。對於較大的模型而言,這種方法會更加有效,畢竟整個圖更小了一點。
這種方法使用多個tf.Session
對象:每一個worker過程都會包含一個,不過不一樣的Session會指向不一樣的目標worker。這個tf.Session
對象便可以在單一的Python客戶端中建立,也能夠在多個客戶端中建立。
Client
一個典型的客戶端通常會構建一個TensorFlow的圖而且使用tensorflow::Session
來完成與集羣的交互。客戶端通常會用Python或者C++編寫,通常來講一個客戶端能夠同時與多個服務端進行交互(參考上文的重複訓練),而且一個服務端也能夠同時服務於多個客戶端。
Cluster
一個TensorFlow集羣會包含一個或者多個TensorFlow的服務端,被切分爲一系列命名的job,而每一個job又會負責一系列的tasks。一個集羣通常會專一於一個相對高層的目標,譬如用多臺機器並行地訓練一個神經網絡。
Job
一個job會包含一系列的致力於某個相同目標的task。譬如,一個叫ps
(意思是參數服務)的job會用於處理存儲於更新Variables相關的工做。而一個叫worker
的job會用於承載那些用於計算密集型的無狀態節點。通常來講一個job中的tasks會運行在不一樣的機器中。
Master service
Master Service是一個RPC服務用於與一系列遠端的分佈式設備進行交互。Master Service實現了tensorflow::Session
接口, 而且用來協調多個worker service。
Task
一個Task通常會關聯到某個單一的TensorFlow服務端的處理過程,屬於一個特定的job而且在該job的任務列表中有個惟一的索引。
TensorFlow server
用於運行grpc_tensorflow_server的處理過程,是一個集羣中的一員,而且想外暴露了一個Master Service與一個Worker Service。
Worker service一個執行部分TensorFlow圖部份內容的RPC服務。