分散式TensorFlow入門教程

碼字不易,歡迎給個贊!

歡迎交流與轉載,文章會同步發布在公眾號:機器學習演算法全棧工程師(Jeemy110)


前言

深度學習在各個領域實現突破的一部分原因是我們使用了更多的數據(大數據)來訓練更複雜的模型(深度神經網路),並且可以利用一些高性能並行計算設備如GPU和FPGA來加速模型訓練。但是有時候,模型之大或者訓練數據量之多可能超出我們的想像,這個時候就需要分散式訓練系統,利用分散式系統我們可以訓練更加複雜的模型(單機無法裝載),還可以加速我們的訓練過程,這對於研究者實現模型的超參數優化是非常有意義的。2017年6月,Facebook發布了他們的論文Accurate, Large Minibatch SGD:Training ImageNet in 1 Hour,文中指出他們採用分布在32個伺服器上的256塊GPUs將Resnet-50模型在ImageNet數據集上的訓練時間從兩周縮短為1個小時。在軟體層面,他們使用了很大的minibatch(8192)來訓練模型,並且使學習速率正比於minibatch的大小。這意味著,採用分散式系統可以實現模型在成百個GPUs上的訓練,從而大大減少訓練時間,你也將有更多的機會去嘗試各種各樣的超參數組合。作為使用人數最多的深度學習框架,TensorFlow從version 0.8開始支持模型的分散式訓練,現在的TensorFlow支持模型的多機多卡(GPUs和 CPUs)訓練。在這篇文章裡面,我將簡單介紹分散式TensorFlow的基礎知識,並通過實例來講解如何使用分散式TensorFlow來訓練模型。

Methods that scale with computation are the future of AI.

—Rich Sutton, 強化學習之父

在開始之前,有必要先簡單介紹一下深度學習的分散式訓練策略以及分散式架構。這有助於理解分散式TensorFlow系統。

分散式訓練策略

模型並行

所謂模型並行指的是將模型部署到很多設備上(設備可能分布在不同機器上,下同)運行,比如多個機器的GPUs。當神經網路模型很大時,由於顯存限制,它是難以在跑在單個GPU上,這個時候就需要模型並行。比如Google的神經機器翻譯系統,其可能採用深度LSTM模型,如下圖所示,此時模型的不同部分需要分散到許多設備上進行並行訓練。深度學習模型一般包含很多層,如果要採用模型並行策略,一般需要將不同的層運行在不同的設備上,但是實際上層與層之間的運行是存在約束的:前向運算時,後面的層需要等待前面層的輸出作為輸入,而在反向傳播時,前面的層又要受限於後面層的計算結果。所以除非模型本身很大,一般不會採用模型並行,因為模型層與層之間存在串列邏輯。但是如果模型本身存在一些可以並行的單元,那麼也是可以利用模型並行來提升訓練速度,比如GoogLeNet的Inception模塊。

模型並行訓練

數據並行

深度學習模型最常採用的分散式訓練策略是數據並行,因為訓練費時的一個重要原因是訓練數據量很大。數據並行就是在很多設備上放置相同的模型,並且各個設備採用不同的訓練樣本對模型訓練。訓練深度學習模型常採用的是batch SGD方法,採用數據並行,可以每個設備都訓練不同的batch,然後收集這些梯度用於模型參數更新。前面所說的Facebook訓練Resnet50就是採用數據並行策略,使用256個GPUs,每個GPU讀取32個圖片進行訓練,如下圖所示,這樣相當於採用非常大的batch( 32	imes 256=8192 )來訓練模型。

數據並行訓練

