分享

GPU介绍及TensorFlow如何使用GPU跑程序

本帖最后由 xuanxufeng 于 2018-6-14 20:30 编辑
问题导读

1.什么是GPU?
2.GPU的工作原理是什么?
3.什么类型的程序适合在GPU上运行?
4.TensorFlow如何使用GPU跑程序?







我们通常了解CPU,也知道他是干嘛的。那么什么是GPU,或许我们听说过GPU用于深度学习的,但是具体是怎么回事,可能搞不明白,这里系统全面的给大家介绍下。

1.什么是GPU
GPU英文全称Graphic Processing Unit,中文翻译为“图形处理器”。GPU是相对于CPU的一个概念,由于在现代的计算机中(特别是家用系统,游戏的发烧友)图形的处理变得越来越重要,需要一个专门的图形的核心处理器。

我们知道了什么是GPU,那么它长什么样?如下图
2521882_5.jpg

2.GPU的工作原理

  简单说GPU就是能够从硬件上支持T&L(Transform and Lighting,多边形转换与光源处理)的显示芯片,因为T&L是3D渲染中的一个重要部分,其作用是计算多边形的3D位置和处理动态光线效果,也可以称为“几何处理”,提供细致的3D物体和高级的光线特效;只不过大多数PC中,T&L的大部分运算是交由CPU处理的(这就也就是所谓的软件T&L),由于CPU的任务繁多,除了T&L之外,还要做内存管理、输入响应等非3D图形处理工作,因此在实际运算的时候性能会大打折扣,常常出现显卡等待CPU数据的情况,其运算速度远跟不上今天复杂三维游戏的要求。但,新一代支持DX10或以上的显卡,在系统为windows vista或以上的环境中,可以把T&L的所有工作交给GPU完成,大大提高显卡运行的效率。也使得显卡对CPU的依赖最大化的减少。



3.什么类型的程序适合在GPU上运行?  
(1)计算密集型的程序。所谓计算密集型(Compute-intensive)的程序,就是其大部分运行时间花在了寄存器运算上,寄存器的速度和处理器的速度相当,从寄存器读写数据几乎没有延时。可以做一下对比,读内存的延迟大概是几百个时钟周期;读硬盘的速度就不说了,即便是SSD, 也实在是太慢了。  
(2)易于并行的程序。GPU其实是一种SIMD(Single Instruction Multiple Data)架构, 他有成百上千个核,每一个核在同一时间最好能做同样的事情。



4.使用GPU跑程序

在TensorFlow中,支持的设备类型是CPU和GPU。它们被表示为strings。例如:

"/cpu:0":机器的CPU
"/gpu:0"你的机器的GPU,如果你有一个。
"/gpu:1"你的机器的第二个GPU等
如果TensorFlow操作既具有CPU和GPU实现,则在将操作分配给设备时,GPU设备将被赋予优先级。例如, matmul具有CPU和GPU内核。在用设备的系统cpu:0和 gpu:0,gpu:0将选择运行matmul。


记录设备布局

要找出您的操作和张量被分配给哪些设备,请创建log_device_placement配置选项设置为的会话True。

[mw_shl_code=bash,true]
# Creates a graph.

a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a')

b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b')

c = tf.matmul(a, b)

# Creates a session with log_device_placement set to True.

sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))

# Runs the op.

print(sess.run(c))
[/mw_shl_code]
应该看到以下输出:
[mw_shl_code=bash,true]Device mapping:

/job:localhost/replica:0/task:0/gpu:0 -> device: 0, name: Tesla K40c, pci bus

id: 0000:05:00.0

b: /job:localhost/replica:0/task:0/gpu:0

a: /job:localhost/replica:0/task:0/gpu:0

MatMul: /job:localhost/replica:0/task:0/gpu:0

[[ 22.  28.]

[ 49.  64.]] [/mw_shl_code]

手动装置放置
如果您希望特定的操作在您选择的设备上运行,而不是自动选择with tf.device 的设备,则可以使用创建设备上下文,使该上下文中的所有操作具有相同的设备分配。

[mw_shl_code=bash,true]
# Creates a graph.

with tf.device('/cpu:0'):

  a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a')

  b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b')

  c = tf.matmul(a, b)

# Creates a session with log_device_placement set to True.

sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))

# Runs the op.

print(sess.run(c)) [/mw_shl_code]

会看到现在a并被b分配到cpu:0。


[mw_shl_code=bash,true]Device mapping:

/job:localhost/replica:0/task:0/gpu:0 -> device: 0, name: Tesla K40c, pci bus

id: 0000:05:00.0

b: /job:localhost/replica:0/task:0/cpu:0

a: /job:localhost/replica:0/task:0/cpu:0

MatMul: /job:localhost/replica:0/task:0/gpu:0

[[ 22.  28.]

[ 49.  64.]]
[/mw_shl_code]

允许GPU内存增长

