有些服務器上可能安裝了多塊GPU供大家共同使用,為了不產生沖突,有時需要按情況指定自己的程序具體在哪些GPU上運行。
(注意:本文主要參考了https://blog.csdn.net/qq_38451119/article/details/81065675,我這里主要是記錄一下,以后自己再用到的時候方便查找)
下面是實驗室GPU的情況:
下面是具體的方法:
1. 在python代碼中通過CUDA_VISIBLE_DEVICES來指定
比如,我要使用上面編號為“3”的GPU來運行我的程序,則需要在自己的程序中加入以下代碼:
1 import os 2 os.environ('CUDA_VISIBLE_DEVICES') = '3'
下面可以通過命令:nvidia-smi 來查看GPU的使用情況:
可以看到編號為“3”的GPU已經被我占用了,而其他幾塊GPU則沒被占用,這種就相當於在我們運行程序的時候,將除編號為“3”的GPU以外的其他GPU全部屏蔽了,只有編號為“3”的GPU對當前運行的程序是可見的。
同樣,如果要占用多塊GPU的話,比如使用編號為”1,2“的GPU來訓練,則上面的代碼可以改成:
import os os.environ('CUDA_VISIBLE_DEVICES')='1,2'
需要注意的是,僅做上述設置還不夠,還需要在代碼中進行一些設置。相較於pytorch,Keras等,TensorFlow的設置要麻煩一些。多GPU並行可分為模型並行和數據並行兩大類,這里介紹一下數據並行方式。數據並行原理:模型參數保存在一個指定gpu/cpu上,模型參數的副本在不同gpu上,每次訓練,提供batch_size*gpu_num數據,並等量拆分成多個batch,分別送入不同GPU。前向在不同gpu上進行,模型參數更新時,將多個GPU后向計算得到的梯度數據進行平均,並在指定GPU/CPU上利用梯度數據更新模型參數。下面以一個例子來說明:
1 #計算平均梯度的函數 2 def average_gradients(tower_grads): 3 average_grads=[] 4 for grad_and_vars in zip(*tower_grads): 5 grads=[] 6 for g,_ in grad_and_vars: 7 expend_g=tf.expand_dims(g,0) 8 grads.append(expend_g) 9 grad=tf.concat(grads,0) 10 grad=tf.reduce_mean(grad,0) 11 v=grad_and_vars[0][1] 12 grad_and_var=(grad,v) 13 average_grads.append(grad_and_var) 14 return average_grads 15 16 #設置GPU數量,每塊GPU上運行的batch大小 17 num_gpus = 2 18 each_gpu_batch = 16 19 batch_size = each_gpu_batch * num_gpus 20 21 #占位符 22 data = tf.placeholder(tf.float32, [batch_size, img_size, img_size, 3]) 23 opt = tf.train.AdamOptimizer(learning_rate=d_lr, beta1=0.5, beta2=0.9) 24 25 #存儲所有GPU上的梯度 26 tower_grads = [] 27 28 # 多GPU並行工作 29 with tf.variable_scope(tf.get_variable_scope()): 30 for i in range(num_gpus): 31 with tf.device("/gpu:%d" % i): 32 with tf.name_scope("tower_%d" % i): 33 _data = data[i*each_gpu_batch:(i+1)*each_gpu_batch] 34 generated = network(_data, s_size=s_size) 35 loss = loss(_data, generated) 36 37 grads = opt.compute_gradients(loss) 38 tower_grads.append(grads) 39 40 tf.get_variable_scope().reuse_variables() 41 42 grads = average_gradients(tower_grads) 43 train_opt = opt.apply_gradients(grads) 44 45 #后面就正常的調用session運行就好了
注意:上述代碼並不能直接運行,只是給出了數據並行所需的步驟。詳細解釋參考:
https://blog.csdn.net/minstyrain/article/details/80986397
https://www.cnblogs.com/hrlnw/p/7779058.html
2. 在終端執行.py文件時通過CUDA_VISIBLE_DEVICES來指定
該方法與方法1本質上是一樣的,只不過一個是在代碼中指定GPU,一個是在執行代碼的命令行中指定GPU。
命令行形式如下:
CUDA_VISIBLE_DEVICES=1 python train.py
3. 在python代碼中通過tf.device()函數來指定訓練時所要使用的GPU
比如,我要使用上面編號為“1”的GPU來運行我的程序,則需要在自己的程序中加入以下代碼:
import tensorflow as tf tf.device('/gpu:1')
下面是實驗結果(注:我自己沒嘗試這種方式,所以下面的實驗結果圖示直接用的博客https://blog.csdn.net/qq_38451119/article/details/81065675中的):
可以看到,這樣指定GPU還是有一點毛病的。雖然指定了第“1“塊GPU來訓練,但是其它幾個GPU也還是被占用,只是模型訓練的時候,是在第1塊GPU上進行。所以,最好使用前面介紹的第1,2種方法。