數據並行可以是同步的(synchronous),也可以是非同步的(asynchronous)。所謂同步指的是所有的設備都是採用相同的模型參數來訓練,等待所有設備的mini-batch訓練完成後,收集它們的梯度然後取均值,然後執行模型的一次參數更新。這相當於通過聚合很多設備上的mini-batch形成一個很大的batch來訓練模型,Facebook就是這樣做的,但是他們發現當batch大小增加時,同時線性增加學習速率會取得不錯的效果。同步訓練看起來很不錯,但是實際上需要各個設備的計算能力要均衡,而且要求集群的通信也要均衡,類似於木桶效應,一個拖油瓶會嚴重拖慢訓練進度,所以同步訓練方式相對來說訓練速度會慢一些。非同步訓練中,各個設備完成一個mini-batch訓練之後,不需要等待其它節點,直接去更新模型的參數,這樣總體會訓練速度會快很多。但是非同步訓練的一個很嚴重的問題是梯度失效問題(stale gradients),剛開始所有設備採用相同的參數來訓練,但是非同步情況下,某個設備完成一步訓練後,可能發現模型參數其實已經被其它設備更新過了,此時這個梯度就過期了,因為現在的模型參數和訓練前採用的參數是不一樣的。由於梯度失效問題,非同步訓練雖然速度快,但是可能陷入次優解(sub-optimal training performance)。非同步訓練和同步訓練在TensorFlow中不同點如下圖所示:

數據並行中的同步方式和非同步方式

為了解決非同步訓練出現的梯度失效問題,微軟提出了一種Asynchronous Stochastic Gradient Descent方法,主要是通過梯度補償來提升訓練效果。應該還有其他類似的研究,感興趣的可以深入了解一下。

分散式訓練架構

前面說的是分散式訓練策略,這裡要談的是系統架構層,包括兩種架構:Parameter server architecture(就是常見的PS架構,參數伺服器)和Ring-allreduce architecture。這裡主要參考Distributed TensorFlow,完全是拿來主義了。

Parameter server架構

在Parameter server架構(PS架構)中,集群中的節點被分為兩類:parameter server和worker。其中parameter server存放模型的參數,而worker負責計算參數的梯度。在每個迭代過程,worker從parameter sever中獲得參數,然後將計算的梯度返回給parameter server,parameter server聚合從worker傳回的梯度,然後更新參數,並將新的參數廣播給worker。採用同步SGD方式的PS架構如下圖所示:

PS架構中的同步SGD訓練方式

在TensorFlow之前,Google採用的是DistBelief框架,其支持PS架構。TensorFlow從DistBelief借鑒了它的很多分散式訓練模式,所以TensorFlow也支持PS架構。Mxnet的主要創建者李沐在前人基礎上開發了更加通用的輕量級ps-lite,如果想深入理解PS架構,可以看一下沐神的講解。PS架構是深度學習最常採用的分散式訓練架構。

Ring-allreduce架構

在Ring-allreduce架構中,各個設備都是worker,並且形成一個環,如下圖所示,沒有中心節點來聚合所有worker計算的梯度。在一個迭代過程,每個worker完成自己的mini-batch訓練,計算出梯度,並將梯度傳遞給環中的下一個worker,同時它也接收從上一個worker的梯度。對於一個包含 N 個worker的環,各個worker需要收到其它個 N-1 worker的梯度後就可以更新模型參數。其實這個過程需要兩個部分:scatter-reduce和allgather,百度的教程對這個過程給出了詳細的圖文解釋。百度開發了自己的allreduce框架,並將其用在了深度學習的分散式訓練中。

Ring-allreduce架構示意圖

相比PS架構,Ring-allreduce架構是帶寬優化的,因為集群中每個節點的帶寬都被充分利用。此外,在深度學習訓練過程中,計算梯度採用BP演算法,其特點是後面層的梯度先被計算,而前面層的梯度慢於前面層,Ring-allreduce架構可以充分利用這個特點,在前面層梯度計算的同時進行後面層梯度的傳遞,從而進一步減少訓練時間。在百度的實驗中,他們發現訓練速度基本上線性正比於GPUs數目(worker數)。

分散式TensorFlow簡介

