資源 | TensorFlow分布式計算機制解讀:以數據並行為重

2021-02-14 機器之心

選自clindatsci

作者:Neil Tenenholtz

機器之心編譯

參與:Jane W、黃小天

Tensorflow 是一個為數值計算(最常見的是訓練神經網絡)設計的流行開源庫。在這個框架中,計算流程通過數據流程圖(data flow graph)設計,這為更改操作結構與安置提供了很大靈活性。TensorFlow 允許多個 worker 並行計算,這對必須通過處理的大量訓練數據訓練的神經網絡是有益的。此外,如果模型足夠大,這種並行化有時可能是必須的。在本文中,我們將探討 TensorFlow 的分布式計算機制。

TensorFlow 計算圖示例

數據並行 VS. 模型並行

當在多個計算節點間分配神經網絡訓練時,通常採用兩種策略:數據並行和模型並行。在前者中,在每個節點上單獨創建模型的實例,並饋送不同的訓練樣本;這種架構允許更高的訓練吞吐量。相反,在模型並行中,模型的單一實例在多個節點間分配,這種架構允許訓練更大的模型(可能不一定適合單節點的存儲器)。如果需要,也可以組合這兩種策略,使給定模型擁有多個實例,每個實例跨越多個節點。在本文中,我們將重點關注數據並行。

數據並行與模型並行的不同形式。左:數據並行;中:模型並行;右:數據並行與模型並行。

TensorFlow 中的數據並行


當使用 TensorFlow 時,數據並行主要表現為兩種形式:圖內複製(in-graph replication)和圖間複製(between-graph replication)。兩種策略之間最顯著的區別在於流程圖的結構與其結果。

圖內複製


圖內複製通常被認為是兩種方法中更簡單和更直接(但更不可擴展的)的方法。當採用這種策略時,需要在分布式的主機上創建一個包含所有 worker 設備中副本的流程圖。可以想像,隨著 worker 數量的增長,這樣的流程圖可能會大幅擴展,這可能會對模型性能產生不利影響。然而,對於小系統(例如,雙 GPU 臺式計算機),由於其簡單性,圖內複製可能是最優的。

以下是使用單個 GPU 的基線 TensorFlow 方法與應用圖內複製方法的代碼片段的對比。考慮到圖內複製方法與擴展(scaling)相關的問題,我們將僅考慮單機、多 GPU 配置的情況。這兩個代碼片段之間的差異非常小,它們的差異僅存在於:對輸入數據的分塊,使得數據在各 worker 間均勻分配,遍歷每個含有 worker 流程圖的設備,並將來自不同 worker 的結果連接起來。通過少量代碼更改,我們可以利用多個設備,這種方法使可擴展性不再成為大障礙,從而在簡單配置下更受歡迎。

# single GPU (baseline)   單個 GPU(基線)

import tensorflow as tf
# place the initial data on the cpu
with tf.device('/cpu:0'):
   input_data = tf.Variable([[1., 2., 3.],[4., 5., 6.],[7., 8., 9.],[10., 11., 12.]])
   b = tf.Variable([[1.], [1.], [2.]])# compute the result on the 0th gpuwith tf.device('/gpu:0'):
   output = tf.matmul(input_data, b)# create a session and runwith tf.Session() as sess:
   sess.run(tf.global_variables_initializer())print sess.run(output)

# in-graph replication   圖內複製
import tensorflow as tf
num_gpus = 2
# place the initial data on the cpu
with tf.device('/cpu:0'):
   input_data = tf.Variable([[1., 2., 3.],[4., 5., 6.],[7., 8., 9.],[10., 11., 12.]])
   b = tf.Variable([[1.], [1.], [2.]])# split the data into chunks for each gpu
inputs = tf.split(input_data, num_gpus)
outputs = []# loop over available gpus and pass input datafor i in range(num_gpus):with tf.device('/gpu:'+str(i)):
       outputs.append(tf.matmul(inputs[i], b))# merge the results of the deviceswith tf.device('/cpu:0'):
   output = tf.concat(outputs, axis=0)# create a session and runwith tf.Session() as sess:
   sess.run(tf.global_variables_initializer())print sess.run(output)

這些更改也可以通過檢查下面的 TensorFlow 流程圖來可視化。增加的 GPU 模塊說明了原始方法的擴展方式。

