4.1 一级存储结构

news2025/1/18 4:42:40

本节介绍 GPU 上的一级缓存结构,重点介绍统一的 L1 数据缓存和暂存器“共享内存”,以及它们如何与计算核心交互。 我们还简要讨论了 L1 纹理缓存的典型微架构。 我们包括对纹理缓存的讨论,虽然它在 GPU 计算应用程序中的使用有限,但是它提供了一些关于 GPU 与 CPU 有何不同的见解和直觉。 最近的一项专利描述了如何统一纹理缓存和 L1 数据(例如,在 NVIDIA 的 Maxwell 和 Pascal GPU 中发现)[Heinrich et al., 2017]。 我们推迟对这种设计的讨论,直到首先考虑纹理缓存的组织方式。 GPU 中一级内存结构的一个有趣方面是它们在遇到危险时如何与核心流水线交互。 如第 3 章所述,流水线冲突可以通过重放指令来处理。 我们扩展了本章前面关于重放的讨论,重点放在内存系统中的危害上。

4.1.1 暂存器内存和一级数据缓存

在 CUDA 编程模型中,“共享内存(shared memory)”是指一个相对较小的内存空间,预期具有低延迟,但给定 CTA 中的所有线程都可以访问它。 在其他架构中,这样的内存空间有时被称为暂存器内存 [Hofstee, 2005]。 访问此内存空间的延迟通常与寄存器文件访问延迟相当。 事实上,早期的 NVIDIA 专利将 CUDA“共享内存”称为全局寄存器文件 [Acocella 和 Goudy,2010]。 在 OpenCL 中,此内存空间称为“本地内存(local memory)”。 从程序员的角度来看,在超出其有限容量的情况下使用共享内存时要考虑的一个关键方面是bank冲突的可能性。 共享存储器作为静态随机存取存储器 (SRAM) 实现,并且在一些专利 [Minkin et al., 2012] 中被描述为每通道一个bank,每个bank具有一个读端口和一个写端口。 每个线程都可以访问所有bank。 当多个线程在给定周期访问同一个bank并且线程希望访问该bank中的不同位置时,就会出现bank冲突。 在详细考虑如何实现共享内存之前,我们首先看一下 L1 数据缓存。

L1 数据高速缓存在高速缓存中维护了全局内存地址空间的一个子集。 在某些架构中,L1 缓存仅包含未被内核修改的位置,这有助于避免因 GPU 缓存不一致性而导致的复杂情况。 从程序员的角度来看,访问全局内存时的一个关键考虑因素是给定 warp 中不同线程访问的内存位置之间的相互关系。 如果 warp 中的所有线程都访问位于单个 L1 数据缓存块中的位置,并且该块不存在于缓存中,则只需将单个请求发送到较低级别的缓存。 这种访问被称为“合并(coalesced)”。 如果 warp 中的线程访问不同的缓存块,则需要生成多个内存访问。 此类访问被称为未合并。 程序员试图避免bank冲突和未合并的访问,但为了简化编程,硬件允许这两种访问。

 

图 4.1 展示了 Minkin 等人所描述的 GPU 缓存结构。 [2012]。 图中的设计实现了统一的共享内存和 L1 数据缓存,这是 NVIDIA 的 Fermi 架构中引入的功能,也存在于 Kepler 架构中。 该图的中心是一个 SRAM 数据阵列 5,它可以被配置 [Minkin et al., 2013] 为部分用于共享内存的直接映射访问,部分作为一种组相联缓存。 该设计通过在处理bank冲突和 L1 数据高速缓存未命中时使用replay机制来支持与指令流水线的非停顿接口。 为了帮助解释这种缓存架构的操作,我们首先考虑如何处理共享内存访问,然后考虑合并的缓存命中,最后考虑缓存未命中和未合并的访问。 对于所有情况,存储器访问请求首先从指令流水线内的加载/存储单元发送到L1高速缓存1。 内存访问请求由一组内存地址组成,每一个对应于 warp 中的每个线程。