好了,言歸正傳,現在開始介紹分散式TensorFlow的基礎知識。在分散式TensorFlow中,參與分散式系統的所有節點或者設備被總稱為一個集群(cluster),一個cluster中包含很多伺服器(server),每個server去執行一項任務(task),server和task是一一對應的。所以,cluster可以看成是server的集合,也可以看成是task的集合。TensorFlow為各個task又增加了一個抽象層,將一系列相似的task集合稱為一個job,比如在PS架構中,習慣稱parameter server的task集合為ps,而稱執行梯度計算的task集合為worker。所以cluster又可以看成是job的集合,不過這只是邏輯上的意義,具體還要看這個server真正幹什麼。在TensorFlow中,job用name(字元串)標識,而task用index(整數索引)標識,那麼cluster中的每個task可以用job的name加上task的index來唯一標識。在分散式系統中,一般情況下各個task在不同的節點或者設備上執行。TensorFlow中用tf.train.ClusterSpec創建一個cluster:

cluster = tf.train.ClusterSpec({"worker": [ "worker0.example.com:2222", "worker1.example.com:2222", "worker2.example.com:2222"],"ps": [ "ps0.example.com:2222", "ps1.example.com:2222"]})

可以看出,cluster接收的其實就是一個字典,字典裡面包含了各個task所在host的主機地址,這個cluster共包含兩類job:ps和worker,共5個task:

/job:worker/task:0/job:worker/task:1/job:worker/task:2/job:ps/task:0/job:ps/task:1

創建好cluster,需要創建各個task的server,使用tf.train.Server函數,比如創建第一個worker的server:

server = tf.train.Server(cluster, job_name="worker", task_index=0)

在創建sever時必須要傳入cluster,這樣每個server才可以知道自己所在的cluster包含哪些hosts,然後server與server之間才可以通信。sever的創建需要在自己所在host上,一旦所有的server在各自的host上創建好了,整個集群就搭建好了,cluster之間的各個server可以互相通信。具體來說,每個server包含兩個組件:masterworker。其中master提供master service,其主要可以提供對cluster中各個設備的遠程訪問(RPC協議),同時它的另外一個重要功能是作為創建tf.Session的target。而worker提供worker service,可以用本地設備執行TF中的計運算元圖。這兩個東西並不好理解,這裡我們先講TensorFlow中的另外一個重要概念:client,先拋出官方英文解釋:

A client is typically a program that builds a TensorFlow graph and constructs a tensorflow::Session to interact with a cluster. Clients are typically written in Python or C++. A single client process can directly interact with multiple TensorFlow servers (see "Replicated training" above), and a single server can serve multiple clients.

這個client是個很重要的概念,簡單來說就是一個程序,它創建了TF的計算圖,並通過建立Session與cluster中的設備進行交互。說白了前面創建的cluster與server只是搭建分散式環境,真正要執行計算需要創建client。對於tf.Session這個類,其第一個參數是target,一般情況下大家確實用不到,因為不指定這個參數的話,Session就默認調用本地設備,但是在分散式環境就需要指定了,這就是server裡面的master(server.target提供這個參數)。實際上,TensorFlow的完整執行邏輯如下圖所示:

TensorFlow計算圖在單機和分散式系統的執行流程圖

就是說client要跑計算時,其實要先要把計算圖以及要執行的節點(Graph中的Node)發給mastermaster負責資源調度(就是這個計算該怎麼執行,在哪些設備執行),最終的執行需要各個worker進程(使用本地設備執行計算),所以每個server會包含masterworker兩個部分。關於master的具體作用,可以參考一下TF教程中的TensorFlow Architecture,不過這裡貼一張圖,大家意淫一下:

分散式TensorFlow中的master劃分子圖

上面簡單解釋了一下serverclient相關的一些重要概念,幫助大家理解分散式TensorFlow的執行邏輯。那麼,在構建Graph時如何調用cluster中的各個server呢?很簡單,使用tf.device,只需要指定task的詳細信息即可:

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 = ...