圖內複製的可視化。左:原始圖。右:圖內複製的結果圖。

圖間複製


認識到圖內複製在擴展上的局限性,圖間複製的優勢在於運用大量節點時保證模型性能。這是通過在每個 worker 上創建計算圖的副本來實現的,並且不需要主機保存每個 worker 的圖副本。通過一些 TensorFlow 技巧來協調這些 worker 的圖——如果兩個單獨的節點在同一個 TensorFlow 設備上分配一個具有相同名稱的變量,則這些分配將被合併,變量將共享相同的後端存儲,從而這兩個 worker 將合併在一起。

但是,必須確保設備的正確配置。如果兩個 worker 在不同的設備上分配變量,則不會發生合併。對此,TensorFlow 提供了 replica_device_setter 函數。只要每個 worker 以相同的順序創建計算圖,replica_device_setter 為變量分配提供了確定的方法,確保變量在同一設備上。這將在下面的代碼中演示。

由於圖間複製在很大程度上重複了原始圖,因此多數相關的修改實際上都在集群中節點的配置上。因此,下面的代碼段將只針對這一點進行改動。重要的是要注意,這個腳本通常會在集群中的每臺機器上執行,但具體的命令行參數不同。下面來逐行研究代碼。

import sysimport tensorflow as tf
# specify the cluster's architecture
cluster = tf.train.ClusterSpec({'ps': ['192.168.1.1:1111'],'worker': ['192.168.1.2:1111','192.168.1.3:1111']})# parse command-line to specify machine
job_type = sys.argv[1]  # job type: "worker" or "ps"
task_idx = sys.argv[2]  # index job in the worker or ps list# as defined in the ClusterSpec# create TensorFlow Server. This is how the machines communicate.
server = tf.train.Server(cluster, job_name=job_type, task_index=task_idx)# parameter server is updated by remote clients.# will not proceed beyond this if statement.if job_type == 'ps':
   server.join()else:# workers onlywith tf.device(tf.train.replica_device_setter(
                       worker_device='/job:worker/task:'+task_idx,
                       cluster=cluster)):# build your model here as if you only were using a single machinewith tf.Session(server.target):# train your model here

運行分布式 TensorFlow 的第一步是使用 tf.train.ClusterSpec 來指定集群的架構。節點通常分為兩個角色(或「job」):含有變量的參數伺服器(「ps」)和執行大量計算的「worker」。下面提供每個節點的 IP 地址和埠。接下來,腳本必須確定其 job 類型和在網絡中的索引;這通常是通過將命令行參數傳遞給腳本並解析來實現的。job_type 指定節點是運行 ps 還是 worker 任務,而 task_idx 指定節點在 ps 或 worker 列表中的索引。使用以上變量創建 TensorFlow 伺服器,用於連接各設備。

接下來,如果節點是參數伺服器,它只連接它們的線程並等待它們終止。雖然似乎沒有特定的 ps 代碼,但圖元素實際上是由 worker 推送到 ps 的。

相反,如果設備是 worker,則使用 replica_device_setter 構建我們的模型,以便在前面討論的這些 ps 伺服器上連續分配參數。這些副本將在很大程度上與單機的流程圖相同。最後,我們創建一個 tf.Session 並訓練我們的模型。

總結


希望本文清楚地闡述了與分布式 TensorFlow 相關的一些術語和技術。在以後的文章中,我們將詳細探討與此相關及其它的主題。

原文連結:https://clindatsci.com/blog/2017/5/31/distributed-tensorflow

本文為機器之心編譯,轉載請聯繫本公眾號獲得授權

✄---

加入機器之心(全職記者/實習生):hr@jiqizhixin.com

投稿或尋求報導:editor@jiqizhixin.com

廣告&商務合作:bd@jiqizhixin.com


點擊閱讀原文,查看機器之心官網↓↓↓

