【31】GPU(下):为什么深度学习需要使用GPU?

【计算机组成原理】学习笔记——总目录

【31】GPU(下):为什么深度学习需要使用GPU?

  • 引言
  • 一、Shader 的诞生和可编程图形处理器【GPU发展历史】
    • 1、可编程管线(Programable Function Pipeline)的引入
    • 2、着色器(Shader)的出现
    • 3、统一着色器架构(Unified Shader Architecture)的出现
  • 二、现代 GPU 的三个核心创意
    • 1、芯片瘦身【减掉多余的电路(应对各种风险的电路)】
    • 2、多核并行 和 SIMT【多个并行的ALU】
    • 3、GPU里的“超线程”【更多的执行上下文】
  • 三、GPU 在深度学习上的性能差异【和CPU比较】
    • 1、实例计算【需要花点时间明确计算的各个值代表什么】
    • 2、对比CPU性能—>结论
  • 四、总结【个人总结的重点】

引言

通过 3dFx 的 Voodoo 或者 NVidia 的 TNT 这样的图形加速卡,CPU 就不需要再去处理一个个像素点的图元处理、栅格化和片段处理这些操作。而 3D 游戏也是从这个时代发展起来的。

下图是“古墓丽影”游戏的多边形建模的变化。这个变化,则是从 1996 年到 2016 年,这 20 年来显卡的进步带来的。
【31】GPU(下):为什么深度学习需要使用GPU?_第1张图片

一、Shader 的诞生和可编程图形处理器【GPU发展历史】

1、可编程管线(Programable Function Pipeline)的引入

  1. 加速卡的出现:顶点处理仍然在CPU完成,所以图形渲染仍然受制于CPU的性能【GPU再好,如果CPU不好,也不行】

  2. 1999年,NVidia推出GeForce 256 显卡,带有顶点处理的功能。但GPU没有可编程能力,程序员需要改加速卡的配置,来实现不同的渲染效果。

  3. GPU需要可编程能力:在整个的渲染管线(Graphics Pipeline)的一些特别步骤,能够自定义处理的算法或操作

2001年的Direct3D 8.0开始,微软第一次引入 可编程管线(Programable Function Pipeline)的概念。
【31】GPU(下):为什么深度学习需要使用GPU?_第2张图片

2、着色器(Shader)的出现

一开始的可编程管线呢,仅限于顶点处理(Vertex Processing)和片段处理(Fragment Processing)部分。比起原来只能通过显卡和 Direct3D 这样的图形接口提供的固定配置,程序员们终于也可以开始在图形效果上开始大显身手了。

这些可以编程的接口,我们称之为 Shader,中文名称就是着色器。之所以叫“着色器”,是因为一开始这些“可编程”的接口,只能修改顶点处理和片段处理部分的程序逻辑。我们用这些接口来做的,也主要是光照、亮度、颜色等等的处理,所以叫着色器。

Vertex Shader和Fragment Shader的指令集虽然一样,但硬件电路是分开的【可减少硬件设计的复杂程度】,会造成浪费【一个在运行时,另一个什么也不干】,GPU成本也更高。

3、统一着色器架构(Unified Shader Architecture)的出现

既然大家用的指令集是一样的,那不如就在 GPU 里面放很多个一样的 Shader 硬件电路,然后通过统一调度,把顶点处理、图元处理、片段处理这些任务,都交给这些 Shader 去处理,让整个 GPU 尽可能地忙起来。这样的设计,就是我们现代 GPU 的设计,就是 统一着色器架构

有意思的是,这样的 GPU 并不是先在 PC 里面出现的,而是来自于一台游戏机,就是微软的 XBox 360。后来,这个架构才被用到 ATI 和 NVidia 的显卡里。这个时候的“着色器”的作用,其实已经和它的名字关系不大了,而是变成了一个通用的抽象计算模块的名字。

【GPU被用来做各种通用计算(深度学习的火热)】

正是因为 Shader 变成一个“通用”的模块,才有了把 GPU 拿来做各种通用计算的用法,也就是 GPGPU(General-Purpose Computing on Graphics Processing Units,通用图形处理器)。而正是因为 GPU 可以拿来做各种通用的计算,才有了过去 10 年深度学习的火热

二、现代 GPU 的三个核心创意

讲完了现代 GPU 的进化史,那么接下来,我们就来看看,为什么现代的 GPU 在图形渲染、深度学习上能那么快。

