在多GPU情況下TensorFlow如何指定在哪些GPU上運行程序


有些服務器上可能安裝了多塊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種方法。


免責聲明!

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



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