很簡單,就如同把cluster裡面的設備當成本機設備一樣使用,至於怎麼真正執行,那就是系統層面的事了。構建了Graph後,我們需要創建Session來執行計算圖:

with tf.Session("grpc://worker7.example.com:2222") as sess: for _ in range(10000): sess.run(train_op)

注意由於是分散式系統,需要指定Session的target參數,或者採用grpc+主機地址,或者直接利用sever.target,兩個是完全一樣的。下面我們通過一個簡單的實例來理解上面過程,這個例子的cluster共包含3個task:1個ps和2個worker。

import tensorflow as tftf.app.flags.DEFINE_string("ps_hosts", "localhost:2222", "ps hosts")tf.app.flags.DEFINE_string("worker_hosts", "localhost:2223,localhost:2224", "worker hosts")tf.app.flags.DEFINE_string("job_name", "worker", "ps orworker")tf.app.flags.DEFINE_integer("task_index", 0, "Index of task within the job")FLAGS = tf.app.flags.FLAGSdef main(_): ps_hosts = FLAGS.ps_hosts.split(",") worker_hosts = FLAGS.worker_hosts.split(",") # create cluster cluster = tf.train.ClusterSpec({"ps": ps_hosts, "worker": worker_hosts}) # create the server server = tf.train.Server(cluster, job_name=FLAGS.job_name, task_index=FLAGS.task_index) server.join()if __name__ == "__main__": tf.app.run()

注意這裡用單機環境模擬多機環境,然後分別執行下面三個命令行來創建三個server:

python example.py --job_name=ps --task_index=0python example.py --job_name=worker --task_index=0python example.py --job_name=worker --task_index=1

執行完畢後,三個server都處在等待狀態,現在我們在創建一個client來執行一個計算圖,並且採用/job:worker/task:0這個server所對應的master,即grpc://localhost:2223來創建Session,如下所示:

import tensorflow as tfif __name__ == "__main__": with tf.device("/job:ps/task:0"): x = tf.Variable(tf.ones([2, 2])) y = tf.Variable(tf.ones([2, 2])) with tf.device("/job:worker/task:0"): z = tf.matmul(x, y) + x with tf.device("/job:worker/task:1"): z = tf.matmul(z, x) + x with tf.Session("grpc://localhost:2223") as sess: sess.run(tf.global_variables_initializer()) val = sess.run(z) print(val)

其實這個client就是一個進程,但是其在計算時需要依靠cluster中的device來執行部分計運算元圖。值得注意的是上面的程序我們遵循了PS架構,參數放置在ps,而worker執行計算。但是在TensorFlow中,其實每個task所屬的job只是一個概念,並沒有什麼差別,就是說對於上面的程序,你完全可以把參數放置在worker上。所以說,TensorFlow的分散式架構支持PS模式,並且也往往採用這種方式,但是TensorFlow並不完全與PS架構對等。

複製訓練(Replicated training)