1、芯片瘦身【减掉多余的电路(应对各种风险的电路)】

【CPU主要用来实现处理乱序执行、进行分支预测,高速缓存部分—>计算功能不会有更大的提升】
我们先来回顾一下,之前花了很多讲仔细讲解的现代 CPU。现代 CPU 里的晶体管变得越来越多,越来越复杂,其实已经不是用来实现“计算”这个核心功能,而是拿来实现处理乱序执行、进行分支预测,以及我们之后要在存储器讲的高速缓存部分

而在 GPU 里,这些电路就显得有点多余了,GPU 的整个处理过程是一个流式处理(Stream Processing)的过程。因为没有那么多分支条件,或者复杂的依赖关系,我们可以把 GPU 里这些对应的电路都可以去掉,做一次小小的瘦身,只留下取指令、指令译码、ALU 以及执行这些计算需要的寄存器和缓存就好了。一般来说,我们会把这些电路抽象成三个部分,就是下面图里的 (1)取指令和指令译码、(2)ALU 和(3)执行上下文
【31】GPU(下):为什么深度学习需要使用GPU?_第3张图片

2、多核并行 和 SIMT【多个并行的ALU】

这样一来,我们的 GPU 电路就比 CPU 简单很多了。于是,我们就可以在一个 GPU 里面,塞很多个这样并行的 GPU 电路来实现计算,就好像 CPU 里面的多核 CPU 一样。和 CPU 不同的是,我们不需要单独去实现什么多线程的计算。因为 GPU 的运算是天然并行的
【31】GPU(下):为什么深度学习需要使用GPU?_第4张图片我们在上一讲里面其实已经看到,无论是对多边形里的顶点进行处理,还是屏幕里面的每一个像素进行处理,每个点的计算都是独立的。所以,简单地添加多核的 GPU,就能做到并行加速。不过光这样加速还是不够,工程师们觉得,性能还有进一步被压榨的空间。

【SIMT(Single Instruction,Multiple Threads)的引入】
我们在第 27 讲里面讲过,CPU 里有一种叫作 SIMD 的处理技术。这个技术是说,在做向量计算的时候,我们要执行的指令是一样的,只是同一个指令的数据有所不同而已。在 GPU 的渲染管线里,这个技术可就大有用处了。

无论是顶点去进行线性变换,还是屏幕上临近像素点的光照和上色,都是在用相同的指令流程进行计算。所以,GPU 就借鉴了 CPU 里面的 SIMD,用了一种叫作SIMT(Single Instruction,Multiple Threads)的技术。SIMT 呢,比 SIMD 更加灵活。在 SIMD 里面,CPU 一次性取出了固定长度的多个数据,放到寄存器里面,用一个指令去执行。而 SIMT,可以把多条数据,交给不同的线程去处理

各个线程里面执行的指令流程是一样的,但是可能根据数据的不同,走到不同的条件分支。这样,相同的代码和相同的流程,可能执行不同的具体的指令。这个线程走到的是 if 的条件分支,另外一个线程走到的就是 else 的条件分支了。

于是,我们的 GPU 设计就可以进一步进化,也就是在取指令和指令译码的阶段,取出的指令可以给到后面多个不同的 ALU 并行进行运算。这样,我们的一个 GPU 的核里,就可以放下更多的 ALU,同时进行更多的并行运算了。
【31】GPU(下):为什么深度学习需要使用GPU?_第5张图片

3、GPU里的“超线程”【更多的执行上下文】

虽然 GPU 里面主要以数值计算为主。不过既然已经是一个“通用计算”的架构了,GPU 里面也避免不了会有 if…else 这样的条件分支。但是,在 GPU 里我们可没有 CPU 这样的分支预测的电路。这些电路在上面“芯片瘦身”的时候,就已经被我们砍掉了。

所以,GPU 里的指令,可能会遇到和 CPU 类似的“流水线停顿”问题。想到流水线停顿,你应该就能记起,我们之前在 CPU 里面讲过超线程技术。在 GPU 上,我们一样可以做类似的事情,也就是遇到停顿的时候,调度一些别的计算任务给当前的 ALU

和超线程一样,既然要调度一个不同的任务过来,我们就需要针对这个任务,提供更多的执行上下文。所以,一个 Core 里面的执行上下文的数量,需要比 ALU 多