共享内存访问操作

对于共享内存访问,仲裁器确定 warp 中请求的地址是否会导致bank冲突。 如果请求的地址会导致一个或多个bank冲突,则仲裁器将请求分成两部分。 第一部分包括 warp 中没有 bank 冲突的线程子集的地址。 原始请求的这一部分被仲裁器接受,供缓存进一步处理。 第二部分包含那些与第一部分中的地址发生bank冲突的地址。 这部分原始请求返回到指令流水线,必须重新执行。 这种后续执行称为“重放(replay)”。 在存储原始共享内存请求的重放部分的位置上存在折衷。 虽然可以通过从指令缓冲区重放内存访问指令来节省空间,但这会在访问大型寄存器文件时消耗能量。 在能源效率上一个更好的替代方案可能是为LSU中的内存访问指令重放提供有限的缓冲,并避免在缓冲区中的可用空间即将用完时从指令缓冲区调度内存访问操作。 在考虑重放请求会发生什么之前,让我们考虑一下内存请求的已接受部分是如何处理的。

由于共享内存是直接映射的,共享内存请求的接受部分绕过标签单元(tag unit)3内的标签查找。 当接受共享内存加载请求时,仲裁器会安排一个到指令流水线内的寄存器文件的回写事件,因为在没有bank冲突的情况下,直接映射内存查找的延迟是恒定的。 tag单元确定每个线程的请求映射到哪个bank,以便控制地址交叉开关(crossbar)4,crossbar将地址分配给数据阵列内的各个bank。 数据阵列 5 内的每个bank都是 32 bit宽,并且具有自己的解码器,允许独立访问每个bank中的不同行。 数据通过数据交叉开关 6 返回到适当线程的通道以存储在寄存器文件中。 只有与 warp 中活跃线程对应的通道才会将值写入寄存器文件。

假设共享内存查找延迟是一个时钟周期,共享内存请求的重放部分可以在前一个接受部分之后的周期访问 L1 缓存仲裁器。 如果这个重放部分又遇到bank冲突,它会进一步细分为接受和重放部分。

高速缓存读取操作

接下来,让我们考虑如何处理对全局内存空间的加载。 由于只有全局内存空间的一个子集缓存在 L1 中,tag单元将需要检查数据是否存在于缓存中。 虽然数据阵列是高度bank化设计的,以允许通过单个 warp 灵活访问共享内存,但每个周期对全局内存的访问仅限于单个缓存块。 此限制有助于减少相对于缓存数据量的tag存储开销,这也是标准 DRAM 芯片的标准接口的结果。 在 Fermi 和 Kepler 架构中,L1 缓存块大小为 128 字节,在 Maxwell 和 Pascal 架构[NVIDIA Corp.] 中进一步分为四个 32 字节段 [Liptay,1968]。 32 字节的段大小对应于可以在单次访问中从最近的图形 DRAM 芯片(例如 GDDR5)中读取的最小数据大小。 每个 128 字节的高速缓存块由 32 个bank中同一行的 32 bit 组成。

加载/存储单元 1 计算内存地址并应用合并规则将 warp 的内存访问分解为单独的合并访问,然后将这些访问馈送到仲裁器 2 。 如果没有足够的资源可用,仲裁器可能会拒绝请求。 例如,如果访问映射到的高速缓存集中的所有路都忙,或者在待处理请求表7中没有空闲条目,这将在下面描述。 假设有足够的资源可用于处理未命中,对于一次缓存命中,仲裁器请求指令流水线在固定周期数之后安排一次到寄存器文件的回写。 同时,仲裁器还请求tag单元 3 检查访问实际上命中或未命中。 在高速缓存命中的情况下,访问数据阵列5所有bank中的适当行并且将数据返回6到指令流水线中的寄存器文件。 与共享内存访问的情况一样,仅更新与活动线程对应的寄存器通道。