前面已經說過了,深度學習模型分散式訓練最常用的是數據並行策略,在TensorFlow中稱這為複製訓練(Replicated training),就是說多個worker使用不同的mini-batch訓練相同的模型,計算出的梯度用於更新放置在ps的模型參數。由於複製訓練是一種最常用的模式,TensorFlow也增加了一些庫函數來簡化複製訓練的實現。在TensorFlow中共有四種不同的方式來實現複製訓練:

  1. In-graph replication:只構建一個client,這個client構建一個Graph,Graph中包含一套模型參數,放置在ps上,同時Graph中包含模型計算部分的多個副本,每個副本都放置在一個worker上,這樣多個worker可以同時訓練複製的模型。TensorFlow教程中的使用多個GPUs訓練cifar10分類模型就屬於這個類型,每個GPUs上的計運算元圖是相同的,但是屬於同一個Graph。這種方法很少使用,因為一旦client掛了,整個系統就全崩潰了,容錯能力差。
  2. Between-graph replication:每個worker都創建一個client,這個client一般還與task的主程序在同一進程中。各個client構建相同的Graph,但是參數還是放置在ps上。這種方式就比較好,一個worker的client掛掉了,系統還可以繼續跑。
  3. Asynchronous training:非同步方式訓練,各個worker自己干自己的,不需要與其它worker來協調,前面也已經詳細介紹了非同步訓練,上面兩種方式都可以採用非同步訓練。
  4. Synchronous training:同步訓練,各個worker要統一步伐,計算出的梯度要先聚合才可以執行一次模型更新,對於In-graph replication方法,由於各個worker的計運算元圖屬於同一個Graph,很容易實現同步訓練。但是對於Between-graph replication方式,各個worker都有自己的client,這就需要系統上的設計了,TensorFlow提供了tf.train.SyncReplicasOptimizer來實現Between-graph replication的同步訓練。

由於在TensorFlow中最常用的是Between-graph replication方式,這裡著重講一下如何實現這種方式。在Between-graph replication中,各個worker都包含一個client,它們構建相同的計算圖,然後把參數放在ps上,TensorFlow提供了一個專門的函數tf.train.replica_device_setter來方便Graph構建,先看代碼:

# cluster包含兩個ps 和三個 workercluster_spec = { "ps": ["ps0:2222", "ps1:2222"], "worker": ["worker0:2222", "worker1:2222", "worker2:2222"]}cluster = tf.train.ClusterSpec(cluster_spec)with tf.device(tf.train.replica_device_setter( worker_device="/job:worker/task:%d" % FLAGS.task_index, cluster=cluster)): # Build your graph v1 = tf.Variable(...) # assigned to /job:ps/task:0 v2 = tf.Variable(...) # assigned to /job:ps/task:1 v3 = tf.Variable(...) # assigned to /job:ps/task:0 # Run compute

使用tf.train.replica_device_setter可以自動把Graph中的Variables放到ps上,而同時將Graph的計算部分放置在當前worker上,省去了很多麻煩。由於ps往往不止一個,這個函數在為各個Variable分配ps時默認採用簡單的round-robin方式,就是按次序將參數挨個放到各個ps上,但這個方式可能不能使ps負載均衡,如果需要更加合理,可以採用tf.contrib.training.GreedyLoadBalancingStrategy策略。

採用Between-graph replication方式的另外一個問題,由於各個worker都獨立擁有自己的client,但是對於一些公共操作比如模型參數初始化與checkpoint文件保存等,如果每個client都獨立進行這些操作,顯然是對資源的浪費。為了解決這個問題,一般會指定一個worker為chief worker,它將作為各個worker的管家,協調它們之間的訓練,並且完成模型初始化和模型保存和恢復等公共操作。在TensorFlow中,可以使用tf.train.MonitoredTrainingSession創建client的Session,並且其可以指定哪個worker是chief worker。關於這些方面,想深入理解可以看一下2017 TensorFlow 開發峰會的官方講解,其中也對分散式TensorFlow的容錯機製做了簡單介紹。

Between-graph replication方式的編程結構圖

MNIST分散式訓練實例

最後,我們給出MNIST的分散式訓練實例,採用Between-graph replication方式,並且同步訓練和非同步訓練都支持。在這個例子中,cluster共包含2個ps和2個worker,其中worker1為chief worker。代碼如下:

