天天看點

centos7.6檢視什麼程序跑的流量_Horovod之分布式訓練原理,安裝,tensorflow例子以及注意事項(為什麼慢)。

最近由于工作需要,重新研究了下horovod,然後簡單總結下。

Horovod原理

詳細可看原論文 總結: 1. Horovod 使用ring-all-reduce分布式計算方式 2. 運作過程: * 前向 每個模型收到batch size大小的輸入以及計算gradients * 後向時,每個模型分别計算gradients * 使用allreduce計算average gradients * 使用gradient進行更新 不同的gpu使用不同的訓練資料訓練,再使用allredece做整合,相當于增加了batch size

Horovod 安裝

推薦使用滿足cuda版本的各個軟體的最新版本。

openmpi
nccl
horovod
tf/pytorch
           

Tensorflow例子

tf的session運作時可以添加hooks(鈎子)和scanfold(腳手架)指定sess跑前,跑後要幹些什麼額外操作。 常見的hook有: LoggingTensorHook:自動個n步輸出日志。 CheckpointSaverHook:自動儲存檔案以及自動從最新的ckpt恢複。 簡單的來說,

hook就是将一些每一步訓練前後常用操作寫成一個端口

,友善複用。

Horovod定義了兩種初始化變量的方法 1. 不适用hook

bcast = hvd.broadcast_global_variables(0)
           
  1. 使用hooks
hooks = [hvd.BroadcastGlobalVariablesHook(0)]
           

以下會分别做相關的介紹。

1. Session(不使用hooks)

import tensorflow as tf
import horovod.tensorflow as hvd


# Initialize Horovod
hvd.init()

# Pin GPU to be used to process local rank (one GPU per process)
config = tf.ConfigProto()
config.gpu_options.visible_device_list = str(hvd.local_rank())

# Build model...
loss = ...
opt = tf.train.AdagradOptimizer(0.01 * hvd.size())

# Add Horovod Distributed Optimizer
opt = hvd.DistributedOptimizer(opt)

# Add hook to broadcast variables from rank 0 to all other processes during
# initialization.
bcast = hvd.broadcast_global_variables(0)


# Make training operation
train_op = opt.minimize(loss)

# Save checkpoints only on worker 0 to prevent other workers from corrupting them.
checkpoint_dir = '/tmp/train_logs' if hvd.rank() == 0 else None

with tf.train.Session(config=config,hooks=hooks) as sess:
  bcast.run()
  while not sess.should_stop():
    # Perform synchronous training.
    mon_sess.run(train_op)
           

2. MonitoredTrainingSession版本(使用hooks)

Session版本也可以使用hooks, 使用以下代碼可以

使用session調用hooks

call hooks.begin()
sess = tf.compat.v1.Session()
call hooks.after_create_session()
while not stop is requested:
  call hooks.before_run()
  try:
    results = sess.run(merged_fetches, feed_dict=merged_feeds)
  except (errors.OutOfRangeError, StopIteration):
    break
  call hooks.after_run()
call hooks.end()
sess.close()
           

直接使用MonitoredTrainingSession,自動調用hooks會比較友善。

import tensorflow as tf
import horovod.tensorflow as hvd


# Initialize Horovod
hvd.init()

# Pin GPU to be used to process local rank (one GPU per process)
config = tf.ConfigProto()
config.gpu_options.visible_device_list = str(hvd.local_rank())

# Build model...
loss = ...
opt = tf.train.AdagradOptimizer(0.01 * hvd.size())

# Add Horovod Distributed Optimizer
opt = hvd.DistributedOptimizer(opt)

# Add hook to broadcast variables from rank 0 to all other processes during
# initialization.
hooks = [hvd.BroadcastGlobalVariablesHook(0)]

# Make training operation
train_op = opt.minimize(loss)

# Save checkpoints only on worker 0 to prevent other workers from corrupting them.
checkpoint_dir = '/tmp/train_logs' if hvd.rank() == 0 else None