当访问tag单元时,如果确定请求触发缓存未命中,仲裁器通知LSU它必须重放请求并且并行地将请求信息发送到待处理请求表(pending request table) 7 。 待处理请求表提供的功能与 CPU 高速缓存系统中传统的未命中状态保持寄存器 [Kroft, 1981] 所支持的功能是一样的。 NVIDIA 专利 [Minkin et al., 2012, Nyland et al., 2011] 中描述了至少两个版本的待处理请求表。 与图 4.1 中所示的 L1 缓存架构相关的版本看起来有点类似于传统的 MSHR。 用于数据高速缓存的传统 MSHR 包含高速缓存未命中的块地址以及有关块偏移量的信息以及在将块填充到高速缓存中时需要写入的相关寄存器。 通过记录多个块偏移量和寄存器来支持对同一块的多次未命中。 图 4.1 中的 PRT 支持将两个请求合并到同一个块,并记录必要的信息来通知指令流水线重放哪个延迟内存访问。

图 4.1 中所示的 L1 数据缓存是虚拟索引和虚拟标记的。 与现代 CPU 微架构主要采用虚拟索引/物理标记的 L1 数据缓存相比,这可能令人惊讶。 CPU 使用此结构来避免在上下文切换时刷新 L1 数据缓存的开销 [Hennessy 和 Patterson,2011]。 虽然 GPU 在 warp 发出的每个周期都有效地执行上下文切换,但 warp 是同一应用程序的一部分。 基于页的虚拟内存在 GPU 中仍然具有优势,即使它只能一次运行单个操作系统应用程序,因为它有助于简化内存分配并减少内存碎片。 在 PRT 中分配了一个条目之后,内存请求被转发到内存管理单元 (MMU) 8,用于虚拟地址到物理地址的转换,并从那里通过交叉互连到适当的内存分区单元。 正如将在第 4.3 节中扩展的那样,内存分区单元包含一组 L2 缓存以及一个内存访问调度器。 除了有关要访问哪个物理内存地址和要读取多少字节的信息外,内存请求还包含一个“subid”,可用于在内存请求返回到内核时查找 PRT 中包含有关请求信息的条目。

一旦存储器加载请求响应返回到核心,它就被MMU传递到填充单元9。 填充单元依次使用内存请求中的 subid 字段在 PRT 中查找有关请求的信息。 这包括可以由填充单元通过仲裁器 2 传递给LSU以重新安排加载的信息,然后通过在将行放入数据数组后锁定缓存中的行来保证加载缓存命中 5.

缓存写入操作

图 4.1 中的 L1 数据缓存可以支持写穿和回写策略。 因此,可以通过多种方式处理对全局内存的存储指令(写入)。 写入的具体内存空间决定了此次写入是被视为写穿还是写回。 许多 GPGPU 应用程序中对全局内存的访问预计具有非常差的时间局部性,因为通常内核的编写方式是线程在退出前将数据写入大型数组。 对于此类访问,不分配写入策略的写穿 [Hennessy 和 Patterson,2011] 可能比较好。 相比之下,寄存器溢出到堆栈的本地内存写入可能会显示出良好的时间局部性,随后的加载说明使用写分配策略进行写回 [Hennessy and Patterson, 2011]比较好。

不管写入共享内存还是全局内存,数据首先放置在写入数据缓冲区(WDB)10中。 对于未合并的访问或当某些线程被屏蔽时,只有缓存块的一部分被写入。 如果该块存在于高速缓存中,则可以通过数据交叉开关6将数据写入数据阵列。 如果缓存中不存在数据,则必须首先从 L2 缓存或 DRAM 内存中读取数据块。 如果使缓存中任何陈旧数据的标签无效,则完全填充缓存块的合并写入可能会绕过缓存。

