通用图形处理器设计GPGPU基础与架构(三)

一、前言

        前两篇已经介绍了 GPGPU 的背景 和 GPGPU 的编程模型相关的内容,本文将在 SIMT 计算模型的基础上,介绍 GPGPU 控制核心架构微体系结构的设计。

二、CPU-GPGPU 异构计算系统

       一个由 CPU 和 GPGPU 构成的异构计算平台如下图所示,GPGPU 通过 PCI-E(Peripheral Component Interconnect Express)接口连接到 CPU 上 。CPU 作为控制主体统筹整个系统的运行。 

        一次 kernel 函数的实现步骤如下:

       ① CPU 通过 PCI-E 与 GPGPU  进行通信,将程序中的 kernel 函数加载到 GPGPU 中的 SP 和 SM 上执行;

       ② 在驱动 kernel 函数的进行计算前,需要先将代码、配置和运行数据从硬盘加载到主机端存储器中;

       ③ 接着,由一系列运行和驱动 API 将数据传送到 GPGPU 的设备端存储器中;

       ④ 然后,GPGPU 启动 kernel 函数,通过大算力完成计算。

       ⑤ 最后,CPU 将结果由设备端存储器传送回主机端存储器,等待下一次调用。

        以上是一种 CPU-GPGPU 的异构计算架构。还有一种架构是 CPU 和 GPGPU 两者公用主机端存储器,例如 AMD 的异构系统架构(Heterogeneous System Architecture,HSA),它采用硬件支持的统一寻址,使得 CPU 和 GPGPU 能够直接访问主机端存储器,借助 CPU 与 GPGPU 之间的内部总线作为传输通道,通过动态分配系统的物理存储器资源保证了两者的一致性,提高了两者之间数据通信的效率。

       另有一种高性能变种是使用多个 GPGPU 并行工作。这种形式需要借助特定的互连结构和协议将多个 GPGPU 有效地组织起来。例如 NVIDIA 的 DGX  系统。它通过 NVIDIA 开发的一种总线及通信协议 NVLink,采用点对点结构、串列传输等技术,实现多 GPGPU 之间的高速互连。

三、GPGPU 架构

       不同型号的 GPGPU 产品虽有所差异,但其核心的整体架构存在一定的共性。下图为一个典型的 GPGPU 架构,其核心部分包含了众多可编程多处理器,NVIDIA  称之为流多处理器(Streaming   Multiprocesosr,SM),AMD 称之为计算单元(Compute Unit,CU)。每个 SM 又包含了多个流处理器(Streaming Processor,SP),NVIDIA称之为 CUDA 核心,AMD 称之为PE(Processin  Element),支持整型、浮点和矩阵运算等多种不同类型的计算。

        SM 构成了 GPGPU 核心架构的主体。它们从主机接口的命令队列接收 CPU 发送来的任务,并通过一个全局调度器分派到各个可编程多处理器上执行。SM 通过片上的互连结构与多个存储分区相连实现更高并行度的高带宽访存操作。每个存储分区包含了第二级缓存(L2 cache)和对应的 DRAM 分区。此外,SM 中包含了大量的 SP,如上图右侧所示,SP 由指令驱动,以流水化的方式执行指令,提高指令级并行度。

       面对数以万计的线程,硬件资源仍然有限,因此硬件会对海量的线程进行分批次的处理。 GPGPU 中往往采用线程束( NVIDIA 称为 warp,AMD 称为 wavefront) 的方式创建、管理、调度和执行一个批次的多个线程。当前,一种典型的配置是一个 warp 包含32个线程, 一个  wavefront 包括64个线程。当这些线程具有相同的指令路径时,GPGPU 就可以获得最高的效率和性能。

四、GPGPU 指令流水线

       流水线技术是利用指令级并行,提高处理器 IPC(Instruction Per Cycle)的重要技术之一。不同功能的电路单元组成一条指令处理流水线,利用各个单元同时处理不同指令的不同阶段,可使得多条指令同时在处理器内核中运行,从而提高各单元的利用率指令的平均执行速度。在大多数 GPGPU 架构中,虽然指令的执行粒度变为包含多个线程的线程束,但为了提高指令级并行,仍然会采用流水线的方式提高线程束指令的并行度,与单指令流水线相比,可以想象成水管变得更粗。

       上图显示了一种典型的 GPGPU 架构流水线设计。可以看到,每个线程束按照流水方式执行指令的读取(fetch)解码(decode)发射(issue)执行(execute)写回(writeback)过程。这一过程与标量流水线非常类似,但不同之处在于 GPGPU 的流水线以线程束为粒度执行,各个线程束相互独立。

       接下来将对上图涉及的所有模块进行详解。

