Commit a8d0afc1 by 刘昀达

前期工作

parents
# 一、微架构体系
微架构又称为微体系结构/微处理器体系结构。是在计算机工程中,将一种给定的指令集架构在处理器中执行的方法。一种给定指令集可以在不同的微架构中执行。实施中可能因应不同的设计目的和技术提升而有所不同。计算机架构是微架构和指令集设计的结合。
## (一)概述
GPGPU-Sim 3.x由CPU部分和GPU部分组成。
GPGPU-Sim 3.x中的微体系结构(时序)模型仅对GPU时序周期建模。它不对CPU时序或PCI Express时序(即CPU和GPU之间的内存传输时间)建模。
目前正在努力提供组合的CPU和GPU模拟器,其中GPU部分由GPGPU-Sim建模。
GPGPU-Sim 3.x对GPU微体系结构进行建模,类似于NVIDIA GeForce 8x,9x和Fermi系列中的微体系结构。
GPGPU-Sim的目的是为架构研究提供基础,而不是对任何特定的商用GPU进行精确建模。也就是说,GPGPU-Sim 3.x已针对NVIDIA GT 200和NVIDIA Fermi GPU架构进行了校准。
## (二)Top-Level Organization
### 1、简介
- SIMT(Single Instruction Multiple Thread):单指令多线程
- SIMD (Single Instruction Multiple Data):单指令多数据流
SIMT内核为高度多线程的流水线SIMD处理器建模,大致相当于NVIDIA所谓的流式多处理器(SM)或AMD所谓的计算单元(CU)。
### 2、时钟域
GPGPU-Sim支持四个独立的时钟域:
(1)SIMT核心群集时钟域
(2)互连网络时钟域
(3)L2高速缓存时钟域,该域适用于除DRAM外的存储器分区单元中的所有逻辑
(4)DRAM时钟域
时钟频率可以具有任意值(它们不必是彼此的倍数)。换句话说,我们假设时钟域之间存在同步器。
在GPGPU-Sim 3.x仿真模型中,相邻时钟域中的单元通过时钟交叉缓冲区进行通信,这些缓冲区以源域的时钟速率填充,并以目标域的时钟速率耗尽。(怎么理解这个?)
## (三)SIMT核心集群
The SIMT Cores are grouped into SIMT Core Clusters。
SIMT核心集群中的SIMT核心共享一个公共端口,用于连接互连网络。
如图所示:
- 每个SIMT Core Clusters包含多个SIMT Core
- 使用一个 response FIFO 队列来接收来自互联网络的数据包。
- 数据包会被定向到:指令缓存器 或者 存储 pipeline(LDST Uint)。数据包出队
- 若数据包不能被SIMT Core接收,则队列停止
- 为了在LDST单元上生成内存请求,每个SIMT内核都有其自己的互连网络输入端口injection port。
- 但是,输入端口缓冲区(injection port buffer)由群集中的所有SIMT内核共享。
## (四)SIMT核心
SIMT内核对高度多线程的流水线SIMD处理器进行建模,大致相当于NVIDIA所谓的流式多处理器(SM)或AMD所谓的计算单元(CU)。
流处理器(SP)或CUDA核心将对应于SIMT核心中ALU pipeline内的通道。
### 1、Front End
Front End包括:指令高速缓存访问(Fetch)和指令缓冲逻辑(I-Buffer)、Score Board和调度逻辑、SIMT堆栈(SIMT-Stack)。
#### 1.1、Fetch and Decode
##### (1)I-Buffer基本概念
The instruction buffer (I-Buffer) block用来保存从指令缓存中取出来的指令。I-Buffer是静态分区的,因此运行在SIMT core上的所有warps都有专用的存储空间来保存指令。
补充一些有关GPU的概念:CUDA编程——GPU架构,由sp,sm,thread,block,grid,warp说起
硬件上:
- SP:最基本的处理单元,streaming processor,也称为CUDA core。最后具体的指令和任务都是在SP上处理的。GPU进行并行计算,也就是很多个SP同时做处理。
- SM:多个SP加上其他的一些资源组成一个streaming multiprocessor。也叫GPU大核,其他资源如:warp scheduler,register,shared memory等。
SM可以看做GPU的心脏(对比CPU核心),register和shared memory是SM的稀缺资源。
CUDA将这些资源分配给所有驻留在SM中的threads。因此,这些有限的资源就使每个SM中active warps有非常严格的限制,也就限制了并行能力。
软件上:
- thread:一个CUDA的并行程序会被以许多个threads来执行。
- warp:GPU执行程序时的调度单位,目前cuda的warp的大小为32,同在一个warp的线程,以不同数据资源执行相同的指令,这就是所谓 SIMT。
- block:数个threads会被群组成一个block,同一个block中的threads可以同步,也可以通过shared memory通信。
- grid:多个blocks则会再构成grid。
##### (2)I-Buffer功能
当前模型中,每个warp拥有三个I-Buffer实体,每个I-Buffer都有:有效位、就绪位 与 已经解码的warp指令:
- 有效位:指示当前I-Buffer中存在未发布(执行?)的warp已解码指令
- 就绪位:指示该warp指令已经准备好发布到执行pipeline中了
就绪位置位:在计划(schedule)与发布(issue)阶段,使用scoreBoard logic和硬件资源使之置位(感觉在说,这个置位是硬件完成的)
I-Buffer初始化为空,有效位与就绪位均被禁用
##### (3)I-Buffer取指
若warp在I-Buffer中没有任何有效指令,则可以执行取指操作
- Warp按照schedule以循环的方式来访问指令高速Cache
- 选中warp后,读取请求将会被发送到指令高速cache中,请求包括:下一条指令的地址(我的理解:就是让指令高速cache把下一条指令发送到这个地址中)。
- 默认情况下,将会取出两个连续的指令
- 一旦warp收到指令,就会激活I-Buffer中的有效位,直到该warp的所有指令都issue到了执行pipeline
#### 1.2、Instruction Issue
第二个round robin arbiter选择一个warp,从I-Buffer发布到其余 pipeline。This round robin arbiter is decoupled from the round robin arbiter used to schedule instruction cache accesses.
issue调度器可以配置成:在一个cycle里,issue多个指令,这些指令来自于同一个warp。
当前的每个有效指令(即:已经译码过了,但是没有issue),需要坚持其warp是否有资格issue:
- (1)它的warp没有在障碍处等待
- (2)它的I-Buffer条目中有有效指令(设置了有效位)
- (3)ScoreBoard检查通过(有关更多详细信息,请参见记分板部分)
- (4)指令流水线的操作数访问阶段没有停止。
内存指令(加载,存储或memory barriers)被issue到内存 pipeline。
对于其他指令,它始终首选使用SP pipeline进行操作(issue),这种情况下SP pipeline与SFU pipeline都能使用。
但是,如果检测到control hazard,则将清除与该warp对应的I-Buffer中的指令。warp的下一个pc将更新为指向下一条指令(假定所有分支均未采用)。
有关处理控制流的更多信息,请参阅SIMT Stack。
#### 1.3、SIMT Stack
每个warp的SIMT堆栈被用于处理单指令多线程上的 execution of branch divergence。
这里解释一下divergence:
```
因为所有同一个warp中的thread必须执行相同的指令,那么如果这些线程在遇到控制流语句时,如果进入不同的分支,那么同一时刻除了正在执行的分之外,其余分支都被阻塞了,十分影响性能。
这类问题就是warp divergence。
请注意,warp divergence问题只会发生在同一个warp中。
```
由于divergence降低了这些体系结构的效率,因此可以采用不同的技术来降低这种影响。
最简单的技术之一是: post-dominator stack-based reconvergence mechanism. 。为了提高SIMT架构的效率,This technique synchronizes the divergent branches at the earliest guaranteed reconvergence point。与以前的GPGPU-Sim版本一样,GPGPU-Sim 3.x也采用这种机制。
Entries of the SIMT stack represents a different divergence level。在每个divergence branch中,一个new entry被放入到栈顶,当warp达到它的reconvergence point的时候,栈顶的entry将会被弹出。每个entry都会存储新分支的target PC,the immediate post dominator reconvergence PC and the active mask of threads that are diverging to this branch.
在这个模型中,每个warp的SIMT堆栈将会在对应的warp指令issue后更新,在no divergence时, The target PC通常会更新到下一个PC;但是在有divergence时,new entries将会与new target PC、the active mask that corresponds to threads that diverge to this PC以及their immediate reconvergence point PC压入堆栈中。因此,如果在栈顶的next PC不等于the PC of the instruction currently under check,就会有control hazard。更多有关信息: Dynamic Warp Formation: Efficient MIMD Control Flow on SIMD Graphics Hardware
请注意,众所周知,NVIDIA和AMD实际上是使用特殊指令来修改其差异堆栈的内容。 这些散度堆栈指令未在PTX中公开,但在实际的硬件SASS指令集中可见(使用decuda或NVIDIA的cuobjdump可见)。 当现在版本的GPGPU-Sim 3.x配置为通过PTXPlus执行SASS(请参阅PTX与PTXPlus)时,它会忽略这些低级指令,而是会创建一个可比较的控制流程图来标识立即的后支配者。 我们计划在将来的GPGPU-Sim 3.x版本中支持执行低级分支指令。
#### 1.4、Scoreboard
Scoreboard 会检查WAW和RAW有没有dependency hazards。正如之前所说的,经由warp写入的寄存器在issue阶段会被保留,ScoreBoard用过warp的ID来索引(找到寄存器),每个寄存器的编号都有与之对应的warp ID,在ScoreBoard中保留的寄存器 会在写回阶段释放。
已经译码过的指令不会马上issue,而是需要ScoreBoard确认没有WAW或者RAW hazards 时,才能issue。
**如何检测WAW或者RAW hazards?**
ScoreBoard通过跟踪来检查是否有这种情况:寄存器将要被一个已经issue的指令执行写入,但是还没有写入。
The scoreboard detects WAW and RAW hazards by tracking which registers will be written to by an instruction that has issued but not yet written its results back to the register file.(记分板通过跟踪已发出但尚未将其结果写回到寄存器文件中的指令将写入哪些寄存器来检测WAW和RAW危害。)
### 2、Register Access and the Operand Collector
各种NVIDIA专利都描述了一种称为“Operand Collector”的结构。 The operand collector is a set of buffers and arbitration logic used to provide the appearance of a multiported register file using multiple banks of single ported RAMs. (Operand Collector是一组缓冲区和arbitration logic,使用多个Single ported RAM Bank提供多端口寄存器文件的外观)。
overall arrangement节省面积、降低功耗,这对于提高throughput很重要。 请注意,AMD还使用存储区寄存器文件,但编译器负责确保对这些文件进行访问,以免发生存储区冲突。
下图展示了GPGPU-Sim 3.x models 的 operand collector详细构造:
![](_v_images/_1569811744_3802.png)
指令译码之后,有个硬件单元称为:collector unit,该单元被分配于保存指令的源操作数。
collector unit不是通过寄存器重命名来消除 name dependencies的,而是及时对space register operand 进行访问,从而确保在一个cycle内,不会对bank进行多次访问。
在上图所示的结构中,4个collector unit都包含了3个operand entries,每个operand entry有4个字段:有效位、寄存器标识符、就绪位以及操作数(operand data )。
每个操作数有128个比特组成(int 类型大小32位?或者是128位) (one four byte value for each scalar thread in a warp)
collector unit包含了标识符,用于表示这条指令属于哪个warp。
The arbitrator为每个bank设置了一个读取请求队列,用于保存访问请求直到请求被批准(执行)。当从译码阶段接收到指令同时collector unit处于可用状态是,将会分配指令与操作数(我理解的是把指令分给某个warp),并设置warp、寄存器标识符、有效位。
此外,源操作数的读取请求将会在arbiter中的读取请求队列中。为了简化设计,数据写回请求的优先级要高于读取请求。arbiter选择一组无冲突的访问(最多4个),发送到register file。为了减少crossbar和collector unit的面积,需要进行选择,因此每个收集器单元每个周期仅接收一个操作数。
当从寄存器文件中读取每个操作数并将其放入相应的collect unit时,将设置“就绪位”。 最后,当所有操作数准备就绪时,将指令发布到SIMD执行单元。
在我们的模型中,每个后端pipeline(SP,SFU,MEM)都有一组专用的collector unit,它们共享一组通用collector unit。 每个pipeline可用的单元数和capacity of the pool of the general units是可配置的。
### 3、ALU Pipelines
GPGPU-Sim v3.x为两种类型的ALU功能单元建模。
- SP单元执行除先验条件外的所有类型的ALU指令。
- SFU单元执行先验指令(正弦,余弦,对数等,换而言之就是结果确定的数学计算?)。
两种类型的单元均已流水线化和SIMD化。
SP单元通常每个周期可以执行一条warp的指令,而SFU单元只能每隔几个周期执行一条新的warp的指令,具体取决于指令类型。例如,SFU单元可以每4个周期执行一个正弦指令,或者每2个周期执行一个倒数指令。不同类型的指令也具有不同的执行等待时间。
每个SIMT core具有一个SP unit和一个SFU unit。 每个单元(SP或者SFU)都有一个来自operand collector的independent issue port。
两个单元共享连接到同一个用于写回阶段的输出流水线寄存器。 在操作数收集器的输出处有一个result bus allocator,以确保这些单元永远不会由于共享的写回而停顿。 每条指令在发布给任一单元之前都需要在结果总线中分配一个循环时隙。 请注意,内存pipeline具有其自己的写回阶段,并且不受此结果总线分配器(result bus allocator)的管理。
### 4、Memory Pipeline (LDST unit)
GPGPU-Sim支持CUDA中在PTX中可见的各种内存空间。
在我们的模型中,每个SIMT内核具有4个不同的片上1级内存(on-chip level 1 memories):共享内存,数据缓存,常量缓存(constant cache)和纹理缓存(texture cache)。
下表展示了4片上存储器为哪种类型的存储器访问服务:
![](_v_images/_1569829196_21208.png)
![](_v_images/_1569829386_1166.png)
尽管将这些模型建模为单独的物理结构,但它们都是内存管线(LDST单元)的所有组件,因此它们都共享相同的写回阶段。下面介绍如何为这些空间提供服务:
- (1)纹理内存:对纹理内存的访问被缓存在L1纹理缓存(仅保留用于纹理访问)中,并且也缓存在L2缓存(如果存在的话)中。
L1纹理缓存是1998年论文[3]中描述的一种特殊设计。 GPU上的线程无法写入纹理存储空间,因此L1纹理缓存是只读的。
- (2)共享内存:每个SIMT内核包含一个可配置数量的shared scratchpad memory,可由thread block中的线程共享。 该存储器空间不受任何L2的支持(就是不存在L2 cache?),并且由程序员明确管理。
- (3)常量存储器:常量和参数存储器被缓存在只读常量缓存中。
- (4)参数存储器:见上文
- (5)本地内存(Local Memory):缓存在L1数据缓存中,并由L2支持(两级cache)。 除了无法在本地(私有)数据共享的情况下将值写回逐出外,类似于下面的全局内存的方式处理(Treated in a fashion similar to global memory below except values are written back on eviction since there can be no sharing of local (private) data.)。
- (6)全局存储器(Global Memory):全局和本地访问都由L1数据缓存提供服务。 如CUDA 3.1编程指南中所述,从同一个warp通过标量线程进行的访问以half-warp合并(Accesses by scalar threads from the same warp are coalesced on a half-warp basis)。1个SIMT core周期最多可以处理2个访问(These accesses are processed at a rate of 2 per SIMT core cycle),因此可以在一个周期内为完全合并为2个访问(每半个循环一次)的一条存储器指令提供服务。
对于那些产生两个以上访问的指令,这些指令将以每个周期完成2个访问的速率来访问存储系统。 因此,如果一条内存指令产生32条访问(warp中每个通道一个),则将至少需要16个SIMT核心周期才能将指令移至下一个流水线阶段。
#### 4.1、L1 Data Cache
L1数据缓存是每个SIMT核心的专用 non-blocking 一级缓存,用于本地和全局内存访问。 The L1 cache is not banked,并且能够在每个SIMT核心周期为两个合并的内存请求(访问)提供服务。 传入的内存请求不得跨越L1数据高速缓存中的两个或更多高速缓存行。 还要注意,L1数据高速缓存不是一致的(应该是在说和内存中的数据不一定一致,没有使用写穿透策略)。
下表总结了L1数据缓存的写入策略。
![](_v_images/_1569833604_5959.png)
#### 4.2、Texture Cache
纹理缓存模型是预取纹理缓存(我的理解是先从内存中取出一部分数据)。纹理存储器访问主要表现出空间局部性(例如:矩阵,当取出某一行中的某个数(int),可以顺带一并取出该行的所有的数据,并且所花费的时间几乎是一样的),纹理存储器在这里的大小为:16KB。详情见:[CUDA纹理存储器的特性及其使用](https://blog.csdn.net/zhangpinghao/article/details/16833489)
在实际的图形使用场景中,许多纹理缓存访问会丢失(类似于cache未命中)。 DRAM中访问纹理的等待时间约为100个周期。考虑到较大的内存访问延迟和较小的缓存大小,何时在缓存中分配行的问题变得至关重要。
预取纹理缓存如何解决访问丢失(未命中)问题?通过设置标签数组、数据数组。标签数组表示:100个周期之后,仍然未被访问的cache的状态。数据数组表示:未命中时,cache的状态。(The prefetching texture cache solves the problem by temporally decoupling the state of the cache tags from the state of the cache blocks. The tag array represents the state the cache will be in when misses have been serviced 100's of cycles later. The data array represents the state after misses have been serviced. )
The key to making this decoupling work is to use a reorder buffer to ensure returning texture miss data is placed into the data array in the same order the tag array saw the access.详情见:[Prefetching in a Texture Cache Architecture](http://www-graphics.stanford.edu/papers/texture_prefetch/texture_prefetch_comp.pdf)
#### 4.3、Constant (Read only) Cache
通过L1常量缓存访问常量和参数存储器。此缓存是通过标签数组实现的,并且类似于L1数据缓存,但无法写入。
### 5、Thread Block / CTA / Work Group Scheduling
线程块(CUDA术语中的协作线程数组(CTA)或OpenCL术语中的工作组)一次发给SIMT Core。
在每个SIMT Core时钟周期中,线程块发布机制都会以循环方式选择并循环遍历SIMT Core集群。对于每个选定的SIMT核心群集,将以循环方式选择并循环遍历SIMT核心。对于每个选定的SIMT核心,如果该SIMT核心上有足够的可用资源,则会从选定的内核向该核心issue单个线程块。
如果在应用程序中使用了多个CUDA流或命令队列,则可以在GPGPU-Sim中同时执行多个内核。
可以在不同的SIMT core上执行不同的内核;单个SIMT Core一次只能执行来自单个内核的线程块。
如果同时执行多个内核,则选择发给每个SIMT core的内核也是循环的。
当前,在[CUDA编程手册](https://docs.nvidia.com/pdf/CUDA_C_Programming_Guide.pdf)中详细介绍了:如何在CUDA体系结构上并发执行内核。
## (五)互连网络
通过互连网络通信的包只有4种:
(1)从SIMT core集群发送到内存分区的读请求
(2)从SIMT core集群发送到内存分区的写请求
(3)从内存分区发送到SIMT core集群的读应答
(4)从内存分区发送到SIMT core集群的写确认
这4中包,通过2个网络发送,模拟两个互连网络:一个用于从SIMT核心群集到内存分区的流量,另一个用于从内存分区回到SIMT核心群集的流量。
2个buffer:
(1)injection buffer(icnt <- SIMT or 内存分区)
(2)ejection buffer(icnt -> SIMT or 内存分区)
We effectively have a two stage buffer per virtual channel at the output, the first stage contains a buffer per virtual channel that has the same space as the buffers internal to the network, the next stage buffer per virtual channel is where we cross from one clock domain to the other--we push flits into the second stage buffer in the interconnect clock domain, and remove whole packets from the second stage buffer in the shader or L2/DRAM clock domain. We return a credit only when we are able to move a flit from the first stage buffer to the second stage buffer (and this occurs at the interconnect clock frequency).
{
"created_time": "2019-11-18T10:20:46Z",
"files": [
{
"attachment_folder": "",
"attachments": [
],
"created_time": "2019-11-18T10:26:36Z",
"modified_time": "2019-11-18T10:26:36Z",
"name": "MicroArchitecture.md"
}
],
"sub_directories": [
],
"version": "1"
}
{
"created_time": "2019-11-18T10:21:11Z",
"files": [
{
"attachment_folder": "",
"attachments": [
],
"created_time": "2019-11-18T10:24:34Z",
"modified_time": "2019-11-18T10:24:34Z",
"name": "gpu-sim.md"
}
],
"sub_directories": [
],
"version": "1"
}
# 一、 GPGPU-SIM模拟器的配置文件
## (一) 初始化shader的配置文件
### 1、 每个shader的线程数
### 2、 warp的大小
### 3、 确定流水线的级数,每个stage的名称
### 4、 SP、SFU的延迟
### 5、 L1 cache配置
##### (1) cache类型
根据cache的种类,可以分为三种:
```
enum FuncCache {
FuncCachePreferNone = 0,
FuncCachePreferShared = 1,
FuncCachePreferL1 = 2
};
```
##### (2) cache的策略
实际上下面四个配置文件都是同一个类,不过根据输入的string,其相关参数会有所不同:
```
int ntok = sscanf(config,"%u:%u:%u,%c:%c:%c:%c:%c,%c:%u:%u,%u:%u,%u",
&m_nset, &m_line_sz, &m_assoc, &rp, &wp, &ap, &wap,
&sif, &mshr_type, &m_mshr_entries, &m_mshr_max_merge,
&m_miss_queue_size, &m_result_fifo_entries,
&m_data_port_width);
```
###### ①、 替换策略
cache更新的时候:
```
switch (rp) {
case 'L': m_replacement_policy = LRU; break;
case 'F': m_replacement_policy = FIFO; break;
default: exit_parse_error();
}
```
###### ②、 写策略 (Write Hit的时候,所采用的策略)
```
switch (wp) {
case 'R': m_write_policy = READ_ONLY; break; // 只读不写
case 'B': m_write_policy = WRITE_BACK; break; // 写回(只修改cache的内容):在数据更新时只写入缓存Cache,只在数据被替换出缓存时,被修改(用dirty标记)的缓存数据才会被写到后端存储(主存)
case 'T': m_write_policy = WRITE_THROUGH; break; // 在数据更新时,同时写入缓存Cache和后端存储(主存);
case 'E': m_write_policy = WRITE_EVICT; break; // 全局内存的策略,网上查了下没找到相关资料
case 'L': m_write_policy = LOCAL_WB_GLOBAL_WT; break; // 也没找到相关资料
default: exit_parse_error();
}
```
![](_v_images/_1571627235_3742.png)
这里先来解释下,一般情况下,cache发生Miss 或 Hit的时候的策略:
![](_v_images/_1571627636_6995.png)
###### ③、 分配策略
```
switch (ap) {
case 'm': m_alloc_policy = ON_MISS; break;
case 'f': m_alloc_policy = ON_FILL; break;
default: exit_parse_error();
}
```
###### ④、 mshr类型
```
switch (mshr_type) {
case 'F': m_mshr_type = TEX_FIFO; assert(ntok==13); break;
case 'A': m_mshr_type = ASSOC; break;
default: exit_parse_error();
}
```
MSHR:Miss Status Holding Registers ,未命中状态保留寄存器,用于保存未命中的状态(是指某个未命中的cache的行列)
MSHR表,用来存放miss轨迹的,我的理解是,这个MSHR是用来调试或者计算性能的时候才会用到
###### ⑤、 写分配策略 (Write Miss的时候,采用的策略)
```
switch(wap){
case 'W': m_write_alloc_policy = WRITE_ALLOCATE; break; // 将要写的地址所在的块先从main memory(主存)调入cache中,然后写cache;
case 'N': m_write_alloc_policy = NO_WRITE_ALLOCATE; break; // 将要写的内容直接写回main memory;
default: exit_parse_error();
}
```
![](_v_images/_1571627248_19089.png)
这里先来解释下,一般情况下,cache发生Miss 或 Hit的时候的策略:
![](_v_images/_1571627636_6995.png)
###### ⑥、 索引策略??
很迷,不知道怎么用
```
switch(sif){
case 'H': m_set_index_function = FERMI_HASH_SET_FUNCTION; break;
case 'C': m_set_index_function = CUSTOM_SET_FUNCTION; break;
case 'L': m_set_index_function = LINEAR_SET_FUNCTION; break;
default: exit_parse_error();
}
```
#### 5.1、 L1I的配置
#### 5.2、 L1T的配置
#### 5.3、 L1C的配置
#### 5.4、 L1D的配置
#### 5.5、 配置纹理cache的line大小
#### 5.6、 配置常量cache的line大小
## (二) 初始化主存(显存)的配置
内存延迟表示系统进入数据存取操作就绪状态前等待内存响应的时间,它通常用4个连着的阿拉伯数字来表示,例如 “3-4-4-8” ,一般而言四个数中越往后值越大,这4个数字越小,表示内存性能越好。
- 第一个数字最为重要,表示注册读取命令到第一个输出数据之间的延迟(CAS Latency),即: CL值,单位是时钟周期。这是纵向地址脉冲的反应时间。
- 第二个数字表示内存行地址控制器预充电时间(RAS Precharge),即: tRP。指内存从结束一个行访问到重新开始的间隔时间。
- 第三个数字表示从内存行地址到列地址的延迟时间(RAS to CAS Delay),即: tRCD。
- 第四个数字表示内存行地址控制器激活时间Act-to-Precharge Precharge Delay , 即:tRAS
### 1、 nbk
number of banks,bank的数量
### 2、 tCCD
Column to Column Delay (RD/WR to RD/WR different banks)
列到列的访问时延
### 3、 tRRD
Row to Row Delay (Active to Active different banks)
行到行的访问时延
### 4、 tRCD
Row to Column Delay (Active to RD/WR/RTR/WTR/LTR)
行到列的访问时延
### 5、 tRAS
Active to PRECHARGE command period
### 6、 tRP
PRECHARGE command period
### 7、 tRC
Active to Active command period (same bank)
### 8、 CL
CAS Latency,是指内存纵向地址脉冲的反应时间,是在一定频率下衡量不同规范内存的重要标志之一。对于PC1600和PC2100的内存来说,其规定的CL应该为2,即他读取数据的延迟时间是两个时钟周期。
### 9、 WL
WRITE latency
### 10、 tCDLR
Last data-in to Read Delay (switching from write to read)
### 11、 tWR
WRITE recovery time
### 12、nbkgrp
number of bank groups
bank组的数量
### 13、tCCDL
column to column delay between accesses to different bank groups
在不同的bank组之间的列到列的时延
### 14、tRTPL
read to precharge delay between accesses to different bank groups
### 15、 tRCDWR
### 16、 tRTW
### 17、 tWTR
### 18、 tWTP
### 19、 dram_atom_size
## (三) 初始化时钟的配置
### 1、 设置core的频率
### 2、 设置icnt的频率
### 3、 设置L2的频率
### 4、 设置DRAM的频率
### 5、 根据频率计算:时钟周期
时钟周期 == 频率的倒数
## (四) 初始化电源配置
## (五) 初始化跟踪器
在trace文件里面,将对应的使能位置位true
# 二、 GPGPU-SIM模拟器
## (一) 初始化
## (二) 运行函数(cycle)
首先介绍一下,4个时钟域:
(1)core的时钟,即:SM
(2)DRAM的时钟,即:主存
(3)L2 cache的时钟,L2 cache在DRAM里面,类似于缓存区一样的功能,解决icnt与DRAM之间速度不匹配的问题
(4)icnt的时钟,即:互联网络
整体图:
![](_v_images/_1572395378_1046.png)
### 1、 gpgpu_sim::cycle()
#### 1.1、 寻找下一个时钟
通过计算上述4个时钟域的最小值,确定本轮循环中,工作的是哪些部件(core、ICNT、DRAM、L2)
#### 1.2、运行core部分
##### 1.2.1、微体系结构
![](_v_images/_1573450806_16776.png)
##### 1.2.2、代码流程
(2)从icnt的ejection buffer中取出指令,放入到cluster的FIFO队列
(1)根据mf类型,将ICNT中FIFO的指令放入 LDST 或者 指令cache
#### 1.3、运行ICNT部分
##### 1.3.1、微体系结构
ICNT 与 L2 cache之间的交互
![](_v_images/_1573087770_2078.png)
##### 1.3.2、代码流程
将主存中的指令(包含所需数据) -> ICNT的缓冲区
#### 1.4、运行DRAM部分
##### 1.4.1、微体系结构
DRAM与L2 cache之间的数据交互
![](_v_images/_1573042254_4079.png)
##### 1.4.2、代码流程
(1) DRAM的操作:主要是DRAM与L2之间的数据交互
(2) L2 cache将来自ICNT的请求传到DRAM,DRAM完成请求后将数据传给L2 cache
#### 1.5、运行L2 cache(内存子分区)部分
##### 1.5.1、微体系结构
L2 cache 与 DRAM之间的交互
###### (1)内存子分区的运行函数(cycle)
![](_v_images/_1573087801_10874.png)
###### (2)L2 cache的运行函数(cycle)
**未命中队列(L2 cache bank)**中取出请求放入**内存端口(L2->DRAM队列)**
##### 1.5.2、代码流程
#### 1.6、运行ICNT部分
暂时没有看懂
#### 1.7、运行CORE部分
##### 1.7.0、基础知识
因为这部分涉及一些指令和流水线的相关知识,在此补充一下
###### 1.7.0.1、指令(CPU)
**(1)指令分类**
大致分为4类:
①、运算类指令:加减乘除,逻辑运算等,比如:ADD
②、传送类指令:从存储器到通用存储器等,比如:MOV
③、控制类指令:暂停处理器,标志位的操作等,比如:NOP
![](_v_images/_1573438280_17186.png)
④、转移类指令:无条件转移、过程调用等,比如:JMP
**(2)指令译码(X86)**
这里给出的是CPU的译码,GPU应该也是这么做的
![](_v_images/_1573438033_19314.png)
###### 1.7.0.2、流水线(CPU)
**(1)流水线冒险**
![](_v_images/_1573438726_30560.png)
**(2)结构冒险**
![](_v_images/_1573438867_29885.png)
①、指令与数据放在同一内存
②、同时读、写寄存器
**(3)数据冒险**
![](_v_images/_1573439010_13632.png)
**(4)控制冒险**
![](_v_images/_1573439068_30697.png)
##### 1.7.1、微体系结构
###### (1)GPU的SM架构
![](_v_images/_1573174946_21395.png)
###### (3)CUDA core
![](_v_images/_1573175069_22056.png)
###### (4)概览图
![](_v_images/_1573175210_7314.png)
###### (5)代码中的core(相当于SM)
##### 1.7.2、运行cluster(cluster->cycle)
依次运行cluster中的core(SM)
注意这里面的
###### (1)fetch
取指操作确定了:指令的资源、warp,但是真正有效的指令还没有放进来(万事俱备只等译码,等decode译码之后直接放入指定的buffer)
m_inst_fetch_buffer :指令存放的buffer
###### (2)decode
一次译码1条或者2条指令
通过函数: ptx_fetch_inst。 取出译码之后的指令放入 m_inst_fetch_buffer
判断指令的操作数类型,更新统计信息
###### (3)issue
issue操作实际上是调度器操作,运行调度器: schedulers[i]->cycle()
根据指令的不同,可能会产生流水线停滞
###### (4)read_operands
无代码
###### (5)execute
###### (6)writeback
##### 1.7.3、计算流水线的占空比
##### 1.7.4、将CTA(block)发布到core
##### 1.7.5、刷新L1缓存 or 刷新L2缓存
##### 1.7.6、快照
{
"attachment_folder": "_v_attachments",
"created_time": "2019-11-18T10:20:15Z",
"files": [
],
"image_folder": "",
"recycle_bin_folder": "_v_recycle_bin",
"sub_directories": [
{
"name": "Microarchitecture_Model"
},
{
"name": "Software_Design_of_GPGPU-Sim"
}
],
"version": "1"
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment