『開發技術』GPU訓練加速原理(附KerasGPU訓練技巧)


0.深入理解GPU訓練加速原理

我們都知道用GPU可以加速神經神經網絡訓練(相較於CPU),具體的速度對比可以參看我之前寫的速度對比博文: [深度應用]·主流深度學習硬件速度對比(CPU,GPU,TPU)

GPU是如何加速的呢?

我打算從兩個方面來解答:

  • 單個GPU較於CPU加速:

在訓練網絡中,其實大量的運算資源都消耗在了數值計算上面,大部分網絡訓練的過程都是1.計算loss,2.根據loss求梯度,3.再根據梯度更新參數(梯度下降原理)。無論在GPU還是CPU中,都是不斷重復123步。但是由於CPU是通用計算單元(並不擅長數值運行),而GPU特長是圖像處理(數值計算)。所以GPU更加適合訓練網絡,從而起到加速效果。

  • 多GPU較於單GPU加速:

一般在GPU訓練中,同一個GPU中,batch_size的大小,決定訓練的速度,batch_size越小,訓練一輪所需的步數(data_len/batch_size)就會越大,從而花費時間越多。

下面介紹下使用多GPU數據並行加速原理:

假設一台機器上有k塊GPU。給定需要訓練的模型,每塊GPU及其相應的顯存將分別獨立維護一份完整的模型參數。在模型訓練的任意一次迭代中,給定一個隨機小批量,我們將該批量中的樣本划分成k份並分給每塊顯卡的顯存一份。然后,每塊GPU將根據相應顯存所分到的小批量子集和所維護的模型參數分別計算模型參數的本地梯度。接下來,我們把k塊顯卡的顯存上的本地梯度相加,便得到當前的小批量隨機梯度。之后,每塊GPU都使用這個小批量隨機梯度分別更新相應顯存所維護的那一份完整的模型參數。下圖描繪了使用2塊GPU的數據並行下的小批量隨機梯度的計算。

 使用2塊GPU的數據並行下的小批量隨機梯度的計算

我們回憶下梯度下降的過程,1.計算loss,2.根據loss求梯度,3.再根據梯度更新參數。

使用上述的多GPU數據並行方法,可以理解為把batch_size擴大了k倍,從而總的時間縮短為了k分之1,實現了多GPU計算訓練。

其實每一個GPU上網絡的參數都是相同的,因為都是從相同的loss做的更新。


1.如何在 GPU 上運行 Keras?

如果你以 TensorFlow 或 CNTK 后端運行,只要檢測到任何可用的 GPU,那么代碼將自動在 GPU 上運行。

如果你以 Theano 后端運行,則可以使用以下方法之一:

方法 1: 使用 Theano flags。

THEANO_FLAGS=device=gpu,floatX=float32 python my_keras_script.py

"gpu" 可能需要根據你的設備標識符(例如gpu0,gpu1等)進行更改。

方法 2: 創建 .theanorc指導教程

方法 3: 在代碼的開頭手動設置 theano.config.devicetheano.config.floatX

import theano theano.config.device = 'gpu' theano.config.floatX = 'float32' 

 

2.如何在多 GPU 上運行 Keras 模型?

我們建議使用 TensorFlow 后端來執行這項任務。有兩種方法可在多個 GPU 上運行單個模型:數據並行設備並行

在大多數情況下,你最需要的是數據並行。

數據並行

數據並行包括在每個設備上復制一次目標模型,並使用每個模型副本處理不同部分的輸入數據。Keras 有一個內置的實用函數 keras.utils.multi_gpu_model,它可以生成任何模型的數據並行版本,在多達 8 個 GPU 上實現准線性加速。

有關更多信息,請參閱 multi_gpu_model 的文檔。這里是一個快速的例子:

from keras.utils import multi_gpu_model # 將 `model` 復制到 8 個 GPU 上。 # 假定你的機器有 8 個可用的 GPU。 parallel_model = multi_gpu_model(model, gpus=8) parallel_model.compile(loss='categorical_crossentropy', optimizer='rmsprop') # 這個 `fit` 調用將分布在 8 個 GPU 上。 # 由於 batch size 為 256,每個 GPU 將處理 32 個樣本。 parallel_model.fit(x, y, epochs=20, batch_size=256) 

設備並行

設備並行性包括在不同設備上運行同一模型的不同部分。對於具有並行體系結構的模型,例如有兩個分支的模型,這種方式很合適。

這種並行可以通過使用 TensorFlow device scopes 來實現。這里是一個簡單的例子: 

# 模型中共享的 LSTM 用於並行編碼兩個不同的序列 input_a = keras.Input(shape=(140, 256)) input_b = keras.Input(shape=(140, 256)) shared_lstm = keras.layers.LSTM(64) # 在一個 GPU 上處理第一個序列 with tf.device_scope('/gpu:0'): encoded_a = shared_lstm(tweet_a) # 在另一個 GPU上 處理下一個序列 with tf.device_scope('/gpu:1'): encoded_b = shared_lstm(tweet_b) # 在 CPU 上連接結果 with tf.device_scope('/cpu:0'): merged_vector = keras.layers.concatenate([encoded_a, encoded_b], axis=-1) 

3.參考 

1.http://zh.d2l.ai/chapter_computational-performance/multiple-gpus.html

2.https://keras.io/zh/getting-started/faq/#how-can-i-run-a-keras-model-on-multiple-gpus


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM