CPU 处理器结构:冯诺依曼结构
组成部分:
- 一个包含算数逻辑单元和处理寄存器的处理单元
- 一个包含指令寄存器和程序计数器的控制单元
- 内存存储数据和指令
- 额外大存储器
- 输入、输出设备
指令的处理过程,是从内存中读取数据和指令到寄存器中执行该指令,寄存器的读取速度非常快,所以关键的地方是从内存中读取,这是瓶颈所在,称为冯诺依曼瓶颈。
克服冯诺依曼瓶颈的方法有缓存,预取和多线程。
缓存,多级缓存减少从内存中读取数据的时间
预取,预测数据,预先读取
多线程
CPU 的多线程
指令级多线程
- 单处理器的性能 => 指令数/秒 = 指令数/时钟周期 * 时钟周期/秒 成为 ILP值
- 而影响每个周期指令数的因素是是否有指令依赖
- 指令依赖比如:a = b + c d = e + f m = e * f
- 由于第三条指令依赖于第一二条执行结束,所以当前周期不能执行完,需要等待下一个周期执行,这就是影响周期指令数的原因,称为并行障碍
- 指令管线化:是 ILP 的基础,它将一条指令完整的流程分成多个阶段,每个阶段允许一个单独的指令执行
- ILP 对于程序员是透明的,但是了解它对于编写并行程序比较重要
线程级多线程
- 单核处理器或多核处理器中的一个核内部,拥有同时处理多个线程的能力。
- 这些线程共享各种资源,包括计算单元,寄存器,缓存等
- 多线程处理器的多线程,并不是真正的同时执行,而是通过处理器的控制交叉执行
- 时分多线程:
- 块多线程:会一直执行一个线程知道遇到很大的延迟才切换
- 交叉多线程:每一个时钟周期都使用与上一个周期不同的线程
- 同时多线程:可以同时有来自多个线程的指令在执行,采用特殊的处理器,包含不止一个逻辑处理器,同时拥有从多个线程获取指令的能力
处理器级别并行
- 多个处理器,可以同时执行多个线程
- 多处理器架构的通信
- 共享内存:每个处理器拥有自己的缓存,由于硬件托管要同步缓存,会造成极大代价
- 基于网络的消息传递
GPU 并行架构
- 内存模型:程序托管,与CPU的缓存自动同步不同
- 全局内存:GPU 内核函数访问最慢的内存, CPU 与 GPU 进行数据传输使用的内存
- 常量 / 纹理内存:只是全局内存的虚拟地址映射,但可以提供对全局内存的高速缓存,都是只读内存
- 对于数据不太集中或利用率不高的内存访问,尽量不要用常量内存,如果缓存命中失败,会增加访问全局内存的次数
- 纹理内存缓存存储器提供了基于硬件的线性插值功能,为纹理内存提供更高效的处理
- 共享内存:每个 block 都有一个共享内存,内部的局部数据访问全局内存太慢了,所以需要一个共享内存作为高速缓存
- 共享内存被平均分成了相同尺寸的存储体,这些存储体可以被同时使用。比如矩阵运算,一个 block 负责一个矩阵,那么需要对应个数的存储体去计算矩阵中的每一个值
- 寄存器:GPU有数量巨大的寄存器,每个线程有几到几十个寄存器可用,GPU 寄存器并不会像 CPU 一样,它写入寄存器的数据会一直留在寄存器中,直到有新的数据写入或者当前线程执行完毕自动退出,寄存器数据被重置
- GPU内核函数的本地变量会自动写入到寄存器,这些变量不会自动更新到全局内存中,只有计算结束或者需要存储时才写入
- CPU 和 GPU 组成非对等计算环境,CPU 充当宿主程序,负责串行计算,GPU 负责高密度并行特征程序的计算
- 这些在 GPU 上执行的并行计算程序叫做内核函数