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號