4.1 前段:取指与译码

1.取指单元

       取指单元是根据程序计数器(Program Counter,PC)的值,从指令缓存中取出要执行指令的硬件单元。取出来的指令经过译码后会保存在指令缓冲中,等待指令后续的调度、发射和执行。

       在标量流水线中, 一般只需要一个 PC 来记录下一条指令的地址。但由于 GPGPU 中同时存在多个线程束且每个线程束执行的进度可能并不一致,取指单元中就需要保留多个 PC 值,用于记录每个线程束各自的执行进度和需要读取的下一条指令位置。这个数目应该与可编程多处理器中允许的最大线程束数量相同。

2.指令缓存

       指令缓存接收到取指单元的PC, 读取缓存中的指令并发送给译码单元进行解码。指令高速缓存(I-Cache)可以减少直接从设备端存储器中读取指令的次数。本质上指令缓存也是缓存,可以采用传统的组相联结构FIFOLRU(Least Recently Used) 等替换策略来进行设计。取指单元对指令缓存的访问也可能会发生不同的情况:如果命中(cache hit),指令会被传送至译码单元;如果缺失(cache miss),会向下一层存储请求缺失的块,等到缺失块回填指令缓存后(refill),访问缺失的线程束指令会再次访问指令缓存。

3.译码单元

       译码单元对指令缓存中取出的指令进行解码,并且将解码后的指令放入指令缓冲中对应的空余位置上。根据 SASS 指令集的定义和二进制编码规则,译码单元会判断指令的功能、指令所需的源寄存器、目的寄存器和相应类型的执行单元或存储单元等信息,进而给出控制信号,控制 整个线程束流水线的运行。

4. 指令缓冲

       指令缓冲用于暂存解码后的指令,等待发射。考虑到每个 SM 中会有许多线程束在执行,指令缓冲可以采用静态划分的方式来为每个线程束提供专门的指令条目,保留已解码待发射的指令。每个指令条目(entry)一般包含一条解码后的指令和两个标记位,即一个有效位(valid)和一个就绪位(ready)。有效位表示该条指令是有效的已解码未发射指令,而就绪位表示该指令已经就绪可以发射。就绪的指令往往需要通过诸如记分牌(scoreboard)的相关性检查等一系列条件,并且需要有空闲的硬件资源才能得以发射。 

       指令缓冲中的有效位还会反馈给取指单元,表明指令缓冲中是否有空余的指定条目用于取指新的线程束指令。如果有空余条目,应尽快利用取指单元从指令缓存中获得该线程束的后续指令;如果没有空余条目,则需要等待指令缓冲中该线程束的指令被发射出去后条目被清空才能进行指令读取。

4.2 中段:调度与发射

       指令的调度与发射作为指令流水的中段,连接了前段取指和后段执行部分,对流水线的执行效率有着重要的影响。

1. 调度单元

       调度单元通过线程束调度器(warp scheduler)选择指令缓冲中某个线程束的就绪指令发射执行。发射会从寄存器文件中读取源寄存器(source register)传送给执行单元。调度器则很大程度上决定了流水线的执行效率。为了确保指令可以执行,调度单元需要通过各种检查以确保指令就绪并且有空闲执行单元才能发射。这些检查包括没有线程在等待同步栅栏没有数据相关导致的竞争和冒险等

2.记分牌

       记分牌单元(scoreboard)主要是检查指令之间可能存在的相关性依赖,如写后写(Write-After-Write,WAW)写后读(Read-After-Write,RAW),以确保流水化的指令仍然可以正确执行。记分牌算法通过标记目标寄存器的写回状态为“未写回”,确保后续读取该寄存器的指令或再次写入该寄存器的指令不会被发射出来。直到前序指令对该目的寄存器的写回操作完成,该目的寄存器才会被允许读取或写入新的数据。

3.分支单元和 SIMT 堆栈

       对于指令中存在条件分支的情况,例如if…else…语句,它们会破坏 SIMT 的执行方式。 条件分支会根据线程束内每个线程运行时得到的判断结果,对各个线程的执行进行单独控制,这就需要借助分支单元,主要是活跃掩码(active mask) SIMT 堆栈进行管理,解决一个线程束内线程执行不同指令的问题。

4.寄存器文件和操作数收集

       指令执行之前会访问寄存器文件(register file)取源操作数。指令执行完成后还需要写回寄存器文件完成目的寄存器的更新。寄存器文件作为每个可编程多处理器中离执行单元最近的存储层次,需要为该可编程多处理器上所有线程束的线程提供寄存器数值。

       出于电路性能、面积和功耗的考虑,寄存器文件会分 Bank 设计,且每个 Bank 只有少量访问端口(如单端口)的设计方式。对不同 bank 的数据同时读取可以在同周期完成,但是不同请求如果在同一 Bank,就会出现Bank Conflict 而影响流水线性能。

4.3 后段:执行与写回

       作为指令执行的后段,计算单元是对指令执行具体操作的实现,存储访问单元则完成数据加载及存储操作。

1.计算单元

       GPGPU 需要为每个可编程多处理器配备许多相同的流处理器单元来完成一个线程束中多个线程的计算需求,同时还配备了多种不同类型的计算单元,用来支持不同的指令类型,如整型、浮点、特殊函数、矩阵运算等。不同类型的指令从寄存器文件中获得源操作数, 并将各自的结果写回到寄存器文件中。

       作为基本的算术需求,GPGPU 中提供了较为完整的算术逻辑类指令,支持通用处理程序的执行。在 NVIDIA  GPGPU 架构中,流处理器单元体现为 CUDA 核心,它提供了整型运算能力和单精度浮点运算能力。不同的架构会配备不同数量的双精度浮点硬件单元, 以不同的方式对双精度浮点操作进行支持,以满足高性能科学计算的需求。

2.存储访问单元

       存储访问单元负责通用处理程序中 load  store 等指令的处理。由于配备了具有字节寻址能力的 load  store 等指令,GPGPU 可以执行通用处理程序。

       GPGPU 一般会包含多种类型的片上存储空间,如共享存储器、L1 数据缓存、常量缓存和纹理缓存等。存储访问单元实现了对这些存储空间的统一管理, 进而实现对全局存储器的访问。同时针对 GPGPU 的大规模 SIMT 架构特点,存储访问单元还配备了地址生成单元(Address Generation Unit,AGU)、冲突处理(bank conflict)、地址合并、MSHR(Miss Status Handling Registers)等单元来提高存储器访问的带宽并减小开销。当需要访问共享存储器中的数据时,冲突处理单元会处理可能存在的 Bank conflict,并允许在多周期完成数据的读取。对于全局存储器和局部存储器中的数据,load/store 指令会将同一线程束中多个线程产生的请求合并成一个或多个存储块的请求。面对 GPGPU 巨大的线程数量,存储访问单元通过合并单元将零散的请求合并成大块的请求,利用 MSHR 元支持众多未完成的请求,有效地掩盖了对外部存储器的访问延时,提升了访问的效率。

五、总结

       本文介绍了 GPGPU 的经典架构和指令流水线,下一篇将针对影响 GPGPU 性能最大的分支情况介绍解决方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/46725.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源AI智能名片S2B2C商城小程序:重塑营销一体化新生态,引领未来商业潮流!

在互联网时代,尤其是移动互联网的迅猛发展下,顾客的认知与购买行为发生了翻天覆地的变化。曾经,顾客的认知和购买是两个相对独立的过程,不仅时间不同步,空间上也存在明显的分离。但如今,微信、App、电子商务…

MATLAB中Simulink.SimulationData.Dataset用法

目录 语法 说明 示例 访问使用Dataset格式记录的数据 打开模型vdp 使用 Dataset 对象来组合模拟输入信号 Simulink.SimulationData.Dataset的功能是访问已记录的模拟数据或组合模拟输入数据。 语法 ds Simulink.SimulationData.Dataset ds Simulink.SimulationData.Da…

如何在gitee上创建远程仓库?

登录gitee网站后 填写自己的仓库信息后点击创建 然后来到一个新的界面可以看到自己的仓库地址 这样一个空白的仓库就建立好了 也可以按需选择初始化仓库

jmeter-beanshell学习10-字符串补齐位数

每天都遇到新问题,今天又一个场景,一个字符串,如果不足11位,则左边补0,补够11位。 先要获取字符串长度,然后计算差多少位,补齐。今天又发现一个Object类型,这个类型有点厉害&#x…

ARM 虚拟机FVP环境搭建

ARM Fixed Virtual Platforms (FVPs) 是由 ARM 提供的一系列虚拟化硬件模拟器,用于在物理硬件可用之前开发和测试软件。FVP 模型非常适用于软件开发、验证和性能分析,涵盖了从裸机到操作系统和复杂 SoC 系统的各种应用。 这里以Cortex-M55为例&#xff0…

【区块链 + 智慧政务】中国铁塔区块链委托代征开票应用 | FISCO BCOS应用案例

中国铁塔是全球规模最大的通信铁塔基础设施服务提供者。通信塔站址点多面广,业主构成复杂,因此产生海量税务、合同、票据等信息。为进一步提高场租或供电取票的及时性和规范性,严格遵循税务相关的要求,中国铁塔采用国产开源联盟链…