请注意,图 4.1 中描述的缓存结构不支持缓存一致性。 例如,假设在 SM 1 上执行的线程读取内存位置 A 并且该值存储在 SM 1 的 L1 数据缓存中,然后在 SM 2 上执行的另一个线程写入内存位置 A。如果 在内存位置A从 SM 1 的 L1 数据缓存中被驱逐之前 ,SM 1 上的任何线程读取内存位置 A ,它将获得旧值而不是新值。 为避免此问题,从 Kepler 开始的 NVIDIA GPU 仅允许对寄存器溢出和堆栈数据的本地内存访问或将只读全局内存数据放置在 L1 数据缓存中。 最近的研究探讨了如何在 GPU 上启用一致的 L1 数据缓存 [Ren 和 Lis,2017 年,Singh 等人,2013 年] 以及对明确定义的 GPU 内存一致性模型的需求 [Alglave 等人,2015 年]。

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

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

相关文章

前端GC垃圾回收机制

js中的管理是自动的,对象不再被引用时就是垃圾,不能从根上访问时也是垃圾。 能够访问到的对象就是可达对象(引用,作用域链),可达的标准就是从根触发是否能够被找到,根可以理解为是全局变量。 …

【机器学习】 - 作业7: 某闯关类手游用户流失预测

课程链接: 清华大学驭风计划 代码仓库:Victor94-king/MachineLearning: MachineLearning basic introduction (github.com) 驭风计划是由清华大学老师教授的,其分为四门课,包括: 机器学习(张敏教授) , 深度学习(胡晓林教授), 计算…

并发和线程

并行和并发 1.并行跟并发有什么区别? 从操作系统的角度来看,线程是CPU分配的最小单位。 并行就是同一时刻,两个线程都在执行。这就要求有两个CPU去分别执行两个线程。 并发就是同一时刻,只有一个执行,但是一个时间段…

详解HTTPS加密过程

目录 前言 HTTPS是什么 HTTPS的工作过程 引入对称加密 引入非对称加密 引入证书 总结 前言 对于HTTP上篇文章已经做了详细的解释了。众所周知,HTTPS要比HTTP要安全,但是为什么HTTPS要比HTTP安全呢? 这篇文章主要研究HTTPS的加密机制…

操作系统-X18 linux日志审计

Linux日志审计 在unix/类unix(Linux)系统中,日志是内核(内存)的一部分。 用于记录系统、程序运行中发生的各种事件 通过阅读日志,有助于诊断和解决系统故障 日志文件的分类 ①内核及系统日志 由系统sysl…

队列及其实现

目录 一&#xff1a;队列 1.队列的概念及结构 2.队列的实现 <1>.初始化队列 <2>.队尾入队列 <3>.队头出队列 <4>.获取队列头部元素 <5>.获取队列队尾元素 <6>.获取队列中有效元素个数 <7>.销毁队列 二&#xff1a;完整代…

如何完全卸载IDEA

工欲善其事必先利其器&#xff0c;我们在用idea的时候&#xff0c;idea的环境出现了莫名其妙的问题&#xff0c;怎么也找不到问题原因。有时候也可能是安装了不知名VB脚本&#xff0c;给系统装了一大堆的环境变量(如下图所示)&#xff0c;这个时候你可以试着把idea卸载重新安装…

Jetpack Compose UI预览

Android开发 Jetpack_Compose_2 UI预览Preview 前言 在学习jetpack compose如何编写ui之前&#xff0c;我认为还是应该先了解与Android studio配合的UI预览Preview。 这样就可以立刻看到UI效果&#xff0c;从而方便后续学习验证代码。 所需依赖 implementation "androidx…

CAPL(vTESTStudio) - 自动创建带有时间戳的报告和log

目录 getLocalTime - 获取本地时间函数 代码示例 获取当前时间并形成格式:"2023_05_22_23_20_18"

Qt中的坐标系

Qt中的坐标系 Qt中的坐标系与win10上画图工具的联系 上面这个图片的水印挡住了重要信息,然后又截了一张,显然,画图工具的像素就是Qt中的坐标系,所以,以后查坐标系直接打开Qt:画笔位置所显示的像素就是Qt的坐标!!! 再总结一下: 好奇:win10上的画图工具是qt写的吗? 答: 不是…

【SpringCloud】Nacos