三、GPU 在深度学习上的性能差异【和CPU比较】

在通过芯片瘦身、SIMT 以及更多的执行上下文,我们就有了一个更擅长并行进行暴力运算的 GPU。这样的芯片,也正适合我们今天的深度学习的使用场景。

一方面,GPU 是一个可以进行**“通用计算”的框架**,我们可以通过编程,在 GPU 上实现不同的算法
另一方面,现在的深度学习计算,都是超大的向量和矩阵海量的训练样本的计算。整个计算过程中,没有复杂的逻辑和分支,非常适合 GPU 这样并行、计算能力强的架构。

1、实例计算【需要花点时间明确计算的各个值代表什么】

我们去看 NVidia 2080 显卡的技术规格,就可以算出,它到底有多大的计算能力。
【31】GPU(下):为什么深度学习需要使用GPU?_第6张图片

2080 一共有 46 个 SM(Streaming Multiprocessor,流式处理器),这个 SM 相当于 GPU 里面的 GPU Core,所以你可以认为这是一个 46 核的 GPU,有 46 个取指令指令译码的渲染管线。每个 SM 里面有 64 个 Cuda Core。你可以认为,这里的 Cuda Core 就是我们上面说的 ALU 的数量或者 Pixel Shader 的数量,46x64 呢一共就有 2944 个 Shader。然后,还有 184 个 TMU,TMU 就是 Texture Mapping Unit,也就是用来做纹理映射的计算单元,它也可以认为是另一种类型的 Shader
在这里插入图片描述2080 的主频是 1515MHz,如果自动超频(Boost) 的话,可以到 1700MHz。而 NVidia 的显卡,根据硬件架构的设计,每个时钟周期可以执行两条指令【这是如何做到的?。所以,能做的浮点数运算的能力,就是:

(2944 + 184)× 1700 MHz × 2 = 10.06 TFLOPS

【疑问】 我实际计算下来是10.63 TFLOPS:在这里插入图片描述,问题处在哪里?

对照一下官方的技术规格,正好就是 10.07TFLOPS。

2、对比CPU性能—>结论

那么,最新的 Intel i9 9900K 的性能是多少呢?不到 1TFLOPS【如何计算???。而 2080 显卡和 9900K 的价格却是差不多的。

所以,在实际进行深度学习的过程中,用 GPU 所花费的时间,往往能减少一到两个数量级。而大型的深度学习模型计算,往往又是多卡并行,要花上几天乃至几个月。这个时候,用 CPU 显然就不合适了。

今天,随着 GPGPU 的推出,GPU 已经不只是一个图形计算设备,更是一个用来做数值计算的好工具了。同样,也是因为 GPU 的快速发展,带来了过去 10 年深度学习的繁荣

四、总结【个人总结的重点】

  • 一、GPU发展历史

      1. 加速卡(顶点处理仍在CPU完成,图像渲染受制于CPU的性能
      1. 带有顶点处理功能的显卡:NVidia推出GeForce 256 显卡
      1. 可编程管线(Programable Function Pipeline)的引入:2001年的Direct3D 8.0【微软第一次引入】
      1. 开始时的可编程管线:仅限于 顶点处理 和 片段处理。可编程接口称之为Shader,即着色器。此时,硬件电路是分开的,会造成资源浪费【一个运行时,另一个啥也不不干】
      1. 统一着色器架构(Unified Shader Architecture)【现代GPU的设计】出现:Shader硬件电路都统一,图形渲染的任何任务都由GPU统一调度,然后由Shader处理。
    • 【GPU应用到深度学习中】因为 Shader 变成一个“通用”的模块,可用来做各种通用计算,即GPGPU(General-Purpose Computing on Graphics Processing Units,通用图形处理器)。而正是因为 GPU 可以拿来做各种通用的计算,才有了过去 10 年深度学习的火热
  • 二、现代 GPU 的三个核心创意

      1. 芯片瘦身【减掉多余的电路(应对各种风险的电路)】
      1. 多核并行 和 SIMT(Single Instruction,Multiple Threads)【多个并行的ALU】
      1. GPU里的“超线程”【更多的执行上下文】
  • 三、GPU在深度学习上的优势 【必须明白:实例计算的过程】

【计算机组成原理】学习笔记——总目录

你可能感兴趣的:(深度学习,GPU,统一着色器架构,可编程管线,GPGPU)