# 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(checkpoint_dir=checkpoint_dir,
                                       config=config,
                                       hooks=hooks) as mon_sess:
  while not mon_sess.should_stop():
    # Perform synchronous training.
    mon_sess.run(train_op)
           

運作

  1. train.py指定使用哪些gpu
os.environ["CUDA_VISIBLE_DEVICES"] = "2,3"
           
  1. 運作指令
horovodrun -np 2 python *.py
           

注意事項

  1. 保證安裝環境正常 Open MPI 3.1.3可能有問題,推薦使用 3.1.2或者更新到Open MPI 4.0.0. 使用正确版本的tensorflow,tf1.13.1對于多程序處理可能有問題。
  2. 正确的gpu cpu綁定參數 運作horovodrun和miprun時使用正确的參數(理想情況下,控制gpu的程序應該和最近的cpu接口綁定,這個取決于伺服器的主機闆以及cpu類型,推薦使用—map-by socket。)

    mpirun —map-by socket

  3. 每個gpu一個程序 訓練代碼中加入

    Python config.gpu_options.visible_device_list = str(hvd.local_rank())

# 4為gpu數量 mpirun -np 4

4. 檢視每個gpu使用的程序數目以及占用顯存大小是否正常。

  1. GPU使用率低下,資料讀取過慢 保證使用tf.data多線程讀取方式或者搞笑的資料預處理方式 一般來說gpu使用率要達到80-95,10-25說明使用率過低
  2. 檢查哪些問題使得gpu運作過慢 使用horovod timeline 或者 nvprof 檢視哪裡有問題
    1. tf data pipeline過慢,檢視官方代碼https://github.com/tensorflow/models/tree/master/official/vision/image_classification
    2. GPU之間資料交換有問題,保證你正在使用 InfiniBand.使用NCCL_DEBUG=INFO檢視資料交換細節進行檢查

      mpirun -np 4 — map-by socket -x NCCL_DEBUG=INFO python something.py -{params} or use horovodrun which includes the –x binding.

  3. GPUs 資料交換 檢視gpu通訊保證gpu之間正常分布式訓練。 用NCCL_DEBUG=INFO檢視資料交換細節。 下為正常運作的輸出結果。

    gpu002:1299562:1299573 [0] NCCL INFO Ring 00 : 0[0] -> 1[1] via P2P/IPC gpu028:149460:149495 [0] NCCL INFO Ring 01 : 16 -> 0 [send] via NET/IB/0 gpu009:164181:164216 [0] NCCL INFO Ring 01 : 12 -> 8 [receive] via NET/IB/0 gpu009:164181:164216 [0] NCCL INFO Ring 01 : 4 -> 8 [receive] via NET/IB/0

  4. 其他通用的建議
    1. 使用 較大的batchsize 塞滿gpu,但要考慮batchsize和 收斂性 的問題。
    2. 學習率使用正常的學習率$times$gpu數目,同僚使用正常的學習率和scaled的學習率做訓練,看哪個能好
    3. 使用最新版本的軟體

注意事項總結

  1. 正确的cpu gpu綁定方式
  2. 不浪費多餘的gpu,一個gpu一個程序
  3. 使用高效的data pipeline
  4. 優化gpu使用率達到80%以上
  5. 使用最新版本的cuda相關軟體,cuda以及nccl

分布式訓練總結

  1. tensorflow使用horovod能夠有效的利用多gpu進行訓練,而且随着gpu使用的越多,horovod提升的效果越明顯。
centos7.6檢視什麼程式跑的流量_Horovod之分布式訓練原理,安裝,tensorflow例子以及注意事項(為什麼慢)。
  1. 個人覺得使用多gpu的初衷是需要試驗較大的batch size或者網絡模型比較大,達到臨界的batch size需要做大量的實驗。如果為了提升網絡模型訓練速度,不如多用用profile或者改進data pipeline。

參考資料

  1. https://github.com/horovod/horovod
  2. https://towardsdatascience.com/why-is-your-horovod-slower-than-the-usual-201b4b8574d5
  3. https://mc.ai/a-quick-guide-to-distributed-training-with-tensorflow-and-horovod-on-amazon-sagemaker/