【Tensorflow】并行GPU计算


声明:

本文参考书籍《实战Google深度学习框架》
参考链接:实战Google深度学习框架:TensorFlow计算加速


0.简介

在很多情况下,我们仅仅依靠CPU去训练深度学习程序是十分耗时间的,所以我们需要将深度学习框架在GPU上进行模型训练。但是,对于更加复杂的神经网络或者更加庞大的数据集,单个GPU已经无法满足我们的计算量需求,所以需要将训练过程并行在多个GPU上。


1.TensorFlow使用GPU

Tensorflow通过调用tf.device()来指定运行下一步操作的设备,这个设备可以是本地的CPU或者是GPU,也可以是远程的服务器。
tf.device()可以通过设备号进行设备选择。对于GPU而言,通过/gpu:0/gpu:1进行选择,但是对于CPU而言,所有的CPU都是通过/cpu:0的方式进行选择。
CPU
测试一:

import tensorflow as tf
with tf.device('/cpu:0'):
    a = tf.constant([1.0, 2.0, 3.0], shape=[3], name='a')
    b = tf.constant([1.0, 2.0, 3.0], shape=[3], name='b')
    c = a + b
with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess:
    print(sess.run(c))

测试一输出:

add: (Add): /job:localhost/replica:0/task:0/cpu:0
b: (Const): /job:localhost/replica:0/task:0/cpu:0
a: (Const): /job:localhost/replica:0/task:0/cpu:0

测试二:

import tensorflow as tf
with tf.device('/cpu:1'):
    a = tf.constant([1.0, 2.0, 3.0], shape=[3], name='a')
    b = tf.constant([1.0, 2.0, 3.0], shape=[3], name='b')
    c = a + b
with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess:
    print(sess.run(c))

测试二输出(出现错误):

available devices are [ /job:localhost/replica:0/task:0/cpu:0, /job:localhost/replica:0/task:0/gpu:0, /job:localhost/replica:0/task:0/gpu:1 ].

因此对于GPU而言,我们可以通过编号进行选择,但是对于CPU而言,所有的CPU都需要作为/cpu:0使用。

GPU

import tensorflow as tf
with tf.device('/gpu:0'):
    a = tf.constant([1.0, 2.0, 3.0], shape=[3], name='a')
with tf.device('/gpu:1'):
    b = tf.constant([1.0, 2.0, 3.0], shape=[3], name='b')
    c = a + b
with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess:
    print(sess.run(c))

输出:

add: (Add): /job:localhost/replica:0/task:0/gpu:1
b: (Const): /job:localhost/replica:0/task:0/gpu:1
a: (Const): /job:localhost/replica:0/task:0/gpu:0

输出操作日志
Tensorflow通过在构建Session中设置参数log_device_placement来打印出运行每一个操作的设备的信息(参见上面的程序)。

设备优先级
对于有GPU的设备而言(安装的是Tensorflow的GPU版本),程序会优先将运算自动部署在GPU上进行计算,如果是多GPU环境,Tensoflow只会将运算优先放在/gpu:0上进行计算。因此很多时候我们需要对不同的运算制定特定的设备进行运行。

非法指定设备
对于Tensorflow而言,并不是所有的操作都可以放置在GPU上进行运算,如果强制将某些操作制定在GPU上运行的话,会导致程序错误。对于不同版本的Tensorflow而言,对GPU的支持程度也是不一致的,如果在程序中全部使用强制指定设备的方式会降低程序的可移植性。在Tensorflow的kernel中定义了哪些操作可以运行在GPU设备上。

import tensorflow as tf
with tf.device('/gpu:0'):
    a = tf.Variable(1., name='a')
with tf.device('/gpu:0'):
    b = tf.Variable(1, name='b')
with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess:
    print(sess.run(tf.global_variables_initializer()))

输出:

Cannot assign a device for operation 'b': Could not satisfy explicit device specification '/device:GPU:0' because no supported kernel for GPU devices is available.

如上例,对于变量b因为是整数类型,因此在GPU上运行出现了错误。其实在GPU上,tf.Variable只支持实数型参数(float16, float32, double)。为避免这个问题,TensorFlow在生成会话时可以指定allow_soft_placement参数。当allow_soft_placement参数设置为True时,如果运算无法由GPU执行,那么TensorFlow会自动将它放到CPU上执行。

import tensorflow as tf
with tf.device('/gpu:0'):
    a = tf.Variable(1., name='a')
with tf.device('/gpu:0'):
    b = tf.Variable(1, name='b')
with tf.Session(config=tf.ConfigProto(allow_soft_placement=True,log_device_placement=True)) as sess:
    print(sess.run(tf.global_variables_initializer()))

虽然GPU可以加速TensorFlow的计算,但一般来说不会把所有的操作全部都放在GPU上。一般来说,CPU进行流控,GPU进行密集型计算任务,将数据转入或转出GPU都会消耗时间,而且当GPU与内存进行数据交换的时候也会消耗时间。


2.深度学习并行模式

常见的并行化深度学习模型训练方式有两种:同步模式和异步模式。深度学习的模型训练过程是一个迭代过程,在每一轮的迭代过程,前向传播算法会根据当前的参数取值计算出一小部分训练数据上的预测值,然后根据反向传播算法去优化损失函数从而更新网络层参数。因此在不同的设备上进行并行训练时,只需要将数据分发到多个设备上即可,核心问题在于如何进行参数更新。

异步方式
这里写图片描述
在训练的过程中,不同的设备训练进度是不一致的。因此,不同的设备会在不同的时间去获取参数的最新值,设备与设备之间完全独立,每个设备都会根据当前时间的参数值然后取小部分训练数据进行训练,并独立的去反向传播更新参数值。
这里写图片描述
可以看到每一个设备之间是互相独立进行的。(但是在异步处理过程中,要注意参数的访问,避免出现资源争夺等问题)

这里写图片描述
但是在异步模式下,容易导致模型无法优化的最优解。如图所示,假设在 t0 t 0 点,设备 a a b同时获取到网络层参数,现在根据梯度下降的原理,需要将值向左迭代,此时如果是一个设备更新参数,可能会达到极小值点,但是如果两个设备都对过去的参数进行更新,就会导致更新过度,更新到 t1 t 1 点。

同步方式
这里写图片描述
在同步模式下,所有的设备同时读取参数的取值,并且当反向传播算法完成之后同步更新参数的取值。单个设备不会单独对参数进行更新,而会等待所有设备都完成反向传播之后再统一更新参数 。在每一轮迭代时,不同设备首先统一读取当前参数的取值,并随机获取一小部分数据。然后在不同设备上运行反向传播过程得到在各自训练数据上参数的梯度。注意虽然所有设备使用的参数是一致的,但是因为训练数据不同,所以得到参数的梯度就可能不一样。当所有设备完成反向传播的计算之后,需要计算出不同设备上参数梯度的平均值,最后再根据平均值对参数进行更新。

总结

  • 现在常见的随机梯度下降本身就是梯度下降算法的一个近似解法,即使对于梯度下降算法而言,也不一定会得到全局最优解。
  • 在很多环境中,异步模式的结果不一定比同步模式的结果差。
  • 同步模式耗时间。

3.多GPU并行测试

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值