import tensorflow as tffrom tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_setstf.app.flags.DEFINE_string("ps_hosts", "localhost:2222", "ps hosts")tf.app.flags.DEFINE_string("worker_hosts", "localhost:2223,localhost:2224", "worker hosts")tf.app.flags.DEFINE_string("job_name", "worker", "ps orworker")tf.app.flags.DEFINE_integer("task_index", 0, "Index of task within the job")tf.app.flags.DEFINE_integer("num_workers", 2, "Number of workers")tf.app.flags.DEFINE_boolean("is_sync", False, "using synchronous training or not")FLAGS = tf.app.flags.FLAGSdef model(images): """Define a simple mnist classifier""" net = tf.layers.dense(images, 500, activation=tf.nn.relu) net = tf.layers.dense(net, 500, activation=tf.nn.relu) net = tf.layers.dense(net, 10, activation=None) return netdef main(_): ps_hosts = FLAGS.ps_hosts.split(",") worker_hosts = FLAGS.worker_hosts.split(",") # create the cluster configured by `ps_hosts and worker_hosts cluster = tf.train.ClusterSpec({"ps": ps_hosts, "worker": worker_hosts}) # create a server for local task server = tf.train.Server(cluster, job_name=FLAGS.job_name, task_index=FLAGS.task_index) if FLAGS.job_name == "ps": server.join() # ps hosts only join elif FLAGS.job_name == "worker": # workers perform the operation # ps_strategy = tf.contrib.training.GreedyLoadBalancingStrategy(FLAGS.num_ps) # Note: tf.train.replica_device_setter automatically place the paramters (Variables) # on the ps hosts (default placement strategy: round-robin over all ps hosts, and also # place multi copies of operations to each worker host with tf.device(tf.train.replica_device_setter(worker_device="/job:worker/task:%d" % (FLAGS.task_index), cluster=cluster)): # load mnist dataset mnist = read_data_sets("./dataset", one_hot=True) # the model images = tf.placeholder(tf.float32, [None, 784]) labels = tf.placeholder(tf.int32, [None, 10]) logits = model(images) loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=labels)) # The StopAtStepHook handles stopping after running given steps. hooks = [tf.train.StopAtStepHook(last_step=2000)] global_step = tf.train.get_or_create_global_step() optimizer = tf.train.AdamOptimizer(learning_rate=1e-04) if FLAGS.is_sync: # asynchronous training # use tf.train.SyncReplicasOptimizer wrap optimizer # ref: https://www.tensorflow.org/api_docs/python/tf/train/SyncReplicasOptimizer optimizer = tf.train.SyncReplicasOptimizer(optimizer, replicas_to_aggregate=FLAGS.num_workers, total_num_replicas=FLAGS.num_workers) # create the hook which handles initialization and queues hooks.append(optimizer.make_session_run_hook((FLAGS.task_index==0))) train_op = optimizer.minimize(loss, global_step=global_step, aggregation_method=tf.AggregationMethod.ADD_N) # The MonitoredTrainingSession takes care of session initialization, # restoring from a checkpoint, saving to a checkpoint, and closing when done # or an error occurs. with tf.train.MonitoredTrainingSession(master=server.target, is_chief=(FLAGS.task_index == 0), checkpoint_dir="./checkpoint_dir", hooks=hooks) as mon_sess: while not mon_sess.should_stop(): # mon_sess.run handles AbortedError in case of preempted PS. img_batch, label_batch = mnist.train.next_batch(32) _, ls, step = mon_sess.run([train_op, loss, global_step], feed_dict={images: img_batch, labels: label_batch}) if step % 100 == 0: print("Train step %d, loss: %f" % (step, ls))if __name__ == "__main__": tf.app.run()

非同步執行時,分別執行下面四條語句:

python distributed_mnist.py --ps_hosts=localhost:2222,localhost:2223 --worker_hosts=localhost:2224,localhost:2225 --job_name=ps --task_index=0python distributed_mnist.py --ps_hosts=localhost:2222,localhost:2223 --worker_hosts=localhost:2224,localhost:2225 --job_name=ps --task_index=1python distributed_mnist.py --ps_hosts=localhost:2222,localhost:2223 --worker_hosts=localhost:2224,localhost:2225 --job_name=worker --task_index=0python distributed_mnist.py --ps_hosts=localhost:2222,localhost:2223 --worker_hosts=localhost:2224,localhost:2225 --job_name=worker --task_index=1