相關焦點

  • 分布式TensorFlow入門教程
    深度學習在各個領域實現突破的一部分原因是我們使用了更多的數據(大數據)來訓練更複雜的模型(深度神經網絡),並且可以利用一些高性能並行計算設備如GPU和FPGA來加速模型訓練。所以除非模型本身很大,一般不會採用模型並行,因為模型層與層之間存在串行邏輯。但是如果模型本身存在一些可以並行的單元,那麼也是可以利用模型並行來提升訓練速度,比如GoogLeNet的Inception模塊。模型並行訓練深度學習模型最常採用的分布式訓練策略是數據並行,因為訓練費時的一個重要原因是訓練數據量很大。
  • TensorFlow 2.0 分布式訓練
    tf.distribute.MirroredStrategy 是一種簡潔且高性能的,數據並行的同步式分布式策略,主要支持多個 GPU 在同一臺主機上訓練。以下代碼展示了使用 MirroredStrategy 策略,在 TensorFlow Datasets 中的部分圖像數據集上使用 Keras 訓練 MobileNetV2 的過程:import tensorflow as tfimport tensorflow_datasets as tfdsnum_epochs = 5batch_size_per_replica
  • 教程 | TensorFlow 官方解讀:如何在多系統和網絡拓撲中構建高性能模型
    這個操作有其內部線程,線程由佔用最少的 CPU 資源的 I/O 時間主導,這就允許它可與模型的其餘部分並行運行。並行圖像處理從 RecordInput 讀取圖像後,它們作為張量被傳遞至圖像處理管道。一旦副本無法按時完成運行,需要這些張量的計算將會停止並且導致性能下降。在此實現中,data_flow_ops.StagingArea 用於明確排定並行副本。最終的結果是當 GPU 上的計算開始時,所有張量已可用。
  • 社區分享 | Spark 玩轉 TensorFlow 2.0
    利用 Spark 的分布式計算能力,從而可以讓訓練好的 TensorFlow 模型在成百上千的機器上分布式並行執行模型推斷。本案例以 TensorFlow 2.0 的 tf.keras 接口訓練的線性模型為例進行演示。在本例基礎上稍作修改則可以用 Spark 調用訓練好的各種複雜的神經網絡模型進行分布式模型推斷。
  • 分布式訓練的方案和效率對比
    本文內容使用 Tensorflow 內部的工具對訓練過程進行 profiling,找出訓練速度的瓶頸數據並行和模型並行的簡介,並基於一個例子分析兩者的優劣。不同數據並行方案(parameter server 模式和 allreduce 模式,同步更新和異步更新)的詳細介紹和實現,並基於實例給出通信-計算時間比的簡單估算。
  • 是時候放棄TensorFlow集群,擁抱Horovod了
    更多優質內容請關注微信公眾號「AI 前線」(ID:ai-front) 當數據較多或者模型較大時,為提高機器學習模型訓練效率,一般採用多 GPU 的分布式訓練。按照並行方式,分布式訓練一般分為數據並行和模型並行兩種:注意,上述中的不用 GPU 可以是同一臺機上的多個 GPU,也可以是不用機上的 GPU。
  • TensorFlow 2.4 來了:上線對分布式訓練和混合精度的新功能支持
    TensorFlow 2.4 的更新包括對於分布式訓練和混合精度的新功能支持,對 NumPy API 子集的試驗性支持以及一些用於監測性能瓶頸的新工具。和 MultiWorkerMirroredStrategy 類似,ParameterServerStrategy 是一種多工作器(multi-worker)數據並行策略,但梯度更新是異步的。參數伺服器訓練集群由工作伺服器和參數伺服器組成。變量在參數伺服器上創建,然後在每個步驟中由工作器讀取和更新。變量的讀取和更新在工作器之間是獨立進行的,不存在任何同步。
  • 步履不停:TensorFlow 2.4 新功能一覽!
    與 MultiWorkerMirroredStrategy 一樣,ParameterServerStrategy 是一種多工作器數據並行策略;但其梯度更新方式為異步執行。 參數伺服器訓練集群包含工作節點和參數伺服器。系統會在參數伺服器上創建變量,然後工作節點會在每個步驟中進行讀取和更新。變量的讀取和更新會在各工作節點上獨立進行,同時無需採取任何同步操作。
  • 簡單粗暴上手TensorFlow 2.0,北大學霸力作,必須人手一冊!(附資源)
    github.com/snowkylin/tensorflow-handbook/tree/master/source/_static/code/zh本手冊所有章節如下圖,不僅包含 TensorFlow 的概述,還含有基礎、部署、大規模訓練與加速、擴展,以及附錄部分。
  • TensorFlow 2.4來了:上線對分布式訓練和混合精度的新功能支持
    TensorFlow 2.4 的更新包括對於分布式訓練和混合精度的新功能支持,對 NumPy API 子集的試驗性支持以及一些用於監測性能瓶頸的新工具。和 MultiWorkerMirroredStrategy 類似,ParameterServerStrategy 是一種多工作器(multi-worker)數據並行策略,但梯度更新是異步的。參數伺服器訓練集群由工作伺服器和參數伺服器組成。變量在參數伺服器上創建,然後在每個步驟中由工作器讀取和更新。變量的讀取和更新在工作器之間是獨立進行的,不存在任何同步。
  • 【他山之石】愛不釋手的TensorFlow 小技巧及張量詮釋
    「他山之石,可以攻玉」,站在巨人的肩膀才能看得更高,走得更遠。
  • 【翻譯】Sklearn 與 TensorFlow 機器學習實用指南 —— 第9章 (上)啟動並運行TensorFlow
    最重要的是,Tensorflow 可以將圖分解為多個塊並在多個 CPU 或 GPU 上並行運行(如圖 9-2 所示)。 TensorFlow 還支持分布式計算,因此您可以在數百臺伺服器上分割計算,從而在合理的時間內在龐大的訓練集上訓練龐大的神經網絡(請參閱第 12 章)。 TensorFlow 可以訓練一個擁有數百萬個參數的網絡,訓練集由數十億個具有數百萬個特徵的實例組成。
  • Tensorflow for Java + Spark-Scala分布式機器學習計算框架的應用實踐
    import tensorflow as tffrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.layers import Dense,Dropout,Convolution2D,MaxPooling2D,Flattenfrom tensorflow.keras.optimizers
  • 基於tensorflow的深度學習MultiGPU訓練實戰
    它的優點很明顯,大模型訓練,缺點就是模型分片之間的通信和數據傳輸很耗時,所以不能簡單說,模型並行就一定比數據並行要快。數據並行適用於數據量比較小時快速訓練模型,模型並行適用於大數據、大模型場景下。下面主要基於tensorflow講一個數據並行化的實例。1、  單機多卡訓練:給個例子,比如一臺機器上裝有4個GPU卡,以cpu做為PS(master),主要保存一下參數和變量,進行梯度平均。其餘4個GPU訓練模型(worker),進行一些計算量比加大的操作。
  • 深度學習框架TensorFlow 官方文檔中文版
    一個 TensorFlow 圖描述了計算的過程. 為了進行計算, 圖必須在 會話 裡被啟動. 會話 將圖的 op 分發到諸如 CPU 或 GPU 之類的 設備 上, 同時提供執行 op 的方法. 這些方法執行後, 將產生的 tensor 返回.
  • 詳解:深度學習框架數據Pipeline設計
    AI框架的數據處理主要利用CPU運算,訓練則利用GPU/AI晶片,兩者是並行的。其核心是把數據處理算子處理抽象為了兩類:數據集算子和Tensor算子。數據集算子主要負責計算資源的調度和輸入輸出的控制,Tensor算子負責具體的數據增強的計算。
  • TensorFlow 篇 | TensorFlow 數據輸入格式之 TFRecord
    03使用 MapReduce 生成在數據處理環節,我們可能會使用 MapReduce 進行一些預處理操作,同時我們也希望可以直接藉助 MapReduce 任務來生成多個 TFRecord 數據文件以供分布式訓練使用,為了滿足這一需求, TensorFlow 生態提供了一個擴展庫 tensorflow-hadoop ,它包含了 TFRecord
  • 深度學習框架(TensorFlow、keras、PyTorch)
    一、TensorFlow(參見中文文檔)TensorFlow其命名基於工作原理,tensor 意為張量(即多維數組),flow 意為流動。
  • 分布式TensorFlow入坑指南:從實例到代碼帶你玩轉多機器深度學習
    GitHub 地址:https://github.com/mrahtz/distributed_tensorflow_a_gentle_introduction簡介import tensorflow as tf比方說,我們希望多個進程共享一些共同的參數。
  • 大數據下基於Tensorflow框架的深度學習示例教程
    大數據架構中採用的是hadoop系統以及Kerberos安全認證,深度學習採用的是分布式的Tensorflow架構,hadoop解決了大數據的存儲問題,而分布式Tensorflow解決了大數據訓練的問題。本教程是我們團隊在開發基於深度學習的實時欺詐預警服務時,部署深度學習這一模塊時總結出的經驗,感興趣的歡迎深入交流。