RHCSA —— 第五节 (Linux中执行命令)

目录 一、命令格式 命令 分为两种:内置命令 和 外部命令 选项:指定命令的运行特性,指明要运行命令中的哪一个功能代码。 参数:命令的作用对象,即命令对什么生效。 小技巧 二、ls 命令 (list&#xff0…

惠海H5112A降压恒流芯片IC 60V72V80V100V转24V36V48V多路共阳输出景观LED点光源

H5112A是一款外围电路简单的多功能平均电流型LED恒流驱动器,适用于5-90V电压范围的非隔离式大功率恒流LED驱动领域。芯片采用了平均电流模式控制,输出电流精度在士3%;输出电流对输入输出电压以及电感不敏感;芯片内部集成了环路补偿,外围电路更…

CV09_深度学习模块之间的缝合教学(4)--调参

深度学习就像炼丹。炉子就是模型,火候就是那些参数,材料就是数据集。 1.1 参数有哪些 调参调参,参数到底是哪些参数? 1.网络相关的参数:(1)神经网络网络层 (2)隐藏层…

AIGC笔记--基于Stable Diffusion实现图片的inpainting

1--完整代码 SD_Inpainting 2--简单代码 import PIL import torch import numpy as np from PIL import Image from tqdm import tqdm import torchvision from diffusers import AutoencoderKL, UNet2DConditionModel, DDIMScheduler from transformers import CLIPTextMod…

flutter 手写 TabBar

前言: 这几天在使用 flutter TabBar 的时候 我们的设计给我提了一个需求: 如下 Tabbar 第一个元素 左对齐,试了下TabBar 的配置,无法实现这个需求,他的 配置是针对所有元素的。而且 这个 TabBar 下面的 滑块在移动的时…

4.定时器

原理 时钟源:定时器是内部时钟源(晶振),计数器是外部计时长度:对应TH TL计数器初值寄存器(高八位,低八位)对应的中断触发函数 中断源中断处理函数Timer0Timer0_Routine(void) interrupt 1Timer1Timer1_Routine(void) …

爬虫学习 | 01 Web Scraper的使用

目录 背景介绍: 第一部分:Web Scraper简介 1.什么是Web Scraper: Web Scraper🛒 主要用途: 2.为什么选择Web Scraper: 第二部分:安装Web Scraper ​​​​​1.打开google浏览器&#xf…

object-C 解答算法:合并两个有序数组(leetCode-88)

合并两个有序数组(leetCode-88) 题目如下图:(也可以到leetCode上看完整题目,题号88) 首先搞懂,什么叫“非递减顺序” 非递减顺序,是指一个序列中的元素从前往后(或从左到右)保持不减少或相等。 这意味着序列中的元素可以保持相同的值,但不会…

实战:SpringBoot扩展功能ExitCodeGenerator生成的退出代码

1. 简介 ExitCodeGenerator是 Spring Boot 框架中的一个接口,它允许应用程序退出时生成自定义的退出代码。你可以根据不同的退出码,执行相应的动作,如:资源清理,日志记录等。 我们可以通过实现ExitCodeGenerator接口…

全网最适合入门的面向对象编程教程:17 类和对象的Python实现-鸭子类型与“file-like object“

全网最适合入门的面向对象编程教程:17 类和对象的 Python 实现-鸭子类型与“file-like object“ 摘要: 本文主要介绍了 Python 中创建自定义类时鸭子类型的基本定义、特点和应用场景,同时列举了**“file-like object“** 的例子对鸭子类型进…

axios以post方式提交表单形式数据

某些后端框架请求接口必须走form表单提交的那种形式&#xff0c;但前端很少有<form action"接口地址" method"post"></form>这种写法去提交表单数据&#xff0c;所以前端需要用axios模拟一个表单提交接口。 Content-Type 代表发送端&#xff0…

单链表的介绍和实现

前言 Hello,小伙伴们&#xff0c;你们的作者君又回来了&#xff0c;今天我将带领大家继续学习另一种线性表&#xff1a;单链表&#xff0c; 准备好的小伙伴三连打卡上车&#xff0c;你们的支持就是我更新的动力&#xff0c;一定不要吝啬手中的三连哟&#xff0c;万分感谢&…

ElementUI el-select 组件动态设置disabled后,高度变更的问题解决办法

问题描述 Vue2 项目在使用 el-select 组件时&#xff0c;动态将disabled变更为了 true&#xff0c;元素的高度发生了变化。 问题原因 通过浏览器开发人员工具面板&#xff0c;发现&#xff0c;组件内的 input 元素被动态设置了height的样式&#xff1a; 在项目中检查后并…

深度解析:如何优雅地删除GitHub仓库中的特定commit历史

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…