01
异构计算的兴起
从英特尔 1971 年开发出第一个商用处理器 Intel 4004 开始, 微处理器所带来的计算机和互联网革命开始改变着我们的世界. 同时, 英特尔创始人之一的戈登. 摩尔提出了一个广为流传的摩尔定律: 每 24 个月会将芯片的性能提高一倍 .
随着互联网的爆炸式发展和信息化的普及, 尤其近几年机器学习, 深度学习, 无人驾驶, 气象预测, 工业仿真等领域的快速发展和崛起. 通用 CPU 在处理海量计算, 海量数据时暴露出越来越多的 性能瓶颈 :
●并行度低
●带宽小
●时延高
面对越来越多的多元化的计算需求, 越来越多的场景开始引入诸如 GPU,FPGA 等硬件进行加速, 异构计算开始兴起.
所谓 异构计算 (Heterogeneous Computing) , 主要指不同类型的指令集和体系架构的计算单元组成一个混合的系统执行计算的特殊方式.
特别在人工智能领域, 目前以 CPU + GPU 为代表的异构计算已成为加速 AI 创新的新一代计算架构.
0 2
GPU 的加速原理
从上述图片中可以看出, CPU 的摩尔定律基本失效. 当前工艺水平已不断接近物理极限, 发展步履维艰, 提升主频已难以维持. 只能从多核考虑, 而 CPU 的多核也因为大量的 cache 及控制器占据了大部分的芯片面积, 也难以再延续摩尔定律.
高并行, 高带宽的异构计算 成为必然的选择 . 作为当前高并行计算的通用方案, GPU 正以超摩尔的速度在快速迭代.
本文主要从以下两个方面对其加速原理做一些浅显概述, 抛砖引玉:
2.1 硬件架构
●数以千计的计算核心
● 高带宽
GPU 一推出就包含了比 CPU 更多的处理单元, 更大的带宽; 当前 CPU 最多也只有几十个核, 但即使是普通级别的 GPU 就包含了成百上千个处理单元, 高端的甚至更多, 这对于大量重复处理过程有着天生的优势. 下图展示了 CPU 和 GPU 架构的对比:
看的出: GPU 与 CPU 在内部设计上也有许多相似处, 都有控制器, 计算单元 (ALU),Cache. 同时, 在结构上也有着很明显的差异.
CPU 为了适应更复杂的环境和降低访问延迟, 大部分面积都给了控制器和寄存器.
与之相比, GPU 拥有更多的 ALU 用于数据处理, 而非数据高速缓存和流控制, 这样的结构适合密集型数据的并行处理, 即在一个时刻可以并行处理多个数据; 这里引用一张网上针对 GPU 与 CPU 的计算能力对比 测试结果:
可以看出, 尽管是用的 GForce 的游戏级显卡, 单精度与双精度的计算能力仍然远高出 CPU 的处理能力.
硬件结构上的差异, 直接反馈到计算性能上的不同. 从上图中可以反应出 GPU 的计算性能的巨大差距.
当然, 上面的图只是方便对比 CPU 与 GPU 在架构上的异同, 我们看一下当前 Nvidia 最强算力的 V100 硬件架构图感受一下:
Volta v100 架构
可以看出, 满屏都是密集的计算单元.
Nvidia 为其堆了 84 个 SM (流多处理器) ,5376 个 FP32 核心, 5376 个 INT32 核心, 2688 个 FP64 核心, 672 个 Tensor 核心, 336 个纹理单元, 6144KB 的 L2 缓存...
这其中的每一个核心, 其实就相当于一个简化版的 CPU,GPU 通过数以千计的计算核心来隐藏数据的访问延迟.
当然, 影响性能的不仅只是计算核心的多少, 内存架构也是一个不可忽视的因素, 其内存模型如下:
与 CPU 类似, GPU 为了提升带宽, 也设计了多层级的临近缓存结构, 如: 寄存器, 共享内存, L1 缓存, L2 缓存, 纹理内存, 常量内存, 全局显存, 其存取速度从寄存器到全局显存依次递减:
程序设计时, 合理使用上述内存, 可以有效提升 GPU 的利用率和吞吐率.
2.2 并行计算引擎
为充分利用 GPU 的计算核心, Nvidia 同时还推出了基于 C 扩展的通用并行计算架构 --CUDA, 利用 CUDA 技术, 可以将那些 GPU 内的处理核心调度起来, 成为线程处理器去解决数据的密集计算.
该架构极大的降低了开发人员操作 GPU 的开发门槛, 方便解决一些复杂的计算问题, 其编程模型如下:
CUDA 编程模型是基于 C 的扩展, 所以上手相对比较容易, Nvidia 同时也提供了比较丰富的 API 和基础的运行库, 方便开发和复用.
当然如果需要自己写核函数, 还是需要系统的进行学习, CUDA 开发容易, 写好较难, 需要对其硬件及软件架构都比较了解, 才能设计出一个高效的高并发程序.
对于并行计算引擎, 主要有以下三个层面的并行:
● 基于网格的流并行;
● 基于线程块不需要通信的粗粒度并行 ;
● 基于块内线程可以通信的细粒度并行 .
在具体介绍前, 先了解一下 GPU 的线程模型:
其线程组织与硬件的对应关系大致如下:
2.2.1 流并行
GPU 中的流并行可以理解为 CPU 上的任务并行, 即每个流都可以看作是一个独立的任务.
每个流中的代码执行顺序类似于 CPU 上的队列, 严格按照操作加入顺序执行. 只要 GPU 支持设备重叠功能, 则 GPU 在执行一个核函数的同时, 可以同时在设备与主机之间执行复制操作.
将操作放入流的队列时应采用宽度优先方式而非深度优先, 即多个流交叉添加, 这样我们就可以隐藏掉数据在主机和设备端的数据传输时间, 从而提升 GPU 的利用率.
2.2.2 块并行
块并行可以类似理解为 CPU 的多进程模型. 在执行时, GPU 的任务分配单元将网格分配到 GPU,GPU 根据启动配置信息将块分配到 SM 上.
任务分配单元使用轮询策略: 轮询查看 SM 是否还有足够的资源来执行新的块, 如果有则给 SM 分配一个新的块, 如果没有则查看下一个 SM.
决定能否分配的因素有: 每个块使用的共享存储器大小, 寄存器大小, 以及其它的一些限制条件; 所以程序员可以通过调整块内线程数, 每个线程使用的寄存器和共享存储器来进行隐式的块分配控制, 不同块之间的执行没有顺序, 完全并行.
2.2.3 线程并行
线程并行我们应该比较熟悉. 在 CUDA 中, warp 是 SM 执行的最小单位, 由 SM 以连续的方式自动进行分组, 所以对程序员来说是透明的, 同一个 warp 里的 thread, 加载不同的数据, 执行相同的指令, 即单指令多线程模型, 它的大小可能会随着硬件的发展而变化. 当前每个 warp 由 32 个线程组成, 同一个 warp 是严格串行的, 因此在 warp 内是无须同步的.
在一个 SM 中可能同时有来自不同块的 warp. 当一个块中的 warp 在进行访存或者同步等高延迟操作时, 另一个 warp 可以占用 SM 中的计算资源. 这样在 SM 内就实现了简单的乱序执行.
当 GPU 资源比较充足时, 所有的线程束都能并发执行. 理论上, 一个 SM 里的 thread 越 多, 越能隐藏 latency, 但同时, 也会让每个 thread 能使用的资源更少. 因此, 在写代码或优化时要做一些取舍和均衡.
03
总结
随着大数据, 人工智能等计算产业的演进, 以及 5G 的普及, 物联网等新技术的推动, 面对数据的爆炸式增长, 对算力增长的长期需求将会不断催生更多的异构计算单元, 计算多元化的趋势将会获得更加广泛的发展空间, 如 CPU+FPGA,CPU+ASIC, 或者 AMD 已融合了 CPU+GPU 的 APU 等异构架构, 大数据和 AI 唤醒了异构计算的兴起, 异构计算的发展会促进更多行业的发展和变革.
投稿 | 机器学习平台
编辑 | sea
排版 | sea
往期推荐
在看点一下 大家都知道
来源: http://www.tuicool.com/articles/bMjYNvY