Page 37 - 《软件学报》2020年第9期
P. 37

2658                                 Journal of Software  软件学报 Vol.31, No.9,  September 2020

         度.LSTM 是一种特殊的 RNN,用来解决 RNN 存在的长期依赖问题,即相关信息与预测位置的间隔很大而导致
         RNN 无法学习连接信息.LSTM 的隐藏层比传统 RNN 复杂,是一种拥有 3 种“门”的特殊网络结构,从而更有效地
         保存长期记忆.其中:“遗忘门”的作用是让循环神经网络“忘记”之前没有用的信息,“输入门”决定哪些部分记忆
         进入当前时刻的状态,“输出门”决定当前时刻的输出.
             当前主流的 DNN 开发及运行框架包括 TensorFlow(Google)           [31] ,PyTorch(Facebook) [32] ,Caffe(Berkeley 大
         学) [33] ,其他 DNN 框架如 Theano(Montreal 大学),Keras(Keras-Team),MXNet(Amazon),CNTK(Microsoft)的用户基
         础远比不上前 3 种.DNN 框架的运行原理(以 TensorFlow 为例           [34] ):首先,将用户基于应用层 API 编写的、以神经
         网络算法为代表训练或推理过程表达为数据流图计算;在运行时,把数据流图转换成 C++核心层的细粒度、抽
         象化运行时状态,进而在计算设备(CPU 或 GPU)上以一致而有效的方式调度执行.主流的 DNN 框架能够支持在
         个人电脑、大型数据中心的服务器、嵌入式设备等多种平台上运行.
         1.3   嵌入式GPU
             图像处理器(graphics processing unit,简称 GPU)最初是计算机系统中加速图形图像运算的专用芯片,如今
         的 GPU 因集成了大量的处理器核心,具有了非常强大的并行处理能力,并且已经被广泛应用于通用计算领域,
         例如游戏开发、图像处理、视频处理、科学计算、大数据、深度学习等领域.当前,国际主流的 GPU 厂商主要
         有通用计算领域的 NVIDIA,AMD(ATI),Intel(CPU 内置显示核心)以及移动计算领域的 ARM,Qualcomm,
         PowerVR 等.本节选择最为广泛的 NVIDIA GPU 系列,先介绍普通 PC 平台 GPU,了解 GPU 的一般架构和工作
         原理.在此基础上,再介绍嵌入式 GPU 的架构和工作特点.
             PC 平台的 GPU 计算卡一般通过高速的 PCI-E(peripheral communications interconnect express)总线与主板
         上的北桥芯片相连.PCI-E 是连接 GPU 卡与 CPU 的全双工高速总线.PCI-E 2.0 的传输速率为 5GB/s,PCI-E 3.0
         提升到了 8GB/s.PCI-E 总线能够为每块 GPU 卡提供确定的读写带宽,而不受所挂载的 GPU 卡数量的影响.图 2
         显示了一块 NVIDIA GPU 芯片的架构模块示意图,包括 3 种关键模块                 [35] :流处理器簇(streaming multiprocessor,
         简称 SM)、流处理器(streaming processor,简称 SP)、(全局、常量、共享)内存.“流”是一个 GPU 操作队列,该队
         列中的操作(可能由多个主机线程发出)将以添加到流中的先后顺序而依次执行.可以将一个流看作是 GPU 上
         的一个任务,不同流里的任务可以并行执行.所以一个流对应于并发的概念,多个流对应并行的概念.GPU 是由
         多个 SM 组成的 SM 阵列,每个 SM 包含 8N 个 SP(SP 也称 CUDA(compute unified device  architecture)
         核,G80/GT200 中有 8 个 SP,RTX2080 中有 64 个 SP),每个 SP 都是一个设计简单的处理器.全局内存(global
         memory)就是 GPU 卡的显存.纹理内存(texture memory)和常量内存(constant memory)都是针对全局内存的一个
         特殊视图.其中,纹理内存是在显示 2D 或 3D 图像时存储插值计算所需要的数据,常量内存用于存储只读数据.
         每个 SM 通过总线可以独立访问 3 种内存.每个 SM 内部都有共享内存(shared memory).与 CPU 不同,它没有自
         动完成数据替换的硬件逻辑,而是完全由程序员控制,所以它是一种程序可控的高速缓存.
             主流的 GPU 通用编程接口包括 NVIDIA 公司开发的 CUDA 运算平台、苹果公司持有但是保持开放的
         OpenCL(open computing language)标准、微软公司开发的 Direct(direct compute)标准.CUDA [36] 是 C 语言的一种
         扩展,支持基于 PTX(parallel thread execution)虚拟指令集的运行时编译,即 CUDA 代码先被编译成并行线程执
         行(parallel thread execution,简称 PTX)这种中间形式,然后再次编译为原生的 GPU 微码;并且向前兼容(forwards
         compatibility),即无论 GPU 的硬件结构如何改变,为早期 CUDA 设备编写的程序依然能够运行在最新的 CUDA
         设备上.CUDA 编程模型是一种异构模型.CUDA 程序可以在 CPU 和 GPU 上并行运行,在 CPU 上运行的代码段
         叫 Host code,在 GPU 上运行的代码段叫 Device code,其中包含若干 kernel 函数.每一个 kernel 在 GPU 上执行时
         会启动很多线程运行同样的代码指令,即单指令多线程(single-instruction multiple-thread,简称 SIMT)的并行计
         算模型.Kernel 线程的数量取决于程序员为 kernel 函数指定的参数 num_blocks(线程块数)和 num_threads(每个
         线程块内执行 kernel 函数的线程数).这两个参数的配置会影响 kernel 函数的执行性能.每个 SM 最多能处理的
         线程数是有上界,也就间接影响每个 SM 最多能容纳的线程块(thread block)的数量.另外,每 32 个线程组成一个
         线程束(wrap),线程束是 GPU 调度和执行的基本单元.一个线程块所管理的线程束等于 num_threads 除以 32 并
   32   33   34   35   36   37   38   39   40   41   42