AMD CDNA3汇编指令说明
在AMD CDNA架构中,s_waitcnt指令用于确保特定类型的指令(如内存操作或数据共享操作)完成后再继续执行后续指令。以下是vmcnt和lgkmcnt后数字的具体含义及用户汇编代码中的用法分析:
1. 计数器的定义
AMD CDNA架构通过三个计数器管理指令依赖性:
vmcnt(Vector Memory Count):追踪未完成的向量内存操作(如global_load、buffer_store等)。lgkmcnt(LDS/GDS/Constant/Message Count):追踪未完成的LDS/GDS指令、标量内存操作(如S_LOAD)和消息指令(如S_SENDMSG)。expcnt(Export Count):追踪未完成的VGPR导出指令(如GDS操作)。
2. 参数含义
s_waitcnt vmcnt(N):等待向量内存操作完成,直到未完成操作数 ≤ N。s_waitcnt lgkmcnt(M):等待LDS/GDS/标量内存/消息操作完成,直到未完成操作数 ≤ M。
例如:
s_waitcnt vmcnt(0):等待所有向量内存操作完成。s_waitcnt lgkmcnt(4):允许最多有4个LDS/GDS/标量内存/消息操作未完成。
3. 用户代码分析
汇编指令序列
global_load_dwordx4 v[12:15], v[12:13], off nt ; 向量内存加载(vmcnt++) ds_read_b128 v[16:19], v10 ; LDS读取(lgkmcnt++, 每条ds_read递增1次) ds_read_b128 v[20:23], v6 ds_read2_b32 v[28:29], v11 offset1:1 ds_read_b128 v[24:27], v24 ds_read2_b32 v[30:31], v11 offset0:2 offset1:3 s_waitcnt vmcnt(0) lgkmcnt(4) ; 等待所有向量内存操作完成,且未完成的LDS操作 ≤4 s_waitcnt lgkmcnt(3) ; 等待未完成的LDS操作 ≤3 s_waitcnt lgkmcnt(2) ; 等待未完成的LDS操作 ≤2 s_waitcnt lgkmcnt(1) ; 等待未完成的LDS操作 ≤1 s_waitcnt lgkmcnt(0) ; 等待所有LDS操作完成
具体行为
-
初始状态:
- 执行5条
ds_read指令后,lgkmcnt初始值为5。 global_load_dwordx4指令会增加vmcnt至1。
- 执行5条
-
s_waitcnt vmcnt(0):- 等待向量内存操作完成(即
vmcnt降为0)。 - 此时
global_load_dwordx4的数据已可用。
- 等待向量内存操作完成(即
-
s_waitcnt lgkmcnt(4):- 等待最多4个LDS操作未完成。假设此时已有一个LDS操作完成(
lgkmcnt=4),继续执行后续指令。
- 等待最多4个LDS操作未完成。假设此时已有一个LDS操作完成(
-
后续
lgkmcnt递减:- 通过逐步降低允许的未完成操作数(4→3→2→1→0),确保LDS数据按需逐批就绪,避免数据竞争。
4. 关键规则
- LDS操作的单次计数:每条
ds_read指令(无论读取多少DWord)仅递增lgkmcnt一次。 - 标量内存操作的特殊规则:例如
S_LOAD_DWORDX4会递增lgkmcnt4次(因加载4 DWord),但用户代码中未涉及。 - 顺序性:同类指令(如多个LDS读取)按序完成,但不同类指令(如LDS和标量内存)可能乱序完成。
在AMD CDNA架构中,ds_read_b128指令的作用和计数器行为可以通过以下关键点解释:
5. LDS操作与向量内存操作的区别
- LDS(Local Data Share):是工作组内共享的低延迟本地内存,用于线程间通信。其操作(如
ds_read/ds_write)属于共享内存访问,而非全局内存或设备内存访问。 - 向量内存操作:指针对全局内存(Global Memory)或设备内存的访问(如
global_load、buffer_load等)。这些操作需要经过内存控制器和缓存层次结构,延迟较高。
6. 计数器分类
AMD CDNA架构通过三个计数器管理指令依赖性:
vmcnt(Vector Memory Count):仅追踪全局内存操作(如global_load、buffer_store等)。lgkmcnt(LDS/GDS/Constant/Message Count):追踪LDS操作、GDS操作、标量内存操作(如S_LOAD)和消息指令(如S_SENDMSG)。
7. ds_read_b128的归类
ds_read_b128指令从LDS读取128位数据到VGPR中,属于LDS操作,因此仅递增lgkmcnt,而不影响vmcnt。global_load等全局内存指令:需要与设备内存交互,会递增vmcnt。
8. 为何vmcnt不增加?
- 内存层级差异:LDS是片上共享内存,访问延迟极低,由专门的硬件单元管理,不经过全局内存控制器。
- 计数器设计分离:AMD将LDS操作与全局内存操作分开管理,以避免不同内存层次的依赖混淆,简化同步逻辑。
9. 验证依据
文档中明确说明:
- LDS操作归类(Chapter 11):
- LDS访问由
lgkmcnt管理,用于同步工作组内数据共享。 - 向量内存操作由
vmcnt管理,用于全局内存访问。
- LDS访问由
- 计数器定义(Chapter 3.1):
vmcnt仅针对全局内存的读写和原子操作。lgkmcnt覆盖LDS、GDS、标量内存和消息操作。
10. 汇编指令解释
1. global_load_dwordx4 v[20:23], v[20:21], off nt
- 功能:从全局内存异步加载4个Dword(16字节)到VGPR
v20-v23。 - 参数:
v[20:23]:目标VGPR范围。v[20:21]:地址VGPR对(低32位在v20,高32位在v21)。off:无偏移。nt:Non-Temporal提示(绕过缓存)。
- 计数器:
vmcnt增加1(全局内存操作)。
2. ds_read_b128 v[20:23], v6
- 功能:从LDS地址
v6异步加载128位(16字节)到VGPRv20-v23。 - 参数:
v[20:23]:目标VGPR。v6:LDS地址源VGPR。
- 计数器:
lgkmcnt增加1(LDS操作)。
3. ds_read2_b32 v[28:29], v11 offset1:1
- 功能:从LDS基地址
v11的两个偏移位置读取两个32位数据。- 第一个Dword:地址
v11(偏移0)。 - 第二个Dword:地址
v11 + 4(偏移1,步长为4字节)。
- 第一个Dword:地址
- 参数:
offset1:1:第二个Dword的偏移量。
- 计数器:
lgkmcnt增加1(每个ds_read操作递增一次)。
4. ds_read2_b32 v[30:31], v11 offset0:2 offset1:3
- 功能:从LDS基地址
v11的两个偏移位置读取两个32位数据。- 第一个Dword:地址
v11 + 8(偏移2,步长为4字节)。 - 第二个Dword:地址
v11 + 12(偏移3)。
- 第一个Dword:地址
- 参数:
offset0:2:第一个Dword的偏移量。offset1:3:第二个Dword的偏移量。
- 计数器:
lgkmcnt增加1。
5. ds_read_b128 v[24:27], v18 offset:1024
- 功能:从LDS地址
v18 + 1024异步加载128位(16字节)到VGPRv24-v27。 - 参数:
offset:1024:LDS地址的固定偏移。
- 计数器:
lgkmcnt增加1。
6. scratch_store_dwordx4 off, v[24:27], s23
- 功能:将VGPR
v24-v27中的4个Dword存储到Scratch内存地址s23 + off。 - 参数:
s23:Scratch内存基地址的标量寄存器。off:无附加偏移。
- 计数器:
vmcnt增加1(Scratch操作属于FLAT格式,视为向量内存操作)。
7. scratch_store_dwordx2 off, v[28:29], s23 offset:32
- 功能:将VGPR
v28-v29中的2个Dword存储到Scratch内存地址s23 + 32。 - 参数:
offset:32:相对于基地址的附加偏移。
- 计数器:
vmcnt增加1。
8. scratch_load_dword v6, off, s23
- 功能:从Scratch内存地址
s23加载1个Dword到VGPRv6。 - 参数:
off:无偏移。
- 计数器:
vmcnt增加1。
9. scratch_load_dword v19, off, s23 offset:4
- 功能:从Scratch内存地址
s23 + 4加载1个Dword到VGPRv19。 - 参数:
offset:4:附加偏移量。
- 计数器:
vmcnt增加1。
11. 问题1:scratch_store_dwordx4和scratch_load_dword是否影响vmcnt?
结论:
- 是,Scratch操作属于向量内存操作(FLAT格式),会递增
vmcnt计数器。 - 依据(文档Chapter 4.4):
VM_CNT(Vector Memory Count):追踪所有向量内存操作(包括MUBUF、MTBUF和FLAT格式)。 FLAT格式包含Scratch操作(如
scratch_load和scratch_store),因此会递增vmcnt。
12. 问题2:scratch_store_dwordx2 off, v[28:29], s23 offset:32,这条指令中地址偏移32的单位是byte还是dwordx2?请从指令集文档中找到依据?
根据AMD CDNA架构文档中Scratch指令的地址偏移规则(见第12.15.2节"Scratch Instructions"),以下是对scratch_store_dwordx2 off, v[28:29], s23 offset:32指令偏移量单位的分析:
结论
指令中的偏移量 offset:32 的单位为字节(Byte),而非Dwordx2。
依据
-
指令语义定义:
- Scratch指令(如
scratch_store)的地址计算规则与 FLAT内存操作 一致(见第10章)。文档明确说明:FLAT格式的地址偏移(offset)以字节为单位(Chapter 10.3.1: "Addressing")。
- Scratch指令(如
-
对齐规则:
- 若以Dword为单位,偏移量为32时实际地址偏移为 32×4=128字节,这与常见的内存对齐要求(如64字节对齐)冲突。文档无此类特殊对齐规则的描述。
-
同类指令验证:
scratch_load_dword等同类指令的偏移量单位均为字节。
13. 问题3:global_load_dwordx4 v[20:23], v[20:21], off nt,这条指令的偏移是off,如果有偏移的话,单位也是byte么?请从指令集文档中找到依据
根据AMD CDNA架构文档中MUBUF指令的地址偏移规则(见Chapter 9.1.5 "Buffer Addressing"),以下是关键分析:
结论
global_load_dwordx4指令的偏移量参数 off 的单位为字节(Byte)。
依据
-
MUBUF指令的地址计算定义:
- MUBUF(内存缓冲指令)的地址计算公式为:
Base Address + SGPR_address + offset其中offset是符号扩展的12位立即数(范围为 -2048 至 +2047 字节)。文档明确指出:For MUBUF instructions, the offset is a 12-bit signed byte offset.
- MUBUF(内存缓冲指令)的地址计算公式为:
-
对齐规则:
- 在第9.1.7节"Alignment"中,强调地址必须按数据尺寸对齐(例如:
dwordx4需对齐到16字节),但偏移量本身仍以字节为单位。这与字节粒度寻址一致。
- 在第9.1.7节"Alignment"中,强调地址必须按数据尺寸对齐(例如:
-
同类指令验证:
- FLAT/Scratch指令(如
scratch_store_dwordx2)的偏移量明确以字节为单位(见Chapter 10),MUBUF遵循相同设计原则。
- FLAT/Scratch指令(如
总结
global_load_dwordx4的 off 参数是 12位有符号字节偏移,范围 -2048 至 +2047 字节。这是AMD CDNA架构的统一内存寻址设计。
14. 问题4:vmcnt(Vector Memory Count,lgkmcnt(LDS/GDS/Constant/Message Count),expcnt(Export Count)这3个计数器支持的最大值分别是多少?
根据AMD CDNA架构文档中状态寄存器的定义,三个计数器的最大支持值如下:
计数器最大值
-
vmcnt(Vector Memory Count)- 位数:6位
- 最大值:26−1=6326−1=63
- 功能:追踪未完成的全局向量内存操作(如
global_load、buffer_store等)。
-
lgkmcnt(LDS/GDS/Constant/Message Count)- 位数:4位
- 最大值:24−1=1524−1=15
- 功能:追踪未完成的LDS操作、GDS操作、标量内存读取(如
S_LOAD)和消息指令(如S_SENDMSG)。
-
expcnt(Export Count)- 位数:3位
- 最大值:23−1=723−1=7
- 功能:追踪未完成的导出操作(如GDS指令)。
依据(文档第3.1节)
在状态寄存器概述中明确标注了三个计数器的大小:
| Counter | Bit Width | Max Value |
|---|---|---|
| VMCNT | 6 | 63 |
| LGKMCNT | 4 | 15 |
| EXPCNT | 3 | 7 |
总结
- 使用
S_WAITCNT指令时,需确保参数不超过最大值:s_waitcnt vmcnt(63) lgkmcnt(15) expcnt(7)
- 超过最大值会导致未定义行为。
END

浙公网安备 33010602011771号