前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2.3 tensorflow单机多GPU并行

2.3 tensorflow单机多GPU并行

作者头像
锦小年
发布2019-07-01 15:08:40
4.1K0
发布2019-07-01 15:08:40
举报
文章被收录于专栏:锦小年的博客锦小年的博客

现在很多服务器配置都是单机上配有多个GPU卡。tensorflow默认占用全部的gpu的显存,但是只在第一块GPU上进行计算,这样对于显卡的利用率不高。

1. 指定运行GPU,不占用其他gpu的显存。

这种模式就是单卡多任务,一个任务一个卡。

代码语言:javascript
复制
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0,1" # 指定gpu编号,从0开始

这样可以在不同的卡上运行不同参数的程序,达到调参的目的。

2. 多GPU并行

有时候想要把所有GPU用在同一个模型里,以节省训练时间,方便快速查看结果。这个时候需要用到GPU并行。 gpu并行有模型并行和数据并行,又分为同步和异步模式。单机多卡一般采用同步的数据并行模式:不同gpu共享变量,不同gpu运算不同数据的loss和梯度后在cpu里平均后更新到被训练参数。 tensorflow中的GPU并行策略是(下图,全网都是这个图): 每个GPU中都存有一个模型,但共享所有需要训练的变量。分别在gpu里计算不同batchsize的数据的损失以及损失的梯度,在cpu里收集所有显卡的损失的梯度后求平均值,再更新到变量里。

在这里插入图片描述
在这里插入图片描述

对应代码:

代码语言:javascript
复制
# 计算平均梯度的函数,该函数全网统一
def average_gradients(tower_grads):
    """Calculate the average gradient for each shared variable across all towers.
    Note that this function provides a synchronization point across all towers.
    Args:
      tower_grads: List of lists of (gradient, variable) tuples. The outer list
        is over individual gradients. The inner list is over the gradient
        calculation for each tower.
    Returns:
       List of pairs of (gradient, variable) where the gradient has been averaged
       across all towers.
    """
    average_grads = []
    for grad_and_vars in zip(*tower_grads):
        grads = []
        for g, _ in grad_and_vars:
            expend_g = tf.expand_dims(g, 0)
            grads.append(expend_g)
        grad = tf.concat(grads, 0)
        grad = tf.reduce_mean(grad, 0)
        v = grad_and_vars[0][1]
        grad_and_var = (grad, v)
        average_grads.append(grad_and_var)
    return average_grads

def train_multi_gpu():
    global graph
    # cpu里设置好输入占位符
    with graph.as_default(), tf.device('/cpu:0'):
        # input
        x = tf.placeholder(tf.float32, shape=[None, SPACE_I_DIMS, SPACE_J_DIMS, SPACE_K_DIMS, 1], name='x')
        y_ = tf.placeholder(tf.int64, shape=[None, 1])
        drop_rate = tf.placeholder(tf.float32)

        # learning rate
        global_step = tf.train.get_or_create_global_step()
        lr = tf.train.exponential_decay(
            lr0,
            global_step,
            decay_steps=lr_step,
            decay_rate=lr_decay,
            staircase=True)

        # optimaizer
        opt = tf.train.AdamOptimizer(learning_rate=lr)
		#用列表收集每个gpu的梯度
        tower_grad = []

        with tf.variable_scope(tf.get_variable_scope()):
            # gpu
            for i in range(NUM_GPUS):
                with tf.device('/gpu:%d' % i):
                    with tf.name_scope('gpu_%d' % i) as scope:
                        with tf.name_scope("tower_%d" % i):
                        	#每个gpu里放不同的数据
                            _x = x[i * batch_size:(i + 1) * batch_size]
                            _y = y_[i * batch_size:(i + 1) * batch_size]

                            # calculate inference
                            y = inference(_x, reuse=False, drop_rate=drop_rate)
                            # loss
                            mse_loss = tf.losses.mean_squared_error(_y, y)
                            cur_loss = mse_loss
							# 当前梯度
                            cur_grad = opt.compute_gradients(cur_loss)
                            tower_grad.append(cur_grad)
							#变量共享
                            tf.get_variable_scope().reuse_variables()
		#计算平均梯度
        grads = average_gradients(tower_grad)
        # 更新参数
        apply_grident_op = opt.apply_gradients(grads, global_step=global_step)
		#参数初始化
        init = tf.global_variables_initializer()

    # train steps
    with tf.Session(config=config).as_default() as sess:
        # init all variables
        init.run()
        try:
            for i in range(max_steps):

                # get next step data
                x_batch, y_batch, id, sex = sess.run(trian_next_batch)
           		#训练
                _ = sess.run(
                        [apply_grident_op], feed_dict={
                            x: x_batch,
                            y_: y_batch,
                            drop_rate: 0.2,
                        })

需要注意的是batchsize的大小,batchsize = batchsize_single_gpu * gpu_nums,例如单gpu的为32,有4块gpu,则总的batchsize为32*4=128.在代码中也很清楚的显示出了tensorflow多gpu并行的原理。

3. 注意事项

  • 多gpu并行训练速度会提升,但不是完全线性的,因为gpu之间的通信需要时间。例如单gpu训练100步要50秒,训练了3200个数据,4块gpu并行训练100步可能要150s,但训练数据为3200*4.
  • gpu数量不易选过多,由于前端总线带宽的限制,不同GPU延迟不一样,导致单步时间过长。
  • 多卡并行需要的cpu开销很大,所以对服务器的整体性能要求更高一些。如果服务器整体性能不是很好,还是单卡多任务吧。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年06月30日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 指定运行GPU,不占用其他gpu的显存。
  • 2. 多GPU并行
  • 3. 注意事项
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档