自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

調參俠看過來!兩個提高深度學習訓練效率的絕技

人工智能 深度學習
本文分享了通過GPU利用率和分布式訓練Horovod框架來提升深度學習訓練。

[[343402]]

 1. 訓練的瓶頸在哪里

  •  GPU利用率低:模型訓練時GPU顯存沾滿了,但是GPU的利用率比較不穩(wěn)定,有時候0%,有時候90%,忽高忽低。   

  •  訓練的數(shù)據量大:訓練數(shù)據大,在百萬/千萬的量級,訓練一個Epoch需要很長時間,模型迭代周期過長。

2. 提高GPU利用率:CPU vs GPU

GPU利用率低, 主要原因是CPU處理的效率跟不上GPU

2.1 CPU vs GPU的通信

  •  CPU負責加載數(shù)據+數(shù)據預處理,并不斷的在內存和顯存之間交互數(shù)據
  •  GPU負責模型訓練(圖片來自網絡)

2.2 解決方案

采用多進程并行處理,加快CPU加載數(shù)據的性能

  •  keras keras 中提供了workers use_multiprocessing來采用多進程方式,并行處理數(shù)據,并push到隊列中,共GPU模型訓練。因為進程之間可能相互影響資源,并不是越大越好,workers可以設置2,4,8。 
  1. run_model.fit_generator(  
  2.               generator=training_generator 
  3.               class_weight={0: config.weights, 1: 1},  
  4.               epochsepochs=epochs,  
  5.               verbose=1 
  6.               steps_per_epochsteps_per_epoch=steps_per_epoch,  
  7.               callbacks=callbacks_list 
  8.               validation_data=valid_generator
  9.               validation_stepsvalidation_steps=validation_steps,  
  10.               shuffle=True 
  11.               workers=8 
  12.               use_multiprocessing=True 
  13.               max_queue_size=20 
  •  pytorch torch在加載數(shù)據中提供類似參數(shù)num_workers。pin_memory=True可以直接加載到顯存中,而不需要內存 
  1. torch.utils.data.DataLoader(image_datasets[x],  
  2.                              batch_sizebatch_size=batch_size,   
  3.                              shuffle=True 
  4.                              num_workers=8 
  5.                              pin_memory=True

3. 分布式并行訓練

3.1 并行模式

當訓練的數(shù)據量很大時,可以通過多個機器多個GPU來提高訓練的效率。不同于hadoop和spark等分布式數(shù)據處理框架,深度學習訓練因為要涉及參數(shù)的前項傳播和反向傳播,有兩種并行方式:

  •  模型并行( model parallelism ):分布式系統(tǒng)中的不同機器(GPU/CPU等)負責網絡模型的不同部分,通常是神經網絡模型的不同網絡層被分配到不同的機器,或者同一層內部的不同參數(shù)被分配到不同機器。一般是超大的模型,一張顯卡放不下的情況,如NLP的模型。模型并行的缺點是層和層之間可能存在依賴關系,不能完全的并行。(圖片來自網絡)  

  •  數(shù)據并行( data parallelism ):不同的機器有同一個模型的多個副本,每個機器分配到不同的數(shù)據,然后將所有機器的計算結果按照某種方式合并。這種就比較適合大數(shù)據的情況。數(shù)據并行要解決的問題是數(shù)據的分割和傳輸,以及參數(shù)的更新。

3.2 數(shù)據并行

Facebook在《Accurate, Large Minibatch SGD: Training ImageNet in 1 Hour》介紹了使用 256 塊 GPU 進行 ResNet-50 網絡「數(shù)據并行」訓練的方法

  •  數(shù)據分割: 選用大的batch-size, 按照worker數(shù)量進行分割, 分發(fā)到不同worker執(zhí)行
  •  參數(shù)更新:參數(shù)的更新有兩種模式(1)參數(shù)服務器 (2) ring環(huán)狀更新(無服務器模式)

3.2.1 參數(shù)服務器模式

參數(shù)服務器模式,見下圖。在每個worker執(zhí)行完一個batch的訓練后,反向傳播參數(shù)的時候,所有的worker都會把參數(shù)傳給參數(shù)服務器,進行匯總求均值,之后再傳給每個worker,進入第二個batch的訓練。(圖片來自網絡)

參數(shù)服務器有一個或者多個的結構模式,可以看出這種數(shù)據并行的模式效率是否提升取決于參數(shù)服務器與worker之間的通信效率,也就是最慢的worker的訓練時間和參數(shù)服務器的接收和更新參數(shù)后再回傳的時間。worker數(shù)量多的話,參數(shù)服務器可能存在瓶頸。(圖片來自網絡)

3.2.2 ring-reduce

百度提出的ring-reduce摒棄了參數(shù)服務器,采用環(huán)狀結構來更新參數(shù)。ring-reduce把所有的worker組成一個兩兩相鄰的環(huán)形結構。每個worker只與相鄰的worker交換參數(shù)。經過幾次交換之后,所有的worker都包含其他worker的參數(shù)信息,達到更新的目的。(圖片來自網絡)

下面幾張圖,可以看到其中的幾個步驟;ring-reduce為了加快速度,并不是一次性交換所有的參數(shù);而是先把參數(shù)進行分割,不斷交換分割后參數(shù)。

4. 實現(xiàn)框架:Horovod

Horovod 是 Uber 開源的又一個深度學習工具,它的發(fā)展吸取了 Facebook「一小時訓練 ImageNet 論文」與百度 Ring Allreduce 的優(yōu)點,可為用戶實現(xiàn)分布式訓練提供幫助。https://github.com/horovod/horovod

采用NCCL 替換百度的 ring-allreduce 實現(xiàn)。NCCL 是英偉達的集合通信庫,提供高度優(yōu)化的 ring-allreduce 版本。NCCL 2 允許在多個機器之間運行 ring-allreduc。

如果要把單機的訓練代碼修改成分布式的代碼,只要幾個步驟就可以了 改造分布式訓練:

  •  horovod安裝 建議安裝docker的horovod,省去安裝環(huán)境的麻煩。horovod依賴NCCL 2 open MPI 
  1. $ mkdir horovod-docker-gpu  
  2. $ wget -O horovod-docker-gpu/Dockerfile https://raw.githubusercontent.com/horovod/horovod/master/Dockerfile.gpu  
  3. $ docker build -t horovod:latest horovod-docker-gpu 
  •  機器worker機器之間ssh打通
  •  修改訓練代碼 horovod支持tf,keras,pytorch和mxnet等不同的深度學習框架。以keras為例,修改主要6個步驟 (1) 初始化:hvd.init() (2)分配GPU計算資源:config.gpu_options.visible_device_list = str(hvd.local_rank())(3)分布式的優(yōu)化器來實現(xiàn)參數(shù)的分布式更新:opt = hvd.DistributedOptimizer(opt)(4)定義所有worker模型初始化一致性 hvd.callbacks.BroadcastGlobalVariablesCallback(0)(5)模型保存在某一個worker   
  1. from __future__ import print_function  
  2.    import keras 
  3.    from keras.datasets import mnist  
  4.    from keras.models import Sequential  
  5.    from keras.layers import Dense, Dropout, Flatten  
  6.    from keras.layers import Conv2D, MaxPooling2D  
  7.    from keras import backend as K  
  8.    import math  
  9.    import tensorflow as tf 
  10.    import horovod.keras as hvd  
  11.    # Horovod: initialize Horovod.  
  12.    hvd.init()  
  13.    # Horovod: pin GPU to be used to process local rank (one GPU per process)  
  14.    config = tf.ConfigProto()  
  15.    config.gpu_options.allow_growth = True  
  16.    config.gpu_options.visible_device_list = str(hvd.local_rank())  
  17.    K.set_session(tf.Session(configconfig=config))  
  18.    batch_size = 128  
  19.    num_classes = 10  
  20.    # Horovod: adjust number of epochs based on number of GPUs.  
  21.    epochs = int(math.ceil(12.0 / hvd.size()))  
  22.    # Input image dimensions 
  23.    img_rows, img_cols = 28, 28   
  24.    # The data, shuffled and split between train and test sets  
  25.    (x_train, y_train), (x_test, y_test) = mnist.load_data()   
  26.    if K.image_data_format() == 'channels_first':  
  27.        x_trainx_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)  
  28.        x_testx_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)  
  29.        input_shape = (1, img_rows, img_cols)  
  30.    else:  
  31.        x_trainx_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)  
  32.        x_testx_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)  
  33.        input_shape = (img_rows, img_cols, 1)  
  34.    x_trainx_train = x_train.astype('float32')  
  35.    x_testx_test = x_test.astype('float32')  
  36.    x_train /= 255  
  37.    x_test /= 255  
  38.    print('x_train shape:', x_train.shape)  
  39.    print(x_train.shape[0], 'train samples')  
  40.    print(x_test.shape[0], 'test samples')  
  41.    # Convert class vectors to binary class matrices  
  42.    y_train = keras.utils.to_categorical(y_train, num_classes)  
  43.    y_test = keras.utils.to_categorical(y_test, num_classes)  
  44.    model = Sequential()  
  45.    model.add(Conv2D(32, kernel_size=(3, 3),  
  46.                    activation='relu' 
  47.                    input_shapeinput_shape=input_shape))  
  48.    model.add(Conv2D(64, (3, 3), activation='relu'))  
  49.    model.add(MaxPooling2D(pool_size=(2, 2)))  
  50.    model.add(Dropout(0.25))  
  51.    model.add(Flatten())  
  52.    model.add(Dense(128, activation='relu'))  
  53.    model.add(Dropout(0.5))  
  54.    model.add(Dense(num_classes, activation='softmax'))  
  55.    # Horovod: adjust learning rate based on number of GPUs.  
  56.    opt = keras.optimizers.Adadelta(1.0 * hvd.size())  
  57.    # Horovod: add Horovod Distributed Optimizer.  
  58.    opt = hvd.DistributedOptimizer(opt)  
  59.    model.compile(loss=keras.losses.categorical_crossentropy,  
  60.                optoptimizer=opt,  
  61.                metrics=['accuracy'])  
  62.    callbacks = [ 
  63.         # Horovod: broadcast initial variable states from rank 0 to all other processes.  
  64.        # This is necessary to ensure consistent initialization of all workers when  
  65.        # training is started with random weights or restored from a checkpoint.  
  66.        hvd.callbacks.BroadcastGlobalVariablesCallback(0),  
  67.    ]  
  68.    # Horovod: save checkpoints only on worker 0 to prevent other workers from corrupting them.  
  69.    if hvd.rank() == 0:  
  70.        callbacks.append(keras.callbacks.ModelCheckpoint('./checkpoint-{epoch}.h5'))  
  71.    model.fit(x_train, y_train, 
  72.             batch_sizebatch_size=batch_size,  
  73.            callbackscallbacks=callbacks,  
  74.            epochsepochs=epochs,  
  75.            verbose=1 
  76.            validation_data=(x_test, y_test))  
  77.    score = model.evaluate(x_test, y_test, verbose=0 
  78.    print('Test loss:', score[0])  
  79.    print('Test accuracy:', score[1]) 
  •  利用horovodrun 執(zhí)行分布式訓練

horovodrun -np 16 -H server1:4,server2:4,server3:4,server4:4 python train.py

5. 總結

本文分享了通過GPU利用率和分布式訓練Horovod框架來提升深度學習訓練。

  •  并行CPU加載數(shù)據和預處理,讓GPU不再等待CPU
  •  采用Horovod讓數(shù)據并行來提高大數(shù)據量的訓練的迭代時間 

 

責任編輯:龐桂玉 來源: Python中文社區(qū)
相關推薦

2013-10-14 14:15:21

程序員讀書

2020-11-05 10:57:47

云計算多云公有云

2018-09-29 15:59:18

APPiOS優(yōu)化

2009-10-20 14:10:00

CCIE考試

2018-05-14 12:18:47

AI開發(fā)深度學習框架

2015-11-30 14:10:49

大無線eLTE華為

2009-08-05 09:37:11

云計算CIO

2024-11-18 08:08:21

2023-11-29 13:58:00

模型數(shù)據

2015-09-15 09:12:04

程序媛Google特殊獎勵

2019-01-24 10:18:25

機器學習深度學習圖像處理

2020-05-26 15:16:44

5G兩會全息

2015-02-09 13:48:12

2013-11-08 17:33:52

2022-05-11 07:17:29

MySQLAnsible運維

2020-07-04 11:01:36

Kotlin開發(fā)Android

2011-03-01 13:07:36

MySQLOrder by查詢

2020-03-28 15:48:13

iOS 13.4蘋果體驗

2019-08-08 17:14:31

5G手機華為三星

2011-05-27 11:21:58

打印機技巧
點贊
收藏

51CTO技術棧公眾號