默认情况下,TensorFlow将几乎所有GPU的GPU内存映射 CUDA_VISIBLE_DEVICES到该进程的可见内容。这样做可以通过减少内存碎片来更有效地使用设备上相对宝贵的GPU 内存资源

在某些情况下,该过程仅需要分配可用存储器的一个子集,或只是根据该过程需要增加内存使用量。TensorFlow在会话上提供两个配置选项来控制。

第一个是allow_growth选项,它试图根据运行时分配分配只有GPU内存:它开始分配很少的内存,随着Sessions的运行和更多的GPU内存的需要,我们扩展了TensorFlow所需的GPU内存区域处理。请注意,我们不释放内存,因为这可能会导致更糟糕的内存碎片。要打开此选项,请在ConfigProto中将选项设置为:


[mw_shl_code=bash,true]config = tf.ConfigProto()

config.gpu_options.allow_growth = True

session = tf.Session(config=config, ...) [/mw_shl_code]
第二种方法是
per_process_gpu_memory_fraction
选项,它决定了每个可见GPU应分配的总体内存量的分数。例如,您可以告诉TensorFlow仅通过以下方式分配每个GPU的总内存的40%:

[mw_shl_code=bash,true]config = tf.ConfigProto()

config.gpu_options.per_process_gpu_memory_fraction = 0.4

session = tf.Session(config=config, ...)
[/mw_shl_code]
如果要真正限制TensorFlow进程可用的GPU内存量,这是非常有用的。


在多GPU系统上使用单个GPU
如果您的系统中有多个GPU,则默认情况下将选择具有最低ID的GPU。如果您想在不同的GPU上运行,则需要明确指定首选项:

[mw_shl_code=bash,true]# Creates a graph.

with tf.device('/gpu:2'):

  a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a')

  b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b')

  c = tf.matmul(a, b)

# Creates a session with log_device_placement set to True.

sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))

# Runs the op.

print(sess.run(c)) [/mw_shl_code]

如果您指定的设备不存在,您将获得 InvalidArgumentError:

[mw_shl_code=bash,true]InvalidArgumentError: Invalid argument: Cannot assign a device to node 'b':

Could not satisfy explicit device specification '/gpu:2'

   [[Node: b = Const[dtype=DT_FLOAT, value=Tensor<type: float shape: [3,2]

   values: 1 2 3...>, _device="/gpu:2"]()]] [/mw_shl_code]

如果您想TensorFlow自动选择现有的支持机构运行的情况下,指定一个不存在的操作,您可以设置allow_soft_placement以True创建会话时的配置选项。

[mw_shl_code=bash,true]# Creates a graph.

with tf.device('/gpu:2'):

  a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a')

  b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b')

  c = tf.matmul(a, b)

# Creates a session with allow_soft_placement and log_device_placement set

# to True.

sess = tf.Session(config=tf.ConfigProto(

      allow_soft_placement=True, log_device_placement=True))

# Runs the op.

print(sess.run(c))
[/mw_shl_code]

使用多个GPU
如果您想在多个GPU上运行TensorFlow,您可以以多塔方式构建您的模型,其中每个塔分配给不同的GPU。例如:

[mw_shl_code=bash,true]

# Creates a graph.

c = []

for d in ['/gpu:2', '/gpu:3']:

  with tf.device(d):

    a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3])

    b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2])

    c.append(tf.matmul(a, b))

with tf.device('/cpu:0'):

  sum = tf.add_n(c)

# Creates a session with log_device_placement set to True.

sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))

# Runs the op.

print(sess.run(sum)) [/mw_shl_code]

将看到以下输出。

[mw_shl_code=bash,true]Device mapping:

/job:localhost/replica:0/task:0/gpu:0 -> device: 0, name: Tesla K20m, pci bus

id: 0000:02:00.0

/job:localhost/replica:0/task:0/gpu:1 -> device: 1, name: Tesla K20m, pci bus

id: 0000:03:00.0

/job:localhost/replica:0/task:0/gpu:2 -> device: 2, name: Tesla K20m, pci bus

id: 0000:83:00.0

/job:localhost/replica:0/task:0/gpu:3 -> device: 3, name: Tesla K20m, pci bus

id: 0000:84:00.0

Const_3: /job:localhost/replica:0/task:0/gpu:3

Const_2: /job:localhost/replica:0/task:0/gpu:3

MatMul_1: /job:localhost/replica:0/task:0/gpu:3

Const_1: /job:localhost/replica:0/task:0/gpu:2

Const: /job:localhost/replica:0/task:0/gpu:2

MatMul: /job:localhost/replica:0/task:0/gpu:2

AddN: /job:localhost/replica:0/task:0/cpu:0

[[  44.   56.]

[  98.  128.]] [/mw_shl_code]

cifar10教程是一个很好的例子演示了如何做多GPU训练。

参考:
https://blog.csdn.net/u010859707/article/details/73251648

本帖被以下淘专辑推荐:

已有(1)人评论

跳转到指定楼层
jiangzi 发表于 2018-7-7 10:29:59
不错,学习了~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /5 下一条