此時你會看到兩個worker列印出的step是交叉的,說明此時是非同步執行的,每個worker執行一次梯度計算後,立即將梯度發給ps完成參數更新。

對於同步執行,採用tf.train.SyncReplicasOptimizer,分別執行下面四條語句:

python distributed_mnist.py --ps_hosts=localhost:2222,localhost:2223 --worker_hosts=localhost:2224,localhost:2225 --job_name=ps --task_index=0 --is_sync=Truepython distributed_mnist.py --ps_hosts=localhost:2222,localhost:2223 --worker_hosts=localhost:2224,localhost:2225 --job_name=ps --task_index=1 --is_sync=Truepython distributed_mnist.py --ps_hosts=localhost:2222,localhost:2223 --worker_hosts=localhost:2224,localhost:2225 --job_name=worker --task_index=0 --is_sync=Truepython distributed_mnist.py --ps_hosts=localhost:2222,localhost:2223 --worker_hosts=localhost:2224,localhost:2225 --job_name=worker --task_index=1 --is_sync=True

此時你可以看到兩個worker基本上同時列印相同的step(但是loss是不一樣的),說明是同步執行。值得注意的是,TensorFlow中的同步訓練可能與你想像中不同,它只是收集足夠的梯度(N個step的梯度結果)就聚合這些梯度值然後執行一次參數更新。但是它不管這N個結果是從哪裡來的,如果其中某個worker速度很慢,可能這N個結果都是從其他worker計算出的。言外之意就是chief worker聚合的梯度不一定是從全部worker中收集而來的(參考這個issues)。這個機制很怪異,我想是為了容錯機制,不至於一個worker死掉了而終止整個訓練過程。所以,在同步訓練過程中,最好每個worker的能力都差不多,要不然很難得到想要的加速效果(某個worker慢的話,它計算的梯度可能過期,那麼只能被丟棄,這種情況下這個worker做的就是無用功)。

走的更遠

TensorFlow可以與Hadoop和Spark等工具結合,感興趣的話可以自己深入去學習:

  • TensorFlow官方教程:How to run TensorFlow on Hadoop.
  • Yahho: Open Sourcing TensorFlowOnSpark: Distributed Deep Learning on Big-Data Clusters.

小結

最近打算學習一下分散式TensorFlow,所以系統地看了官方文檔以及一些國外的博客,然後就把其中一些講解得比較好的地方以及自己的學習心得總結了一下,所以就有了此文。但是網上的資料並不是很多,所以文中有錯誤之處在所難免,也懇請各位大佬斧正。很偶然地看到一篇最新的綜述文章Demystifying Parallel and Distributed Deep Learning: An In-Depth Concurrency Analysis,60頁的paper系統總結了深度學習的並行化策略,想深入學習的可以讀讀這個paper。


參考

  1. Distributed TensorFlow.
  2. How to write distributed TensorFlow code?—?with an example on Clusterone.
  3. MNIST實例:Distributing TensorFlow.
  4. Google TF 官網:Distributed TensorFlow.
  5. Distributed TensorFlow(2017 TensorFlow 開發峰會).
  6. Baidu Research: Bringing HPC Techniques to Deep Learning.
  7. TensorFlow學習筆記(9):分散式TensorFlow.
  8. Distributed TensorFlow Example.
  9. TensorFlow白皮書2016:TensorFlow: A System for Large-Scale Machine Learning.
  10. TensorFlow白皮書2015:TensorFlow: Large-Scale Machine Learning on Heterogeneous Distributed Systems.

(註:文中圖片原始來源均可以在文中或者參考文章的鏈接中找到)

碼字不易,歡迎給個贊!

歡迎交流與轉載,文章會同步發布在公眾號:機器學習演算法全棧工程師(Jeemy110)


推薦閱讀:

TAG:深度學習DeepLearning | TensorFlow | 分散式計算 |