文章目录 一、Nacos1、安装2、服务注册和发现3、服务分级存储模型4、负载均衡策略--NacosRule5、服务实例的权重设置 一、Nacos 1、安装 官网&#xff1a;https://nacos.io/zh-cn/ 下载 Github主页: https://github.com/alibaba/nacos Github的Release下载页: https://githu…

linux命令行如何查看命令帮助信息

一&#xff0c;简介 “授之以鱼不如授之以渔”&#xff0c;我们再学习linux命令的时候&#xff0c;想查看某个命令的详细说明&#xff0c;有哪些方法呢&#xff1f;本文来介绍一下如何在命令行查找命令的帮助信息。 二&#xff0c;linux命令格式介绍 Linux命令一般由三部分组…

【深度学习】- 作业1: Softmax实现手写数字识别

课程链接: 清华大学驭风计划 代码仓库&#xff1a;Victor94-king/MachineLearning: MachineLearning basic introduction (github.com) 驭风计划是由清华大学老师教授的&#xff0c;其分为四门课&#xff0c;包括: 机器学习(张敏教授) &#xff0c; 深度学习(胡晓林教授), 计算…

【深度学习】 - 作业7: 图像超分辨率重建

课程链接: 清华大学驭风计划 代码仓库&#xff1a;Victor94-king/MachineLearning: MachineLearning basic introduction (github.com) 驭风计划是由清华大学老师教授的&#xff0c;其分为四门课&#xff0c;包括: 机器学习(张敏教授) &#xff0c; 深度学习(胡晓林教授), 计算…

Linux网络编程—Day10

Linux服务器程序规范 Linux服务器程序一般以后台进程形式运行。后台进程又称守护进程。它没有控制终端&#xff0c;因而也不会意外接收到用户输入。 守护进程的父进程通常是init进程&#xff08;PID为1的进程&#xff09;&#xff1b;Linux服务器程序通常有一套日志系统&#…

Android 11.0 系统设置显示主菜单添加屏幕旋转菜单实现旋转屏幕功能

1.前言 在android11.0的系统rom定制化开发中,在对系统设置进行定制开发中,有产品需求要求增加 旋转屏幕功能的菜单,就是在点击旋转屏幕菜单后弹窗显示旋转0度,旋转 90度,旋转180度, 旋转270度针对不同分辨率的无重力感应的大屏设备的屏幕旋转功能的实现, 接下来就来分析…

chatgpt赋能Python-python_dill

Python dill - 更高效&#xff0c;更强大的对象序列化工具 在Python编程中&#xff0c;对象序列化是一个非常常见的操作&#xff0c;它将Python对象转换为可以存储或传输的格式。Python默认提供了pickle模块来实现序列化&#xff0c;但是pickle存在一些限制&#xff0c;比如无…

usb摄像头驱动-core层usb设备的注册

usb摄像头驱动-core层driver.c 文章目录 usb摄像头驱动-core层driver.cusb_bus_typeusb_device_matchusb_uevent usb_register_driver 在ubuntu中接入罗技c920摄像头打印的信息如下&#xff1a; 在内核中&#xff0c;/driver/usb/core/driver.c 文件扮演了 USB 核心驱动程序管…

复现ms17-010漏洞

复现ms17-010 复现条件环境操作效果 让我们来看看“hkl”在干嘛 复现 条件 1.靶机必须为win8以下。 2.靶机必须同攻击机处于相同网段&#xff08;即倒数第二位相同&#xff09;。 3.靶机的445端口必须要开启。 环境 虚拟机kali为攻击机&#xff0c;win7虚拟机为靶机。 kali…

SELECT LAST_INSERT_ID()自增主键冲突或者为0问题

问题 数据库为mysql&#xff1b; mapper.xml文件为mybatis-generator自动生成的&#xff1b; 连接池使用DruidDataSource&#xff1b; 最终生成的insertSelective如下&#xff1a; 出现问题&#xff1a; 主键冲突&#xff1a;[WMyBatisTraceInterceptor:54][com.mysql.jdbc.…