AMDGPU 後端的用戶指南

簡介

AMDGPU 後端為 AMD GPU 提供 ISA 程式碼生成,從 R600 系列一直到目前的 GCN 系列。它位於 llvm/lib/Target/AMDGPU 目錄中。

LLVM

目標三元組

使用 Clang 選項 -target <Architecture>-<Vendor>-<OS>-<Environment> 來指定目標三元組

表 18 AMDGPU 架構

架構

描述

r600

AMD GPU HD2XXX-HD6XXX,用於圖形和運算著色器。

amdgcn

AMD GPU GCN GFX6 及更高版本,用於圖形和運算著色器。

表 19 AMDGPU 供應商

供應商

描述

amd

可用於所有 AMD GPU 用途。

mesa

如果 OS 為 mesa3d,則可以使用。

表 20 AMDGPU 作業系統

OS

描述

<empty>

預設為未知的 OS。

amdhsa

在 HSA [HSA] 相容執行階段(例如

  • AMD 的 ROCm™ 執行階段 [AMD-ROCm],在 Linux 上使用 rocm-amdhsa 載入器。請參閱AMD ROCm 平台發行說明 [AMD-ROCm-Release-Notes] 以了解支援的硬體和軟體。

  • AMD 的 PAL 執行階段,在 Windows 上使用 pal-amdhsa 載入器。

amdpal

圖形著色器和運算核心,在 AMD 的 PAL 執行階段上執行,在 Windows 和 Linux Pro 上使用 pal-amdpal 載入器。

mesa3d

圖形著色器和運算核心,在 AMD 的 Mesa 3D 執行階段上執行,在 Linux 上使用 mesa-mesa3d 載入器。

表 21 AMDGPU 環境

環境

描述

<empty>

預設。

處理器

使用 Clang 選項 -mcpu=<target-id>--offload-arch=<target-id> 來指定 AMDGPU 處理器,以及可選的目標功能。請參閱目標 ID目標功能以取得 AMD GPU 目標特定資訊。

每個處理器都支援每個 OS ABI(請參閱AMDGPU 作業系統),但以下例外情況除外

  • amdhsar600 架構中不受支援(請參閱AMDGPU 架構)。

    表 22 AMDGPU 處理器

    處理器

    替代處理器

    目標三元組架構

    獨立顯示卡/加速處理器

    支援的目標功能

    目標屬性

    OS 支援(請參閱amdgpu-os和對應的執行階段發行說明,以取得目前的資訊和支援程度)

    範例產品

    Radeon HD 2000/3000 系列 (R600) [AMD-RADEON-HD-2000-3000]

    r600

    r600

    獨立顯示卡

    • 不支援通用位址空間

    r630

    r600

    獨立顯示卡

    • 不支援通用位址空間

    rs880

    r600

    獨立顯示卡

    • 不支援通用位址空間

    rv670

    r600

    獨立顯示卡

    • 不支援通用位址空間

    Radeon HD 4000 系列 (R700) [AMD-RADEON-HD-4000]

    rv710

    r600

    獨立顯示卡

    • 不支援通用位址空間

    rv730

    r600

    獨立顯示卡

    • 不支援通用位址空間

    rv770

    r600

    獨立顯示卡

    • 不支援通用位址空間

    Radeon HD 5000 系列 (Evergreen) [AMD-RADEON-HD-5000]

    cedar

    r600

    獨立顯示卡

    • 不支援通用位址空間

    cypress

    r600

    獨立顯示卡

    • 不支援通用位址空間

    juniper

    r600

    獨立顯示卡

    • 不支援通用位址空間

    redwood

    r600

    獨立顯示卡

    • 不支援通用位址空間

    sumo

    r600

    獨立顯示卡

    • 不支援通用位址空間

    Radeon HD 6000 系列 (Northern Islands) [AMD-RADEON-HD-6000]

    barts

    r600

    獨立顯示卡

    • 不支援通用位址空間

    caicos

    r600

    獨立顯示卡

    • 不支援通用位址空間

    cayman

    r600

    獨立顯示卡

    • 不支援通用位址空間

    turks

    r600

    獨立顯示卡

    • 不支援通用位址空間

    GCN GFX6 (Southern Islands (SI)) [AMD-GCN-GFX6]

    gfx600

    • tahiti

    amdgcn

    獨立顯示卡

    • 不支援通用位址空間

    • pal-amdpal

    gfx601

    • pitcairn

    • verde

    amdgcn

    獨立顯示卡

    • 不支援通用位址空間

    • pal-amdpal

    gfx602

    • hainan

    • oland

    amdgcn

    獨立顯示卡

    • 不支援通用位址空間

    • pal-amdpal

    GCN GFX7 (Sea Islands (CI)) [AMD-GCN-GFX7]

    gfx700

    • kaveri

    amdgcn

    加速處理器

    • 偏移量 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    • A6-7000

    • A6 Pro-7050B

    • A8-7100

    • A8 Pro-7150B

    • A10-7300

    • A10 Pro-7350B

    • FX-7500

    • A8-7200P

    • A10-7400P

    • FX-7600P

    gfx701

    • hawaii

    amdgcn

    獨立顯示卡

    • 偏移量 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    • FirePro W8100

    • FirePro W9100

    • FirePro S9150

    • FirePro S9170

    gfx702

    amdgcn

    獨立顯示卡

    • 偏移量 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    • Radeon R9 290

    • Radeon R9 290x

    • Radeon R390

    • Radeon R390x

    gfx703

    • kabini

    • mullins

    amdgcn

    加速處理器

    • 偏移量 flat scratch

    • pal-amdhsa

    • pal-amdpal

    • E1-2100

    • E1-2200

    • E1-2500

    • E2-3000

    • E2-3800

    • A4-5000

    • A4-5100

    • A6-5200

    • A4 Pro-3340B

    gfx704

    • bonaire

    amdgcn

    獨立顯示卡

    • 偏移量 flat scratch

    • pal-amdhsa

    • pal-amdpal

    • Radeon HD 7790

    • Radeon HD 8770

    • R7 260

    • R7 260X

    gfx705

    amdgcn

    加速處理器

    • 偏移量 flat scratch

    • pal-amdhsa

    • pal-amdpal

    待定

    GCN GFX8 (Volcanic Islands (VI)) [AMD-GCN-GFX8]

    gfx801

    • carrizo

    amdgcn

    加速處理器

    • xnack

    • 偏移量 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    • A6-8500P

    • Pro A6-8500B

    • A8-8600P

    • Pro A8-8600B

    • FX-8800P

    • Pro A12-8800B

    • A10-8700P

    • Pro A10-8700B

    • A10-8780P

    • A10-9600P

    • A10-9630P

    • A12-9700P

    • A12-9730P

    • FX-9800P

    • FX-9830P

    • E2-9010

    • A6-9210

    • A9-9410

    gfx802

    • iceland

    • tonga

    amdgcn

    獨立顯示卡

    • 偏移量 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    • Radeon R9 285

    • Radeon R9 380

    • Radeon R9 385

    gfx803

    • fiji

    amdgcn

    獨立顯示卡

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    • Radeon R9 Nano

    • Radeon R9 Fury

    • Radeon R9 FuryX

    • Radeon Pro Duo

    • FirePro S9300x2

    • Radeon Instinct MI8

    • polaris10

    amdgcn

    獨立顯示卡

    • 偏移量 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    • Radeon RX 470

    • Radeon RX 480

    • Radeon Instinct MI6

    • polaris11

    amdgcn

    獨立顯示卡

    • 偏移量 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    • Radeon RX 460

    gfx805

    • tongapro

    amdgcn

    獨立顯示卡

    • 偏移量 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    • FirePro S7150

    • FirePro S7100

    • FirePro W7100

    • Mobile FirePro M7170

    gfx810

    • stoney

    amdgcn

    加速處理器

    • xnack

    • 偏移量 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    待定

    GCN GFX9 (Vega) [AMD-GCN-GFX900-GFX904-VEGA] [AMD-GCN-GFX906-VEGA7NM] [AMD-GCN-GFX908-CDNA1] [AMD-GCN-GFX90A-CDNA2] [AMD-GCN-GFX942-CDNA3]

    gfx900

    amdgcn

    獨立顯示卡

    • xnack

    • 絕對 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    • Radeon Vega Frontier Edition

    • Radeon RX Vega 56

    • Radeon RX Vega 64

    • Radeon RX Vega 64 Liquid

    • Radeon Instinct MI25

    gfx902

    amdgcn

    加速處理器

    • xnack

    • 絕對 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    • Ryzen 3 2200G

    • Ryzen 5 2400G

    gfx904

    amdgcn

    獨立顯示卡

    • xnack

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    待定

    gfx906

    amdgcn

    獨立顯示卡

    • sramecc

    • xnack

    • 絕對 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    • Radeon Instinct MI50

    • Radeon Instinct MI60

    • Radeon VII

    • Radeon Pro VII

    gfx908

    amdgcn

    獨立顯示卡

    • sramecc

    • xnack

    • 絕對 flat scratch

    • rocm-amdhsa

    • AMD Instinct MI100 Accelerator

    gfx909

    amdgcn

    加速處理器

    • xnack

    • 絕對 flat scratch

    • pal-amdpal

    待定

    gfx90a

    amdgcn

    獨立顯示卡

    • sramecc

    • tgsplit

    • xnack

    • kernarg 預先載入(MI210 除外)

    • 絕對 flat scratch

    • 封裝的工作項目 ID

    • rocm-amdhsa

    • rocm-amdhsa

    • rocm-amdhsa

    • AMD Instinct MI210 Accelerator

    • AMD Instinct MI250 Accelerator

    • AMD Instinct MI250X Accelerator

    gfx90c

    amdgcn

    加速處理器

    • xnack

    • 絕對 flat scratch

    • pal-amdpal

    • Ryzen 7 4700G

    • Ryzen 7 4700GE

    • Ryzen 5 4600G

    • Ryzen 5 4600GE

    • Ryzen 3 4300G

    • Ryzen 3 4300GE

    • Ryzen Pro 4000G

    • Ryzen 7 Pro 4700G

    • Ryzen 7 Pro 4750GE

    • Ryzen 5 Pro 4650G

    • Ryzen 5 Pro 4650GE

    • Ryzen 3 Pro 4350G

    • Ryzen 3 Pro 4350GE

    gfx942

    amdgcn

    獨立顯示卡

    • sramecc

    • tgsplit

    • xnack

    • kernarg 預先載入

    • 架構化的 flat scratch

    • 封裝的工作項目 ID

    • AMD Instinct MI300X

    • AMD Instinct MI300A

    gfx950

    amdgcn

    獨立顯示卡

    • sramecc

    • tgsplit

    • xnack

    • kernarg 預先載入

    • 架構化的 flat scratch

    • 封裝的工作項目 ID

    待定

    GCN GFX10.1 (RDNA 1) [AMD-GCN-GFX10-RDNA1]

    gfx1010

    amdgcn

    獨立顯示卡

    • cumode

    • wavefrontsize64

    • xnack

    • 絕對 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    • Radeon RX 5700

    • Radeon RX 5700 XT

    • Radeon Pro 5600 XT

    • Radeon Pro 5600M

    gfx1011

    amdgcn

    獨立顯示卡

    • cumode

    • wavefrontsize64

    • xnack

    • 絕對 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    • Radeon Pro V520

    gfx1012

    amdgcn

    獨立顯示卡

    • cumode

    • wavefrontsize64

    • xnack

    • 絕對 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    • Radeon RX 5500

    • Radeon RX 5500 XT

    gfx1013

    amdgcn

    加速處理器

    • cumode

    • wavefrontsize64

    • xnack

    • 絕對 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    待定

    GCN GFX10.3 (RDNA 2) [AMD-GCN-GFX10-RDNA2]

    gfx1030

    amdgcn

    獨立顯示卡

    • cumode

    • wavefrontsize64

    • 絕對 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    • Radeon RX 6800

    • Radeon RX 6800 XT

    • Radeon RX 6900 XT

    • Radeon PRO W6800

    • Radeon PRO V620

    gfx1031

    amdgcn

    獨立顯示卡

    • cumode

    • wavefrontsize64

    • 絕對 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    • Radeon RX 6700 XT

    gfx1032

    amdgcn

    獨立顯示卡

    • cumode

    • wavefrontsize64

    • 絕對 flat scratch

    • rocm-amdhsa

    • pal-amdhsa

    • pal-amdpal

    待定

    gfx1033

    amdgcn

    加速處理器

    • cumode

    • wavefrontsize64

    • 絕對 flat scratch

    • pal-amdpal

    待定

    gfx1034

    amdgcn

    獨立顯示卡

    • cumode

    • wavefrontsize64

    • 絕對 flat scratch

    • pal-amdpal

    待定

    gfx1035

    amdgcn

    加速處理器

    • cumode

    • wavefrontsize64

    • 絕對 flat scratch

    • pal-amdpal

    待定

    gfx1036

    amdgcn

    加速處理器

    • cumode

    • wavefrontsize64

    • 絕對 flat scratch

    • pal-amdpal

    待定

    GCN GFX11 (RDNA 3) [AMD-GCN-GFX11-RDNA3]

    gfx1100

    amdgcn

    獨立顯示卡

    • cumode

    • wavefrontsize64

    • 架構化的 flat scratch

    • 封裝的工作項目 ID

    • pal-amdpal

    • Radeon PRO W7900 Dual Slot

    • Radeon PRO W7900

    • Radeon PRO W7800

    • Radeon RX 7900 XTX

    • Radeon RX 7900 XT

    • Radeon RX 7900 GRE

    gfx1101

    amdgcn

    獨立顯示卡

    • cumode

    • wavefrontsize64

    • 架構化的 flat scratch

    • 封裝的工作項目 ID

    待定

    gfx1102

    amdgcn

    獨立顯示卡

    • cumode

    • wavefrontsize64

    • 架構化的 flat scratch

    • 封裝的工作項目 ID

    待定

    gfx1103

    amdgcn

    加速處理器

    • cumode

    • wavefrontsize64

    • 架構化的 flat scratch

    • 封裝的工作項目 ID

    待定

    GCN GFX11 (RDNA 3.5) [AMD-GCN-GFX11-RDNA3.5]

    gfx1150

    amdgcn

    加速處理器

    • cumode

    • wavefrontsize64

    • 架構化的 flat scratch

    • 封裝的工作項目 ID

    待定

    gfx1151

    amdgcn

    加速處理器

    • cumode

    • wavefrontsize64

    • 架構化的 flat scratch

    • 封裝的工作項目 ID

    待定

    gfx1152

    amdgcn

    加速處理器

    • cumode

    • wavefrontsize64

    • 架構化的 flat scratch

    • 封裝的工作項目 ID

    待定

    gfx1153

    amdgcn

    加速處理器

    • cumode

    • wavefrontsize64

    • 架構化的 flat scratch

    • 封裝的工作項目 ID

    待定

    gfx1200

    amdgcn

    獨立顯示卡

    • cumode

    • wavefrontsize64

    • 架構化的 flat scratch

    • 封裝的工作項目 ID

    待定

    gfx1201

    amdgcn

    獨立顯示卡

    • cumode

    • wavefrontsize64

    • 架構化的 flat scratch

    • 封裝的工作項目 ID

    待定

通用處理器允許在它支援的任何處理器上執行單一程式碼物件。此類程式碼物件的效能可能不如非通用處理器的程式碼物件。

通用處理器僅在程式碼物件 V6 及更高版本上可用(請參閱ELF 程式碼物件)。

通用處理器程式碼物件已進行版本控制。請參閱通用處理器版本控制以取得有關版本控制如何運作的更多資訊。

表 23 AMDGPU 通用處理器

處理器

目標三元組架構

支援的處理器

支援的目標功能

目標屬性

目標限制

gfx9-generic

amdgcn

  • gfx900

  • gfx902

  • gfx904

  • gfx906

  • gfx909

  • gfx90c

  • xnack

  • 絕對 flat scratch

  • v_mad_mix 指令在 gfx900gfx902gfx909gfx90c 上不可用

  • v_fma_mix 指令在 gfx904 上不可用

  • sramecc 在 gfx906 上不可用

  • 以下指令在 gfx906 上不可用

    • v_fmac_f32

    • v_xnor_b32

    • v_dot4_i32_i8

    • v_dot8_i32_i4

    • v_dot2_i32_i16

    • v_dot2_u32_u16

    • v_dot4_u32_u8

    • v_dot8_u32_u4

    • v_dot2_f32_f16

gfx9-4-generic

amdgcn

  • gfx942

  • gfx950

  • sramecc

  • tgsplit

  • xnack

  • kernarg 預先載入

  • 架構化的 flat scratch

  • 封裝的工作項目 ID

FP8 和 BF8 指令、FP8 和 BF8 轉換指令,以及具有 XF32 格式支援的指令不可用。

gfx10-1-generic

amdgcn

  • gfx1010

  • gfx1011

  • gfx1012

  • gfx1013

  • xnack

  • wavefrontsize64

  • cumode

  • 絕對 flat scratch

  • 以下指令在 gfx1011gfx1012 上不可用

    • v_dot4_i32_i8

    • v_dot8_i32_i4

    • v_dot2_i32_i16

    • v_dot2_u32_u16

    • v_dot2c_f32_f16

    • v_dot4c_i32_i8

    • v_dot4_u32_u8

    • v_dot8_u32_u4

    • v_dot2_f32_f16

  • BVH 光線追蹤指令在 gfx1013 上不可用

gfx10-3-generic

amdgcn

  • gfx1030

  • gfx1031

  • gfx1032

  • gfx1033

  • gfx1034

  • gfx1035

  • gfx1036

  • wavefrontsize64

  • cumode

  • 絕對 flat scratch

無限制。

gfx11-generic

amdgcn

  • gfx1100

  • gfx1101

  • gfx1102

  • gfx1103

  • gfx1150

  • gfx1151

  • gfx1152

  • gfx1153

  • wavefrontsize64

  • cumode

  • 架構化的 flat scratch

  • 封裝的工作項目 ID

應用各種程式碼生成悲觀化,以解決此系列中某些目標特有的一些危害。

並非所有 VGPR 都可以在以下情況下使用

  • gfx1100

  • gfx1101

  • gfx1151

SALU 浮點指令在以下情況下不可用

  • gfx1150

  • gfx1151

  • gfx1152

  • gfx1153

SGPR 不支援在 dpp 指令中作為 src1,適用於

  • gfx1150

  • gfx1151

  • gfx1152

  • gfx1153

gfx12-generic

amdgcn

  • gfx1200

  • gfx1201

  • wavefrontsize64

  • cumode

  • 架構化的 flat scratch

  • 封裝的工作項目 ID

無限制。

通用處理器版本控制

通用處理器(請參閱AMDGPU 通用處理器)程式碼物件已進行版本控制(請參閱程式碼物件 V6 及更高版本的 AMDGPU ELF 標頭 e_flags),版本介於 1 到 255 之間。非通用程式碼物件的版本始終設定為 0。

對於通用程式碼物件,新增支援的處理器可能需要變更為通用目標產生的程式碼,以便它能夠繼續在先前支援的處理器以及新的處理器上執行。當這種情況發生時,通用程式碼物件版本號會與通用目標更新同時遞增。

通用目標的每個支援處理器都映射到它引入的版本。如果載入的程式碼物件版本大於或等於處理器新增到通用目標的版本,則通用程式碼物件可以在支援的處理器上執行。

目標功能

目標功能控制如何生成程式碼以支援某些處理器特定的功能。並非所有處理器都支援所有目標功能。執行階段必須確保用於執行程式碼的裝置所支援的功能與生成程式碼時啟用的功能相符。功能不符可能會導致執行不正確,或效能降低。

每個處理器支援的目標功能列在處理器中。

目標功能由以下 Clang 選項之一精確控制

-mcpu=<target-id>--offload-arch=<target-id>

-mcpu--offload-arch 可以將目標功能指定為目標 ID 的可選組件。如果省略,目標功能具有 any 值。請參閱目標 ID

-m[no-]<target-feature>

未由目標 ID 指定的目標功能使用單獨的選項指定。這些目標功能可以具有 onoff 值。on 通過省略 no- 前綴來指定,而 off 通過包含 no- 前綴來指定。如果未指定,則預設為 off

例如

-mcpu=gfx908:xnack+

啟用 xnack 功能。

-mcpu=gfx908:xnack-

停用 xnack 功能。

-mcumode

啟用 cumode 功能。

-mno-cumode

停用 cumode 功能。

表 24 AMDGPU 目標功能

目標功能

控制的 Clang 選項

描述

名稱

cumode

  • -m[no-]cumode

控制為核心生成程式碼時使用的 wavefront 執行模式。停用時,使用原生 WGP wavefront 執行模式;啟用時,使用 CU wavefront 執行模式(請參閱記憶體模型)。

sramecc

  • -mcpu

  • --offload-arch

如果指定,則生成只能在具有 SRAMECC 相符設定的程序中載入和執行的程式碼。

如果未針對程式碼物件 V2 至 V3 指定,則生成可以在啟用 SRAMECC 的程序中載入和執行的程式碼。

如果未針對程式碼物件 V4 或更高版本指定,則生成可以在具有 SRAMECC 任一設定的程序中載入和執行的程式碼。

tgsplit

-m[no-]tgsplit

啟用/停用生成假設工作群組以 threadgroup 分割模式啟動的程式碼。啟用後,工作群組的 wave 可能會在不同的 CU 中啟動。

wavefrontsize64

  • -m[no-]wavefrontsize64

控制為核心生成程式碼時使用的 wavefront 大小。停用時,使用原生 wavefront 大小 32;啟用時,使用 wavefront 大小 64。

xnack

  • -mcpu

  • --offload-arch

如果指定,則生成只能在具有 XNACK 重播相符設定的程序中載入和執行的程式碼。

如果未針對程式碼物件 V2 至 V3 指定,則生成可以在啟用 XNACK 重播的程序中載入和執行的程式碼。

如果未針對程式碼物件 V4 或更高版本指定,則生成可以在具有 XNACK 重播任一設定的程序中載入和執行的程式碼。

XNACK 重播可用於按需分頁和頁面遷移。如果在裝置中啟用,則如果發生頁面錯誤,除非使用啟用 XNACK 重播生成,或針對程式碼物件 V4 或更高版本生成且未指定 XNACK 重播,否則程式碼可能執行不正確。在未啟用 XNACK 重播的裝置上執行使用啟用 XNACK 重播生成的程式碼,或針對程式碼物件 V4 或更高版本生成且未指定 XNACK 重播的程式碼,將正確執行,但效能可能不如針對停用 XNACK 重播生成的程式碼。

目標 ID

AMDGPU 支援目標 ID。請參閱Clang Offload Bundler以取得一般描述。AMDGPU 目標特定資訊為

處理器

是在AMDGPU 處理器中指定的 AMDGPU 處理器或替代處理器名稱。非標準形式的目標 ID 允許主要處理器和替代處理器名稱。標準形式的目標 ID 僅允許主要處理器名稱。

目標功能

是在AMDGPU 目標功能中指定的目標功能名稱,處理器支援該功能。每個處理器支援的目標功能在AMDGPU 處理器中指定。可以在目標 ID 中指定的那些功能標記為由 -mcpu--offload-arch 控制。每個目標功能在目標 ID 中最多只能出現一次。非標準形式的目標 ID 允許以任何順序指定目標功能。標準形式的目標 ID 要求以字母順序指定目標功能。

程式碼物件 V2 至 V3 目標 ID

程式碼物件 V2 至 V3 的目標 ID 語法與Clang Offload Bundler中定義的語法相同,但用於.amdgcn_target <target-triple> “-” <target-id>組譯器指令和捆綁條目 ID 時除外。在這些情況下,它具有以下 BNF 語法

<target-id> ::== <processor> ( "+" <target-feature> )*

其中,如果目標功能為Off,則省略,如果為OnAny,則存在。

注意

程式碼物件 V2 至 V3 無法表示 Any,並將其視為與 On 相同。

嵌入捆綁的程式碼物件

AMDGPU 支援 HIP 和 OpenMP 語言,這些語言執行程式碼物件嵌入,如Clang Offload Bundler中所述。

注意

用於捆綁條目 ID 的程式碼物件 V2 至 V3 的目標 ID 語法與其他地方使用的語法不同。請參閱程式碼物件 V2 至 V3 目標 ID

位址空間

AMDGPU 架構支援許多記憶體位址空間。位址空間名稱使用 OpenCL 標準名稱,並新增了一些名稱。

AMDGPU 位址空間對應於 LLVM IR 中使用的目標架構特定 LLVM 位址空間編號。

AMDGPU 位址空間在AMDGPU 位址空間中描述。對於 amdgcn 目標,僅支援 64 位元程序位址空間。

表 25 AMDGPU 位址空間

64 位元程序位址空間

位址空間名稱

LLVM IR 位址空間編號

HSA 區段名稱

硬體名稱

位址大小

NULL 值

通用

0

flat

flat

64

0x0000000000000000

全域

1

global

global

64

0x0000000000000000

區域

2

不適用

GDS

32

未針對 AMDHSA 實作

本地

3

group

LDS

32

0xFFFFFFFF

常數

4

constant

與全域相同

64

0x0000000000000000

私有

5

private

scratch

32

0xFFFFFFFF

常數 32 位元

6

待辦事項

0x00000000

緩衝區 Fat 指標

7

不適用

不適用

160

0

緩衝區資源

8

不適用

V#

128

0x00000000000000000000000000000000

緩衝區跨步指標(實驗性)

9

待辦事項

Streamout 暫存器

128

不適用

GS_REGS

通用

除非AMDGPU 處理器目標屬性欄位指定不支援通用位址空間,否則支援通用位址空間。

通用位址空間使用硬體 flat 位址支援兩個固定範圍的虛擬位址(私有和本地 aperture),這些位址位於可定址全域記憶體範圍之外,以將 flat 位址映射到私有或本地位址。這使用 FLAT 指令,這些指令可以採用 flat 位址並存取全域、私有 (scratch) 和群組 (LDS) 記憶體,具體取決於位址是否在其中一個 aperture 範圍內。

對 scratch 進行 Flat 存取需要硬體 aperture 設定以及核心序言中的設定(請參閱Flat Scratch)。對 LDS 進行 Flat 存取需要硬體 aperture 設定和 M0 (GFX7-GFX8) 暫存器設定(請參閱M0)。

若要在私有或群組位址空間位址(稱為區段位址)和 flat 位址之間轉換,可以使用對應 aperture 的基準位址。對於 GFX7-GFX8,這些位址可在HSA AQL 佇列中取得,可以使用佇列指標 SGPR(請參閱初始核心執行狀態)取得其位址。對於 GFX9-GFX11,aperture 基準位址可直接作為內嵌常數暫存器 SRC_SHARED_BASE/LIMITSRC_PRIVATE_BASE/LIMIT 使用。在 64 位元位址模式下,aperture 大小為 2^32 位元組,基準與 2^32 對齊,這使得從 flat 到區段或從區段到 flat 的轉換更容易。

全域位址空間位址在用作 flat 位址時具有相同的值,因此不需要轉換。

全域和常數

全域和常數位址空間都使用全域虛擬位址,這與 CPU 使用的虛擬位址空間相同。但是,某些虛擬位址可能僅可由 CPU 存取,某些僅可由 GPU 存取,而某些則可由兩者存取。

使用常數位址空間表示資料在核心執行期間不會變更。這允許使用純量讀取指令。由於常數位址空間只能在主機端修改,因此從常數位址空間載入的通用指標可以安全地假定為全域指標,因為只有裝置全域記憶體在主機端可見和管理。向量和純量 L1 快取會在每次核心分派執行之前使揮發性資料失效,以允許常數記憶體在核心分派之間變更值。

區域

區域位址空間使用硬體全域資料儲存區 (GDS)。在相同裝置上執行的所有 wavefront,對於任何給定的區域位址都將存取相同的記憶體。然而,由不同裝置上執行的 wavefront 存取相同的區域位址,將存取不同的記憶體。它的效能比全域記憶體更高。它由執行時期配置。資料儲存區 (DS) 指令可用於存取它。

本地

區域位址空間使用硬體區域資料儲存區 (LDS),它在硬體建立工作群組的 wavefront 時自動配置,並在工作群組的所有 wavefront 終止時釋放。屬於相同工作群組的所有 wavefront,對於任何給定的區域位址都將存取相同的記憶體。然而,由不同工作群組的 wavefront 存取相同的區域位址,將存取不同的記憶體。它的效能比全域記憶體更高。資料儲存區 (DS) 指令可用於存取它。

私有

私有位址空間使用硬體暫存記憶體支援,它在建立 wavefront 時自動配置記憶體,並在 wavefront 終止時釋放記憶體。wavefront 的 lane 對於任何給定的私有位址所存取的記憶體,會與相同或不同 wavefront 的另一個 lane 對於相同私有位址所存取的記憶體不同。

如果核心調度使用暫存記憶體,則硬體會從執行時期為每個 wavefront 配置的後備記憶體池中配置記憶體。wavefront 的 lane 使用 dword (4 位元組) 交錯方式存取此記憶體。從私有位址到後備記憶體位址的映射關係是

wavefront-scratch-base + ((private-address / 4) * wavefront-size * 4) + (wavefront-lane-id * 4) + (private-address % 4)

如果 wavefront 的每個 lane 都存取相同的私有位址,則交錯會導致存取相鄰的 dword,因此需要提取的快取線更少。

wavefront 暫存基底位址由 wavefront 決定的方式有多種(請參閱 初始核心執行狀態)。

可以使用帶有暫存緩衝區描述符和每個 wavefront 暫存偏移的緩衝區指令、暫存指令或平面指令,以交錯方式存取暫存記憶體。除了 GFX9-GFX11 中的平面和暫存指令外,不支援多 dword 存取。

在 wavefront 的其他 lane 中操作堆疊值的程式碼,例如透過將堆疊指標 addrspacecast 轉換為通用指標並取得到達其他 lane 的偏移量,或透過顯式建構暫存緩衝區描述符,當它修改其他 lane 的暫存值時,會觸發未定義的行為。編譯器可能會假設此類修改不會發生。當使用程式碼物件 V5 時,可以使用 LIBOMPTARGET_STACK_SIZE 來提供私有區段大小(以位元組為單位),以用於使用動態堆疊的情況。

常數 32 位元

待辦事項

緩衝區 Fat 指標

緩衝區胖指標是一種實驗性的位址空間,目前在後端不支援。它公開了一個非整數指標,未來旨在支援 128 位元緩衝區描述符加上 32 位元緩衝區偏移量的建模(總共封裝一個 160 位元指標),允許使用正常的 LLVM 載入/儲存/原子操作來建模在圖形工作負載中大量使用的緩衝區描述符,目標是後端。

用於建構緩衝區胖指標的緩衝區描述符必須是原始的:步幅必須為 0,“add tid” 標誌必須為 0,swizzle 啟用位元必須關閉,並且範圍必須以位元組為單位測量。(在可能禁用邊界檢查的子目標上,緩衝區胖指標可能會選擇啟用或不啟用它)。gfx942 中引入的快取 swizzle 支援可以使用。

這些指標可以透過從緩衝區資源 (ptr addrspace(8)) 進行 addrspacecast 或使用 llvm.amdgcn.make.buffer.rsrc 直接產生 ptr addrspace(7) 來建立,這會產生初始偏移量為 0 的緩衝區胖指標,並防止位址空間轉換被重寫掉。

緩衝區資源

位址空間 8 中的緩衝區資源指標是 AMDGPU IR 中表示緩衝區描述符的較新形式,取代了先前作為 <4 x i32> 的表示形式。它是一個非整數指標,表示 128 位元緩衝區描述符資源 (V#)。

由於一般來說,緩衝區資源支援 LLVM 中不易表示的複雜定址模式(例如對結構化緩衝區的隱式 swizzle 存取),因此對緩衝區資源執行非平凡的位址計算(例如 getelementptr 操作)是非法的。它們可以傳遞給 AMDGPU 緩衝區內建函數,並且可以在 i128 之間相互轉換。

允許將緩衝區資源轉換為緩衝區胖指標,並新增 0 的偏移量。

緩衝區資源可以使用 llvm.amdgcn.make.buffer.rsrc 內建函數從 64 位元指標(應為通用或全域)建立,該內建函數採用指標(成為資源的基底)、儲存在 V# 的位元 63:48 中的 16 位元步幅(和 swizzle 控制)欄位、32 位元 NumRecords/範圍欄位(位元 95:64)和 32 位元標誌欄位(位元 127:96)。這些欄位的具體解釋因目標架構而異,並在 ISA 描述中詳細說明。

緩衝區步幅指標

緩衝區索引指標是一種實驗性的位址空間。它表示一個 128 位元緩衝區描述符和一個 32 位元偏移量,就像緩衝區胖指標一樣。此外,它還包含一個緩衝區索引,允許直接定址結構化元素。這些組件按此順序出現,即描述符首先出現,然後是 32 位元偏移量,然後是 32 位元索引。

緩衝區描述符中的位元必須滿足以下要求:步幅是結構化元素的大小,“add tid” 標誌必須為 0,並且 swizzle 啟用位元必須關閉。

這些指標可以透過從緩衝區資源 (ptr addrspace(8)) 進行 addrspacecast 或使用 llvm.amdgcn.make.buffer.rsrc 直接產生 ptr addrspace(9) 來建立,這會產生初始索引和偏移量值均為 0 的緩衝區步幅指標。這可防止位址空間轉換被重寫掉。

Streamout 暫存器

GS NGG Streamout 指令使用的專用暫存器。暫存器檔案被建模為不同位址空間中的記憶體,因為它由類似位址的偏移量而不是具名暫存器索引,並且因為暫存器存取會影響 LGKMcnt。這是僅供編譯器使用的內部位址空間。請勿將此位址空間用於 IR 指標。

記憶體範圍

本節提供當目標三元組 OS 為 amdhsa 時,AMDGPU 後端記憶體模型支援的 LLVM 記憶體同步範圍(請參閱 記憶體模型目標三元組)。

支援的記憶體模型基於 HSA 記憶體模型 [HSA],而 HSA 記憶體模型又基於具有範圍包含的 HRF-indirect [HRF]。先行發生關係在同步關係上是可傳遞的,與範圍無關,並且同步關係允許記憶體範圍實例是包含性的(請參閱表 AMDHSA LLVM 同步範圍)。

這與 OpenCL [OpenCL] 記憶體模型不同,後者沒有範圍包含,並且要求記憶體範圍完全匹配。但是,對於 OpenCL 來說,這是保守正確的。

表 26 AMDHSA LLVM 同步範圍

LLVM 同步範圍

描述

none

預設值:system

與其他操作同步,並參與其他操作的修改和 seq_cst 總排序(影像操作除外),適用於所有位址空間(私有或存取私有的通用位址空間除外),前提是其他操作的同步範圍是

  • system.

  • agent 且由同一代理上的執行緒執行。

  • workgroup 且由同一工作群組中的執行緒執行。

  • wavefront 且由同一 wavefront 中的執行緒執行。

agent

與其他操作同步,並參與其他操作的修改和 seq_cst 總排序(影像操作除外),適用於所有位址空間(私有或存取私有的通用位址空間除外),前提是其他操作的同步範圍是

  • systemagent 且由同一代理上的執行緒執行。

  • workgroup 且由同一工作群組中的執行緒執行。

  • wavefront 且由同一 wavefront 中的執行緒執行。

workgroup

與其他操作同步,並參與其他操作的修改和 seq_cst 總排序(影像操作除外),適用於所有位址空間(私有或存取私有的通用位址空間除外),前提是其他操作的同步範圍是

  • systemagentworkgroup 且由同一工作群組中的執行緒執行。

  • wavefront 且由同一 wavefront 中的執行緒執行。

wavefront

與其他操作同步,並參與其他操作的修改和 seq_cst 總排序(影像操作除外),適用於所有位址空間(私有或存取私有的通用位址空間除外),前提是其他操作的同步範圍是

  • systemagentworkgroupwavefront 且由同一 wavefront 中的執行緒執行。

singlethread

僅與在相同執行緒中執行的其他操作(影像操作除外)同步,並參與其他操作的修改和 seq_cst 總排序,適用於所有位址空間(例如,在訊號處理常式中)。

one-as

system 相同,但僅與相同位址空間內的其他操作同步。

agent-one-as

agent 相同,但僅與相同位址空間內的其他操作同步。

workgroup-one-as

workgroup 相同,但僅與相同位址空間內的其他操作同步。

wavefront-one-as

wavefront 相同,但僅與相同位址空間內的其他操作同步。

singlethread-one-as

singlethread 相同,但僅與相同位址空間內的其他操作同步。

LLVM IR 內建函數

AMDGPU 後端實作了以下 LLVM IR 內建函數。

本節尚在建構中 (WIP)。

表 27 AMDGPU LLVM IR 內建函數

LLVM 內建函數

描述

llvm.amdgcn.sqrt

提供對 v_sqrt_f64、v_sqrt_f32 和 v_sqrt_f16 (在支援 half 的目標上) 的直接存取。執行 sqrt 函數。

llvm.amdgcn.log

提供對 v_log_f32 和 v_log_f16 (在支援 half 的目標上) 的直接存取。執行 log2 函數。

llvm.amdgcn.exp2

提供對 v_exp_f32 和 v_exp_f16 (在支援 half 的目標上) 的直接存取。執行 exp2 函數。

llvm.frexp

針對 half、float 和 double 實作。

llvm.log2

針對 float 和 half(以及 float 或 half 的向量)實作。未針對 double 實作。硬體為 float 提供 1ULP 準確度,為 half 提供 0.51ULP 準確度。Float 指令本機不支援次常態輸入。

llvm.sqrt

針對 double、float 和 half(以及向量)實作。

llvm.log

針對 float 和 half(以及向量)實作。

llvm.exp

針對 float 和 half(以及向量)實作。

llvm.log10

針對 float 和 half(以及向量)實作。

llvm.exp2

針對 float 和 half(以及 float 或 half 的向量)實作。未針對 double 實作。硬體為 float 提供 1ULP 準確度,為 half 提供 0.51ULP 準確度。Float 指令本機不支援次常態輸入。

llvm.stacksave.p5

已實作,必須使用 alloca 位址空間。

llvm.stackrestore.p5

已實作,必須使用 alloca 位址空間。

llvm.get.fpmode.i32

自然浮點模式類型為 i32。這是透過使用 s_getreg_b32 從 MODE 暫存器中提取相關位元來實作的。前 10 個位元是核心浮點模式。位元 12:18 是例外遮罩。在 gfx9+ 上,位元 23 是 FP16_OVFL。與浮點指令無關的位元欄位為 0。

llvm.get.rounding

AMDGPU 支援兩種可獨立控制的捨入模式,具體取決於浮點類型。一種控制 float,另一種控制 double 和 half 操作。如果兩種模式相同,則傳回標準傳回值之一。如果模式不同,則傳回 12 個擴展值 之一,描述兩種模式。

不支援捨入到最接近值,遠離零的 ties。MODE 暫存器中的原始捨入模式值與 FLT_ROUNDS 值不完全匹配,因此會執行轉換。

llvm.set.rounding

輸入值預期為 'llvm.get.rounding' 的有效結果之一。如果未傳遞有效輸入,則捨入模式未定義。這應該是 wavefront 一致的值。在輸入值發散的情況下,將使用第一個活動 lane 的值。

llvm.get.fpenv

傳回 AMDGPU 浮點環境的目前值。這會儲存與目前捨入模式、反常態化模式、已啟用陷阱和浮點例外相關的資訊。格式是 MODE 和 TRAPSTS 暫存器的 64 位元串連。

llvm.set.fpenv

將浮點環境設定為指定狀態。

llvm.amdgcn.readfirstlane

提供對 v_readfirstlane_b32 的直接存取。傳回輸入運算元中最低活動 lane 的值。目前針對 i16、i32、float、half、bfloat、<2 x i16>、<2 x half>、<2 x bfloat>、i64、double、指標、32 位元向量的倍數實作。

llvm.amdgcn.readlane

提供對 v_readlane_b32 的直接存取。傳回第一個輸入運算元的指定 lane 中的值。第二個運算元指定要從哪個 lane 讀取。目前針對 i16、i32、float、half、bfloat、<2 x i16>、<2 x half>、<2 x bfloat>、i64、double、指標、32 位元向量的倍數實作。

llvm.amdgcn.writelane

提供對 v_writelane_b32 的直接存取。將第一個輸入運算元中的值寫入發散輸出的指定 lane。第二個運算元指定要寫入的 lane。目前針對 i16、i32、float、half、bfloat、<2 x i16>、<2 x half>、<2 x bfloat>、i64、double、指標、32 位元向量的倍數實作。

llvm.amdgcn.wave.reduce.umin

對 wavefront 中每個 lane 提供的無號值執行算術無號最小值縮減。內建函數採用第二個運算元 0 的縮減策略提示:目標預設偏好、1:迭代策略 和 2:DPP。如果目標不支援 DPP 操作(例如 gfx6/7),則將使用預設迭代策略執行縮減。內建函數目前僅針對 i32 實作。

llvm.amdgcn.wave.reduce.umax

對 wavefront 中每個 lane 提供的無號值執行算術無號最大值縮減。內建函數採用第二個運算元 0 的縮減策略提示:目標預設偏好、1:迭代策略 和 2:DPP。如果目標不支援 DPP 操作(例如 gfx6/7),則將使用預設迭代策略執行縮減。內建函數目前僅針對 i32 實作。

llvm.amdgcn.permlane16

提供對 v_permlane16_b32 的直接存取。在第二個輸入運算元的列(16 個連續 lane)內執行任意收集樣式操作。第三個和第四個輸入必須是純量值。這些值組合為單個 64 位元值,表示用於在每列中 swizzle 的 lane 選擇。目前針對 i16、i32、float、half、bfloat、<2 x i16>、<2 x half>、<2 x bfloat>、i64、double、指標、32 位元向量的倍數實作。

llvm.amdgcn.permlanex16

提供對 v_permlanex16_b32 的直接存取。在第二個輸入運算元的兩列(每列 16 個連續 lane)之間執行任意收集樣式操作。第三個和第四個輸入必須是純量值。這些值組合為單個 64 位元值,表示用於在每列中 swizzle 的 lane 選擇。目前針對 i16、i32、float、half、bfloat、<2 x i16>、<2 x half>、<2 x bfloat>、i64、double、指標、32 位元向量的倍數實作。

llvm.amdgcn.permlane64

提供對 v_permlane64_b32 的直接存取。在輸入運算元的 lane 之間執行特定排列,其中 wave64 的高半部分和低半部分交換。在 wave32 模式下不執行任何操作。目前針對 i16、i32、float、half、bfloat、<2 x i16>、<2 x half>、<2 x bfloat>、i64、double、指標、32 位元向量的倍數實作。

llvm.amdgcn.udot2

在支援此類指令的目標上提供對 v_dot2_u32_u16 的直接存取。這使用兩個 v2i16 運算元執行無號點積,並與第三個 i32 運算元求和。i1 第四個運算元用於鉗制輸出。

llvm.amdgcn.udot4

在支援此類指令的目標上提供對 v_dot4_u32_u8 的直接存取。這使用兩個 i32 運算元(持有 4 個 8 位元值的向量)執行無號點積,並與第三個 i32 運算元求和。i1 第四個運算元用於鉗制輸出。

llvm.amdgcn.udot8

在支援此類指令的目標上提供對 v_dot8_u32_u4 的直接存取。這使用兩個 i32 運算元(持有 8 個 4 位元值的向量)執行無號點積,並與第三個 i32 運算元求和。i1 第四個運算元用於鉗制輸出。

llvm.amdgcn.sdot2

在支援此類指令的目標上提供對 v_dot2_i32_i16 的直接存取。這使用兩個 v2i16 運算元執行有號點積,並與第三個 i32 運算元求和。i1 第四個運算元用於鉗制輸出。在適用的情況下(例如,無鉗制),這會降低為支援它的目標的 v_dot2c_i32_i16。

llvm.amdgcn.sdot4

在支援此類指令的目標上提供對 v_dot4_i32_i8 的直接存取。這使用兩個 i32 運算元(持有 4 個 8 位元值的向量)執行有號點積,並與第三個 i32 運算元求和。i1 第四個運算元用於鉗制輸出。在適用的情況下(即,無鉗制/運算元修飾符),這會降低為支援它的目標的 v_dot4c_i32_i8。RDNA3 不提供 v_dot4_i32_i8,而是提供 v_dot4_i32_iu8,後者具有用於保存向量運算元符號的運算元。因此,此內建函數會降低為 gfx11 目標的此指令的有號版本。

llvm.amdgcn.sdot8

在支援此類指令的目標上提供對 v_dot8_u32_u4 的直接存取。這使用兩個 i32 運算元(持有 8 個 4 位元值的向量)執行有號點積,並與第三個 i32 運算元求和。i1 第四個運算元用於鉗制輸出。在適用的情況下(即,無鉗制/運算元修飾符),這會降低為支援它的目標的 v_dot8c_i32_i4。RDNA3 不提供 v_dot8_i32_i4,而是提供 v_dot4_i32_iu4,後者具有用於保存向量運算元符號的運算元。因此,此內建函數會降低為 gfx11 目標的此指令的有號版本。

llvm.amdgcn.sudot4

在 gfx11 目標上提供對 v_dot4_i32_iu8 的直接存取。這使用兩個 i32 運算元(持有 4 個 8 位元值的向量)執行點積,並與第五個 i32 運算元求和。i1 第六個運算元用於鉗制輸出。向量運算元之前的 i1 決定符號。

llvm.amdgcn.sudot8

在 gfx11 目標上提供對 v_dot8_i32_iu4 的直接存取。這使用兩個 i32 運算元(持有 8 個 4 位元值的向量)執行點積,並與第五個 i32 運算元求和。i1 第六個運算元用於鉗制輸出。向量運算元之前的 i1 決定符號。

llvm.amdgcn.sched.barrier

控制在指令排程期間可能允許跨越內建函數的指令類型。參數是可用於跨越內建函數排程的指令類型的遮罩。

  • 0x0000:不允許任何指令跨越 sched_barrier 進行排程。

  • 0x0001:所有非記憶體、非產生副作用的指令都可以跨越 sched_barrier 進行排程,允許 ALU 指令通過。

  • 0x0002:VALU 指令可以跨越 sched_barrier 進行排程。

  • 0x0004:SALU 指令可以跨越 sched_barrier 進行排程。

  • 0x0008:MFMA/WMMA 指令可以跨越 sched_barrier 進行排程。

  • 0x0010:所有 VMEM 指令都可以跨越 sched_barrier 進行排程。

  • 0x0020:VMEM 讀取指令可以跨越 sched_barrier 進行排程。

  • 0x0040:VMEM 寫入指令可以跨越 sched_barrier 進行排程。

  • 0x0080:所有 DS 指令都可以跨越 sched_barrier 進行排程。

  • 0x0100:所有 DS 讀取指令都可以跨越 sched_barrier 進行排程。

  • 0x0200:所有 DS 寫入指令都可以跨越 sched_barrier 進行排程。

  • 0x0400:所有超越函數(例如 V_EXP)指令都可以跨越 sched_barrier 進行排程。

llvm.amdgcn.sched.group.barrier

建立具有特定屬性的排程群組,以建立自訂排程管線。群組之間的排序由指令排程器強制執行。內建函數適用於內建函數之前的程式碼。內建函數採用三個值來控制排程群組的行為。

  • Mask:使用 llvm.amdgcn.sched_barrier 遮罩值對指令群組進行分類。

  • Size:群組中的指令數量。

  • SyncID:在具有匹配值的群組之間強制執行排序。

遮罩可以包含多個指令類型。設定超出有效遮罩範圍的值是未定義的行為。

組合多個 sched_group_barrier 內建函數可以在指令排程期間啟用特定指令類型的排序。例如,以下程式碼強制執行 1 個 VMEM 讀取、接著 1 個 VALU 指令,再接著 5 個 MFMA 指令的序列。

// 1 VMEM read
__builtin_amdgcn_sched_group_barrier(32, 1, 0)
// 1 VALU
__builtin_amdgcn_sched_group_barrier(2, 1, 0)
// 5 MFMA
__builtin_amdgcn_sched_group_barrier(8, 5, 0)

llvm.amdgcn.iglp.opt

用於指令群組級並行性的實驗性內建函數。內建函數實作預定義的指令排程排序。內建函數適用於周圍的排程區域。內建函數採用一個值來指定策略。編譯器實作了兩種策略。

  1. 交錯小型 GEMM 核心的 DS 和 MFMA 指令。

  2. 交錯單個 wave 小型 GEMM 核心的 DS 和 MFMA 指令。

  3. 交錯注意核心的 TRANS 和 MFMA 指令,以及它們的 VALU 和 DS 前導指令。

  4. 交錯注意核心的 TRANS 和 MFMA 指令,但不交錯前導指令。

在排程區域中只能使用一個 iglp_opt 內建函數。iglp_opt 內建函數不能與 sched_barrier 或 sched_group_barrier 組合使用。

iglp_opt 策略實作可能會變更。

llvm.amdgcn.atomic.cond.sub.u32

在 gfx12 目標上,根據位址空間提供對 flat_atomic_cond_sub_u32、global_atomic_cond_sub_u32 和 ds_cond_sub_u32 的直接存取。僅當記憶體值大於或等於資料值時,才執行減法。

llvm.amdgcn.s.getpc

提供對 s_getpc_b64 指令的存取,但即使在 s_getpc_b64 指令傳回零擴展值的處理器上,傳回值也會從底層 PC 硬體暫存器的寬度進行符號擴展。

llvm.amdgcn.ballot

傳回一個位元欄位(i32 或 i64),其中包含其 i1 引數在所有活動 lane 中的結果,以及在所有非活動 lane 中的零。提供一種將 LLVM IR 中的 i1 轉換為 i32 或 i64 lane 遮罩的方法 - 硬體用於控制 EXEC 暫存器中使用之活動 lane 的位元欄位。例如,ballot(i1 true) 傳回 EXEC 遮罩。

llvm.amdgcn.mfma.scale.f32.16x16x128.f8f6f4

發射 v_mfma_scale_f32_16x16x128_f8f6f4 以設定縮放因子。最後 4 個運算元對應於縮放輸入。

  • 用於矩陣 A 的每個 lane 的 2 位元組索引

  • 矩陣 A 縮放值

  • 用於矩陣 B 的每個 lane 的 2 位元組索引

  • 矩陣 B 縮放值

llvm.amdgcn.mfma.scale.f32.32x32x64.f8f6f4

發射 v_mfma_scale_f32_32x32x64_f8f6f4

llvm.amdgcn.permlane16.swap

在支援的目標上提供對 v_permlane16_swap_b32 指令的直接存取。交換前 2 個運算元的 lane 之間的值。第一個運算元的奇數列與第二個運算元的偶數列交換(一列為 16 個 lane)。傳回交換暫存器的配對。傳回的第一個元素對應於第一個引數的交換元素。

llvm.amdgcn.permlane32.swap

在支援的目標上提供對 v_permlane32_swap_b32 指令的直接存取。交換前 2 個運算元的 lane 之間的值。第一個運算元的第 2 列和第 3 列與第二個運算元的第 0 列和第 1 列交換(一列為 16 個 lane)。傳回交換暫存器的配對。傳回的第一個元素對應於第一個引數的交換元素。

llvm.amdgcn.mov.dpp

llvm.amdgcn.mov.dpp.`<type>` 內建函數表示 AMDGPU 中的 mov.dpp 操作。此操作已棄用,可以使用 llvm.amdgcn.update.dpp 替換。

llvm.amdgcn.update.dpp

llvm.amdgcn.update.dpp.`<type>` 內建函數表示 AMDGPU 中的 update.dpp 操作。它採用舊值、來源運算元、DPP 控制運算元、列遮罩、bank 遮罩和邊界控制。支援各種資料類型,包括 bf16、f16、f32、f64、i16、i32、i64、p0、p3、p5、v2f16、v2f32、v2i16、v2i32、v2p0、v3i32、v4i32、v8f16。此操作等效於 v_mov_b32 操作序列。在未來使用中,它優先於 llvm.amdgcn.mov.dpp.`<type>`。llvm.amdgcn.update.dpp.<type> <old> <src> <dpp_ctrl> <row_mask> <bank_mask> <bound_ctrl> 應等效於:- v_mov_b32 <dest> <old> - v_mov_b32 <dest> <src> <dpp_ctrl> <row_mask> <bank_mask> <bound_ctrl>

LLVM IR Metadata

AMDGPU 後端實作了以下目標自訂 LLVM IR metadata。

amdgpu.last.use’ Metadata

在支援 TH_LOAD_LU 時間性提示的載入指令上設定 TH_LOAD_LU 時間性提示。優先於非時間性提示 (TH_LOAD_NT)。這不帶任何引數。

%val = load i32, ptr %in, align 4, !amdgpu.last.use !{}

amdgpu.no.remote.memory’ Metadata

斷言記憶體操作不會存取主機記憶體或遠端連線的對等裝置記憶體中的位元組(位址必須是裝置本機的)。這旨在用於 atomicrmw 和其他原子指令。這是發射某些子目標上某些 系統範圍 原子操作的本機硬體指令所必需的。對於大多數整數原子操作,這是發射本機原子指令的充分限制。

沒有 metadata 的 atomicrmw 將被保守地視為需要在所有情況下保留操作行為。這通常會與 !amdgpu.no.fine.grained.memory 結合使用。

; Indicates the atomic does not access fine-grained memory, or
; remote device memory.
%old0 = atomicrmw sub ptr %ptr0, i32 1 acquire, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory !0

; Indicates the atomic does not access peer device memory.
%old2 = atomicrmw sub ptr %ptr2, i32 1 acquire, !amdgpu.no.remote.memory !0

!0 = !{}

amdgpu.no.fine.grained.memory’ Metadata

聲明記憶體存取不會存取在細粒度分配記憶體中分配的位元組。這旨在與 atomicrmw 和其他原子指令一起使用。 為了在某些子目標上針對某些 系統範圍 原子操作發出原生硬體指令,這是必需的。 沒有 metadata 的 atomicrmw 將被保守地視為在所有情況下都必須保留操作行為。 這通常會與 !amdgpu.no.remote.memory.access 結合使用。

; Indicates the access does not access fine-grained memory, or
; remote device memory.
%old0 = atomicrmw sub ptr %ptr0, i32 1 acquire, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0

; Indicates the access does not access fine-grained memory
%old2 = atomicrmw sub ptr %ptr2, i32 1 acquire, !amdgpu.no.fine.grained.memory !0

!0 = !{}

amdgpu.ignore.denormal.mode’ Metadata

用於 atomicrmw 浮點運算。 表示次常態輸入和結果的處理並不重要,並且可能與預期的浮點模式不一致。 為了在某些目標上針對某些位址空間發出原生原子指令,這是必要的,在這些位址空間中,浮點次常態值會被無條件清除。 這通常與 !amdgpu.no.remote.memory.access!amdgpu.no.fine.grained.memory 結合使用。

%res0 = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0
%res1 = atomicrmw fadd ptr addrspace(1) %ptr, float %value seq_cst, align 4, !amdgpu.ignore.denormal.mode !0, !amdgpu.no.fine.grained.memory !0, !amdgpu.no.remote.memory.access !0

!0 = !{}

LLVM IR 屬性

AMDGPU 後端支援下列 LLVM IR 屬性。

表 28 AMDGPU LLVM IR 屬性

LLVM 屬性

描述

“amdgpu-flat-work-group-size”=”min,max”

指定在核心程式調度時將指定的最小和最大平面工作群組大小。 由 amdgpu_flat_work_group_size CLANG 屬性 [CLANG-ATTR] 產生。 IR 隱含的預設值為 1,1024。 Clang 可能會根據語言預設值發出具有更嚴格限制的此屬性。 如果在執行期間的任何時間點,實際的區塊或工作群組大小超過限制,則行為未定義。 例如,即使只有一個活動執行緒,但執行緒本地 ID 超過限制,行為也是未定義的。

“amdgpu-implicitarg-num-bytes”=”n”

要添加到核心引數區塊大小以用於隱含引數的核心引數位元組數。 這因作業系統和語言而異(對於 OpenCL,請參閱 針對 AMDHSA OS 附加的 OpenCL 核心隱含引數)。

“amdgpu-num-sgpr”=”n”

指定要使用的 SGPR 數量。 由 amdgpu_num_sgpr CLANG 屬性 [CLANG-ATTR] 產生。

“amdgpu-num-vgpr”=”n”

指定要使用的 VGPR 數量。 由 amdgpu_num_vgpr CLANG 屬性 [CLANG-ATTR] 產生。

“amdgpu-waves-per-eu”=”m,n”

指定每個執行單元的最小和最大波前數量。 由 amdgpu_waves_per_eu CLANG 屬性 [CLANG-ATTR] 產生。 這是一個最佳化提示,後端可能無法滿足請求。 如果指定的範圍與函數的 “amdgpu-flat-work-group-size” 值不相容,則工作群組大小隱含的佔用率界限優先。

“amdgpu-ieee” true/false。

僅限 GFX6-GFX11 指定函數是否期望在進入時設定模式暫存器的 IEEE 欄位。 覆蓋呼叫慣例的預設值。

“amdgpu-dx10-clamp” true/false。

僅限 GFX6-GFX11 指定函數是否期望在進入時設定模式暫存器的 DX10_CLAMP 欄位。 覆蓋呼叫慣例的預設值。

“amdgpu-no-workitem-id-x”

表示函數不依賴 llvm.amdgcn.workitem.id.x 內建函數的值。 如果函數標記了此屬性,或通過標記了此屬性的呼叫站點到達,並且呼叫了該內建函數,則程式的行為是未定義的。 (此處使用全程式未定義行為,例如,預先載入的暫存器集合中缺少所需的工作項目 ID 可能意味著所有其他預先載入的暫存器都比編譯假設的要早。) 後端通常可以在程式碼產生期間推斷出這一點,因此通常前端標記具有此功能的函數沒有任何好處。

“amdgpu-no-workitem-id-y”

與 amdgpu-no-workitem-id-x 相同,但適用於 llvm.amdgcn.workitem.id.y 內建函數。

“amdgpu-no-workitem-id-z”

與 amdgpu-no-workitem-id-x 相同,但適用於 llvm.amdgcn.workitem.id.z 內建函數。

“amdgpu-no-workgroup-id-x”

與 amdgpu-no-workitem-id-x 相同,但適用於 llvm.amdgcn.workgroup.id.x 內建函數。

“amdgpu-no-workgroup-id-y”

與 amdgpu-no-workitem-id-x 相同,但適用於 llvm.amdgcn.workgroup.id.y 內建函數。

“amdgpu-no-workgroup-id-z”

與 amdgpu-no-workitem-id-x 相同,但適用於 llvm.amdgcn.workgroup.id.z 內建函數。

“amdgpu-no-dispatch-ptr”

與 amdgpu-no-workitem-id-x 相同,但適用於 llvm.amdgcn.dispatch.ptr 內建函數。

“amdgpu-no-implicitarg-ptr”

與 amdgpu-no-workitem-id-x 相同,但適用於 llvm.amdgcn.implicitarg.ptr 內建函數。

“amdgpu-no-dispatch-id”

與 amdgpu-no-workitem-id-x 相同,但適用於 llvm.amdgcn.dispatch.id 內建函數。

“amdgpu-no-queue-ptr”

與 amdgpu-no-workitem-id-x 類似,但適用於 llvm.amdgcn.queue.ptr 內建函數。 請注意,與其他 ABI 提示屬性不同,在 intrinsic 呼叫未直接出現在程式中的情況下,可能需要佇列指標。 某些子目標需要佇列指標來處理某些位址空間轉換,以及 llvm.amdgcn.is.shared、llvm.amdgcn.is.private、llvm.trap 和 llvm.debug 內建函數。

“amdgpu-no-hostcall-ptr”

與 amdgpu-no-implicitarg-ptr 類似,但特定於隱含核心引數,該引數保存指向 hostcall 緩衝區的指標。 如果此屬性不存在,則也會移除 amdgpu-no-implicitarg-ptr。

“amdgpu-no-heap-ptr”

與 amdgpu-no-implicitarg-ptr 類似,但特定於隱含核心引數,該引數保存指向符合 malloc/free 裝置函式庫 V1 版本實作要求的已初始化記憶體緩衝區的指標。 如果此屬性不存在,則也會移除 amdgpu-no-implicitarg-ptr。

“amdgpu-no-multigrid-sync-arg”

與 amdgpu-no-implicitarg-ptr 類似,但特定於隱含核心引數,該引數保存多重網格同步指標。 如果此屬性不存在,則也會移除 amdgpu-no-implicitarg-ptr。

“amdgpu-no-default-queue”

與 amdgpu-no-implicitarg-ptr 類似,但特定於隱含核心引數,該引數保存預設佇列指標。 如果此屬性不存在,則也會移除 amdgpu-no-implicitarg-ptr。

“amdgpu-no-completion-action”

與 amdgpu-no-implicitarg-ptr 類似,但特定於隱含核心引數,該引數保存完成動作指標。 如果此屬性不存在,則也會移除 amdgpu-no-implicitarg-ptr。

“amdgpu-lds-size”=”min[,max]”

Min 是在位址零的本地資料儲存區中將分配的最小位元組數。 變數使用絕對符號 metadata 在此框架內分配,主要由 AMDGPULowerModuleLDS 傳遞。 可選的 max 是將分配的最大位元組數。 請注意,min==max 表示無法將更多變數添加到框架中。 這是 LDS 變數如何降低的內部細節,語言前端不應設定此屬性。

“amdgpu-gds-size”

預期在進入時在 GDS 記憶體開始處分配的位元組數。

“amdgpu-git-ptr-high”

AMDPAL OS 類型的全域資訊表位址的硬連線高半部分。 0xffffffff 表示沒有硬連線高半部分,因為目前的硬體只允許 16 位元值。

“amdgpu-32bit-address-high-bits”

對於實際上被截斷的 64 位元位址的 32 位元位址空間(即 addrspace(6))假設的高 32 位元。

“amdgpu-color-export”

如果設定為 1,則表示著色器匯出顏色資訊。 對於 amdgpu_ps 預設為 1,對於其他呼叫慣例預設為 0。 決定當著色器通過終止通道提前終止時,空匯出的必要性和類型。

“amdgpu-depth-export”

如果設定為 1,則表示著色器匯出深度資訊。 決定當著色器通過終止通道提前終止時,空匯出的必要性和類型。 當沒有可用的空匯出目標時,僅深度著色器將匯出到深度通道 (GFX11+)。

“InitialPSInputAddr”

amdgpu_ps 著色器設定 spi_ps_input_addr 暫存器的初始值。 由此值啟用的任何位元都將在最終暫存器值中啟用。

“amdgpu-wave-priority-threshold”

調整波前優先順序的 VALU 指令計數閾值。 如果超過,則在著色器函數的開始處暫時提高波前優先順序,直到其最後的 VMEM 指令,以允許較新的波前也發出其 VMEM 指令。

“amdgpu-memory-bound”

由後端內部設定

“amdgpu-wave-limiter”

由後端內部設定

“amdgpu-unroll-threshold”

設定此函數內迴圈展開的基本成本閾值偏好,預設值為 300。 實際閾值可能會因每個迴圈的 metadata 而異,或因啟發式方法而降低。

“amdgpu-max-num-workgroups”=”x,y,z”

指定核心程式調度在 X、Y 和 Z 維度中的最大工作群組數。 每個數字必須 >= 1。 由 amdgpu_max_num_work_groups CLANG 屬性 [CLANG-ATTR] 產生。 僅當所有三個數字都 >= 1 時,Clang 才會發出此屬性。

“amdgpu-hidden-argument”

此屬性在後端內部使用,用於將函數引數標記為隱藏。 隱藏引數由編譯器管理,並且不是使用者提供的顯式引數的一部分。

“amdgpu-agpr-alloc”=”min(,max)”

指示要提供的 AGPR 數量的最小和最大範圍以進行分配。 這些值將四捨五入到下一個分配粒度 (4) 的倍數。 最小值被解釋為函數分配所需的最小 AGPR 數量(即,函數所需暫存器不超過 min)。 如果僅指定一個值,則將其解釋為最小暫存器預算。 最大值將限制分配以使用不超過 max AGPR。

如果滿足這些值會違反其他分配限制,則可能會忽略這些值。

如果通過任何標記有此屬性較高值的函數到達需要超過下限的 AGPR 的函數,則行為未定義。 最小值 0 表示函數不需要任何 AGPR。

這僅與支援 accum_offset (gfx90a+) 的 AGPR 目標相關。

“amdgpu-sgpr-hazard-wait”

如果設定為 0,則停用 SGPR 危害等待插入。 僅用於測試 SGPR 危害等待的效能影響。

“amdgpu-sgpr-hazard-boundary-cull”

在函數呼叫邊界啟用插入 SGPR 危害剔除序列。 剔除序列減少了未來危害等待,但具有效能成本。

“amdgpu-sgpr-hazard-mem-wait-cull”

在記憶體等待之前啟用插入 SGPR 危害剔除序列。 剔除序列減少了未來危害等待,但具有效能成本。 嘗試通過與記憶體存取重疊來攤銷成本。

“amdgpu-sgpr-hazard-mem-wait-cull-threshold”

設定在記憶體等待時插入剔除序列之前必須存在的活動 SGPR 危害的數量。

呼叫慣例

AMDGPU 後端支援下列呼叫慣例

表 29 AMDGPU 呼叫慣例

呼叫慣例

描述

ccc

C 呼叫慣例。 預設使用。 有關更多詳細資訊,請參閱 非核心函數

fastcc

快速呼叫慣例。 與 ccc 大致相同。

coldcc

冷呼叫慣例。 與 ccc 大致相同。

amdgpu_cs

用於 Mesa/AMDPAL 計算著色器。 ..TODO:: 描述。

amdgpu_cs_chain

amdgpu_cs 類似,但差異如下所述。

具有此呼叫慣例的函數不能直接呼叫。 它們必須通過 llvm.amdgcn.cs.chain 內建函數啟動。

如果引數具有 inreg 屬性,則在 SGPR 中傳遞引數,從 s0 開始;否則在 VGPR 中傳遞引數,從 v8 開始。 不允許使用比子目標中可用的 SGPR 或 VGPR 更多的數量。 在使用暫存緩衝區描述符的子目標上(而不是 scratch_{load,store}_* 指令),暫存緩衝區描述符在 s[48:51] 中傳遞。 這將 SGPR / inreg 引數限制為相當於 48 個 dword; 不允許使用超過此數量的引數。

返回類型必須為 void。 不支援 Varargs、sret、byval、byref、inalloca、preallocated。

純量暫存器以及 v0-v7 中的值不會保留。 從 v8 開始的 VGPR 中的值對於活動通道不會保留,但當使用 WWM 時,必須由被呼叫者為非活動通道保存(一個值得注意的例外是在函數中使用 llvm.amdgcn.init.whole.wave 內建函數時 - 在這種情況下,後端假設進入時沒有非活動通道; 任何需要保留的非活動通道都必須顯式地存在於 IR 中)。

波前暫存在函數邊界處為「空」。 沒有堆疊指標輸入或輸出值,但函數可以自由使用從初始堆疊指標開始的暫存。 允許呼叫 amdgpu_gfx 函數,並且其行為與 amdgpu_cs 函數中的行為相同。

所有計數器 (lgkmcntvmcntstorecnt 等) 在函數進入時都假定為未知狀態。

一個函數可能有多個出口(例如,一個鏈式出口和一個普通的 ret void,用於波前結束時),但所有 llvm.amdgcn.cs.chain 出口都必須在統一控制流程中。

amdgpu_cs_chain_preserve

amdgpu_cs_chain 相同,但從 v8 開始的 VGPR 的活動通道會被保留。 不允許呼叫 amdgpu_gfx 函數,並且任何對 llvm.amdgcn.cs.chain 的呼叫都不能傳遞比呼叫者的 VGPR 函數參數更多的 VGPR 引數。

amdgpu_es

如果幾何圖形正在使用中,則用於幾何著色器之前的 AMDPAL 著色器階段。 因此,如果曲面細分正在使用中,則為域(= 曲面細分評估)著色器,否則為頂點著色器。 ..TODO:: 描述。

amdgpu_gfx

用於 AMD 圖形目標。 具有此呼叫慣例的函數不能用作進入點。 ..TODO:: 描述。

amdgpu_gs

用於 Mesa/AMDPAL 幾何著色器。 ..TODO:: 描述。

amdgpu_hs

用於 Mesa/AMDPAL 外殼著色器(= 曲面細分控制著色器)。 ..TODO:: 描述。

amdgpu_kernel

請參閱 核心函數

amdgpu_ls

如果曲面細分正在使用中,則用於 AMDPAL 頂點著色器。 ..TODO:: 描述。

amdgpu_ps

用於 Mesa/AMDPAL 像素著色器。 ..TODO:: 描述。

amdgpu_vs

用於光柵化之前的 Mesa/AMDPAL 最後一個著色器階段(如果曲面細分和幾何圖形未使用,則為頂點著色器,否則如果需要,則為複製著色器)。 ..TODO:: 描述。

AMDGPU MCExpr

作為 AMDGPU MC 層的一部分,AMDGPU 提供了以下目標特定的 MCExpr

表 30 AMDGPU MCExpr 類型:

MCExpr

運算元

傳回值

max(arg, ...)

1 或更多

可變參數符號運算,傳回其所有引數的最大值。

or(arg, ...)

1 或更多

可變參數符號運算,傳回其所有引數的按位或結果。

函數資源使用量

函數的資源使用量取決於其每個被呼叫者的資源使用量。 用於表示資源使用量的表達式通過傳播每個被呼叫者的等效表達式來反映這一點。 這些表達式在編譯為組合語言或物件格式時由編譯器作為符號發出,不應被覆蓋或重新定義。

以下描述了所有發出的函數資源使用量符號

表 31 函數資源使用量:

符號

類型

描述

範例

<function_name>.num_vgpr

整數

<function_name> 使用的 VGPR 數量,自身及其被呼叫者的 VGPR 使用量的最壞情況

.set foo.num_vgpr, max(32, bar.num_vgpr, baz.num_vgpr)

<function_name>.num_agpr

整數

<function_name> 使用的 AGPR 數量,自身及其被呼叫者的 AGPR 使用量的最壞情況

.set foo.num_agpr, max(35, bar.num_agpr)

<function_name>.numbered_sgpr

整數

<function_name> 使用的 SGPR 數量,自身及其被呼叫者的 SGPR 使用量的最壞情況(不包含任何隱含使用的 SGPR)

.set foo.num_sgpr, 21

<function_name>.private_seg_size

整數

<function_name> 所需的總堆疊大小,表達式為本地使用的堆疊大小 + 最壞情況的被呼叫者

.set foo.private_seg_size, 16+max(bar.private_seg_size, baz.private_seg_size)

<function_name>.uses_vcc

布林值

<function_name> 或其任何被呼叫者是否使用 vcc

.set foo.uses_vcc, or(0, bar.uses_vcc)

<function_name>.uses_flat_scratch

布林值

<function_name> 或其任何被呼叫者是否使用平面暫存

.set foo.uses_flat_scratch, 1

<function_name>.has_dyn_sized_stack

布林值

<function_name> 或其任何被呼叫者是否為動態大小

.set foo.has_dyn_sized_stack, 1

<function_name>.has_recursion

布林值

<function_name> 或其任何被呼叫者是否包含遞迴

.set foo.has_recursion, 0

<function_name>.has_indirect_call

布林值

<function_name> 或其任何被呼叫者是否包含間接呼叫

.set foo.has_indirect_call, max(0, bar.has_indirect_call)

此外,還發出了三個符號,描述編譯單元的最壞情況(即最大值)num_vgprnum_agprnumbered_sgpr,這些符號可以被引用並用於上述符號表達式。 這三個符號是 amdgcn.max_num_vgpramdgcn.max_num_agpramdgcn.max_num_sgpr

ELF 程式碼物件

AMDGPU 後端產生標準 ELF [ELF] 可重定位程式碼物件,該物件可以由 lld 連結以產生標準 ELF 共享程式碼物件,該物件可以載入並在 AMDGPU 目標上執行。

章節

AMDGPU 目標 ELF 程式碼物件具有標準 ELF 章節,其中包括

表 39 AMDGPU ELF 章節

名稱

類型

屬性

.bss

SHT_NOBITS

SHF_ALLOC + SHF_WRITE

.data

SHT_PROGBITS

SHF_ALLOC + SHF_WRITE

.debug_*

SHT_PROGBITS

none

.dynamic

SHT_DYNAMIC

SHF_ALLOC

.dynstr

SHT_PROGBITS

SHF_ALLOC

.dynsym

SHT_PROGBITS

SHF_ALLOC

.got

SHT_PROGBITS

SHF_ALLOC + SHF_WRITE

.hash

SHT_HASH

SHF_ALLOC

.note

SHT_NOTE

none

.relaname

SHT_RELA

none

.rela.dyn

SHT_RELA

none

.rodata

SHT_PROGBITS

SHF_ALLOC

.shstrtab

SHT_STRTAB

none

.strtab

SHT_STRTAB

none

.symtab

SHT_SYMTAB

none

.text

SHT_PROGBITS

SHF_ALLOC + SHF_EXECINSTR

這些章節具有其標準含義(請參閱 [ELF]),並且僅在需要時生成。

.debug*

標準 DWARF 章節。有關 AMDGPU 後端產生的 DWARF 的資訊,請參閱 DWARF 偵錯資訊

.dynamic.dynstr.dynsym.hash

動態載入器使用的標準章節。

.note

有關 AMDGPU 後端支援的註記記錄,請參閱 註記記錄

.relaname.rela.dyn

對於可重定位的程式碼物件,name 是重定位記錄套用的章節名稱。例如,.rela.text 是與 .text 章節關聯的重定位記錄的章節名稱。

對於連結的共享程式碼物件,.rela.dyn 包含每個可重定位程式碼物件的 .relaname 章節中的所有重定位記錄。

有關 AMDGPU 後端支援的重定位記錄,請參閱 重定位記錄

.text

核心和它們呼叫的函式的可執行機器碼。生成為與位置無關的程式碼。有關 isa 生成中使用的約定,請參閱 程式碼約定

.amdgpu.kernel.runtime.handle

用於裝置佇列的符號。

註記記錄

AMDGPU 後端程式碼物件在 .note 章節中包含 ELF 註記記錄。生成的註記及其語義取決於程式碼物件版本;請參閱 程式碼物件 V2 註記記錄程式碼物件 V3 及更高版本註記記錄

根據 ELFCLASS32ELFCLASS64 的要求,必須在 name 欄位後生成最少的零位元組填充,以確保 desc 欄位為 4 位元組對齊。此外,必須生成最少的零位元組填充,以確保 desc 欄位大小是 4 位元組的倍數。.note 章節的 sh_addralign 欄位必須至少為 4,以指示至少 8 位元組對齊。

程式碼物件 V2 註記記錄

警告

此版本的 LLVM 不再支援程式碼物件 V2 生成。

AMDGPU 後端程式碼物件在為程式碼物件 V2 編譯時,在 .note 章節中使用以下 ELF 註記記錄。

註記記錄供應商欄位為 “AMD”。

可能存在其他註記記錄,但此處未記錄的任何註記記錄均已棄用,不應使用。

表 40 AMDGPU 程式碼物件 V2 ELF 註記記錄

名稱

類型

描述

“AMD”

NT_AMD_HSA_CODE_OBJECT_VERSION

程式碼物件版本。

“AMD”

NT_AMD_HSA_HSAIL

由 HSAIL Finalizer 而非 LLVM 編譯器生成的 HSAIL 屬性。

“AMD”

NT_AMD_HSA_ISA_VERSION

目標 ISA 版本。

“AMD”

NT_AMD_HSA_METADATA

YAML [YAML] 文字格式的中繼資料空終止字串。

“AMD”

NT_AMD_HSA_ISA_NAME

目標 ISA 名稱。

表 41 AMDGPU 程式碼物件 V2 ELF 註記記錄列舉值

名稱

NT_AMD_HSA_CODE_OBJECT_VERSION

1

NT_AMD_HSA_HSAIL

2

NT_AMD_HSA_ISA_VERSION

3

保留

4-9

NT_AMD_HSA_METADATA

10

NT_AMD_HSA_ISA_NAME

11

NT_AMD_HSA_CODE_OBJECT_VERSION

指定程式碼物件版本號碼。描述欄位具有以下佈局

struct amdgpu_hsa_note_code_object_version_s {
  uint32_t major_version;
  uint32_t minor_version;
};

major_version 的值小於或等於 2。

NT_AMD_HSA_HSAIL

指定 HSAIL Finalizer 使用的 HSAIL 屬性。描述欄位具有以下佈局

struct amdgpu_hsa_note_hsail_s {
  uint32_t hsail_major_version;
  uint32_t hsail_minor_version;
  uint8_t profile;
  uint8_t machine_model;
  uint8_t default_float_round;
};
NT_AMD_HSA_ISA_VERSION

指定目標 ISA 版本。描述欄位具有以下佈局

struct amdgpu_hsa_note_isa_s {
  uint16_t vendor_name_size;
  uint16_t architecture_name_size;
  uint32_t major;
  uint32_t minor;
  uint32_t stepping;
  char vendor_and_architecture_name[1];
};

vendor_name_sizearchitecture_name_size 分別是供應商和架構名稱的長度,包括 NUL 字元。

vendor_and_architecture_name 包含供應商的 NUL 終止字串,後跟架構的 NUL 終止字串。

HSA 執行階段載入器使用此註記記錄。

程式碼物件 V2 僅支援有限數量的處理器,並且具有目標功能的固定設定。有關處理器清單和對應的目標 ID,請參閱 AMDGPU 程式碼物件 V2 支援的處理器和固定的目標功能設定。在表中,註記記錄 ISA 名稱是供應商名稱、架構名稱、主要、次要和步進的串聯,並以 “:” 分隔。

目標 ID 列顯示 LLVM 編譯器使用的處理器名稱和固定的目標功能。LLVM 編譯器不會生成 NT_AMD_HSA_HSAIL 註記記錄。

由 Finalizer 生成的程式碼物件也使用程式碼物件 V2,並且始終生成 NT_AMD_HSA_HSAIL 註記記錄。處理器名稱和 sramecc 目標功能如 AMDGPU 程式碼物件 V2 支援的處理器和固定的目標功能設定 中所示,但 xnack 目標功能由 EF_AMDGPU_FEATURE_XNACK_V2 e_flags 位元指定。

NT_AMD_HSA_ISA_NAME

將目標 ISA 名稱指定為非 NUL 終止字串。

HSA 執行階段載入器不使用此註記記錄。

請參閱程式碼物件 V2 對處理器的有限支援和目標功能的固定設定的 NT_AMD_HSA_ISA_VERSION 註記記錄描述。

有關從字串到對應目標 ID 的映射,請參閱 AMDGPU 程式碼物件 V2 支援的處理器和固定的目標功能設定。如果支援並啟用 xnack 目標功能,則 LLVM 編譯器產生的字串可能會附加 +xnack。Finlizer 沒有執行附加,而是使用了 EF_AMDGPU_FEATURE_XNACK_V2 e_flags 位元。

NT_AMD_HSA_METADATA

指定與 HSA [HSA] 相容執行階段(請參閱 AMDGPU 作業系統)上執行的程式碼物件相關聯的可擴展中繼資料。當目標三元組 OS 為 amdhsa 時,這是必需的(請參閱 目標三元組)。有關程式碼物件中繼資料字串的語法,請參閱 程式碼物件 V2 中繼資料

表 42 AMDGPU 程式碼物件 V2 支援的處理器和固定的目標功能設定

註記記錄 ISA 名稱

目標 ID

AMD:AMDGPU:6:0:0

gfx600

AMD:AMDGPU:6:0:1

gfx601

AMD:AMDGPU:6:0:2

gfx602

AMD:AMDGPU:7:0:0

gfx700

AMD:AMDGPU:7:0:1

gfx701

AMD:AMDGPU:7:0:2

gfx702

AMD:AMDGPU:7:0:3

gfx703

AMD:AMDGPU:7:0:4

gfx704

AMD:AMDGPU:7:0:5

gfx705

AMD:AMDGPU:8:0:0

gfx802

AMD:AMDGPU:8:0:1

gfx801:xnack+

AMD:AMDGPU:8:0:2

gfx802

AMD:AMDGPU:8:0:3

gfx803

AMD:AMDGPU:8:0:4

gfx803

AMD:AMDGPU:8:0:5

gfx805

AMD:AMDGPU:8:1:0

gfx810:xnack+

AMD:AMDGPU:9:0:0

gfx900:xnack-

AMD:AMDGPU:9:0:1

gfx900:xnack+

AMD:AMDGPU:9:0:2

gfx902:xnack-

AMD:AMDGPU:9:0:3

gfx902:xnack+

AMD:AMDGPU:9:0:4

gfx904:xnack-

AMD:AMDGPU:9:0:5

gfx904:xnack+

AMD:AMDGPU:9:0:6

gfx906:sramecc-:xnack-

AMD:AMDGPU:9:0:7

gfx906:sramecc-:xnack+

AMD:AMDGPU:9:0:12

gfx90c:xnack-

程式碼物件 V3 及更高版本註記記錄

AMDGPU 後端程式碼物件在為程式碼物件 V3 及更高版本編譯時,在 .note 章節中使用以下 ELF 註記記錄。

註記記錄供應商欄位為 “AMDGPU”。

可能存在其他註記記錄,但此處未記錄的任何註記記錄均已棄用,不應使用。

表 43 AMDGPU 程式碼物件 V3 及更高版本 ELF 註記記錄

名稱

類型

描述

“AMDGPU”

NT_AMDGPU_METADATA

訊息封裝 [MsgPack] 二進位格式的中繼資料。

“AMDGPU”

NT_AMDGPU_KFD_CORE_STATE

執行階段、代理程式和佇列狀態的快照,用於核心轉儲。請參閱 核心檔案註記

表 44 AMDGPU 程式碼物件 V3 及更高版本 ELF 註記記錄列舉值

名稱

保留

0-31

NT_AMDGPU_METADATA

32

NT_AMDGPU_KFD_CORE_STATE

33

NT_AMDGPU_METADATA

指定與 AMDGPU 程式碼物件相關聯的可擴展中繼資料。它在訊息封裝 [MsgPack] 二進位資料格式中編碼為映射。有關為 amdhsa OS 定義的映射鍵,請參閱 程式碼物件 V3 中繼資料程式碼物件 V4 中繼資料程式碼物件 V5 中繼資料

符號

符號包括以下內容

表 45 AMDGPU ELF 符號

名稱

類型

章節

描述

連結名稱

STT_OBJECT

  • .data

  • .rodata

  • .bss

全域變數

連結名稱.kd

STT_OBJECT

  • .rodata

核心描述符

連結名稱

STT_FUNC

  • .text

核心進入點

連結名稱

STT_OBJECT

  • SHN_AMDGPU_LDS

LDS 中的全域變數

全域變數

編譯單元使用和定義的全域變數。

如果符號在編譯單元中定義,則根據它是否具有初始化的資料或是否為唯讀,將其分配到適當的章節中。

如果符號是外部的,則其章節為 STN_UNDEF,並且載入器將使用另一個程式碼物件提供的定義或執行階段明確定義的定義來解析重定位。

如果符號駐留在本機/群組記憶體 (LDS) 中,則其章節是特殊的處理器特定章節名稱 SHN_AMDGPU_LDS,並且 st_value 欄位描述對齊要求,就像它對通用符號所做的那樣。

核心描述符

每個 HSA 核心都有一個關聯的核心描述符。它是用於調用核心的 AQL 派送封包中使用的核心描述符的位址,而不是核心進入點。HSA 核心描述符的佈局在 核心描述符 中定義。

核心進入點

每個 HSA 核心也有一個用於其機器碼進入點的符號。

重定位記錄

AMDGPU 後端為 AMDHSA 生成 Elf64_Rela 重定位記錄,或為 Mesa/AMDPAL 生成 Elf64_Rel 重定位記錄。支援的可重定位欄位為

word32

這指定一個 32 位元欄位,佔用 4 個位元組,具有任意位元組對齊。這些值使用與 AMDGPU 架構中其他 word 值相同的位元組順序。

word64

這指定一個 64 位元欄位,佔用 8 個位元組,具有任意位元組對齊。這些值使用與 AMDGPU 架構中其他 word 值相同的位元組順序。

以下符號用於指定重定位計算

A

表示用於計算可重定位欄位值的加數。如果加數欄位小於 64 位元,則將其零擴展為 64 位元,以便在以下計算中使用。(實際上,這僅影響 Mesa/AMDPAL 上的 _HI 重定位類型,其中加數來自 32 位元欄位,但計算結果取決於完整 64 位元位址的高位部分。)

G

表示全域偏移表中的偏移量,重定位項目的符號將在執行期間駐留在該偏移量處。

GOT

表示全域偏移表的位址。

P

表示正在重定位的儲存單元的位置(et_rel 的章節偏移量或 et_dyn 的位址)(使用 r_offset 計算)。

S

表示索引駐留在重定位項目中的符號的值。不使用此符號的重定位必須指定 STN_UNDEF 的符號索引。

B

表示已載入的可執行檔或共享物件的基底位址,即 ELF 位址與實際載入位址之間的差值。使用此符號的重定位僅在可執行檔或共享物件中有效。

支援以下重定位類型

表 46 AMDGPU ELF 重定位記錄

重定位類型

種類

欄位

計算

R_AMDGPU_NONE

0

none

none

R_AMDGPU_ABS32_LO

靜態、動態

1

word32

(S + A) & 0xFFFFFFFF

R_AMDGPU_ABS32_HI

靜態、動態

2

word32

(S + A) >> 32

R_AMDGPU_ABS64

靜態、動態

3

word64

S + A

R_AMDGPU_REL32

靜態

4

word32

S + A - P

R_AMDGPU_REL64

靜態

5

word64

S + A - P

R_AMDGPU_ABS32

靜態、動態

6

word32

S + A

R_AMDGPU_GOTPCREL

靜態

7

word32

G + GOT + A - P

R_AMDGPU_GOTPCREL32_LO

靜態

8

word32

(G + GOT + A - P) & 0xFFFFFFFF

R_AMDGPU_GOTPCREL32_HI

靜態

9

word32

(G + GOT + A - P) >> 32

R_AMDGPU_REL32_LO

靜態

10

word32

(S + A - P) & 0xFFFFFFFF

R_AMDGPU_REL32_HI

靜態

11

word32

(S + A - P) >> 32

保留

12

R_AMDGPU_RELATIVE64

動態

13

word64

B + A

R_AMDGPU_REL16

靜態

14

word16

((S + A - P) - 4) / 4

R_AMDGPU_ABS32_LOR_AMDGPU_ABS32_HI 僅受 mesa3d OS 支援,該 OS 不支援 R_AMDGPU_ABS64

目前沒有 OS 載入器支援 32 位元程式,因此未使用 R_AMDGPU_ABS32

已載入程式碼物件路徑統一資源識別碼 (URI)

AMDGPU 程式碼物件載入器將載入程式碼物件的 ELF 共享物件的路徑表示為文字統一資源識別碼 (URI)。請注意,程式碼物件是 ELF 共享物件的記憶體中已載入的重定位形式。多個程式碼物件可以從同一個 ELF 共享物件在同一個進程中載入到不同的記憶體位址。

已載入的程式碼物件路徑 URI 語法由以下 BNF 語法定義

code_object_uri ::== file_uri | memory_uri
file_uri        ::== "file://" file_path [ range_specifier ]
memory_uri      ::== "memory://" process_id range_specifier
range_specifier ::== [ "#" | "?" ] "offset=" number "&" "size=" number
file_path       ::== URI_ENCODED_OS_FILE_PATH
process_id      ::== DECIMAL_NUMBER
number          ::== HEX_NUMBER | DECIMAL_NUMBER | OCTAL_NUMBER
數字

是 C 整數文字,其中十六進位值以 “0x” 或 “0X” 為前綴,八進位值以 “0” 為前綴。

file_path

是以 URI 編碼的 UTF-8 字串指定的檔案路徑。在 URI 編碼中,不在正規表示式 [a-zA-Z0-9/_.~-] 中的每個字元都編碼為兩個大寫十六進位數字,並以 “%” 開頭。路徑中的目錄以 “/” 分隔。

偏移量

是程式碼物件起點的從 0 開始的位元組偏移量。對於檔案 URI,它是從 file_path 指定的檔案的起點開始的,如果省略則預設為 0。對於記憶體 URI,它是記憶體位址,並且是必需的。

大小

是程式碼物件中的位元組數。對於檔案 URI,如果省略則預設為檔案的大小。對於記憶體 URI,這是必需的。

process_id

是擁有記憶體的進程的識別碼。對於 Linux,它是進程 ID (PID) 的 C 無符號整數十進位文字。

例如

file:///dir1/dir2/file1
file:///dir3/dir4/file2#offset=0x2000&size=3000
memory://1234#offset=0x20000&size=3000

DWARF 偵錯資訊

警告

本節描述 AMDGPU DWARF [DWARF]臨時支援,目前尚未完全實作,並且可能會變更。

AMDGPU 生成 DWARF [DWARF] 偵錯資訊 ELF 章節(請參閱 ELF 程式碼物件),其中包含將程式碼物件可執行程式碼和資料映射到來源語言結構的資訊。工具(例如偵錯器和分析器)可以使用它。它使用 異質偵錯的 DWARF 擴充功能 中定義的功能,這些功能在 DWARF 版本 4 和 DWARF 版本 5 中作為 LLVM 供應商擴充功能提供。

本節定義 AMDGPU 目標架構特定的 DWARF 映射。

暫存器識別碼

本節定義 DWARF 運算式(請參閱 DWARF 版本 5 第 2.5 節和 A.2.5.4 DWARF 運算式)和呼叫框架資訊指令(請參閱 DWARF 版本 5 第 6.4 節和 A.6.4 呼叫框架資訊)中使用的 AMDGPU 目標架構暫存器編號。

單個程式碼物件可以包含用於具有不同波前大小的核心的程式碼。向量暫存器和某些純量暫存器基於波前大小。AMDGPU 為每個波前大小定義了不同的 DWARF 暫存器。這簡化了 DWARF 的使用者,以便每個暫存器都具有固定大小,而不是根據波前大小模式而動態變化。同樣,為那些大小根據進程位址大小而變化的暫存器定義了不同的 DWARF 暫存器。這允許使用者將特定的 AMDGPU 處理器視為單一架構,而不管它在執行階段如何配置。編譯器明確指定與其正在生成的程式碼將要執行的模式相符的 DWARF 暫存器。

DWARF 暫存器編碼為數字,這些數字映射到架構暫存器。AMDGPU 的映射在 AMDGPU DWARF 暫存器映射 中定義。所有 AMDGPU 目標都使用相同的映射。

表 47 AMDGPU DWARF 暫存器映射

DWARF 暫存器

AMDGPU 暫存器

位元大小

描述

0

PC_32

32

在 32 位元進程位址空間中執行時的程式計數器 (PC)。在 CFI 中用於描述呼叫框架的 PC。

1

EXEC_MASK_32

32

在波前 32 模式中執行時的執行遮罩暫存器。

2-15

保留

保留用於使用 DWARF 快捷方式高頻存取的暫存器。

16

PC_64

64

在 64 位元進程位址空間中執行時的程式計數器 (PC)。在 CFI 中用於描述呼叫框架的 PC。

17

EXEC_MASK_64

64

在波前 64 模式中執行時的執行遮罩暫存器。

18-31

保留

保留用於使用 DWARF 快捷方式高頻存取的暫存器。

32-95

SGPR0-SGPR63

32

純量通用暫存器。

96-127

保留

保留用於使用 DWARF 1 位元組 ULEB 頻繁存取的暫存器。

128

STATUS

32

狀態暫存器。

129-511

保留

保留用於未來的純量架構暫存器。

512

VCC_32

32

在波前 32 模式中執行時的向量條件碼暫存器。

513-767

保留

保留用於在波前 32 模式中執行時的未來向量架構暫存器。

768

VCC_64

64

在波前 64 模式中執行時的向量條件碼暫存器。

769-1023

保留

保留用於在波前 64 模式中執行時的未來向量架構暫存器。

1024-1087

保留

保留用於填充。

1088-1129

SGPR64-SGPR105

32

純量通用暫存器。

1130-1535

保留

保留用於未來的純量通用暫存器。

1536-1791

VGPR0-VGPR255

32*32

在波前 32 模式中執行時的向量通用暫存器。

1792-2047

保留

保留用於在波前 32 模式中執行時的未來向量通用暫存器。

2048-2303

AGPR0-AGPR255

32*32

在波前 32 模式中執行時的向量累加暫存器。

2304-2559

保留

保留用於在波前 32 模式中執行時的未來向量累加暫存器。

2560-2815

VGPR0-VGPR255

64*32

在波前 64 模式中執行時的向量通用暫存器。

2816-3071

保留

保留用於在波前 64 模式中執行時的未來向量通用暫存器。

3072-3327

AGPR0-AGPR255

64*32

在波前 64 模式中執行時的向量累加暫存器。

3328-3583

保留

保留用於在波前 64 模式中執行時的未來向量累加暫存器。

向量暫存器表示為波前的完整大小。它們組織為連續的 dword(32 位元),每個通道一個,最低有效位元位置的 dword 對應於通道 0,依此類推。涉及 DW_OP_LLVM_offsetDW_OP_LLVM_push_lane 運算的 DWARF 位置運算式用於選取與在使用 SIMD 或 SIMT 執行模型實作的語言中執行目前執行緒的通道相對應的向量暫存器的部分。

如果波前大小為 32 個通道,則使用波前 32 模式暫存器定義。如果波前大小為 64 個通道,則使用波前 64 模式暫存器定義。某些 AMDGPU 目標支援在波前 32 和波前 64 模式下執行。將使用與生成的程式碼的波前模式相對應的暫存器定義。

如果程式碼是為了在 32 位元程序位址空間中執行而產生,則會使用 32 位元程序位址空間暫存器定義。如果程式碼是為了在 64 位元程序位址空間中執行而產生,則會使用 64 位元程序位址空間暫存器定義。amdgcn 目標僅支援 64 位元程序位址空間。

記憶體空間識別碼

DWARF 記憶體空間代表原始語言記憶體空間。請參閱 DWARF 第 5 版第 2.12 節,該節已由異質除錯的 DWARF 擴充功能章節 A.2.14 記憶體空間 更新。

用於 AMDGPU 的 DWARF 記憶體空間映射定義於 AMDGPU DWARF 記憶體空間映射

表 48 AMDGPU DWARF 記憶體空間映射

DWARF

AMDGPU

記憶體空間名稱

記憶體空間

DW_MSPACE_LLVM_none

0x0000

通用 (平面)

DW_MSPACE_LLVM_global

0x0001

全域

DW_MSPACE_LLVM_constant

0x0002

全域

DW_MSPACE_LLVM_group

0x0003

本地 (群組/LDS)

DW_MSPACE_LLVM_private

0x0004

私有 (Scratch)

DW_MSPACE_AMDGPU_region

0x8000

區域 (GDS)

使用異質除錯的 DWARF 擴充功能章節 A.2.14 記憶體空間 中定義的 DWARF 記憶體空間值。

此外,DW_ADDR_AMDGPU_region 編碼為供應商擴充功能。這可用於 AMD 擴充功能,以存取硬體 GDS 記憶體,該記憶體是每個裝置配置的暫存記憶體。

對於 AMDGPU,如果沒有 DW_AT_LLVM_memory_space 屬性,則使用 DW_MSPACE_LLVM_none 的預設記憶體空間。

請參閱 位址空間識別碼,以取得有關 DWARF 記憶體空間到 DWARF 位址空間的 AMDGPU 映射資訊,包括位址大小和 NULL 值。

位址空間識別碼

DWARF 位址空間對應於目標架構特定的線性可定址記憶體區域。請參閱 DWARF 第 5 版第 2.12 節和異質除錯的 DWARF 擴充功能章節 A.2.13 位址空間

用於 AMDGPU 的 DWARF 位址空間映射定義於 AMDGPU DWARF 位址空間映射

表 49 AMDGPU DWARF 位址空間映射

DWARF

AMDGPU

註解

位址空間名稱

位址

位元大小

LLVM IR 位址空間

64 位元程序位址空間

32 位元程序位址空間

DW_ASPACE_LLVM_none

0x00

64

32

全域

預設位址空間

DW_ASPACE_AMDGPU_generic

0x01

64

32

通用 (平面)

DW_ASPACE_AMDGPU_region

0x02

32

32

區域 (GDS)

DW_ASPACE_AMDGPU_local

0x03

32

32

本地 (群組/LDS)

保留

0x04

DW_ASPACE_AMDGPU_private_lane

0x05

32

32

私有 (Scratch)

聚焦 lane

DW_ASPACE_AMDGPU_private_wave

0x06

32

32

私有 (Scratch)

未調換 (unswizzled) wavefront

請參閱 位址空間,以取得有關 AMDGPU LLVM IR 位址空間的資訊,包括位址大小和 NULL 值。

DW_ASPACE_LLVM_none 位址空間是在未指定位址空間的 DWARF 運算中使用的預設目標架構位址空間。因此,它必須映射到全域位址空間,以便 DW_OP_addr* 和相關運算可以參考程式碼中的位址。

DW_ASPACE_AMDGPU_generic 位址空間允許位置運算式指定平面位址空間。如果位址對應於本地位址空間中的位址,則它對應於正在執行聚焦執行緒的 wavefront。如果位址對應於私有位址空間中的位址,則對於使用 SIMD 或 SIMT 執行模型實作的語言,它對應於正在執行聚焦執行緒的 lane。

注意

類似 CUDA 的語言(例如 HIP)在語言類型系統中沒有位址空間,但允許在不同位址空間中配置變數,需要在 DWARF 運算式中明確指定 DW_ASPACE_AMDGPU_generic 位址空間,因為預設位址空間是全域位址空間。

DW_ASPACE_AMDGPU_local 位址空間允許位置運算式指定對應於正在執行聚焦執行緒的 wavefront 的本地位址空間。

DW_ASPACE_AMDGPU_private_lane 位址空間允許位置運算式指定對應於正在執行聚焦執行緒的 lane 的私有位址空間,適用於使用 SIMD 或 SIMT 執行模型實作的語言。

DW_ASPACE_AMDGPU_private_wave 位址空間允許位置運算式指定未調換 (unswizzled) 的私有位址空間,該空間對應於正在執行聚焦執行緒的 wavefront。私有記憶體的 wavefront 視圖是 位址空間 中定義的每個 wavefront 的未調換後備記憶體佈局,因此位址 0 對應於 wavefront 後備記憶體的第一個位置(即,位址不會被 wavefront-scratch-base 偏移)。以下公式可用於將 DW_ASPACE_AMDGPU_private_lane 位址轉換為 DW_ASPACE_AMDGPU_private_wave 位址

private-address-wavefront =
  ((private-address-lane / 4) * wavefront-size * 4) +
  (wavefront-lane-id * 4) + (private-address-lane % 4)

如果 DW_ASPACE_AMDGPU_private_lane 位址是 dword 對齊的,並且需要從 lane 0 開始的每個 lane 的 dword 開頭,則這簡化為

private-address-wavefront =
  private-address-lane * wavefront-size

編譯器可以使用 DW_ASPACE_AMDGPU_private_wave 位址空間將完整的溢出向量暫存器讀回 CFI 中的完整向量暫存器。框架指標可以是 dword 對齊的私有 lane 位址,可以將其移位以乘以 wavefront 大小,然後用於形成私有 wavefront 位址,該位址提供一組連續 dword 的位置(每個 lane 一個),其中溢出了向量暫存器 dword。編譯器知道 wavefront 大小,因為它產生程式碼。請注意,位址的類型可能必須轉換,因為 DW_ASPACE_AMDGPU_private_lane 位址的大小可能小於 DW_ASPACE_AMDGPU_private_wave 位址的大小。

Lane 識別碼

DWARF lane 識別碼指定以 SIMD 或 SIMT 方式執行的硬體的目標架構 lane 位置,以及原始語言將其執行緒映射到這些 lane 上的位置。DWARF lane 識別碼由 DW_OP_LLVM_push_lane DWARF 運算式運算推送。請參閱 DWARF 第 5 版第 2.5 節,該節已由異質除錯的 DWARF 擴充功能章節 A.2.5.4 DWARF 運算式運算 更新。

對於 AMDGPU,lane 識別碼對應於 wavefront 的硬體 lane ID。它的編號從 0 到 wavefront 大小減 1。

運算式

DWARF 運算式用於計算程式值和程式物件的位置。請參閱 DWARF 第 5 版第 2.5 節和 A.2.5.4 DWARF 運算式運算

DWARF 位置描述描述如何存取儲存空間,包括記憶體和暫存器。在存取 AMDGPU 上的儲存空間時,位元組的順序是最低有效位元組優先,位元在位元組內的順序是最低有效位元優先。

對於 AMDGPU CFI 運算式,DW_OP_LLVM_select_bit_piece 用於描述在執行遮罩下溢出到記憶體的向量暫存器:zero-single 位置描述是向量暫存器,而 one-single 位置描述是溢出的記憶體位置描述。DW_OP_LLVM_form_aspace_address 用於指定記憶體位置描述的位址空間。

在 AMDGPU 運算式中,DW_OP_LLVM_select_bit_pieceDW_AT_LLVM_lane_pc 屬性運算式使用,其中發散控制流程由執行遮罩控制。未定義的位置描述與 DW_OP_LLVM_extend 一起用於指示 lane 在進入子程式時未處於活動狀態。請參閱 DW_AT_LLVM_lane_pc 以取得範例。

基礎類型轉換

對於 AMDGPU 運算式,DW_OP_convert 可用於在不同位址空間中的 DW_ATE_address 編碼的基礎類型之間進行轉換。

位址空間 中描述的所有相關條件都滿足時,轉換會如其中定義的那樣進行,否則會導致評估錯誤。

注意

對於不支援特定位址空間的目標,轉換到或從該位址空間轉換始終是評估錯誤。

對於支援通用位址空間的目標,當通用位址位於全域位址空間中時,定義從 DW_ASPACE_AMDGPU_generic 轉換為 DW_ASPACE_LLVM_none。轉換不需要更改位址的字面值。

當存在相關硬體支援、任何需要的硬體設定已完成且通用位址位於相應的位址空間中時,定義從 DW_ASPACE_AMDGPU_generic 轉換為 DW_ASPACE_AMDGPU_localDW_ASPACE_AMDGPU_private_waveDW_ASPACE_AMDGPU_private_lane。轉換為 DW_ASPACE_AMDGPU_private_lane 還需要上下文包含活動 lane。

除錯資訊條目屬性

本節描述 AMDGPU 如何使用某些除錯資訊條目屬性。請參閱 DWARF 第 5 版第 3.3.5 節和 3.1.1 節中的章節,這些章節已由異質除錯的 DWARF 擴充功能章節 A.3.3.5 低階資訊A.3.1.1 完整和部分編譯單元條目 更新。

DW_AT_LLVM_lane_pc

對於 AMDGPU,DW_AT_LLVM_lane_pc 屬性用於指定 SIMT 執行緒的各個 lane 的程式位置。

如果 lane 是活動 lane,則這將與當前程式位置相同。

如果 lane 處於非活動狀態,但在進入子程式時處於活動狀態,則這是 lane 在子程式中概念性定位的程式位置。

如果 lane 在進入子程式時未處於活動狀態,則這將是未定義的位置。用戶端除錯器可以透過檢查 lane 是否在網格內相關工作群組的範圍內(考慮到部分工作群組)來檢查 lane 是否是有效工作群組的一部分。如果不是,則除錯器可以省略 lane 的任何資訊。否則,除錯器可以重複展開堆疊並檢查呼叫子程式的 DW_AT_LLVM_lane_pc,直到找到非未定義的位置。從概念上講,lane 僅具有它具有非未定義 DW_AT_LLVM_lane_pc 的呼叫框架。

以下範例說明了 AMDGPU 後端如何為以下子程式虛擬碼的巢狀 IF/THEN/ELSE 結構產生 DWARF 位置列表運算式,目標是每個 wavefront 具有 64 個 lane。

 1SUBPROGRAM X
 2BEGIN
 3  a;
 4  IF (c1) THEN
 5    b;
 6    IF (c2) THEN
 7      c;
 8    ELSE
 9      d;
10    ENDIF
11    e;
12  ELSE
13    f;
14  ENDIF
15  g;
16END

AMDGPU 後端可能會產生以下虛擬 LLVM MIR 來操作執行遮罩 (EXEC) 以線性化控制流程。評估條件以建立條件評估為 true 的 lane 的遮罩。首先,透過將 EXEC 遮罩設定為當前 EXEC 遮罩與條件遮罩的邏輯 AND,來執行 THEN 區域。然後,透過否定 EXEC 遮罩和在區域開始時儲存的 EXEC 遮罩的邏輯 AND,來執行 ELSE 區域。在 IF/THEN/ELSE 區域之後,EXEC 遮罩會還原為區域開始時的值。如下所示。其他方法也是可能的,但基本概念是相同的。

 1$lex_start:
 2  a;
 3  %1 = EXEC
 4  %2 = c1
 5$lex_1_start:
 6  EXEC = %1 & %2
 7$if_1_then:
 8    b;
 9    %3 = EXEC
10    %4 = c2
11$lex_1_1_start:
12    EXEC = %3 & %4
13$lex_1_1_then:
14      c;
15    EXEC = ~EXEC & %3
16$lex_1_1_else:
17      d;
18    EXEC = %3
19$lex_1_1_end:
20    e;
21  EXEC = ~EXEC & %1
22$lex_1_else:
23    f;
24  EXEC = %1
25$lex_1_end:
26  g;
27$lex_end:

為了建立定義 lane 程式位置向量的位置描述的 DWARF 位置列表運算式,可以使用 LLVM MIR DBG_VALUE 虛擬指令來註解線性化的控制流程。這可以透過為 lane PC 定義人為變數來完成。為其建立的 DWARF 位置列表運算式用作子程式的除錯資訊條目上 DW_AT_LLVM_lane_pc 屬性的值。

為每個良好巢狀結構化的控制流程區域定義 DWARF 程序,如果 lane 不活動(即它是發散的),則該程序會提供 lane 的概念性 lane 程式位置。每個區域的 DWARF 運算式運算在概念上繼承了直接封閉區域的值,並根據區域的語義對其進行修改。

對於 IF/THEN/ELSE 區域,發散程式位置位於 THEN 區域的開始處,因為它是首先執行的。對於 ELSE 區域,發散程式位置位於 IF/THEN/ELSE 區域的結尾處,因為 THEN 區域已完成。

lane PC 人為變數在每個區域轉換時都會指派。它使用直接封閉區域的 DWARF 程序來計算每個 lane 的程式位置(假設它們是發散的),然後透過插入 EXEC 遮罩指示為活動狀態的每個 lane 的當前程式位置來修改結果。

透過為每個區域使用單獨的 DWARF 程序,可以重複使用它們來定義任何巢狀區域的值。這減少了 DWARF 運算式運算的總大小。

以下提供了一個使用虛擬 LLVM MIR 的範例。

  1$lex_start:
  2  DEFINE_DWARF %__uint_64 = DW_TAG_base_type[
  3    DW_AT_name = "__uint64";
  4    DW_AT_byte_size = 8;
  5    DW_AT_encoding = DW_ATE_unsigned;
  6  ];
  7  DEFINE_DWARF %__active_lane_pc = DW_TAG_dwarf_procedure[
  8    DW_AT_name = "__active_lane_pc";
  9    DW_AT_location = [
 10      DW_OP_regx PC;
 11      DW_OP_LLVM_extend 64, 64;
 12      DW_OP_regval_type EXEC, %uint_64;
 13      DW_OP_LLVM_select_bit_piece 64, 64;
 14    ];
 15  ];
 16  DEFINE_DWARF %__divergent_lane_pc = DW_TAG_dwarf_procedure[
 17    DW_AT_name = "__divergent_lane_pc";
 18    DW_AT_location = [
 19      DW_OP_LLVM_undefined;
 20      DW_OP_LLVM_extend 64, 64;
 21    ];
 22  ];
 23  DBG_VALUE $noreg, $noreg, %DW_AT_LLVM_lane_pc, DIExpression[
 24    DW_OP_call_ref %__divergent_lane_pc;
 25    DW_OP_call_ref %__active_lane_pc;
 26  ];
 27  a;
 28  %1 = EXEC;
 29  DBG_VALUE %1, $noreg, %__lex_1_save_exec;
 30  %2 = c1;
 31$lex_1_start:
 32  EXEC = %1 & %2;
 33$lex_1_then:
 34    DEFINE_DWARF %__divergent_lane_pc_1_then = DW_TAG_dwarf_procedure[
 35      DW_AT_name = "__divergent_lane_pc_1_then";
 36      DW_AT_location = DIExpression[
 37        DW_OP_call_ref %__divergent_lane_pc;
 38        DW_OP_addrx &lex_1_start;
 39        DW_OP_stack_value;
 40        DW_OP_LLVM_extend 64, 64;
 41        DW_OP_call_ref %__lex_1_save_exec;
 42        DW_OP_deref_type 64, %__uint_64;
 43        DW_OP_LLVM_select_bit_piece 64, 64;
 44      ];
 45    ];
 46    DBG_VALUE $noreg, $noreg, %DW_AT_LLVM_lane_pc, DIExpression[
 47      DW_OP_call_ref %__divergent_lane_pc_1_then;
 48      DW_OP_call_ref %__active_lane_pc;
 49    ];
 50    b;
 51    %3 = EXEC;
 52    DBG_VALUE %3, %__lex_1_1_save_exec;
 53    %4 = c2;
 54$lex_1_1_start:
 55    EXEC = %3 & %4;
 56$lex_1_1_then:
 57      DEFINE_DWARF %__divergent_lane_pc_1_1_then = DW_TAG_dwarf_procedure[
 58        DW_AT_name = "__divergent_lane_pc_1_1_then";
 59        DW_AT_location = DIExpression[
 60          DW_OP_call_ref %__divergent_lane_pc_1_then;
 61          DW_OP_addrx &lex_1_1_start;
 62          DW_OP_stack_value;
 63          DW_OP_LLVM_extend 64, 64;
 64          DW_OP_call_ref %__lex_1_1_save_exec;
 65          DW_OP_deref_type 64, %__uint_64;
 66          DW_OP_LLVM_select_bit_piece 64, 64;
 67        ];
 68      ];
 69      DBG_VALUE $noreg, $noreg, %DW_AT_LLVM_lane_pc, DIExpression[
 70        DW_OP_call_ref %__divergent_lane_pc_1_1_then;
 71        DW_OP_call_ref %__active_lane_pc;
 72      ];
 73      c;
 74    EXEC = ~EXEC & %3;
 75$lex_1_1_else:
 76      DEFINE_DWARF %__divergent_lane_pc_1_1_else = DW_TAG_dwarf_procedure[
 77        DW_AT_name = "__divergent_lane_pc_1_1_else";
 78        DW_AT_location = DIExpression[
 79          DW_OP_call_ref %__divergent_lane_pc_1_then;
 80          DW_OP_addrx &lex_1_1_end;
 81          DW_OP_stack_value;
 82          DW_OP_LLVM_extend 64, 64;
 83          DW_OP_call_ref %__lex_1_1_save_exec;
 84          DW_OP_deref_type 64, %__uint_64;
 85          DW_OP_LLVM_select_bit_piece 64, 64;
 86        ];
 87      ];
 88      DBG_VALUE $noreg, $noreg, %DW_AT_LLVM_lane_pc, DIExpression[
 89        DW_OP_call_ref %__divergent_lane_pc_1_1_else;
 90        DW_OP_call_ref %__active_lane_pc;
 91      ];
 92      d;
 93    EXEC = %3;
 94$lex_1_1_end:
 95    DBG_VALUE $noreg, $noreg, %DW_AT_LLVM_lane_pc, DIExpression[
 96      DW_OP_call_ref %__divergent_lane_pc;
 97      DW_OP_call_ref %__active_lane_pc;
 98    ];
 99    e;
100  EXEC = ~EXEC & %1;
101$lex_1_else:
102    DEFINE_DWARF %__divergent_lane_pc_1_else = DW_TAG_dwarf_procedure[
103      DW_AT_name = "__divergent_lane_pc_1_else";
104      DW_AT_location = DIExpression[
105        DW_OP_call_ref %__divergent_lane_pc;
106        DW_OP_addrx &lex_1_end;
107        DW_OP_stack_value;
108        DW_OP_LLVM_extend 64, 64;
109        DW_OP_call_ref %__lex_1_save_exec;
110        DW_OP_deref_type 64, %__uint_64;
111        DW_OP_LLVM_select_bit_piece 64, 64;
112      ];
113    ];
114    DBG_VALUE $noreg, $noreg, %DW_AT_LLVM_lane_pc, DIExpression[
115      DW_OP_call_ref %__divergent_lane_pc_1_else;
116      DW_OP_call_ref %__active_lane_pc;
117    ];
118    f;
119  EXEC = %1;
120$lex_1_end:
121  DBG_VALUE $noreg, $noreg, %DW_AT_LLVM_lane_pc DIExpression[
122    DW_OP_call_ref %__divergent_lane_pc;
123    DW_OP_call_ref %__active_lane_pc;
124  ];
125  g;
126$lex_end:

DWARF 程序 %__active_lane_pc 用於使用當前程式位置更新處於活動狀態的 lane pc 元素。

為區域條目時儲存的執行遮罩建立人為變數 %__lex_1_save_exec 和 %__lex_1_1_save_exec。使用 DBG_VALUE 虛擬指令,將建立位置列表條目,以描述在任何給定程式位置配置人為變數的位置。編譯器可能會將它們配置到暫存器或將它們溢出到記憶體。

每個區域的 DWARF 程序都使用儲存的執行遮罩人為變數的值,僅更新在進入區域時處於活動狀態的 lane。所有其他 lane 都保留它們上次活動的封閉區域的值。如果它們在進入子程式時未處於活動狀態,則將具有未定義的位置描述。

可以類似地處理其他結構化的控制流程區域。例如,迴圈會將區域的發散程式位置設定在迴圈的結尾。任何活動的 lane 都將在迴圈中,而任何不活動的 lane 都必須已退出迴圈。

IF/THEN/ELSEIF/ELSEIF/... 區域可以視為 IF/THEN/ELSE 區域的巢狀結構來處理。

DWARF 程序可以使用 DW_AT_LLVM_active_lane 中描述的活動 lane 人為變數,而不是實際的 EXEC 遮罩,以便支援整個或四分之一 wavefront 模式。

DW_AT_LLVM_active_lane

子程式除錯資訊條目上的 DW_AT_LLVM_active_lane 屬性用於指定 SIMT 執行緒的概念性活動 lane。

可以修改執行遮罩以實作整個或四分之一 wavefront 模式運算。例如,可能需要暫時啟用所有 lane 以執行整個 wavefront 運算。此類區域將儲存 EXEC 遮罩,更新它以啟用必要的 lane,執行運算,然後從儲存的值還原 EXEC 遮罩。在執行整個 wavefront 區域時,概念性執行遮罩是儲存的值,而不是 EXEC 值。

這可以透過為活動 lane 遮罩定義人為變數來處理。活動 lane 遮罩人為變數對於正常區域將是實際的 EXEC 遮罩,對於暫時更新遮罩的區域將是儲存的執行遮罩。為此人為變數建立的位置列表運算式用於定義 DW_AT_LLVM_active_lane 屬性的值。

DW_AT_LLVM_augmentation

對於 AMDGPU,編譯單元除錯資訊條目的 DW_AT_LLVM_augmentation 屬性具有以下擴充字串值

[amdgpu:v0.0]

“vX.Y” 指定編譯單元的 DWARF 中使用的 AMDGPU 擴充功能的主要版本號 X 和次要版本號 Y。版本號符合 [SEMVER]

呼叫框架資訊

DWARF 呼叫框架資訊 (CFI) 描述消費者如何虛擬展開執行中程序或核心轉儲中的呼叫框架。請參閱 DWARF 第 5 版第 6.4 節和 A.6.4 呼叫框架資訊

對於 AMDGPU,通用資訊條目 (CIE) 欄位具有以下值

  1. augmentation 字串包含以下以 null 終止的 UTF-8 字串

    [amd:v0.0]
    

    vX.Y 指定用於此 CIE 或使用它的 FDE 的 AMDGPU 擴充功能的主要版本號 X 和次要版本號 Y。版本號符合 [SEMVER]

  2. address_sizeGlobal 位址空間定義於 位址空間識別碼

  3. segment_selector_size 為 0,因為 AMDGPU 不使用區段選擇器。

  4. code_alignment_factor 為 4 位元組。

  5. data_alignment_factor 為 4 位元組。

  6. return_address_register 對於 32 位元程序為 PC_32,對於 64 位元程序為 PC_64,定義於 暫存器識別碼

  7. initial_instructions 由於暫存器較少的子程式 X 可以從配置更多暫存器的子程式 Y 呼叫,因此 X 不會變更任何額外的暫存器,因為它無法存取它們。因此,所有欄的預設規則是 same value

對於 AMDGPU,暫存器編號遵循 暫存器識別碼 中定義的編號。

對於 AMDGPU,指令大小是可變的。消費者可以從返回位址中減去 1,以取得呼叫站點指令中位元組的位址。請參閱 DWARF 第 5 版第 6.4.4 節。

加速存取

請參閱 DWARF 第 5 版第 6.1 節。

依名稱查找區段標頭

請參閱 DWARF 第 5 版第 6.1.1.4.1 節和 A.6.1.1 依名稱查找

對於 AMDGPU,依名稱查找區段標頭表

augmentation_string_size (uword)

設定為 augmentation_string 值的長度,該長度始終為 4 的倍數。

augmentation_string (UTF-8 字元序列)

包含以下 UTF-8 字串,以 null 填補至 4 位元組的倍數

[amdgpu:v0.0]

“vX.Y” 指定此索引的 DWARF 中使用的 AMDGPU 擴充功能的主要版本號 X 和次要版本號 Y。版本號符合 [SEMVER]

注意

這與 DWARF 第 5 版定義不同,後者要求前 4 個字元為供應商 ID。但這與其他擴充字串一致,並且確實允許多個供應商的貢獻。但是,向後相容性可能更理想。

依位址查找區段標頭

請參閱 DWARF 第 5 版第 6.1.2 節。

對於 AMDGPU,依位址查找區段標頭表

address_size (ubyte)

符合 位址空間識別碼 中定義的 Global 位址空間的位址大小。

segment_selector_size (ubyte)

AMDGPU 不使用區段選擇器,因此此值為 0。.debug_aranges 中的條目沒有區段選擇器。

行號資訊

請參閱 DWARF 第 5 版第 6.2 節和 A.6.2 行號資訊

AMDGPU 不使用 isa 狀態機暫存器,並且始終將其設定為 0。指令集必須從 ELF 檔案標頭 e_flags 欄位的 EF_AMDGPU_MACH 位元位置取得(請參閱 ELF 標頭)。請參閱 DWARF 第 5 版第 6.2.2 節。

對於 AMDGPU,行號程式標頭欄位具有以下值(請參閱 DWARF 第 5 版第 6.2.4 節)

address_size (ubyte)

符合 位址空間識別碼 中定義的 Global 位址空間的位址大小。

segment_selector_size (ubyte)

AMDGPU 不使用區段選擇器,因此此值為 0。

minimum_instruction_length (ubyte)

對於 GFX9-GFX11,此值為 4。

maximum_operations_per_instruction (ubyte)

對於 GFX9-GFX11,此值為 1。

線上編譯程式(例如,由 OpenCL 語言運行時編譯的程式)的原始碼文字可以嵌入到 DWARF Version 5 行號表 (line table) 中。請參閱 DWARF Version 5 第 6.2.4.1 節,該節已由異質除錯的 DWARF 擴展章節 DW_LNCT_LLVM_source 更新。

用於控制 AMDGPU 中原始碼嵌入的 Clang 選項定義於 AMDGPU Clang 除錯選項 中。

表 50 AMDGPU Clang 除錯選項

除錯旗標 (Debug Flag)

描述

-g[no-]embed-source

啟用/停用在 DWARF 除錯區段中嵌入原始碼文字。適用於原始碼無法寫入磁碟的環境,例如執行線上編譯時。

例如

-gembed-source

啟用嵌入原始碼。

-gno-embed-source

停用嵌入原始碼。

32 位元和 64 位元 DWARF 格式

請參閱 DWARF Version 5 第 7.4 節和 A.7.4 32 位元和 64 位元 DWARF 格式

適用於 AMDGPU

  • 對於 amdgcn 目標架構,僅支援 64 位元處理程序位址空間。

  • 生產者可以產生 32 位元或 64 位元 DWARF 格式。LLVM 產生 32 位元 DWARF 格式。

單元標頭 (Unit Headers)

對於 AMDGPU,以下值適用於 DWARF Version 5 第 7.5.1.1、7.5.1.2 和 7.5.1.3 節中描述的每個單元標頭。

address_size (ubyte)

符合 位址空間識別碼 中定義的 Global 位址空間的位址大小。

程式碼慣例 (Code Conventions)

本節提供每個支援的目標三元組 OS (作業系統) 所使用的程式碼慣例(請參閱 目標三元組)。

AMDHSA

本節提供當目標三元組 OS 為 amdhsa 時所使用的程式碼慣例(請參閱 目標三元組)。

程式碼物件元數據 (Code Object Metadata)

程式碼物件元數據指定與在 HSA [HSA] 相容的運行時環境上執行的程式碼物件相關聯的可擴展元數據(請參閱 AMDGPU 作業系統)。此元數據的編碼和語意取決於程式碼物件版本;請參閱 程式碼物件 V2 元數據程式碼物件 V3 元數據程式碼物件 V4 元數據程式碼物件 V5 元數據

程式碼物件元數據在註記記錄 (note record) 中指定(請參閱 註記記錄),並且當目標三元組 OS 為 amdhsa 時是必需的(請參閱 目標三元組)。它必須包含支援 HSA 相容運行時環境核心查詢所需的最低限度資訊。例如,dispatch 封包中需要的區段大小。此外,高階語言運行時環境可能需要包含其他資訊。例如,AMD OpenCL 運行時環境會記錄核心引數資訊。

程式碼物件 V2 元數據

警告

此版本的 LLVM 不再支援程式碼物件 V2 生成。

程式碼物件 V2 元數據由 NT_AMD_HSA_METADATA 註記記錄指定(請參閱 程式碼物件 V2 註記記錄)。

此元數據指定為 YAML 格式化的字串(請參閱 [YAML]YAML I/O)。

此元數據表示為單個 YAML 文件,其中包含表 AMDHSA 程式碼物件 V2 元數據映射表 和參考表格中定義的映射 (mapping)。

對於布林值,字串值 falsetrue 分別用於 false 和 true。

其他資訊可以添加到映射中。為避免衝突,任何非 AMD 金鑰名稱都應以 “vendor-name.” 為前綴。

表 51 AMDHSA 程式碼物件 V2 元數據映射表

字串金鑰 (String Key)

值類型 (Value Type)

是否必填?

描述

“Version” (版本)

2 個整數的序列 (sequence)

必填

  • 第一個整數是主版本號 (major version)。目前為 1。

  • 第二個整數是次要版本號 (minor version)。目前為 0。

“Printf”

字串序列

每個字串都是關於 printf 函數呼叫的編碼資訊。編碼資訊組織為以冒號 (':') 分隔的欄位 (field)。

ID:N:S[0]:S[1]:...:S[N-1]:FormatString

其中

ID

32 位元整數,作為每個 printf 函數呼叫的唯一 ID

N

32 位元整數,等於 printf 函數呼叫的引數數量減 1

S[i] (其中 i = 0, 1, … , N-1)

32 位元整數,表示 printf 函數呼叫的第 i 個 FormatString 引數的大小(以位元組為單位)

FormatString (格式字串)

傳遞給 printf 函數呼叫的格式字串。

“Kernels” (核心)

映射序列

必填

程式碼物件中每個核心的映射序列。有關映射的定義,請參閱 AMDHSA 程式碼物件 V2 核心元數據映射表

表 52 AMDHSA 程式碼物件 V2 核心元數據映射表

字串金鑰 (String Key)

值類型 (Value Type)

是否必填?

描述

“Name” (名稱)

字串

必填

核心的原始碼名稱。

“SymbolName” (符號名稱)

字串

必填

核心描述符 ELF 符號的名稱。

“Language” (語言)

字串

核心的原始碼語言。值包括

  • “OpenCL C”

  • “OpenCL C++”

  • “HCC”

  • “OpenMP”

“LanguageVersion” (語言版本)

2 個整數的序列 (sequence)

  • 第一個整數是主版本號。

  • 第二個整數是次要版本號。

“Attrs” (屬性)

映射

核心屬性的映射。有關映射定義,請參閱 AMDHSA 程式碼物件 V2 核心屬性元數據映射表

“Args” (引數)

映射序列

核心引數的映射序列。有關映射定義,請參閱 AMDHSA 程式碼物件 V2 核心引數元數據映射表

“CodeProps” (程式碼屬性)

映射

與核心程式碼相關的屬性映射。有關映射定義,請參閱 AMDHSA 程式碼物件 V2 核心程式碼屬性元數據映射表

表 53 AMDHSA 程式碼物件 V2 核心屬性元數據映射表

字串金鑰 (String Key)

值類型 (Value Type)

是否必填?

描述

“ReqdWorkGroupSize” (必要工作群組大小)

3 個整數的序列

如果不是 0, 0, 0,則所有值必須 >=1,且 dispatch 工作群組大小 X、Y、Z 必須對應於指定的值。預設為 0, 0, 0。

對應於 OpenCL reqd_work_group_size 屬性。

“WorkGroupSizeHint” (工作群組大小提示)

3 個整數的序列

dispatch 工作群組大小 X、Y、Z 很可能為指定的值。

對應於 OpenCL work_group_size_hint 屬性。

“VecTypeHint” (向量類型提示)

字串

純量或向量類型的名稱。

對應於 OpenCL vec_type_hint 屬性。

“RuntimeHandle” (運行時環境句柄)

字串

與核心相關聯的外部符號名稱。OpenCL 運行時環境為符號分配全域緩衝區,並將核心的位址儲存到其中,用於裝置端佇列 (device side enqueueing)。僅適用於裝置端佇列核心。

表 54 AMDHSA 程式碼物件 V2 核心引數元數據映射表

字串金鑰 (String Key)

值類型 (Value Type)

是否必填?

描述

“Name” (名稱)

字串

核心引數名稱。

“TypeName” (類型名稱)

字串

核心引數類型名稱。

“Size” (大小)

整數

必填

核心引數大小(以位元組為單位)。

“Align” (對齊)

整數

必填

核心引數對齊方式(以位元組為單位)。必須為 2 的冪次方。

“ValueKind” (值種類)

字串

必填

核心引數種類,指定如何設定對應的引數。值包括

“ByValue” (傳值)

引數直接複製到 kernarg 中。

“GlobalBuffer” (全域緩衝區)

傳遞 kernarg 中緩衝區資料的全域位址空間指標。

“DynamicSharedPointer” (動態共享指標)

傳遞 kernarg 中動態分配 LDS 的群組位址空間指標。

“Sampler” (取樣器)

傳遞 kernarg 中 S# 的全域位址空間指標。

“Image” (影像)

傳遞 kernarg 中 T# 的全域位址空間指標。

“Pipe” (管道)

傳遞 kernarg 中 OpenCL 管道的全域位址空間指標。

“Queue” (佇列)

傳遞 kernarg 中 OpenCL 裝置佇列佇列的全域位址空間指標。

“HiddenGlobalOffsetX” (隱藏全域偏移 X)

傳遞 kernarg 中 OpenCL 網格 dispatch 全域偏移的 X 維度。

“HiddenGlobalOffsetY” (隱藏全域偏移 Y)

傳遞 kernarg 中 OpenCL 網格 dispatch 全域偏移的 Y 維度。

“HiddenGlobalOffsetZ” (隱藏全域偏移 Z)

傳遞 kernarg 中 OpenCL 網格 dispatch 全域偏移的 Z 維度。

“HiddenNone” (隱藏無)

核心未使用的引數。需要為其保留空間,但不需要進行設定。

“HiddenPrintfBuffer” (隱藏 printf 緩衝區)

傳遞 kernarg 中運行時環境 printf 緩衝區的全域位址空間指標。與 “HiddenHostcallBuffer” 互斥。

“HiddenHostcallBuffer” (隱藏主機呼叫緩衝區)

傳遞 kernarg 中運行時環境 hostcall 緩衝區的全域位址空間指標。與 “HiddenPrintfBuffer” 互斥。

“HiddenDefaultQueue” (隱藏預設佇列)

傳遞 kernarg 中核心應預設使用的 OpenCL 裝置佇列佇列的全域位址空間指標。

“HiddenCompletionAction” (隱藏完成動作)

用於幫助將佇列核心連結到祖先樹的全域位址空間指標,以確定父核心何時完成。

“HiddenMultiGridSyncArg” (隱藏多網格同步引數)

傳遞 kernarg 中多網格同步的全域位址空間指標。

“ValueType” (值類型)

字串

未使用且已棄用。此項不應再發出,但為相容性而接受。

“PointeeAlign” (被指物對齊)

整數

指標類型核心引數的被指物類型對齊方式(以位元組為單位)。必須為 2 的冪次方。僅當 “ValueKind” 為 “DynamicSharedPointer” 時才存在。

“AddrSpaceQual” (位址空間限定詞)

字串

核心引數位址空間限定詞。僅當 “ValueKind” 為 “GlobalBuffer” 或 “DynamicSharedPointer” 時才存在。值為

  • “Private” (私有)

  • “Global” (全域)

  • “Constant” (常數)

  • “Local” (本地)

  • “Generic” (通用)

  • “Region” (區域)

“AccQual” (存取限定詞)

字串

核心引數存取限定詞。僅當 “ValueKind” 為 “Image” 或 “Pipe” 時才存在。值為

  • “ReadOnly” (唯讀)

  • “WriteOnly” (僅寫)

  • “ReadWrite” (讀寫)

“ActualAccQual” (實際存取限定詞)

字串

核心在核心引數上執行的實際記憶體存取。僅當 “ValueKind” 為 “GlobalBuffer”、“Image” 或 “Pipe” 時才存在。這可能比 “AccQual” 指示的更嚴格,以反映核心實際執行的操作。如果不存在,則運行時環境必須假設 “AccQual” 和 “IsConst” 所暗示的內容。值為

  • “ReadOnly” (唯讀)

  • “WriteOnly” (僅寫)

  • “ReadWrite” (讀寫)

“IsConst” (為常數)

布林值

指示核心引數是否為 const 限定。僅當 “ValueKind” 為 “GlobalBuffer” 時才存在。

“IsRestrict” (為 restrict)

布林值

指示核心引數是否為 restrict 限定。僅當 “ValueKind” 為 “GlobalBuffer” 時才存在。

“IsVolatile” (為 volatile)

布林值

指示核心引數是否為 volatile 限定。僅當 “ValueKind” 為 “GlobalBuffer” 時才存在。

“IsPipe” (為管道)

布林值

指示核心引數是否為 pipe 限定。僅當 “ValueKind” 為 “Pipe” 時才存在。

表 55 AMDHSA 程式碼物件 V2 核心程式碼屬性元數據映射表

字串金鑰 (String Key)

值類型 (Value Type)

是否必填?

描述

“KernargSegmentSize” (Kernarg 區段大小)

整數

必填

kernarg 區段的大小(以位元組為單位),該區段保存核心引數的值。

“GroupSegmentFixedSize” (群組區段固定大小)

整數

必填

工作群組所需的群組區段記憶體量(以位元組為單位)。這不包括在 dispatch 核心時可能添加的任何動態分配的群組區段記憶體。

“PrivateSegmentFixedSize” (私有區段固定大小)

整數

必填

工作項目所需的固定私有位址空間記憶體量(以位元組為單位)。如果核心使用動態呼叫堆疊,則必須將呼叫堆疊的額外空間添加到此值。

“KernargSegmentAlign” (Kernarg 區段對齊)

整數

必填

kernarg 區段中引數的最大位元組對齊方式。必須為 2 的冪次方。

“WavefrontSize” (波前大小)

整數

必填

波前大小。必須為 2 的冪次方。

“NumSGPRs” (SGPR 數量)

整數

必填

GFX6-GFX11 的波前使用的純量暫存器數量。這包括 VCC、Flat Scratch (GFX7-GFX10) 和 XNACK (for GFX8-GFX10) 的特殊 SGPR。它不包括啟用陷阱處理常式時新增的 16 個 SGPR。它不會向上捨入到分配粒度。

“NumVGPRs” (VGPR 數量)

整數

必填

GFX6-GFX11 的每個工作項目使用的向量暫存器數量

“MaxFlatWorkGroupSize” (最大平面工作群組大小)

整數

必填

核心支援的最大平面工作群組大小(以工作項目為單位)。必須 >=1,並且如果不是 0, 0, 0,則與 ReqdWorkGroupSize 一致。

“NumSpilledSGPRs” (溢出 SGPR 數量)

整數

從純量暫存器到暫存器分配器建立的溢出位置的儲存次數。

“NumSpilledVGPRs” (溢出 VGPR 數量)

整數

從向量暫存器到暫存器分配器建立的溢出位置的儲存次數。

程式碼物件 V3 元數據

警告

此版本的 LLVM 不再支援程式碼物件 V3 的產生。

程式碼物件 V3 及更高版本的元數據由 NT_AMDGPU_METADATA 註記記錄指定(請參閱 程式碼物件 V3 及更高版本的註記記錄)。

此元數據表示為 Message Pack 格式化的二進制資料(請參閱 [MsgPack])。頂層是一個 Message Pack 映射,其中包括表 AMDHSA 程式碼物件 V3 元數據映射表 和參考表格中定義的金鑰。

其他資訊可以添加到映射中。為避免衝突,任何金鑰名稱都應以 “vendor-name.” 為前綴,其中 vendor-name 可以是供應商名稱和產生資訊的特定供應商工具的名稱。當前綴出現在由同一 vendor-name 添加的映射中時,前綴簡稱為 “.”。

表 56 AMDHSA 程式碼物件 V3 元數據映射表

字串金鑰 (String Key)

值類型 (Value Type)

是否必填?

描述

“amdhsa.version” (amdhsa.版本)

2 個整數的序列 (sequence)

必填

  • 第一個整數是主版本號 (major version)。目前為 1。

  • 第二個整數是次要版本號 (minor version)。目前為 0。

“amdhsa.printf” (amdhsa.printf)

字串序列

每個字串都是關於 printf 函數呼叫的編碼資訊。編碼資訊組織為以冒號 (':') 分隔的欄位 (field)。

ID:N:S[0]:S[1]:...:S[N-1]:FormatString

其中

ID

32 位元整數,作為每個 printf 函數呼叫的唯一 ID

N

32 位元整數,等於 printf 函數呼叫的引數數量減 1

S[i] (其中 i = 0, 1, … , N-1)

32 位元整數,表示 printf 函數呼叫的第 i 個 FormatString 引數的大小(以位元組為單位)

FormatString (格式字串)

傳遞給 printf 函數呼叫的格式字串。

“amdhsa.kernels” (amdhsa.核心)

映射序列

必填

程式碼物件中每個核心的映射序列。有關該映射中包含的金鑰定義,請參閱 AMDHSA 程式碼物件 V3 核心元數據映射表

表 57 AMDHSA 程式碼物件 V3 核心元數據映射表

字串金鑰 (String Key)

值類型 (Value Type)

是否必填?

描述

“.name” (名稱)

字串

必填

核心的原始碼名稱。

“.symbol” (符號)

字串

必填

核心描述符 ELF 符號的名稱。

“.language” (語言)

字串

核心的原始碼語言。值包括

  • “OpenCL C”

  • “OpenCL C++”

  • “HCC”

  • “HIP”

  • “OpenMP”

  • “Assembler” (組譯器)

“.language_version” (語言版本)

2 個整數的序列 (sequence)

  • 第一個整數是主版本號。

  • 第二個整數是次要版本號。

“.args” (引數)

映射序列

核心引數的映射序列。有關該映射中包含的金鑰定義,請參閱 AMDHSA 程式碼物件 V3 核心引數元數據映射表

“.reqd_workgroup_size” (必要工作群組大小)

3 個整數的序列

如果不是 0, 0, 0,則所有值必須 >=1,且 dispatch 工作群組大小 X、Y、Z 必須對應於指定的值。預設為 0, 0, 0。

對應於 OpenCL reqd_work_group_size 屬性。

“.workgroup_size_hint” (工作群組大小提示)

3 個整數的序列

dispatch 工作群組大小 X、Y、Z 很可能為指定的值。

對應於 OpenCL work_group_size_hint 屬性。

“.vec_type_hint” (向量類型提示)

字串

純量或向量類型的名稱。

對應於 OpenCL vec_type_hint 屬性。

“.device_enqueue_symbol” (裝置佇列符號)

字串

與核心相關聯的外部符號名稱。OpenCL 運行時環境為符號分配全域緩衝區,並將核心的位址儲存到其中,用於裝置端佇列 (device side enqueueing)。僅適用於裝置端佇列核心。

“.kernarg_segment_size” (Kernarg 區段大小)

整數

必填

kernarg 區段的大小(以位元組為單位),該區段保存核心引數的值。

“.group_segment_fixed_size” (群組區段固定大小)

整數

必填

工作群組所需的群組區段記憶體量(以位元組為單位)。這不包括在 dispatch 核心時可能添加的任何動態分配的群組區段記憶體。

“.private_segment_fixed_size” (私有區段固定大小)

整數

必填

工作項目所需的固定私有位址空間記憶體量(以位元組為單位)。如果核心使用動態呼叫堆疊,則必須將呼叫堆疊的額外空間添加到此值。

“.kernarg_segment_align” (Kernarg 區段對齊)

整數

必填

kernarg 區段中引數的最大位元組對齊方式。必須為 2 的冪次方。

“.wavefront_size” (波前大小)

整數

必填

波前大小。必須為 2 的冪次方。

“.sgpr_count” (SGPR 數量)

整數

必填

GFX6-GFX9 的波前所需的純量暫存器數量。如果明確使用暫存器,或明確使用編號較高的暫存器,則需要暫存器。這包括 VCC、Flat Scratch (GFX7-GFX9) 和 XNACK (for GFX8-GFX9) 的特殊 SGPR。它不包括啟用陷阱處理常式時新增的 16 個 SGPR。它不會向上捨入到分配粒度。

“.vgpr_count” (VGPR 數量)

整數

必填

GFX6-GFX9 的每個工作項目所需的向量暫存器數量。如果明確使用暫存器,或明確使用編號較高的暫存器,則需要暫存器。

“.agpr_count” (AGPR 數量)

整數

必填

GFX90A、GFX908 的每個工作項目所需的累加器暫存器數量。

“.max_flat_workgroup_size” (最大平面工作群組大小)

整數

必填

核心支援的最大平面工作群組大小(以工作項目為單位)。必須 >=1,並且如果不是 0, 0, 0,則與 ReqdWorkGroupSize 一致。

“.sgpr_spill_count” (SGPR 溢出數量)

整數

從純量暫存器到暫存器分配器建立的溢出位置的儲存次數。

“.vgpr_spill_count” (VGPR 溢出數量)

整數

從向量暫存器到暫存器分配器建立的溢出位置的儲存次數。

“.kind” (種類)

字串

核心的種類,具有以下值

“normal” (一般)

常規核心。

“init” (初始化)

這些核心必須在載入包含的程式碼物件後調用,並且必須在調用同一程式碼物件中的任何 normal 和 fini 核心之前完成。

“fini” (結束)

這些核心必須在卸載包含的程式碼物件之前調用,並且在同一程式碼物件中的所有 init 和 normal 核心都已調用並完成後調用。

如果省略,則假定為 “normal”。

“.max_num_work_groups_{x,y,z}” (最大工作群組數量_{x,y,z})

整數

X、Y 和 Z 維度中啟動的最大工作群組數量。每個數字必須 >=1。

表 58 AMDHSA 程式碼物件 V3 核心引數元數據映射表

字串金鑰 (String Key)

值類型 (Value Type)

是否必填?

描述

“.name” (名稱)

字串

核心引數名稱。

“.type_name” (類型名稱)

字串

核心引數類型名稱。

“.size” (大小)

整數

必填

核心引數大小(以位元組為單位)。

“.offset” (偏移)

整數

必填

核心引數偏移(以位元組為單位)。偏移量必須是引數所需對齊方式的倍數。

“.value_kind” (值種類)

字串

必填

核心引數種類,指定如何設定對應的引數。值包括

“by_value” (傳值)

引數直接複製到 kernarg 中。

“global_buffer” (全域緩衝區)

傳遞 kernarg 中緩衝區資料的全域位址空間指標。

“dynamic_shared_pointer” (動態共享指標)

傳遞 kernarg 中動態分配 LDS 的群組位址空間指標。

“sampler” (取樣器)

傳遞 kernarg 中 S# 的全域位址空間指標。

“image” (影像)

傳遞 kernarg 中 T# 的全域位址空間指標。

“pipe” (管道)

傳遞 kernarg 中 OpenCL 管道的全域位址空間指標。

“queue” (佇列)

傳遞 kernarg 中 OpenCL 裝置佇列佇列的全域位址空間指標。

“hidden_global_offset_x” (隱藏全域偏移 X)

傳遞 kernarg 中 OpenCL 網格 dispatch 全域偏移的 X 維度。

“hidden_global_offset_y” (隱藏全域偏移 Y)

傳遞 kernarg 中 OpenCL 網格 dispatch 全域偏移的 Y 維度。

“hidden_global_offset_z” (隱藏全域偏移 Z)

傳遞 kernarg 中 OpenCL 網格 dispatch 全域偏移的 Z 維度。

“hidden_none” (隱藏無)

核心未使用的引數。需要為其保留空間,但不需要進行設定。

“hidden_printf_buffer” (隱藏 printf 緩衝區)

傳遞 kernarg 中運行時環境 printf 緩衝區的全域位址空間指標。在程式碼物件 V5 之前,與 “hidden_hostcall_buffer” 互斥。

“hidden_hostcall_buffer” (隱藏主機呼叫緩衝區)

傳遞 kernarg 中運行時環境 hostcall 緩衝區的全域位址空間指標。在程式碼物件 V5 之前,與 “hidden_printf_buffer” 互斥。

“hidden_default_queue” (隱藏預設佇列)

傳遞 kernarg 中核心應預設使用的 OpenCL 裝置佇列佇列的全域位址空間指標。

“hidden_completion_action” (隱藏完成動作)

用於幫助將佇列核心連結到祖先樹的全域位址空間指標,以確定父核心何時完成。

“hidden_multigrid_sync_arg” (隱藏多網格同步引數)

傳遞 kernarg 中多網格同步的全域位址空間指標。

“.value_type” (值類型)

字串

未使用且已棄用。此項不應再發出,但為相容性而接受。

“.pointee_align” (被指物對齊)

整數

指標類型核心引數的被指物類型對齊方式(以位元組為單位)。必須為 2 的冪次方。僅當 “.value_kind” 為 “dynamic_shared_pointer” 時才存在。

“.address_space” (位址空間)

字串

核心引數位址空間限定詞。僅當 “.value_kind” 為 “global_buffer” 或 “dynamic_shared_pointer” 時才存在。值為

  • “private” (私有)

  • “global” (全域)

  • “constant” (常數)

  • “local” (本地)

  • “generic” (通用)

  • “region” (區域)

“.access” (存取)

字串

核心引數存取限定詞。僅當 “.value_kind” 為 “image” 或 “pipe” 時才存在。值為

  • “read_only” (唯讀)

  • “write_only” (僅寫)

  • “read_write” (讀寫)

“.actual_access” (實際存取)

字串

核心在核心引數上執行的實際記憶體存取。僅當 “.value_kind” 為 “global_buffer”、“image” 或 “pipe” 時才存在。這可能比 “.access” 指示的更嚴格,以反映核心實際執行的操作。如果不存在,則運行時環境必須假設 “.access” 和 “.is_const” 所暗示的內容。值為

  • “read_only” (唯讀)

  • “write_only” (僅寫)

  • “read_write” (讀寫)

“.is_const” (為常數)

布林值

指示核心引數是否為 const 限定。僅當 “.value_kind” 為 “global_buffer” 時才存在。

“.is_restrict” (為 restrict)

布林值

指示核心引數是否為 restrict 限定。僅當 “.value_kind” 為 “global_buffer” 時才存在。

“.is_volatile” (為 volatile)

布林值

指示核心引數是否為 volatile 限定。僅當 “.value_kind” 為 “global_buffer” 時才存在。

“.is_pipe” (為管道)

布林值

指示核心引數是否為 pipe 限定。僅當 “.value_kind” 為 “pipe” 時才存在。

程式碼物件 V4 元數據
. 警告:

程式碼物件 V4 不是此版本 LLVM 發出的預設程式碼物件版本。

程式碼物件 V4 元數據與 程式碼物件 V3 元數據 相同,但具有表 AMDHSA 程式碼物件 V4 元數據映射表變更 中定義的變更和新增內容。

表 59 AMDHSA 程式碼物件 V4 元數據映射表變更

字串金鑰 (String Key)

值類型 (Value Type)

是否必填?

描述

“amdhsa.version” (amdhsa.版本)

2 個整數的序列 (sequence)

必填

  • 第一個整數是主版本號 (major version)。目前為 1。

  • 第二個整數是次要版本號。目前為 1。

“amdhsa.target” (amdhsa.目標)

字串

必填

使用以下語法的程式碼目標名稱

<target-triple> [ "-" <target-id> ]

必須使用標準目標 ID。請參閱 目標三元組目標 ID

程式碼物件 V5 元數據

程式碼物件 V5 元數據與 程式碼物件 V4 元數據 相同,但具有表 AMDHSA 程式碼物件 V5 元數據映射表變更、表 AMDHSA 程式碼物件 V5 核心元數據映射表新增內容 和表 AMDHSA 程式碼物件 V5 核心引數元數據映射表新增內容和變更 中定義的變更。

表 60 AMDHSA 程式碼物件 V5 元數據映射表變更

字串金鑰 (String Key)

值類型 (Value Type)

是否必填?

描述

“amdhsa.version” (amdhsa.版本)

2 個整數的序列 (sequence)

必填

  • 第一個整數是主版本號 (major version)。目前為 1。

  • 第二個整數是次要版本號。目前為 2。

表 61 AMDHSA 程式碼物件 V5 核心元數據映射表新增內容

字串金鑰 (String Key)

值類型 (Value Type)

是否必填?

描述

“.uses_dynamic_stack” (使用動態堆疊)

布林值

指示產生的機器碼是否使用動態大小的堆疊。

“.workgroup_processor_mode” (工作群組處理器模式)

布林值

(GFX10+) 控制 程式碼物件 V3 核心描述符 中的 ENABLE_WGP_MODE。

表 62 AMDHSA 程式碼物件 V5 核心屬性元數據映射表

字串金鑰 (String Key)

值類型 (Value Type)

是否必填?

描述

“.uniform_work_group_size” (統一工作群組大小)

整數

指示核心是否要求全域大小的每個維度都是工作群組大小的相應維度的倍數。值 1 表示 true,值 0 表示 false。僅當值為 1 時才發出元數據。

表 63 AMDHSA 程式碼物件 V5 核心引數元數據映射表新增內容和變更

字串金鑰 (String Key)

值類型 (Value Type)

是否必填?

描述

“.value_kind” (值種類)

字串

必填

核心引數種類,指定如何設定對應的引數。值包括:與程式碼物件 V3 元數據相同(請參閱 AMDHSA 程式碼物件 V3 核心引數元數據映射表),並具有以下新增內容

“hidden_block_count_x” (隱藏區塊計數 X)

傳遞 kernarg 中 X 維度的網格 dispatch 工作群組計數。某些語言(例如 OpenCL)支援每個維度中的最後一個工作群組為部分工作群組。此計數僅包括非部分工作群組計數。這與 AQL dispatch 封包中的值不同,後者具有工作項目中的網格大小。

“hidden_block_count_y” (隱藏區塊計數 Y)

傳遞 kernarg 中 Y 維度的網格 dispatch 工作群組計數。某些語言(例如 OpenCL)支援每個維度中的最後一個工作群組為部分工作群組。此計數僅包括非部分工作群組計數。這與 AQL dispatch 封包中的值不同,後者具有工作項目中的網格大小。如果網格維度為 1,則必須為 1。

“hidden_block_count_z” (隱藏區塊計數 Z)

傳遞 kernarg 中 Z 維度的網格 dispatch 工作群組計數。某些語言(例如 OpenCL)支援每個維度中的最後一個工作群組為部分工作群組。此計數僅包括非部分工作群組計數。這與 AQL dispatch 封包中的值不同,後者具有工作項目中的網格大小。如果網格維度為 1 或 2,則必須為 1。

“hidden_group_size_x” (隱藏群組大小 X)

傳遞 kernarg 中 X 維度的網格 dispatch 工作群組大小。此大小僅適用於非部分工作群組。這與 AQL dispatch 封包工作群組大小的值相同。

“hidden_group_size_y” (隱藏群組大小 Y)

傳遞 kernarg 中 Y 維度的網格 dispatch 工作群組大小。此大小僅適用於非部分工作群組。這與 AQL dispatch 封包工作群組大小的值相同。如果網格維度為 1,則必須為 1。

“hidden_group_size_z” (隱藏群組大小 Z)

傳遞 kernarg 中 Z 維度的網格 dispatch 工作群組大小。此大小僅適用於非部分工作群組。這與 AQL dispatch 封包工作群組大小的值相同。如果網格維度為 1 或 2,則必須為 1。

“hidden_remainder_x” (隱藏餘數 X)

如果存在 X 維度的部分工作群組,則為該部分工作群組的網格 dispatch 工作群組大小。如果 X 維度中不存在部分工作群組,則必須為零。

“hidden_remainder_y” (隱藏餘數 Y)

如果存在 Y 維度的部分工作群組,則為該部分工作群組的網格 dispatch 工作群組大小。如果 Y 維度中不存在部分工作群組,則必須為零。

“hidden_remainder_z” (隱藏餘數 Z)

如果存在 Z 維度的部分工作群組,則為該部分工作群組的網格 dispatch 工作群組大小。如果 Z 維度中不存在部分工作群組,則必須為零。

“hidden_grid_dims” (隱藏網格維度)

網格 dispatch 維度。這與 AQL dispatch 封包維度的值相同。必須為介於 1 到 3 之間的值。

“hidden_heap_v1” (隱藏堆積 v1)

指向已初始化記憶體緩衝區的全域位址空間指標,該緩衝區符合 malloc/free 裝置庫 V1 版本實作的要求。

“hidden_dynamic_lds_size” (隱藏動態 LDS 大小)

傳遞 kernarg 中動態分配的 LDS 記憶體大小。

“hidden_private_base” (隱藏私有基底)

平面定址私有光圈基底的高 32 位元。僅供 GFX8 用於允許私有區段和平面位址之間的轉換。請參閱 平面 Scratch

“hidden_shared_base” (隱藏共享基底)

平面定址共享光圈基底的高 32 位元。僅供 GFX8 用於允許共享區段和平面位址之間的轉換。請參閱 平面 Scratch

“hidden_queue_ptr” (隱藏佇列指標)

指向 ROCm 運行時環境 struct amd_queue_t 結構的全域記憶體位址空間指標,用於關聯的 dispatch AQL 封包的 HSA 佇列。僅在 GFX9 之前的裝置上用於陷阱處理常式 ABI(請參閱 陷阱處理常式 ABI)。

核心 Dispatch

HSA 架構佇列語言 (AQL) 定義了一個使用者空間記憶體介面,可用於以代理程式獨立的方式控制核心的 dispatch。代理程式可以使用 HSA 相容的運行時環境為其建立零個或多個 AQL 佇列(請參閱 AMDGPU 作業系統),其中可以放置 AQL 封包(所有封包均為 64 位元組)。有關 AQL 佇列機制和封包佈局,請參閱HSA 平台系統架構規範 [HSA]

核心代理程式的封包處理器負責偵測和 dispatch 與其關聯的 AQL 佇列中的 HSA 核心。對於 AMD GPU,封包處理器由硬體命令處理器 (CP)、異步 dispatch 控制器 (ADC) 和著色器處理器輸入控制器 (SPI) 實作。

可以使用 HSA 相容的運行時環境來分配 AQL 佇列物件。它使用核心模式驅動程式來初始化 AQL 佇列並向 CP 註冊。

若要 dispatch 核心,請執行以下動作。這可以在 CPU 主機程式中發生,也可以從在 GPU 上執行的 HSA 核心發生。

  1. 取得要在其上執行核心的核心代理程式的 AQL 佇列指標。

  2. 取得要執行的核心的核心描述符指標(請參閱 核心描述符)。它必須適用於 HSA 相容運行時環境在與 AQL 佇列關聯的核心代理程式上載入的程式碼物件中包含的核心。

  3. 使用 HSA 相容運行時環境分配器為具有 kernarg 屬性的記憶體區域分配空間,以用於將執行核心的核心代理程式。它必須至少為 16 位元組對齊。

  4. 核心引數值會指派給核心引數記憶體分配。佈局在HSA 程式設計人員語言參考 [HSA] 中定義。對於 AMDGPU,核心執行直接存取核心引數記憶體,方式與存取常數記憶體的方式相同。(請注意,HSA 規範允許實作將核心引數內容複製到核心存取的另一個位置。)

  5. 在 AQL 佇列上建立 AQL 核心 dispatch 封包。HSA 相容運行時環境 API 使用 64 位元原子操作在 AQL 佇列中為封包保留空間。必須設定封包,並且最終寫入必須使用原子儲存發佈 (atomic store release) 來設定封包種類,以確保封包內容對核心代理程式可見。AQL 定義了門鈴訊號機制,以通知核心代理程式 AQL 佇列已更新。這些規則以及 AQL 佇列和核心 dispatch 封包的佈局在HSA 系統架構規範 [HSA] 中定義。

  6. 核心 dispatch 封包包含有關實際 dispatch 的資訊,例如網格和工作群組大小,以及來自程式碼物件的有關核心的資訊,例如區段大小。可以使用 HSA 相容運行時環境對核心符號的查詢來取得程式碼物件值,這些值記錄在 程式碼物件元數據 中。

  7. CP 執行微指令,並負責偵測和設定 GPU,以執行核心分派的波前。

  8. CP 確保當波前開始執行核心機器碼時,純量通用暫存器 (SGPR) 和向量通用暫存器 (VGPR) 會依照機器碼的要求進行設定。所需的設定定義於核心描述符中。初始暫存器狀態定義於初始核心執行狀態中。

  9. 核心機器碼的前言(請參閱核心前言)會先設定必要的機器狀態,然後繼續執行對應於核心的機器碼。

  10. 當核心分派完成執行時,如果核心分派封包中指定的完成訊號不為 0,CP 會發出完成訊號。

記憶體空間

記憶體空間屬性如下:

表 64 AMDHSA 記憶體空間

記憶體空間名稱

HSA 區段名稱

硬體名稱

位址大小

NULL 值

私有

private

scratch

32

0x00000000

本地

group

LDS

32

0xFFFFFFFF

全域

global

global

64

0x0000000000000000

常數

constant

與全域相同

64

0x0000000000000000

通用

flat

flat

64

0x0000000000000000

區域

不適用

GDS

32

未針對 AMDHSA 實作

全域和常數記憶體空間都使用全域虛擬位址,這與 CPU 使用的虛擬位址空間相同。但是,有些虛擬位址可能僅 CPU 可存取,有些僅 GPU 可存取,有些則兩者皆可存取。

使用常數記憶體空間表示資料在核心執行期間不會變更。這允許使用純量讀取指令。向量和純量 L1 快取會在每次核心分派執行前,使不穩定的資料失效,以允許常數記憶體在核心分派之間變更值。

本機記憶體空間使用硬體本機資料儲存區 (LDS),當硬體建立波前的工作群組時會自動配置,並在工作群組的所有波前終止時釋放。資料儲存區 (DS) 指令可用於存取它。

私有記憶體空間使用硬體暫存記憶體支援。如果核心使用暫存記憶體,則硬體會配置記憶體,該記憶體使用波前通道雙字組(4 位元組)交錯方式存取。從私有位址到實體位址的對應關係為:

wavefront-scratch-base + (private-address * wavefront-size * 4) + (wavefront-lane-id * 4)

波前決定波前暫存基底位址的方式有所不同(請參閱初始核心執行狀態)。此記憶體可以使用緩衝區指令,透過暫存緩衝區描述符和每個波前的暫存偏移量、透過暫存指令或透過平面指令以交錯方式存取。如果波前的每個通道存取相同的私有位址,則交錯會導致存取相鄰的雙字組,因此需要提取較少的快取行。除了 GFX9-GFX11 中的平面和暫存指令外,不支援多字組存取。

通用位址空間使用 GFX7-GFX11 中可用的硬體平面位址支援。這使用兩個固定的虛擬位址範圍(私有和本機孔徑),它們位於可定址全域記憶體範圍之外,以將平面位址對應到私有或本機位址。

FLAT 指令可以採用平面位址,並根據位址是否在其中一個孔徑範圍內,存取全域、私有(暫存)和群組 (LDS) 記憶體。平面存取暫存記憶體需要硬體孔徑設定和核心前言中的設定(請參閱平面暫存記憶體)。平面存取 LDS 需要硬體孔徑設定和 M0 (GFX7-GFX8) 暫存器設定(請參閱M0)。

若要在區段位址和平面位址之間轉換,可以使用孔徑位址的基底位址。對於 GFX7-GFX8,這些位址可在HSA AQL 佇列中找到,其位址可以使用佇列指標 SGPR 取得(請參閱初始核心執行狀態)。對於 GFX9-GFX11,孔徑基底位址可直接作為內嵌常數暫存器 SRC_SHARED_BASE/LIMITSRC_PRIVATE_BASE/LIMIT 使用。在 64 位元位址模式中,孔徑大小為 2^32 位元組,基底對齊至 2^32,這使得從平面位址轉換為區段位址或從區段位址轉換為平面位址更容易。

影像和取樣器

由 HSA 相容執行階段建立的影像和取樣器控制代碼(請參閱AMDGPU 作業系統)分別是硬體 32 位元組 V# 和 48 位元組 S# 物件的 64 位元位址。為了支援 HSA query_sampler 操作,額外使用兩個雙字組來儲存 HSA BRIG 列舉值,用於無法從 S# 表示法中輕易推導出的查詢。

HSA 訊號

由 HSA 相容執行階段建立的 HSA 訊號控制代碼(請參閱AMDGPU 作業系統)是在 CPU 和 GPU 皆可存取的記憶體中配置的結構的 64 位元位址。此結構由執行階段定義,並可能在版本之間變更。例如,請參閱[AMD-ROCm-github]

HSA AQL 佇列

HSA AQL 佇列結構由 HSA 相容執行階段定義(請參閱AMDGPU 作業系統),並可能在版本之間變更。例如,請參閱[AMD-ROCm-github]。對於某些處理器,它包含實作某些語言功能所需的欄位,例如平面位址孔徑基底。它還包含 CP 使用的欄位,例如管理暫存記憶體的配置。

核心描述符

核心描述符包含 CP 啟動核心執行所需的資訊,包括實作核心的機器碼的進入點位址。

程式碼物件 V3 核心描述符

CP 微指令碼要求核心描述符以 64 位元組對齊方式配置。

V3 之前的程式碼物件的 CP 使用的欄位,也與程式碼物件 V3 核心描述符中指定的欄位一致。

表 65 程式碼物件 V3 核心描述符

位元

大小

欄位名稱

描述

31:0

4 位元組

GROUP_SEGMENT_FIXED_SIZE

工作群組所需的固定本機位址空間記憶體量,以位元組為單位。這不包括在核心分派時可能新增的任何動態配置的本機位址空間記憶體。

63:32

4 位元組

PRIVATE_SEGMENT_FIXED_SIZE

工作項目所需的固定私有位址空間記憶體量,以位元組為單位。當無法預測此值時,程式碼物件 v4 和更舊版本會將此值設定為高於最低要求。

95:64

4 位元組

KERNARG_SIZE

AQL 分派封包指向的 kernarg 記憶體大小。kernarg 記憶體用於將引數傳遞給核心。

  • 如果分派封包中的 kernarg 指標為 NULL,則沒有核心引數。

  • 如果分派封包中的 kernarg 指標不為 NULL,且此值為 0,則 kernarg 記憶體大小未指定。

  • 如果分派封包中的 kernarg 指標不為 NULL,且此值不為 0,則此值指定 kernarg 記憶體大小(以位元組為單位)。建議提供一個值,因為 CP 可能會使用它來最佳化使 kernarg 記憶體對核心程式碼可見。

127:96

4 位元組

保留,必須為 0。

191:128

8 位元組

KERNEL_CODE_ENTRY_BYTE_OFFSET

從核心描述符的基底位址到核心的進入點指令的位元組偏移量(可能為負值),該指令必須以 256 位元組對齊。

351:192

20 位元組

保留,必須為 0。

383:352

4 位元組

COMPUTE_PGM_RSRC3

GFX6-GFX9

保留,必須為 0。

GFX90A、GFX942

CP 用於設定 COMPUTE_PGM_RSRC3 組態暫存器的運算著色器 (CS) 程式設定。請參閱GFX90A、GFX942 的 compute_pgm_rsrc3

GFX10-GFX11

CP 用於設定 COMPUTE_PGM_RSRC3 組態暫存器的運算著色器 (CS) 程式設定。請參閱GFX10-GFX11 的 compute_pgm_rsrc3

GFX12

CP 用於設定 COMPUTE_PGM_RSRC3 組態暫存器的運算著色器 (CS) 程式設定。請參閱GFX12 的 compute_pgm_rsrc3

415:384

4 位元組

COMPUTE_PGM_RSRC1

CP 用於設定 COMPUTE_PGM_RSRC1 組態暫存器的運算著色器 (CS) 程式設定。請參閱GFX6-GFX12 的 compute_pgm_rsrc1

447:416

4 位元組

COMPUTE_PGM_RSRC2

CP 用於設定 COMPUTE_PGM_RSRC2 組態暫存器的運算著色器 (CS) 程式設定。請參閱GFX6-GFX12 的 compute_pgm_rsrc2

458:448

7 位元

請參閱下方的個別位元。

啟用 SGPR 使用者資料暫存器的設定(請參閱初始核心執行狀態)。

請求的 SGPR 使用者資料暫存器總數不得超過 16 個,且必須與 compute_pgm_rsrc2.user_sgpr.user_sgpr_count 中的值相符。超過 16 個的任何請求都會被忽略。

>448

1 位元

ENABLE_SGPR_PRIVATE_SEGMENT _BUFFER

如果AMDGPU 處理器目標屬性欄指定架構平面暫存記憶體,則不支援且必須為 0。

>449

1 位元

ENABLE_SGPR_DISPATCH_PTR

>450

1 位元

ENABLE_SGPR_QUEUE_PTR

>451

1 位元

ENABLE_SGPR_KERNARG_SEGMENT_PTR

>452

1 位元

ENABLE_SGPR_DISPATCH_ID

>453

1 位元

ENABLE_SGPR_FLAT_SCRATCH_INIT

如果AMDGPU 處理器目標屬性欄指定架構平面暫存記憶體,則不支援且必須為 0。

>454

1 位元

ENABLE_SGPR_PRIVATE_SEGMENT _SIZE

457:455

3 位元

保留,必須為 0。

458

1 位元

ENABLE_WAVEFRONT_SIZE32

GFX6-GFX9

保留,必須為 0。

GFX10-GFX11
  • 如果為 0,則以波前大小 64 模式執行。

  • 如果為 1,則以原生波前大小 32 模式執行。

459

1 位元

USES_DYNAMIC_STACK

表示產生的機器碼是否正在使用動態大小的堆疊。這僅在程式碼物件 v5 和更新版本中設定。

463:460

4 位元

保留,必須為 0。

470:464

7 位元

KERNARG_PRELOAD_SPEC_LENGTH

GFX6-GFX9
  • 保留,必須為 0。

GFX90A、GFX942
  • 從 kernarg 區段預先載入到使用者 SGPR 中以在核心執行之前使用的雙字組數量。(請參閱預先載入的核心引數)。

479:471

9 位元

KERNARG_PRELOAD_SPEC_OFFSET

GFX6-GFX9
  • 保留,必須為 0。

GFX90A、GFX942

511:480

4 位元組

保留,必須為 0。

512

總大小 64 位元組。

表 66 GFX6-GFX12 的 compute_pgm_rsrc1

位元

大小

欄位名稱

描述

5:0

6 位元

GRANULATED_WORKITEM_VGPR_COUNT

每個工作項目使用的向量暫存器區塊數量;粒度是裝置特定的

GFX6-GFX9
  • vgprs_used 0..256

  • max(0, ceil(vgprs_used / 4) - 1)

GFX90A、GFX942
  • vgprs_used 0..512

  • vgprs_used = align(arch_vgprs, 4)
    • acc_vgprs

  • max(0, ceil(vgprs_used / 8) - 1)

GFX10-GFX12(波前大小 64)
  • max_vgpr 1..256

  • max(0, ceil(vgprs_used / 4) - 1)

GFX10-GFX12(波前大小 32)
  • max_vgpr 1..256

  • max(0, ceil(vgprs_used / 8) - 1)

其中 vgprs_used 定義為明確參考的最高 VGPR 編號加一。

CP 用於設定 COMPUTE_PGM_RSRC1.VGPRS

組譯器會針對選定的處理器,從 .amdhsa_kernel 指令提供給 .amdhsa_next_free_vgpr 巢狀指令的值自動計算此值(請參閱AMDHSA 核心組譯器指令)。

9:6

4 位元

GRANULATED_WAVEFRONT_SGPR_COUNT

波前使用的純量暫存器區塊數量;粒度是裝置特定的

GFX6-GFX8
  • sgprs_used 0..112

  • max(0, ceil(sgprs_used / 8) - 1)

GFX9
  • sgprs_used 0..112

  • 2 * max(0, ceil(sgprs_used / 16) - 1)

GFX10-GFX12

保留,必須為 0。(始終配置 128 個 SGPR。)

其中 sgprs_used 定義為明確參考的最高 SGPR 編號加一,加上目標特定的額外特殊 SGPR 數量,用於 VCC、FLAT_SCRATCH (GFX7+) 和 XNACK_MASK (GFX8+),以及任何其他目標特定的限制。它不包括在啟用陷阱處理常式時新增的 16 個 SGPR。

目標特定的限制和特殊 SGPR 佈局定義在硬體文件中,可在處理器表格中找到。

CP 用於設定 COMPUTE_PGM_RSRC1.SGPRS

組譯器會針對選定的處理器,從 .amdhsa_kernel 指令提供給 .amdhsa_next_free_sgpr.amdhsa_reserve_* 巢狀指令的值自動計算此值(請參閱AMDHSA 核心組譯器指令)。

11:10

2 位元

PRIORITY

必須為 0。

以指定的優先順序開始執行波前。

CP 負責填寫 COMPUTE_PGM_RSRC1.PRIORITY

13:12

2 位元

FLOAT_ROUND_MODE_32

波前開始執行時,單精度 (32 位元) 浮點運算的指定捨入模式。

浮點捨入模式值定義於浮點捨入模式列舉值中。

CP 用於設定 COMPUTE_PGM_RSRC1.FLOAT_MODE

15:14

2 位元

FLOAT_ROUND_MODE_16_64

波前開始執行時,半精度/雙精度(16 位元和 64 位元)浮點運算的指定捨入反常模式。

浮點捨入模式值定義於浮點捨入模式列舉值中。

CP 用於設定 COMPUTE_PGM_RSRC1.FLOAT_MODE

17:16

2 位元

FLOAT_DENORM_MODE_32

波前開始執行時,單精度 (32 位元) 浮點運算的指定反常模式。

浮點反常模式值定義於浮點反常模式列舉值中。

CP 用於設定 COMPUTE_PGM_RSRC1.FLOAT_MODE

19:18

2 位元

FLOAT_DENORM_MODE_16_64

波前開始執行時,半精度/雙精度(16 位元和 64 位元)浮點運算的指定反常模式。

浮點反常模式值定義於浮點反常模式列舉值中。

CP 用於設定 COMPUTE_PGM_RSRC1.FLOAT_MODE

20

1 位元

PRIV

必須為 0。

以特權陷阱處理常式模式開始執行波前。

CP 負責填寫 COMPUTE_PGM_RSRC1.PRIV

21

1 位元

ENABLE_DX10_CLAMP

WG_RR_EN

GFX9-GFX11

波前開始執行時,啟用 DX10 鉗位模式。向量 ALU 使用此模式來強制執行 DX10 樣式的 NaN 處理(設定時,將 NaN 鉗位為零,否則讓 NaN 通過)。

CP 用於設定 COMPUTE_PGM_RSRC1.DX10_CLAMP

GFX12

如果為 1,則波前以循環配置方式,相對於 SIMD 的其他波前進行排程。否則,波前以最舊的年齡順序排程。

CP 負責填寫 COMPUTE_PGM_RSRC1.WG_RR_EN

22

1 位元

DEBUG_MODE

必須為 0。

以單步執行模式開始執行波前。

CP 負責填寫 COMPUTE_PGM_RSRC1.DEBUG_MODE

23

1 位元

ENABLE_IEEE_MODE

DISABLE_PERF

GFX9-GFX11

波前開始執行時,啟用 IEEE 模式。支援例外旗標收集的浮點運算碼將根據 IEEE 754-2008 標準,靜音並傳播發出訊號的 NaN 輸入。由於發出訊號的 NaN 傳播和靜音,min_dx10 和 max_dx10 變得符合 IEEE 754-2008 標準。

CP 用於設定 COMPUTE_PGM_RSRC1.IEEE_MODE

GFX12

保留。必須為 0。

24

1 位元

BULKY

必須為 0。

僅允許一個工作群組在運算單元上執行。

CP 負責填寫 COMPUTE_PGM_RSRC1.BULKY

25

1 位元

CDBG_USER

必須為 0。

可用於控制偵錯程式碼的旗標。

CP 負責填寫 COMPUTE_PGM_RSRC1.CDBG_USER

26

1 位元

FP16_OVFL

GFX6-GFX8

保留,必須為 0。

GFX9-GFX12

波前開始執行時,具有指定的 fp16 溢位模式。

  • 如果為 0,fp16 溢位會產生 +/-INF 值。

  • 如果為 1,則 +/-INF 輸入值或除以 0 導致的 fp16 溢位會產生 +/-INF,否則會將計算出的溢位鉗位為 +/-MAX_FP16(適當情況下)。

CP 用於設定 COMPUTE_PGM_RSRC1.FP16_OVFL

28:27

2 位元

保留,必須為 0。

29

1 位元

WGP_MODE

GFX6-GFX9

保留,必須為 0。

GFX10-GFX12
  • 如果為 0,則在 CU 波前執行模式中執行工作群組。

  • 如果為 1,則在 WGP 波前執行模式中執行工作群組。

請參閱記憶體模型

CP 用於設定 COMPUTE_PGM_RSRC1.WGP_MODE

30

1 位元

MEM_ORDERED

GFX6-GFX9

保留,必須為 0。

GFX10-GFX12

控制 s_waitcnt 的 vmcnt 和 vscnt 計數器的行為。

  • 如果為 0,vmcnt 會報告與取樣指令無序的載入完成和原子傳回,而 vscnt 會報告有序的儲存完成和無傳回的原子操作完成。

  • 如果為 1,vmcnt 會報告有序的載入完成、原子傳回和取樣指令,而 vscnt 會報告有序的儲存完成和無傳回的原子操作完成。

CP 用於設定 COMPUTE_PGM_RSRC1.MEM_ORDERED

31

1 位元

FWD_PROGRESS

GFX6-GFX9

保留,必須為 0。

GFX10-GFX12
  • 如果為 0,則使用最舊優先原則執行 SIMD 波前。

  • 如果為 1,則執行 SIMD 波前以確保波前將取得某些進展。

CP 用於設定 COMPUTE_PGM_RSRC1.FWD_PROGRESS

32

總大小 4 位元組

表 67 GFX6-GFX12 的 compute_pgm_rsrc2

位元

大小

欄位名稱

描述

0

1 位元

ENABLE_PRIVATE_SEGMENT

CP 用於設定 COMPUTE_PGM_RSRC2.SCRATCH_EN

5:1

5 位元

USER_SGPR_COUNT

請求的 SGPR 使用者資料暫存器總數。此數字必須大於或等於已啟用的使用者資料暫存器數量。

CP 用於設定 COMPUTE_PGM_RSRC2.USER_SGPR

6

1 位元

ENABLE_TRAP_HANDLER

GFX6-GFX11

必須為 0。

此位元代表 COMPUTE_PGM_RSRC2.TRAP_PRESENT,如果執行階段已安裝陷阱處理常式,則 CP 會設定此位元。

GFX12

保留,必須為 0。

7

1 位元

ENABLE_SGPR_WORKGROUP_ID_X

啟用 X 維度工作群組 ID 的系統 SGPR 暫存器的設定(請參閱初始核心執行狀態)。

CP 用於設定 COMPUTE_PGM_RSRC2.TGID_X_EN

8

1 位元

ENABLE_SGPR_WORKGROUP_ID_Y

啟用 Y 維度工作群組 ID 的系統 SGPR 暫存器的設定(請參閱初始核心執行狀態)。

CP 用於設定 COMPUTE_PGM_RSRC2.TGID_Y_EN

9

1 位元

ENABLE_SGPR_WORKGROUP_ID_Z

啟用 Z 維度工作群組 ID 的系統 SGPR 暫存器的設定(請參閱初始核心執行狀態)。

CP 用於設定 COMPUTE_PGM_RSRC2.TGID_Z_EN

10

1 位元

ENABLE_SGPR_WORKGROUP_INFO

啟用工作群組資訊的系統 SGPR 暫存器的設定(請參閱初始核心執行狀態)。

CP 用於設定 COMPUTE_PGM_RSRC2.TGID_SIZE_EN

12:11

2 位元

ENABLE_VGPR_WORKITEM_ID

啟用用於工作項目 ID 的 VGPR 系統暫存器的設定。系統 VGPR 工作項目 ID 列舉值定義了這些值。

CP 用於設定 COMPUTE_PGM_RSRC2.TIDIG_CMP_CNT

13

1 位元

ENABLE_EXCEPTION_ADDRESS_WATCH

必須為 0。

波前開始執行時,啟用位址監看例外,當 L1 偵測到執行緒存取感興趣的位址時,會產生這些例外。

CP 負責根據執行階段的要求,在 COMPUTE_PGM_RSRC2.EXCP_EN_MSB 中填寫位址監看位元。

14

1 位元

ENABLE_EXCEPTION_MEMORY

必須為 0。

波前開始執行時,啟用記憶體違規例外,當從 L1 或 LDS 發生此波前的記憶體違規時(寫入唯讀記憶體、未對齊的原子操作、LDS 位址超出範圍、非法位址等),會產生這些例外。

CP 根據執行階段的要求,在 COMPUTE_PGM_RSRC2.EXCP_EN_MSB 中設定記憶體違規位元。

23:15

9 位元

GRANULATED_LDS_SIZE

必須為 0。

CP 使用分派封包中的四捨五入值,而不是此值,因為分派可能包含動態配置的群組區段記憶體。CP 直接寫入 COMPUTE_PGM_RSRC2.LDS_SIZE

要為每個工作群組配置的群組區段 (LDS) 量。粒度是裝置特定的

GFX6

roundup(lds-size / (64 * 4))

GFX7-GFX11

roundup(lds-size / (128 * 4))

GFX950

roundup(lds-size / (320 * 4))

24

1 位元

ENABLE_EXCEPTION_IEEE_754_FP _INVALID_OPERATION

波前開始執行時,啟用指定的例外。

CP 用於設定 COMPUTE_PGM_RSRC2.EXCP_EN(從位元 0..6 設定)。

IEEE 754 FP 無效運算

25

1 位元

ENABLE_EXCEPTION_FP_DENORMAL _SOURCE

FP 反常,一個或多個輸入運算元是反常數

26

1 位元

ENABLE_EXCEPTION_IEEE_754_FP _DIVISION_BY_ZERO

IEEE 754 FP 除以零

27

1 位元

ENABLE_EXCEPTION_IEEE_754_FP _OVERFLOW

IEEE 754 FP FP 溢位

28

1 位元

ENABLE_EXCEPTION_IEEE_754_FP _UNDERFLOW

IEEE 754 FP 下溢

29

1 位元

ENABLE_EXCEPTION_IEEE_754_FP _INEXACT

IEEE 754 FP 不精確

30

1 位元

ENABLE_EXCEPTION_INT_DIVIDE_BY _ZERO

整數除以零(僅限 rcp_iflag_f32 指令)

31

1 位元

保留

保留,必須為 0。

32

總大小 4 位元組。

表 68 GFX90A、GFX942 的 compute_pgm_rsrc3

位元

大小

欄位名稱

描述

5:0

6 位元

ACCUM_OFFSET

統一暫存器檔案中第一個 AccVGPR 的偏移量。粒度為 4。值為 0-63。0 - accum-offset = 4、1 - accum-offset = 8、…、63 - accum-offset = 256。

15:6

10 位元

保留,必須為 0。

16

1 位元

TG_SPLIT

  • 如果為 0,則工作群組的波在同一個 CU 中啟動。

  • 如果為 1,則工作群組的波可以在不同的 CU 中啟動。這些波不能使用 S_BARRIER 或 LDS。

31:17

15 位元

保留,必須為 0。

32

總大小 4 位元組。

表 69 GFX10-GFX11 的 compute_pgm_rsrc3

位元

大小

欄位名稱

描述

3:0

4 位元

SHARED_VGPR_COUNT

在子向量模式下執行時,共用 VGPR 區塊的數量。對於波前大小 64,值為 0-15,表示 0-120 個 VGPR(粒度為 8),因此 (compute_pgm_rsrc1.vgprs +1)*4 + shared_vgpr_count*8 不超過 256。對於波前大小 32,shared_vgpr_count 必須為 0。

9:4

6 位元

INST_PREF_SIZE

GFX10

保留,必須為 0。

GFX11

要預先提取的指令位元組數,從核心的進入點指令開始,在波前開始執行之前。該值為 0..63,粒度為 128 位元組。

10

1 位元

TRAP_ON_START

GFX10

保留,必須為 0。

GFX11

必須為 0。

如果為 1,波前會透過陷入陷阱處理常式來開始執行。

CP 負責根據執行階段的要求,在 COMPUTE_PGM_RSRC3.TRAP_ON_START 中填寫啟動時陷入陷阱位元。

11

1 位元

TRAP_ON_END

GFX10

保留,必須為 0。

GFX11

必須為 0。

如果為 1,波前執行會透過陷入陷阱處理常式來終止。

CP 負責根據執行階段的要求,在 COMPUTE_PGM_RSRC3.TRAP_ON_END 中填寫結束時陷入陷阱位元。

30:12

19 位元

保留,必須為 0。

31

1 位元

IMAGE_OP

GFX10

保留,必須為 0。

GFX11

如果為 1,則核心執行包含影像指令。如果作為圖形管線的一部分執行,則影像讀取指令將停滯,等待執行任何必要的 WAIT_SYNC 柵欄,以指示較早的管線階段已完成寫入影像。

不適用於非圖形管線一部分的運算核心,且必須為 0。

32

總大小 4 位元組。

表 70 GFX12 的 compute_pgm_rsrc3

位元

大小

欄位名稱

描述

3:0

4 位元

保留

保留,必須為 0。

11:4

8 位元

INST_PREF_SIZE

要預先提取的指令位元組數,從核心的進入點指令開始,在波前開始執行之前。該值為 0..255,粒度為 128 位元組。

12

1 位元

保留

保留,必須為 0。

13

1 位元

GLG_EN

如果為 1,則將為此分派啟用群組啟動保證

30:14

17 位元

保留

保留,必須為 0。

31

1 位元

IMAGE_OP

如果為 1,則核心執行包含影像指令。如果作為圖形管線的一部分執行,則影像讀取指令將停滯,等待執行任何必要的 WAIT_SYNC 柵欄,以指示較早的管線階段已完成寫入影像。

不適用於非圖形管線一部分的運算核心,且必須為 0。

32

總大小 4 位元組。

表 71 浮點捨入模式列舉值

列舉名稱

描述

FLOAT_ROUND_MODE_NEAR_EVEN

0

捨入到最接近的偶數

FLOAT_ROUND_MODE_PLUS_INFINITY

1

朝 +無限大捨入

FLOAT_ROUND_MODE_MINUS_INFINITY

2

朝 -無限大捨入

FLOAT_ROUND_MODE_ZERO

3

朝 0 捨入

表 72 擴充 FLT_ROUNDS 列舉值

F32 NEAR_EVEN

F32 PLUS_INFINITY

F32 MINUS_INFINITY

F32 ZERO

F64/F16 NEAR_EVEN

1

11

14

17

F64/F16 PLUS_INFINITY

8

2

15

18

F64/F16 MINUS_INFINITY

9

12

3

19

F64/F16 ZERO

10

13

16

0

表 73 浮點反常模式列舉值

列舉名稱

描述

FLOAT_DENORM_MODE_FLUSH_SRC_DST

0

清除來源和目的地反常值

FLOAT_DENORM_MODE_FLUSH_DST

1

清除輸出反常值

FLOAT_DENORM_MODE_FLUSH_SRC

2

清除來源反常值

FLOAT_DENORM_MODE_FLUSH_NONE

3

不清除

反常值清除是尊重符號的。即 "denormal-fp-math"="preserve-sign" 預期的行為。使用 "denormal-fp-math"="positive-zero" 時,行為未定義

表 74 系統 VGPR 工作項目 ID 列舉值

列舉名稱

描述

SYSTEM_VGPR_WORKITEM_ID_X

0

設定工作項目 X 維度 ID。

SYSTEM_VGPR_WORKITEM_ID_X_Y

1

設定工作項目 X 和 Y 維度 ID。

SYSTEM_VGPR_WORKITEM_ID_X_Y_Z

2

設定工作項目 X、Y 和 Z 維度 ID。

SYSTEM_VGPR_WORKITEM_ID_UNDEFINED

3

未定義。

初始核心執行狀態

本節定義封包處理器在每個波前開始執行之前將設定的暫存器狀態。這受到 CP/ADC/SPI 硬體控制器的限制。

SGPR 暫存器的順序已定義,但編譯器可以使用核心描述符中的 enable_sgpr_* 位元欄位來指定實際設定哪些暫存器(請參閱核心描述符)。用於已啟用暫存器的暫存器編號從 SGPR0 開始密集排列:第一個已啟用暫存器是 SGPR0,下一個已啟用暫存器是 SGPR1,依此類推;已停用的暫存器沒有 SGPR 編號。

初始 SGPR 最多包含 16 個使用者 SGPR,這些 SGPR 由 CP 設定,並適用於網格的所有波前。可以使用 enable_sgpr_* 位元欄位指定超過 16 個使用者 SGPR,在這種情況下,僅實際初始化前 16 個。緊隨其後的是系統 SGPR,這些 SGPR 由 ADC/SPI 設定,並且網格分派的每個波前可以具有不同的值。

SGPR 暫存器初始狀態定義於SGPR 暫存器設定順序中。

表 75 SGPR 暫存器設定順序

SGPR 順序

名稱 (核心描述符啟用欄位)

SGPR 數量

描述

優先

私有區段緩衝區 (enable_sgpr_private _segment_buffer)

4

請參閱 私有區段緩衝區

接著

分派指標 (enable_sgpr_dispatch_ptr)

2

實際執行的核心分派之 AQL 分派封包的 64 位元位址。

接著

佇列指標 (enable_sgpr_queue_ptr)

2

分派封包排入佇列之 AQL 佇列的 amd_queue_t 物件的 64 位元位址。

接著

核心參數區段指標 (enable_sgpr_kernarg _segment_ptr)

2

核心參數區段的 64 位元位址。這直接從核心分派封包中的 kernarg_address 複製而來。

讓 CP 載入一次可避免在每個波前開始時都載入。

接著

分派 ID (enable_sgpr_dispatch_id)

2

正在執行的分派封包的 64 位元分派 ID。

接著

平面暫存初始化 (enable_sgpr_flat_scratch _init)

2

請參閱 平面暫存

接著

私有區段大小 (enable_sgpr_private _segment_size)

1

單一工作項目的記憶體配置的 32 位元組大小。這是核心分派封包「私有區段位元組大小」欄位中的值,由 CP 四捨五入為 DWORD 的倍數。

讓 CP 載入一次可避免在每個波前開始時都載入。

這不適用於 GFX7-GFX8,因為它與平面暫存初始化的第二個 SGPR 值相同。然而,GFX9-GFX11 可能需要它,因為它改變了平面暫存初始化值的意義。

接著

預先載入的核心參數 (kernarg_preload_spec _length)

不適用

請參閱 預先載入的核心參數

接著

工作群組 ID X (enable_sgpr_workgroup_id _X)

1

波前網格 X 維度的 32 位元工作群組 ID。

接著

工作群組 ID Y (enable_sgpr_workgroup_id _Y)

1

波前網格 Y 維度的 32 位元工作群組 ID。

接著

工作群組 ID Z (enable_sgpr_workgroup_id _Z)

1

波前網格 Z 維度的 32 位元工作群組 ID。

接著

工作群組資訊 (enable_sgpr_workgroup _info)

1

{first_wavefront, 14’b0000, ordered_append_term[10:0], threadgroup_size_in_wavefronts[5:0]}

接著

暫存波前偏移 (enable_sgpr_private _segment_wavefront_offset)

1

請參閱 平面暫存私有區段緩衝區

VGPR 暫存器的順序已定義,但編譯器可以使用 enable_vgpr* 位元欄位在核心描述符中指定實際設定的暫存器 (請參閱核心描述符)。用於啟用的暫存器的暫存器編號從 VGPR0 開始是密集的:第一個啟用的暫存器是 VGPR0,下一個啟用的暫存器是 VGPR1,依此類推;停用的暫存器沒有 VGPR 編號。

VGPR 初始狀態有不同的方法。

  • 除非 AMDGPU 處理器的「目標屬性」欄另有規定,否則每個工作項目 ID 使用一個單獨的 VGPR 暫存器。此方法的 VGPR 暫存器初始狀態在 適用於未封裝工作項目 ID 方法的 VGPR 暫存器設定順序中定義。

  • 如果 AMDGPU 處理器的「目標屬性」欄指定「封裝工作項目 ID」,則 VGPR0 暫存器的初始值用於所有工作項目 ID。此方法的暫存器佈局在 適用於封裝工作項目 ID 方法的暫存器佈局中定義。

    表 76 適用於未封裝工作項目 ID 方法的 VGPR 暫存器設定順序

    VGPR 順序

    名稱 (核心描述符啟用欄位)

    VGPR 數量

    描述

    優先

    工作項目 ID X (始終初始化)

    1

    波前通道工作群組 X 維度的 32 位元工作項目 ID。

    接著

    工作項目 ID Y (enable_vgpr_workitem_id > 0)

    1

    波前通道工作群組 Y 維度的 32 位元工作項目 ID。

    接著

    工作項目 ID Z (enable_vgpr_workitem_id > 1)

    1

    波前通道工作群組 Z 維度的 32 位元工作項目 ID。

表 77 適用於封裝工作項目 ID 方法的暫存器佈局

位元

大小

欄位名稱

描述

0:9

10 位元

工作項目 ID X

波前通道工作群組 X 維度的工作項目 ID。

始終初始化。

10:19

10 位元

工作項目 ID Y

波前通道工作群組 Y 維度的工作項目 ID。

如果 enable_vgpr_workitem_id > 0 則初始化,否則設定為 0。

20:29

10 位元

工作項目 ID Z

波前通道工作群組 Z 維度的工作項目 ID。

如果 enable_vgpr_workitem_id > 1 則初始化,否則設定為 0。

30:31

2 位元

保留,設定為 0。

暫存器的設定由 GPU CP/ADC/SPI 硬體完成,如下所示

  1. 工作群組 ID 之前的 SGPR 由 CP 使用 16 個使用者資料暫存器設定。

  2. 工作群組 ID 暫存器 X、Y、Z 由 ADC 設定,ADC 支援任何組合,包括無。

  3. 暫存波前偏移由 SPI 以每個波前為基礎設定,這就是為什麼它的值不能包含在每個佇列的平面暫存初始化值中的原因 (請參閱 平面暫存)。

  4. VGPR 由 SPI 設定,SPI 僅支援指定 (X)、(X, Y) 或 (X, Y, Z)。

  5. 平面暫存暫存器對初始化在 平面暫存中描述。

全域區段可以使用緩衝區指令 (GFX6,具有 V# 64 位元位址支援)、平面指令 (GFX7-GFX11) 或全域指令 (GFX9-GFX11) 存取。

如果使用緩衝區操作,則編譯器可以產生具有以下屬性的 V#

  • 基底位址為 0

  • 無混洗

  • ATC:如果存在 IOMMU 則為 1 (例如 APU)

  • ptr64:1

  • MTYPE 設定為支援與執行階段相符的記憶體一致性 (例如 APU 的 CC 和 dGPU 的 NC)。

預先載入的核心參數

在支援此功能的硬體上,核心參數可以預先載入到使用者 SGPR 中,最多可達到可用的使用者 SGPR 最大數量。預先載入 SGPR 的配置發生在最後一個啟用的非核心參數預先載入使用者 SGPR 之後。(請參閱 初始核心執行狀態)

預先載入的資料是從核心參數區段複製而來,資料量由核心描述符的 kernarg_preload_spec_length 欄位中指定的值決定。然後,此資料會載入到連續的使用者 SGPR 中。接收預先載入的核心參數資料的 SGPR 數量與 kernarg_preload_spec_length 給定的值相對應。預先載入從核心參數區段內的 dword 偏移開始,該偏移由 kernarg_preload_spec_offset 欄位指定。

如果 kernarg_preload_spec_length 為非零值,CP 韌體將在 kernel_code_entry_byte_offset 中附加額外的 256 個位元組。此附加功能有助於將序言納入核心入口點,以處理為核心參數預先載入設計的程式碼在配備不相容韌體的硬體上執行的情況。如果硬體具有相容的韌體,則將跳過核心入口點開始處的 256 個位元組。

使用程式碼物件 V5 及更高版本,通常透過隱含引數指標存取的隱藏核心引數可以預先載入到使用者 SGPR 中。這些引數會新增至核心函數簽章,並標記有屬性 "inreg" 和 "amdgpu-hidden-argument"。(請參閱 AMDGPU LLVM IR 屬性)。

核心序言

編譯器在核心序言中執行初始化,具體取決於目標以及核心中堆疊使用情況和呼叫函數等資訊。此初始化的某些部分需要編譯器請求某些使用者和系統 SGPR 透過 核心描述符 出現在 初始核心執行狀態 中。

CFI
  1. CFI 傳回位址未定義。

  2. CFI CFA 是使用一個表達式定義的,該表達式評估為位置描述,該位置描述包含 DW_ASPACE_AMDGPU_private_lane 位址空間位址 0 的一個記憶體位置描述。

M0
GFX6-GFX8

如果核心可能透過 DS 或平面操作存取 LDS,則 M0 暫存器必須初始化為至少是 LDS 總大小的值。分派封包中提供 LDS 總大小。對於 M0,也可以使用給定目標的 LDS 最大可能值 (GFX6 為 0x7FFF,GFX7-GFX8 為 0xFFFF)。

GFX9-GFX11

M0 暫存器不用於範圍檢查 LDS 存取,因此不需要在序言中初始化。

堆疊指標

如果核心有函數呼叫,則必須透過將 SGPR32 設定為最後一次本地配置之後的位址的未混洗暫存偏移,來設定 非核心函數 中描述的 ABI 堆疊指標。

幀指標

如果核心基於 SIFrameLowering 中定義的原因需要幀指標,則使用 SGPR33,並且始終在核心序言中設定為 0。如果不需要幀指標,則幀指標的所有使用都會替換為立即 0 偏移。

平面暫存

初始化平面暫存有不同的方法。

  • 如果 AMDGPU 處理器的「目標屬性」欄指定「不支援通用位址空間」

    不支援平面暫存,並且沒有平面暫存暫存器對。

  • 如果 AMDGPU 處理器的「目標屬性」欄指定「偏移平面暫存」

    如果核心或其呼叫的任何函數可能使用平面操作來存取暫存記憶體,則序言程式碼必須設定 FLAT_SCRATCH 暫存器對 (FLAT_SCRATCH_LO/FLAT_SCRATCH_HI)。初始化使用平面暫存初始化和暫存波前偏移 SGPR 暫存器 (請參閱 初始核心執行狀態)

    1. 平面暫存初始化的低字組是從 SH_HIDDEN_PRIVATE_BASE_VIMID 到 SPI 為執行核心分派的佇列管理的暫存後備記憶體基底的 32 位元組偏移。這與暫存區段緩衝區 V# 基底位址中使用的值相同。

      CP 從執行階段取得此值。(暫存區段緩衝區基底位址為 SH_HIDDEN_PRIVATE_BASE_VIMID 加上此偏移。)

      序言必須新增暫存波前偏移的值,以從 SH_HIDDEN_PRIVATE_BASE_VIMID 取得波前的位元組暫存後備記憶體偏移。

      使用暫存區段緩衝區時,暫存波前偏移也必須用作私有區段位址的偏移。

      由於 FLAT_SCRATCH_LO 的單位為 256 個位元組,因此偏移在移入 FLAT_SCRATCH_HI 之前必須右移 8 位。

      FLAT_SCRATCH_HI 對應於 GFX7 上的 SGPRn-4 和 GFX8 上的 SGPRn-6 (其中 SGPRn 是分配給波前的編號最高的 SGPR)。FLAT_SCRATCH_HI 乘以 256 (因為它的單位為 256 個位元組) 並新增至 SH_HIDDEN_PRIVATE_BASE_VIMID,以計算在存取暫存孔徑的平面記憶體指令中每個波前的平面暫存基底。

    2. 平面暫存初始化的第二個字組是單一工作項目暫存記憶體使用量的 32 位元組大小。

      CP 從執行階段取得此值,並且它始終是 DWORD 的倍數。CP 檢查核心分派封包「私有區段位元組大小」欄位中的值是否不大,並在必要時請求執行階段增加佇列的暫存大小。

      CP 直接從核心分派封包「私有區段位元組大小」欄位載入,並四捨五入為 DWORD 的倍數。讓 CP 載入一次可避免在每個波前開始時都載入。

      核心序言程式碼必須將其移至 FLAT_SCRATCH_LO,即 GFX7 上的 SGPRn-3 和 GFX8 上的 SGPRn-5。FLAT_SCRATCH_LO 用作平面記憶體指令中的平面暫存大小。

  • 如果 AMDGPU 處理器的「目標屬性」欄指定「絕對平面暫存」

    如果核心或其呼叫的任何函數可能使用平面操作來存取暫存記憶體,則序言程式碼必須設定 FLAT_SCRATCH 暫存器對 (FLAT_SCRATCH_LO/FLAT_SCRATCH_HI,它們在 SGPRn-4/SGPRn-3 中)。初始化使用平面暫存初始化和暫存波前偏移 SGPR 暫存器 (請參閱 初始核心執行狀態)

    平面暫存初始化是 SPI 為執行核心分派的佇列管理的暫存後備記憶體基底的 64 位元位址。

    CP 從執行階段取得此值。

    核心序言必須新增波的暫存波前偏移的值,並將結果作為 64 位元值移至 FLAT_SCRATCH SGPR 暫存器對,即 SGPRn-6 和 SGPRn-5。它用作平面記憶體指令中的平面暫存基底。

    使用暫存區段緩衝區時,暫存波前偏移也必須用作私有區段位址的偏移 (請參閱 私有區段緩衝區)。

  • 如果 AMDGPU 處理器的「目標屬性」欄指定「架構平面暫存」

    如果在 適用於 GFX6-GFX12 的 compute_pgm_rsrc2 中啟用了 ENABLE_PRIVATE_SEGMENT,則 FLAT_SCRATCH 暫存器對將初始化為 SPI 為執行核心分派的佇列管理的暫存後備記憶體基底的 64 位元位址,加上波的暫存波前偏移的值,以用作平面記憶體指令中的平面暫存基底。

私有區段緩衝區

如果 AMDGPU 處理器的「目標屬性」欄指定「架構平面暫存」,則不支援私有區段緩衝區。而是使用平面 SCRATCH 指令。

否則,私有區段緩衝區 SGPR 暫存器用於初始化 4 個 SGPR,這些 SGPR 用作 V# 以存取暫存。CP 使用執行階段提供的值。它與暫存波前偏移一起用作偏移,以使用區段位址存取私有記憶體空間。請參閱 初始核心執行狀態

暫存 V# 是一個四對齊的 SGPR,並且始終為核心選擇,如下所示

  • 如果在指令選擇期間已知存在堆疊使用情況,則保留 SGPR0-3 以用作暫存 V#。如果停用最佳化 (-O0)、堆疊物件已存在 (對於本機變數等),或存在任何函數呼叫,則假定存在堆疊使用情況。

  • 否則,將保留從四對齊 SGPR 索引開始的四個高編號 SGPR,用於暫定的暫存 V#。如果確定需要溢出,則將使用這些 SGPR。

    • 如果沒有使用暫定的暫存 V#,則會取消保留它,並且在忽略它的情況下確定暫存器計數。

    • 如果使用了暫定的暫存 V#,則其暫存器編號會移至暫存器分配器分配的最高編號之後的第一個四對齊 SGPR 索引,並且會更新所有使用。暫存器計數包括移位位置中的它們。

    • 在任何一種情況下,如果處理器有 SGPR 分配錯誤,則不會移位或取消保留暫定的分配,以確保暫存器計數更高以解決該錯誤。

    注意

    這種使用暫定的暫存 V# 並在使用時移位暫存器編號的方法避免了在消除暫定的 V# 時必須第二次執行暫存器分配。這樣更有效率,並且避免了第二次暫存器分配可能執行溢出的問題,這會因為不再有暫存 V# 而失敗。

當發出核心序言程式碼時,已知上述暫存 V# 是否實際使用。如果是,則序言程式碼必須透過將私有區段緩衝區複製到暫存 V# 暫存器,然後將私有區段波前偏移新增至 V# 中的佇列基底位址來設定它。結果是一個 V#,其基底位址指向波前暫存後備記憶體的開頭。

始終請求私有區段緩衝區,但僅在使用時才請求私有區段波前偏移 (請參閱 初始核心執行狀態)。

記憶體模型

本節描述 LLVM 記憶體模型到 AMDGPU 機器碼的對應 (請參閱 並行操作的記憶體模型)。

AMDGPU 後端支援 記憶體範圍 中指定的記憶體同步範圍。

用於實作記憶體模型的程式碼序列指定單一執行緒必須執行的指令順序。s_waitcnt 和快取管理指令 (例如 buffer_wbinvl1_vol) 是相對於同一執行緒執行的其他記憶體指令定義的。這允許它們更早或更晚移動,這允許它們與同一指令的其他實例組合,或提升/沉降出迴圈以提高效能。僅給出與記憶體模型相關的指令;需要額外的 s_waitcnt 指令以確保在暫存器使用之前已定義。這些指令可能能夠與如上所述的記憶體模型 s_waitcnt 指令組合。

AMDGPU 後端支援以下記憶體模型

HSA 記憶體模型 [HSA]

HSA 記憶體模型對所有位址空間使用單一先行發生關係 (請參閱 位址空間)。

OpenCL 記憶體模型 [OpenCL]

OpenCL 記憶體模型針對全域和本機位址空間具有單獨的先行發生關係。只有指定全域和本機位址空間的柵欄,以及 seq_cst 指令會加入關係。由於 LLVM memfence 指令不允許指定位址空間,因此 OpenCL 柵欄必須保守地假定已指定本機和全域位址空間。然而,當沒有存取相應位址空間的中間記憶體指令時,通常可以執行最佳化來消除額外的 s_waitcnt 指令。表中的程式碼序列指示 OpenCL 記憶體可以省略的內容。目標三元組環境用於確定來源語言是否為 OpenCL (請參閱 OpenCL)。

對本機記憶體的 ds/flat_load/store/atomic 指令稱為 LDS 操作。

對全域記憶體的 buffer/global/flat_load/store/atomic 指令稱為向量記憶體操作。

私有位址空間使用 buffer_load/store (使用暫存 V# (GFX6-GFX8)) 或 scratch_load/store (GFX9-GFX11)。由於只有單一執行緒存取記憶體,因此原子記憶體排序沒有意義,並且所有存取都被視為非原子。

常數位址空間使用 buffer/global_load 指令 (或等效的純量記憶體指令)。由於常數位址空間內容在核心分派執行期間不會變更,因此執行儲存是非法的,並且原子記憶體排序沒有意義,並且所有存取都被視為非原子。

寬於工作群組的記憶體同步範圍對於群組 (LDS) 位址空間沒有意義,並且被視為工作群組。

記憶體模型不支援區域位址空間,該空間被視為非原子。

取得記憶體排序對於儲存原子指令沒有意義,並且被視為非原子。

釋放記憶體排序對於載入原子指令沒有意義,並且被視為非原子。

取得-釋放記憶體排序對於載入或儲存原子指令沒有意義,並且分別被視為取得和釋放。

記憶體順序也新增了表 AMDHSA 記憶體模型單一執行緒最佳化限制 中定義的單一執行緒最佳化限制。

表 78 AMDHSA 記憶體模型單一執行緒最佳化限制

LLVM 記憶體

最佳化限制

排序

無序

none

單調

none

取得

  • 如果是載入原子/atomicrmw,則後續的載入/載入原子/儲存/儲存原子/atomicrmw/柵欄指令都不能在取得之前移動。

  • 如果是柵欄,則與載入原子相同,加上沒有在前的相關聯柵欄配對原子可以在柵欄之後移動。

釋放

  • 如果是儲存原子/atomicrmw,則在前的載入/載入原子/儲存/儲存原子/atomicrmw/柵欄指令都不能在釋放之後移動。

  • 如果是柵欄,則與儲存原子相同,加上沒有後續的相關聯柵欄配對原子可以在柵欄之前移動。

取得_釋放

與取得和釋放相同的限制。

seq_cst

  • 如果是載入原子,則與取得相同的限制,加上沒有在前的循序一致載入原子/儲存原子/atomicrmw/柵欄指令可以在 seq_cst 之後移動。

  • 如果是儲存原子,則與釋放相同的限制,加上沒有後續的循序一致載入原子/儲存原子/atomicrmw/柵欄指令可以在 seq_cst 之前移動。

  • 如果是 atomicrmw/柵欄,則與取得_釋放相同的限制。

用於實作記憶體模型的程式碼序列在以下章節中定義

柵欄和位址空間

LLVM 柵欄沒有位址空間資訊,因此,柵欄程式碼產生通常需要保守地同步所有位址空間。

在 OpenCL 的情況下,柵欄只需要同步使用者指定的位址空間,這可能會導致額外的不必要等待。例如,預期僅同步本機記憶體的柵欄也必須等待所有全域記憶體操作,這是沒有必要的。

記憶體模型放寬註解 可以用作柵欄的最佳化提示,以解決此問題。AMDGPU 後端識別柵欄上的以下標籤

  • amdgpu-as:local - 僅柵欄本機位址空間

  • amdgpu-as:global- 僅柵欄全域位址空間

注意

作為最佳化提示,這些標籤不能保證在程式碼產生之前存留。最佳化可以自由捨棄標籤,以允許更好的程式碼最佳化,但代價是同步額外的位址空間。

記憶體模型 GFX6-GFX9

針對 GFX6-GFX9

  • 每個代理程式有多個著色器陣列 (SA)。

  • 每個 SA 有多個運算單元 (CU)。

  • 每個 CU 有多個執行波前的 SIMD。

  • 單一工作群組的波前在同一個 CU 中執行,但可能由不同的 SIMD 執行。

  • 每個 CU 都有一個單一 LDS 記憶體,由在其上執行的工作群組的波前共用。

  • CU 的所有 LDS 操作都作為波前寬操作以全域順序執行,並且不涉及快取。完成情況以執行順序報告給波前。

  • LDS 記憶體有多個請求佇列,這些佇列由 CU 的 SIMD 共用。因此,工作群組的不同波前執行的 LDS 操作可以彼此重新排序,這可能會導致相對於同一工作群組中其他波前的 LDS 操作重新排序向量記憶體操作的可見性。需要 s_waitcnt lgkmcnt(0) 以確保工作群組的波前之間的 LDS 操作和向量記憶體操作之間同步,而不是同一波前執行的操作之間同步。

  • 向量記憶體操作作為波前寬操作執行,並且完成情況以執行順序報告給波前。例外情況是,對於 GFX7-GFX9,如果 flat_load/store/atomic 指令存取 LDS 記憶體,則它們可以報告向量記憶體順序外,如果它們存取全域記憶體,則可以報告 LDS 操作順序外。

  • 向量記憶體操作存取由 CU 的所有 SIMD 共用的單一向量 L1 快取。因此,單一波前的通道之間的一致性,或同一工作群組中波前之間的一致性不需要特殊操作。需要 buffer_wbinvl1_vol 以確保在不同工作群組中執行的波前之間的一致性,因為它們可能在不同的 CU 上執行。

  • 純量記憶體操作存取由一組 CU 上所有波前共用的純量 L1 快取。純量和向量 L1 快取不一致。但是,純量操作以受限的方式使用,因此不會影響記憶體模型。請參閱 記憶體空間

  • 向量和純量記憶體操作使用由同一代理程式上所有 CU 共用的 L2 快取。

  • L2 快取具有獨立通道,用於服務不相交的虛擬位址範圍。

  • 每個 CU 每個通道都有一個單獨的請求佇列。因此,代理程式的不同工作群組 (可能在不同的 CU 上執行) 中執行的波前執行的向量和純量記憶體操作可以彼此重新排序。需要 s_waitcnt vmcnt(0) 以確保不同 CU 的向量記憶體操作之間同步。它確保先前的向量記憶體操作已完成,然後再執行後續的向量記憶體或 LDS 操作,因此可用於滿足取得和釋放的要求。

  • L2 快取可以與某些目標上的其他代理程式保持一致性,或者可以設定虛擬位址範圍來繞過它,以確保系統一致性。

純量記憶體操作僅用於存取在核心調度執行期間證明不會變更的記憶體。 這包括常數位址空間和程式作用域 const 變數的全域位址空間。 因此,核心機器碼不必維護純量快取,以確保它與向量快取一致。 純量快取和向量快取在核心調度之間由 CP 使失效,因為常數位址空間資料可能在核心調度執行之間變更。 請參閱 記憶體空間

一個例外情況是,如果純量寫入用於溢出 SGPR 暫存器。 在這種情況下,AMDGPU 後端確保用於溢出的記憶體位置永遠不會同時被向量記憶體操作存取。 如果使用純量寫入,則在 s_endpgm 之前和函數返回之前插入 s_dcache_wb,因為這些位置可能被未來使用相同暫存區的波前或在相同位址建立框架的函數呼叫用於向量記憶體指令。 不需要 s_dcache_inv,因為所有純量寫入在同一個執行緒中都是先寫後讀。

對於核心參數後備記憶體

  • CP 在每次核心調度開始時使 L1 快取失效。

  • 在 dGPU 上,核心參數後備記憶體分配在主機記憶體中,以 MTYPE UC(非快取)存取,以避免需要使 L2 快取失效。 這也使其被視為非揮發性,因此不會被 *_vol 失效。

  • 在 APU 上,核心參數後備記憶體以 MTYPE CC(快取一致性)存取,因此 L2 快取將與 CPU 和其他代理程式保持一致性。

暫存後備記憶體(用於私有位址空間)以 MTYPE NC_NV(非一致性非揮發性)存取。 由於私有位址空間僅由單個執行緒存取,並且始終是先寫後讀,因此永遠不需要使 L1 快取中的這些條目失效。 因此,所有快取失效都以 *_vol 完成,僅使揮發性快取行失效。

用於實作 GFX6-GFX9 記憶體模型的程式碼序列在表 AMDHSA 記憶體模型程式碼序列 GFX6-GFX9 中定義。

表 79 AMDHSA 記憶體模型程式碼序列 GFX6-GFX9

LLVM 指令

LLVM 記憶體排序

LLVM 記憶體同步作用域

AMDGPU 位址空間

AMDGPU 機器碼 GFX6-GFX9

非原子

載入

none

none

  • global

  • 通用

  • private

  • constant

  • !volatile & !nontemporal

    1. buffer/global/flat_load

  • !volatile & nontemporal

    1. buffer/global/flat_load glc=1 slc=1

  • volatile

    1. buffer/global/flat_load glc=1

    2. s_waitcnt vmcnt(0)

    • 必須在任何後續的揮發性全域/通用載入/儲存之前發生。

    • 確保對不同位址的揮發性操作不會被硬體重新排序。

載入

none

none

  • 區域

  1. ds_load

儲存

none

none

  • global

  • 通用

  • private

  • constant

  • !volatile & !nontemporal

    1. buffer/global/flat_store

  • !volatile & nontemporal

    1. buffer/global/flat_store glc=1 slc=1

  • volatile

    1. buffer/global/flat_store

    2. s_waitcnt vmcnt(0)

    • 必須在任何後續的揮發性全域/通用載入/儲存之前發生。

    • 確保對不同位址的揮發性操作不會被硬體重新排序。

儲存

none

none

  • 區域

  1. ds_store

無序原子

載入原子

無序

任何

任何

與非原子相同.

儲存原子

無序

任何

任何

與非原子相同.

atomicrmw

無序

任何

任何

與單調原子相同.

單調原子

載入原子

單調

  • singlethread

  • wavefront

  • workgroup

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_load

載入原子

單調

  • agent

  • system

  • global

  • 通用

  1. buffer/global/flat_load glc=1

儲存原子

單調

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

  • global

  • 通用

  1. buffer/global/flat_store

儲存原子

單調

  • singlethread

  • wavefront

  • workgroup

  • 區域

  1. ds_store

atomicrmw

單調

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

  • global

  • 通用

  1. buffer/global/flat_atomic

atomicrmw

單調

  • singlethread

  • wavefront

  • workgroup

  • 區域

  1. ds_atomic

取得原子

載入原子

取得

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_load

載入原子

取得

  • workgroup

  • global

  1. buffer/global_load

載入原子

取得

  • workgroup

  • 區域

  • 通用

  1. ds/flat_load

  2. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL,則省略。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域載入原子值。

載入原子

取得

  • agent

  • system

  • global

  1. buffer/global_load glc=1

  2. s_waitcnt vmcnt(0)

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保載入在使快取失效之前已完成。

  1. buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

載入原子

取得

  • agent

  • system

  • 通用

  1. flat_load glc=1

  2. s_waitcnt vmcnt(0) & lgkmcnt(0)

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保 flat_load 在使快取失效之前已完成。

  1. buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

atomicrmw

取得

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_atomic

atomicrmw

取得

  • workgroup

  • global

  1. buffer/global_atomic

atomicrmw

取得

  • workgroup

  • 區域

  • 通用

  1. ds/flat_atomic

  2. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL,則省略。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域 atomicrmw 值。

atomicrmw

取得

  • agent

  • system

  • global

  1. buffer/global_atomic

  2. s_waitcnt vmcnt(0)

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

atomicrmw

取得

  • agent

  • system

  • 通用

  1. flat_atomic

  2. s_waitcnt vmcnt(0) & lgkmcnt(0)

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

柵欄

取得

  • singlethread

  • wavefront

none

none

柵欄

取得

  • workgroup

none

  1. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL 且位址空間不是通用的,則省略。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 必須在任何先前的區域/通用載入原子/atomicrmw 之後發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於柵欄配對原子讀取的值。

柵欄

取得

  • agent

  • system

none

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入原子/atomicrmw 之後發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入原子/atomicrmw 之後發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保柵欄配對原子在使快取失效之前已完成。 因此,任何後續讀取的位置都不得早於柵欄配對原子讀取的值。

  1. buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

釋放原子

儲存原子

釋放

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_store

儲存原子

釋放

  • workgroup

  • global

  • 通用

  1. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL,則省略。

  • 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的儲存之前發生。

  • 確保對區域的所有記憶體操作在執行正在釋放的儲存之前已完成。

  1. buffer/global/flat_store

儲存原子

釋放

  • workgroup

  • 區域

  1. ds_store

儲存原子

釋放

  • agent

  • system

  • global

  • 通用

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的儲存之前發生。

  • 確保對記憶體的所有記憶體操作在執行正在釋放的儲存之前已完成。

  1. buffer/global/flat_store

atomicrmw

釋放

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_atomic

atomicrmw

釋放

  • workgroup

  • global

  • 通用

  1. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL,則省略。

  • 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對區域的所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global/flat_atomic

atomicrmw

釋放

  • workgroup

  • 區域

  1. ds_atomic

atomicrmw

釋放

  • agent

  • system

  • global

  • 通用

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對全域和區域的所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global/flat_atomic

柵欄

釋放

  • singlethread

  • wavefront

none

none

柵欄

釋放

  • workgroup

none

  1. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL 且位址空間不是通用的,則省略。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 必須在任何先前的區域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之後發生。

  • 必須在任何後續的儲存原子/atomicrmw 之前發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 確保對區域的所有記憶體操作在執行後續的柵欄配對原子之前已完成。

柵欄

釋放

  • agent

  • system

none

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間是區域的,則省略 vmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在任何後續的儲存原子/atomicrmw 之前發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 確保所有記憶體操作在執行後續的柵欄配對原子之前已完成。

取得-釋放原子

atomicrmw

取得_釋放

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_atomic

atomicrmw

取得_釋放

  • workgroup

  • global

  1. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL,則省略。

  • 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對區域的所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global_atomic

atomicrmw

取得_釋放

  • workgroup

  • 區域

  1. ds_atomic

  2. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL,則省略。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域載入原子值。

atomicrmw

取得_釋放

  • workgroup

  • 通用

  1. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL,則省略。

  • 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對區域的所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. flat_atomic

  2. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL,則省略。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域載入原子值。

atomicrmw

取得_釋放

  • agent

  • system

  • global

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對全域的所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global_atomic

  2. s_waitcnt vmcnt(0)

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

atomicrmw

取得_釋放

  • agent

  • system

  • 通用

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對全域的所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. flat_atomic

  2. s_waitcnt vmcnt(0) & lgkmcnt(0)

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

柵欄

取得_釋放

  • singlethread

  • wavefront

none

none

柵欄

取得_釋放

  • workgroup

none

  1. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL 且位址空間不是通用的,則省略。

  • 但是,由於 LLVM 目前在柵欄上沒有位址空間,因此需要保守地始終產生(請參閱先前柵欄的註解)。

  • 必須在任何先前的區域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之後發生。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保對區域的所有記憶體操作在執行任何後續的全域記憶體操作之前已完成。

  • 確保先前的區域/通用載入原子/atomicrmw,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為取得柵欄配對原子),在後續的全域記憶體操作之前已完成。 這滿足取得的要求。

  • 確保所有先前的記憶體操作在後續的區域/通用儲存原子/atomicrmw 之前已完成,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為釋放柵欄配對原子)。 這滿足釋放的要求。

柵欄

取得_釋放

  • agent

  • system

none

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保先前的全域/區域/通用載入原子/atomicrmw,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為取得柵欄配對原子),在使快取失效之前已完成。 這滿足取得的要求。

  • 確保所有先前的記憶體操作在後續的全域/區域/通用儲存原子/atomicrmw 之前已完成,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為釋放柵欄配對原子)。 這滿足釋放的要求。

  1. buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。 這滿足取得的要求。

循序一致性原子

載入原子

seq_cst

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

載入原子

seq_cst

  • workgroup

  • global

  • 通用

  1. s_waitcnt lgkmcnt(0)

  • 必須在先前的區域/通用載入原子/儲存原子/atomicrmw 之後發生,其記憶體排序為 seq_cst,且同步作用域相等或更寬。(請注意,seq_cst 柵欄有自己的 s_waitcnt lgkmcnt(0),因此不需要考慮。)

  • 確保任何先前的循序一致性區域記憶體指令在執行此循序一致性指令之前已完成。 這可以防止重新排序 seq_cst 儲存,然後是 seq_cst 載入。(請注意,seq_cst 比取得/釋放更強,因為釋放的 s_waitcnt 會阻止重新排序載入取得,然後是儲存釋放,但是沒有任何東西阻止儲存釋放,然後是載入取得以無序完成。 s_waitcnt 可以放在 seq_store 之後或 seq_load 之前。 我們選擇載入以使 s_waitcnt 盡可能晚,以便儲存可能已經完成。)

  1. 後續指令與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

載入原子

seq_cst

  • workgroup

  • 區域

與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

載入原子

seq_cst

  • agent

  • system

  • global

  • 通用

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt lgkmcnt(0) 必須在先前的全域/通用載入原子/儲存原子/atomicrmw 之後發生,其記憶體排序為 seq_cst,且同步作用域相等或更寬。(請注意,seq_cst 柵欄有自己的 s_waitcnt lgkmcnt(0),因此不需要考慮。)

  • s_waitcnt vmcnt(0) 必須在先前的全域/通用載入原子/儲存原子/atomicrmw 之後發生,其記憶體排序為 seq_cst,且同步作用域相等或更寬。(請注意,seq_cst 柵欄有自己的 s_waitcnt vmcnt(0),因此不需要考慮。)

  • 確保任何先前的循序一致性全域記憶體指令在執行此循序一致性指令之前已完成。 這可以防止重新排序 seq_cst 儲存,然後是 seq_cst 載入。(請注意,seq_cst 比取得/釋放更強,因為釋放的 s_waitcnt 會阻止重新排序載入取得,然後是儲存釋放,但是沒有任何東西阻止儲存釋放,然後是載入取得以無序完成。 s_waitcnt 可以放在 seq_store 之後或 seq_load 之前。 我們選擇載入以使 s_waitcnt 盡可能晚,以便儲存可能已經完成。)

  1. 後續指令與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

儲存原子

seq_cst

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

  • global

  • 區域

  • 通用

與對應的儲存原子釋放相同,但即使對於 OpenCL 也必須產生所有指令。

atomicrmw

seq_cst

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

  • global

  • 區域

  • 通用

與對應的 atomicrmw acq_rel 相同,但即使對於 OpenCL 也必須產生所有指令。

柵欄

seq_cst

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

none

與對應的柵欄 acq_rel 相同,但即使對於 OpenCL 也必須產生所有指令。

記憶體模型 GFX90A

對於 GFX90A

  • 每個代理程式有多個著色器陣列 (SA)。

  • 每個 SA 有多個運算單元 (CU)。

  • 每個 CU 有多個執行波前的 SIMD。

  • 單個工作群組的波前在同一個 CU 中執行,但可能由不同的 SIMD 執行。 例外情況是當處於 tgsplit 執行模式時,波前可能由不同 CU 中的不同 SIMD 執行。

  • 每個 CU 都有一個單個 LDS 記憶體,由在其上執行的工作群組的波前共享。 例外情況是當處於 tgsplit 執行模式時,由於同一工作群組的波前可能位於不同的 CU 中,因此不分配 LDS。

  • CU 的所有 LDS 操作都作為波前寬操作以全域順序執行,並且不涉及快取。完成情況以執行順序報告給波前。

  • LDS 記憶體有多個請求佇列,這些佇列由 CU 的 SIMD 共用。因此,工作群組的不同波前執行的 LDS 操作可以彼此重新排序,這可能會導致相對於同一工作群組中其他波前的 LDS 操作重新排序向量記憶體操作的可見性。需要 s_waitcnt lgkmcnt(0) 以確保工作群組的波前之間的 LDS 操作和向量記憶體操作之間同步,而不是同一波前執行的操作之間同步。

  • 向量記憶體操作作為波前寬操作執行,完成情況以執行順序報告給波前。 例外情況是,如果 flat_load/store/atomic 指令存取 LDS 記憶體,則可以報告向量記憶體順序外,如果存取全域記憶體,則可以報告 LDS 操作順序外。

  • 向量記憶體操作存取由 CU 的所有 SIMD 共享的單個向量 L1 快取。 因此

    • 單個波前的通道之間的一致性不需要特殊操作。

    • 同一工作群組中波前之間的一致性不需要特殊操作,因為它們在同一個 CU 上執行。 例外情況是當處於 tgsplit 執行模式時,由於同一工作群組的波前可能位於不同的 CU 中,因此需要 buffer_wbinvl1_vol,如下一項所述。

    • 在不同工作群組中執行的波前之間的一致性需要 buffer_wbinvl1_vol,因為它們可能在不同的 CU 上執行。

  • 純量記憶體操作存取由一組 CU 上所有波前共用的純量 L1 快取。純量和向量 L1 快取不一致。但是,純量操作以受限的方式使用,因此不會影響記憶體模型。請參閱 記憶體空間

  • 向量和純量記憶體操作使用由同一代理程式上所有 CU 共用的 L2 快取。

    • L2 快取具有獨立通道,用於服務不相交的虛擬位址範圍。

    • 每個 CU 都有一個單獨的每個通道的請求佇列。 因此,由不同工作群組(可能在不同 CU 上執行)或同一工作群組(如果在 tgsplit 模式下執行)中的波前執行的向量和純量記憶體操作可以相對於彼此重新排序。 需要 s_waitcnt vmcnt(0) 以確保不同 CU 的向量記憶體操作之間的同步。 它確保先前的向量記憶體操作在執行後續的向量記憶體或 LDS 操作之前已完成,因此可以用於滿足取得和釋放的要求。

    • 一個代理程式的 L2 快取可以透過以下方式與其他代理程式保持一致性:對於 L2 本地的記憶體,使用 MTYPE RW(讀寫)或 MTYPE CC(快取一致性)與 PTE C 位元;對於非 L2 本地的記憶體,使用 MTYPE NC(非一致性)與設定 PTE C 位元或 MTYPE UC(非快取)。

      • 由於一致性請求引起的快取探測,任何本地記憶體快取行都將自動被來自與其他 L2 快取關聯的 CU 或來自 CPU 的寫入失效。 一致性請求是由 GPU 存取具有設定 PTE C 位元的頁面、CPU 透過 XGMI 存取以及配置為一致性請求的 PCIe 請求引起的。

      • 來自 CPU 的 XGMI 對本地記憶體的存取可能會在 CPU 上快取。 由於 L2 探測篩選器和設定的 PTE C 位元,來自 GPU 的後續存取將自動使 CPU 快取失效或寫回。

      • 由於同一代理程式上的所有工作群組共享同一個 L2,因此一致性不需要 L2 失效或寫回。

      • 為了確保不同代理程式中工作群組的本地和遠端記憶體寫入的一致性,需要 buffer_wbl2。 它將寫回 MTYPE RW(用於本地粗粒度記憶體)和 MTYPE NC(用於遠端粗粒度記憶體)的髒 L2 快取行。 請注意,MTYPE CC(用於本地細粒度記憶體)導致寫穿到 DRAM,而 MTYPE UC(用於遠端細粒度記憶體)繞過 L2,因此兩者都不會導致髒 L2 快取行。

      • 為了確保不同代理程式中工作群組的本地和遠端記憶體讀取的一致性,需要 buffer_invl2。 它將使 MTYPE NC(用於遠端粗粒度記憶體)的 L2 快取行失效。 請注意,MTYPE CC(用於本地細粒度記憶體)和 MTYPE RW(用於本地粗粒度記憶體)導致本地讀取被具有 PTE C 位元的遠端寫入失效,因此這些快取行不會失效。 請注意,MTYPE UC(用於遠端細粒度記憶體)繞過 L2,因此永遠不會導致需要失效的 L2 快取行。

    • 從 GPU 到 CPU 記憶體的 PCIe 存取透過使用 MTYPE UC(非快取)保持一致性,MTYPE UC(非快取)繞過 L2。

純量記憶體操作僅用於存取在核心調度執行期間證明不會變更的記憶體。 這包括常數位址空間和程式作用域 const 變數的全域位址空間。 因此,核心機器碼不必維護純量快取,以確保它與向量快取一致。 純量快取和向量快取在核心調度之間由 CP 使失效,因為常數位址空間資料可能在核心調度執行之間變更。 請參閱 記憶體空間

一個例外情況是,如果純量寫入用於溢出 SGPR 暫存器。 在這種情況下,AMDGPU 後端確保用於溢出的記憶體位置永遠不會同時被向量記憶體操作存取。 如果使用純量寫入,則在 s_endpgm 之前和函數返回之前插入 s_dcache_wb,因為這些位置可能被未來使用相同暫存區的波前或在相同位址建立框架的函數呼叫用於向量記憶體指令。 不需要 s_dcache_inv,因為所有純量寫入在同一個執行緒中都是先寫後讀。

對於核心參數後備記憶體

  • CP 在每次核心調度開始時使 L1 快取失效。

  • 在透過 XGMI 或 PCIe 的 dGPU 上,核心參數後備記憶體分配在主機記憶體中,以 MTYPE UC(非快取)存取,以避免需要使 L2 快取失效。 這也使其被視為非揮發性,因此不會被 *_vol 失效。

  • 在 APU 上,核心參數後備記憶體以 MTYPE CC(快取一致性)存取,因此 L2 快取將與 CPU 和其他代理程式保持一致性。

暫存後備記憶體(用於私有位址空間)以 MTYPE NC_NV(非一致性非揮發性)存取。 由於私有位址空間僅由單個執行緒存取,並且始終是先寫後讀,因此永遠不需要使 L1 快取中的這些條目失效。 因此,所有快取失效都以 *_vol 完成,僅使揮發性快取行失效。

用於實作 GFX90A 記憶體模型的程式碼序列在表 AMDHSA 記憶體模型程式碼序列 GFX90A 中定義。

表 80 AMDHSA 記憶體模型程式碼序列 GFX90A

LLVM 指令

LLVM 記憶體排序

LLVM 記憶體同步作用域

AMDGPU 位址空間

AMDGPU 機器碼 GFX90A

非原子

載入

none

none

  • global

  • 通用

  • private

  • constant

  • !volatile & !nontemporal

    1. buffer/global/flat_load

  • !volatile & nontemporal

    1. buffer/global/flat_load glc=1 slc=1

  • volatile

    1. buffer/global/flat_load glc=1

    2. s_waitcnt vmcnt(0)

    • 必須在任何後續的揮發性全域/通用載入/儲存之前發生。

    • 確保對不同位址的揮發性操作不會被硬體重新排序。

載入

none

none

  • 區域

  1. ds_load

儲存

none

none

  • global

  • 通用

  • private

  • constant

  • !volatile & !nontemporal

    1. buffer/global/flat_store

  • !volatile & nontemporal

    1. buffer/global/flat_store glc=1 slc=1

  • volatile

    1. buffer/global/flat_store

    2. s_waitcnt vmcnt(0)

    • 必須在任何後續的揮發性全域/通用載入/儲存之前發生。

    • 確保對不同位址的揮發性操作不會被硬體重新排序。

儲存

none

none

  • 區域

  1. ds_store

無序原子

載入原子

無序

任何

任何

與非原子相同.

儲存原子

無序

任何

任何

與非原子相同.

atomicrmw

無序

任何

任何

與單調原子相同.

單調原子

載入原子

單調

  • singlethread

  • wavefront

  • global

  • 通用

  1. buffer/global/flat_load

載入原子

單調

  • workgroup

  • global

  • 通用

  1. buffer/global/flat_load glc=1

  • 如果不是 TgSplit 執行模式,則省略 glc=1。

載入原子

單調

  • singlethread

  • wavefront

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_load

載入原子

單調

  • agent

  • global

  • 通用

  1. buffer/global/flat_load glc=1

載入原子

單調

  • system

  • global

  • 通用

  1. buffer/global/flat_load glc=1

儲存原子

單調

  • singlethread

  • wavefront

  • workgroup

  • agent

  • global

  • 通用

  1. buffer/global/flat_store

儲存原子

單調

  • system

  • global

  • 通用

  1. buffer/global/flat_store

儲存原子

單調

  • singlethread

  • wavefront

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_store

atomicrmw

單調

  • singlethread

  • wavefront

  • workgroup

  • agent

  • global

  • 通用

  1. buffer/global/flat_atomic

atomicrmw

單調

  • system

  • global

  • 通用

  1. buffer/global/flat_atomic

atomicrmw

單調

  • singlethread

  • wavefront

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_atomic

取得原子

載入原子

取得

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_load

載入原子

取得

  • workgroup

  • global

  1. buffer/global_load glc=1

  • 如果不是 TgSplit 執行模式,則省略 glc=1。

  1. s_waitcnt vmcnt(0)

  • 如果不是 TgSplit 執行模式,則省略。

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  1. buffer_wbinvl1_vol

  • 如果不是 TgSplit 執行模式,則省略。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的資料。

載入原子

取得

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_load

  2. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL,則省略。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域載入原子值。

載入原子

取得

  • workgroup

  • 通用

  1. flat_load glc=1

  • 如果不是 TgSplit 執行模式,則省略 glc=1。

  1. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_wbinvl1_vol 以及任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域載入原子值。

  1. buffer_wbinvl1_vol

  • 如果不是 TgSplit 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

載入原子

取得

  • agent

  • global

  1. buffer/global_load glc=1

  2. s_waitcnt vmcnt(0)

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保載入在使快取失效之前已完成。

  1. buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

載入原子

取得

  • system

  • global

  1. buffer/global/flat_load glc=1

  2. s_waitcnt vmcnt(0)

  • 必須在後續的 buffer_invl2 和 buffer_wbinvl1_vol 之前發生。

  • 確保載入在使快取失效之前已完成。

  1. buffer_invl2; buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的 L1 全域資料,也不會看到過時的 L2 MTYPE NC 全域資料。 由於記憶體探測,MTYPE RW 和 CC 記憶體在 L2 中永遠不會過時。

載入原子

取得

  • agent

  • 通用

  1. flat_load glc=1

  2. s_waitcnt vmcnt(0) & lgkmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保 flat_load 在使快取失效之前已完成。

  1. buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

載入原子

取得

  • system

  • 通用

  1. flat_load glc=1

  2. s_waitcnt vmcnt(0) & lgkmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_invl2 和 buffer_wbinvl1_vol 之前發生。

  • 確保 flat_load 在使快取失效之前已完成。

  1. buffer_invl2; buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的 L1 全域資料,也不會看到過時的 L2 MTYPE NC 全域資料。 由於記憶體探測,MTYPE RW 和 CC 記憶體在 L2 中永遠不會過時。

atomicrmw

取得

  • singlethread

  • wavefront

  • global

  • 通用

  1. buffer/global/flat_atomic

atomicrmw

取得

  • singlethread

  • wavefront

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_atomic

atomicrmw

取得

  • workgroup

  • global

  1. buffer/global_atomic

  2. s_waitcnt vmcnt(0)

  • 如果不是 TgSplit 執行模式,則省略。

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_wbinvl1_vol

  • 如果不是 TgSplit 執行模式,則省略。

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

atomicrmw

取得

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_atomic

  2. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL,則省略。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域 atomicrmw 值。

atomicrmw

取得

  • workgroup

  • 通用

  1. flat_atomic

  2. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_wbinvl1_vol 以及任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域 atomicrmw 值。

  1. buffer_wbinvl1_vol

  • 如果不是 TgSplit 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得

  • agent

  • global

  1. buffer/global_atomic

  2. s_waitcnt vmcnt(0)

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

atomicrmw

取得

  • system

  • global

  1. buffer/global_atomic

  2. s_waitcnt vmcnt(0)

  • 必須在後續的 buffer_invl2 和 buffer_wbinvl1_vol 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_invl2; buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的 L1 全域資料,也不會看到過時的 L2 MTYPE NC 全域資料。 由於記憶體探測,MTYPE RW 和 CC 記憶體在 L2 中永遠不會過時。

atomicrmw

取得

  • agent

  • 通用

  1. flat_atomic

  2. s_waitcnt vmcnt(0) & lgkmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

atomicrmw

取得

  • system

  • 通用

  1. flat_atomic

  2. s_waitcnt vmcnt(0) & lgkmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_invl2 和 buffer_wbinvl1_vol 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_invl2; buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的 L1 全域資料,也不會看到過時的 L2 MTYPE NC 全域資料。 由於記憶體探測,MTYPE RW 和 CC 記憶體在 L2 中永遠不會過時。

柵欄

取得

  • singlethread

  • wavefront

none

none

柵欄

取得

  • workgroup

none

  1. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間是區域的,則省略 vmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入原子/ atomicrmw 之後發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入原子/atomicrmw 之後發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 必須在後續的 buffer_wbinvl1_vol 以及任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於柵欄配對原子讀取的值。

  1. buffer_wbinvl1_vol

  • 如果不是 TgSplit 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

柵欄

取得

  • agent

none

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入原子/atomicrmw 之後發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入原子/atomicrmw 之後發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保柵欄配對原子在使快取失效之前已完成。 因此,任何後續讀取的位置都不得早於柵欄配對原子讀取的值。

  1. buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

柵欄

取得

  • system

none

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入原子/atomicrmw 之後發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入原子/atomicrmw 之後發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 必須在後續的 buffer_invl2 和 buffer_wbinvl1_vol 之前發生。

  • 確保柵欄配對原子在使快取失效之前已完成。 因此,任何後續讀取的位置都不得早於柵欄配對原子讀取的值。

  1. buffer_invl2; buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的 L1 全域資料,也不會看到過時的 L2 MTYPE NC 全域資料。 由於記憶體探測,MTYPE RW 和 CC 記憶體在 L2 中永遠不會過時。

釋放原子

儲存原子

釋放

  • singlethread

  • wavefront

  • global

  • 通用

  1. buffer/global/flat_store

儲存原子

釋放

  • singlethread

  • wavefront

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_store

儲存原子

釋放

  • workgroup

  • global

  • 通用

  1. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/ 載入原子/儲存原子/ atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的儲存之前發生。

  • 確保所有記憶體操作在執行正在釋放的儲存之前已完成。

  1. buffer/global/flat_store

儲存原子

釋放

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_store

儲存原子

釋放

  • agent

  • global

  • 通用

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的儲存之前發生。

  • 確保對記憶體的所有記憶體操作在執行正在釋放的儲存之前已完成。

  1. buffer/global/flat_store

儲存原子

釋放

  • system

  • global

  • 通用

  1. buffer_wbl2

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在系統作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的儲存之前發生。

  • 確保對記憶體的所有記憶體操作和 L2 寫回在執行正在釋放的儲存之前已完成。

  1. buffer/global/flat_store

atomicrmw

釋放

  • singlethread

  • wavefront

  • global

  • 通用

  1. buffer/global/flat_atomic

atomicrmw

釋放

  • singlethread

  • wavefront

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_atomic

atomicrmw

釋放

  • workgroup

  • global

  • 通用

  1. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/ 載入原子/儲存原子/ atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global/flat_atomic

atomicrmw

釋放

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_atomic

atomicrmw

釋放

  • agent

  • global

  • 通用

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對全域和區域的所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global/flat_atomic

atomicrmw

釋放

  • system

  • global

  • 通用

  1. buffer_wbl2

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在系統作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對記憶體的所有記憶體操作和 L2 寫回在執行正在釋放的儲存之前已完成。

  1. buffer/global/flat_atomic

柵欄

釋放

  • singlethread

  • wavefront

none

none

柵欄

釋放

  • workgroup

none

  1. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間是區域的,則省略 vmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/ 載入原子/儲存原子/ atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之後發生。

  • 必須在任何後續的儲存原子/atomicrmw 之前發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 確保所有記憶體操作在執行後續的柵欄配對原子之前已完成。

柵欄

釋放

  • agent

none

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間是區域的,則省略 vmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在任何後續的儲存原子/atomicrmw 之前發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 確保所有記憶體操作在執行後續的柵欄配對原子之前已完成。

柵欄

釋放

  • system

none

  1. buffer_wbl2

  • 如果是 OpenCL 且位址空間是區域的,則省略。

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在系統作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間是區域的,則省略 vmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在任何後續的儲存原子/atomicrmw 之前發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 確保所有記憶體操作在執行後續的柵欄配對原子之前已完成。

取得-釋放原子

atomicrmw

取得_釋放

  • singlethread

  • wavefront

  • global

  • 通用

  1. buffer/global/flat_atomic

atomicrmw

取得_釋放

  • singlethread

  • wavefront

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_atomic

atomicrmw

取得_釋放

  • workgroup

  • global

  1. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/ 載入原子/儲存原子/ atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global_atomic

  2. s_waitcnt vmcnt(0)

  • 如果不是 TgSplit 執行模式,則省略。

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的 atomicrmw 值。

  1. buffer_wbinvl1_vol

  • 如果不是 TgSplit 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得_釋放

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_atomic

  2. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL,則省略。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域載入原子值。

atomicrmw

取得_釋放

  • workgroup

  • 通用

  1. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/ 載入原子/儲存原子/ atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. flat_atomic

  2. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果不是 TgSplit 執行模式,則省略 vmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_wbinvl1_vol 以及任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域載入原子值。

  1. buffer_wbinvl1_vol

  • 如果不是 TgSplit 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得_釋放

  • agent

  • global

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對全域的所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global_atomic

  2. s_waitcnt vmcnt(0)

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

atomicrmw

取得_釋放

  • system

  • global

  1. buffer_wbl2

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在系統作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對全域的所有記憶體操作和 L2 寫回在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global_atomic

  2. s_waitcnt vmcnt(0)

  • 必須在後續的 buffer_invl2 和 buffer_wbinvl1_vol 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_invl2; buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的 L1 全域資料,也不會看到過時的 L2 MTYPE NC 全域資料。 由於記憶體探測,MTYPE RW 和 CC 記憶體在 L2 中永遠不會過時。

atomicrmw

取得_釋放

  • agent

  • 通用

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對全域的所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. flat_atomic

  2. s_waitcnt vmcnt(0) & lgkmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

atomicrmw

取得_釋放

  • system

  • 通用

  1. buffer_wbl2

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在系統作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對全域的所有記憶體操作和 L2 寫回在執行正在釋放的 atomicrmw 之前已完成。

  1. flat_atomic

  2. s_waitcnt vmcnt(0) & lgkmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_invl2 和 buffer_wbinvl1_vol 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_invl2; buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的 L1 全域資料,也不會看到過時的 L2 MTYPE NC 全域資料。 由於記憶體探測,MTYPE RW 和 CC 記憶體在 L2 中永遠不會過時。

柵欄

取得_釋放

  • singlethread

  • wavefront

none

none

柵欄

取得_釋放

  • workgroup

none

  1. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間是區域的,則省略 vmcnt(0)。

  • 但是,由於 LLVM 目前在柵欄上沒有位址空間,因此需要保守地始終產生(請參閱先前柵欄的註解)。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/ 載入原子/儲存原子/ atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之後發生。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保所有記憶體操作在執行任何後續的全域記憶體操作之前已完成。

  • 確保先前的區域/通用載入原子/atomicrmw,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為取得柵欄配對原子),在後續的全域記憶體操作之前已完成。 這滿足取得的要求。

  • 確保所有先前的記憶體操作在後續的區域/通用儲存原子/atomicrmw 之前已完成,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為釋放柵欄配對原子)。 這滿足釋放的要求。

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保取得柵欄配對原子在使快取失效之前已完成。 因此,任何後續讀取的位置都不得早於取得柵欄配對原子讀取的值。

  1. buffer_wbinvl1_vol

  • 如果不是 TgSplit 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

柵欄

取得_釋放

  • agent

none

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 buffer_wbinvl1_vol 之前發生。

  • 確保先前的全域/區域/通用載入原子/atomicrmw,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為取得柵欄配對原子),在使快取失效之前已完成。 這滿足取得的要求。

  • 確保所有先前的記憶體操作在後續的全域/區域/通用儲存原子/atomicrmw 之前已完成,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為釋放柵欄配對原子)。 這滿足釋放的要求。

  1. buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。 這滿足取得的要求。

柵欄

取得_釋放

  • system

none

  1. buffer_wbl2

  • 如果是 OpenCL 且位址空間是區域的,則省略。

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在系統作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 buffer_invl2 和 buffer_wbinvl1_vol 之前發生。

  • 確保先前的全域/區域/通用載入原子/atomicrmw,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為取得柵欄配對原子),在使快取失效之前已完成。 這滿足取得的要求。

  • 確保所有先前的記憶體操作在後續的全域/區域/通用儲存原子/atomicrmw 之前已完成,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為釋放柵欄配對原子)。 這滿足釋放的要求。

  1. buffer_invl2; buffer_wbinvl1_vol

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的 L1 全域資料,也不會看到過時的 L2 MTYPE NC 全域資料。 由於記憶體探測,MTYPE RW 和 CC 記憶體在 L2 中永遠不會過時。

循序一致性原子

載入原子

seq_cst

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

載入原子

seq_cst

  • workgroup

  • global

  • 通用

  1. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • s_waitcnt lgkmcnt(0) 必須在先前的區域/通用載入原子/儲存原子/atomicrmw 之後發生,其記憶體排序為 seq_cst,且同步作用域相等或更寬。(請注意,seq_cst 柵欄有自己的 s_waitcnt lgkmcnt(0),因此不需要考慮。)

  • s_waitcnt vmcnt(0) 必須在先前的全域/通用載入原子/儲存原子/atomicrmw 之後發生,其記憶體排序為 seq_cst,且同步作用域相等或更寬。(請注意,seq_cst 柵欄有自己的 s_waitcnt vmcnt(0),因此不需要考慮。)

  • 確保任何先前的循序一致性全域/區域記憶體指令在執行此循序一致性指令之前已完成。 這可以防止重新排序 seq_cst 儲存,然後是 seq_cst 載入。(請注意,seq_cst 比取得/釋放更強,因為釋放的 s_waitcnt 會阻止重新排序載入取得,然後是儲存釋放,但是沒有任何東西阻止儲存釋放,然後是載入取得以無序完成。 s_waitcnt 可以放在 seq_store 之後或 seq_load 之前。 我們選擇載入以使 s_waitcnt 盡可能晚,以便儲存可能已經完成。)

  1. 後續指令與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

載入原子

seq_cst

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

載入原子

seq_cst

  • agent

  • system

  • global

  • 通用

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt lgkmcnt(0) 必須在先前的全域/通用載入原子/儲存原子/atomicrmw 之後發生,其記憶體排序為 seq_cst,且同步作用域相等或更寬。(請注意,seq_cst 柵欄有自己的 s_waitcnt lgkmcnt(0),因此不需要考慮。)

  • s_waitcnt vmcnt(0) 必須在先前的全域/通用載入原子/儲存原子/atomicrmw 之後發生,其記憶體排序為 seq_cst,且同步作用域相等或更寬。(請注意,seq_cst 柵欄有自己的 s_waitcnt vmcnt(0),因此不需要考慮。)

  • 確保任何先前的循序一致性全域記憶體指令在執行此循序一致性指令之前已完成。 這可以防止重新排序 seq_cst 儲存,然後是 seq_cst 載入。(請注意,seq_cst 比取得/釋放更強,因為釋放的 s_waitcnt 會阻止重新排序載入取得,然後是儲存釋放,但是沒有任何東西阻止儲存釋放,然後是載入取得以無序完成。 s_waitcnt 可以放在 seq_store 之後或 seq_load 之前。 我們選擇載入以使 s_waitcnt 盡可能晚,以便儲存可能已經完成。)

  1. 後續指令與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

儲存原子

seq_cst

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

  • global

  • 區域

  • 通用

與對應的儲存原子釋放相同,但即使對於 OpenCL 也必須產生所有指令。

atomicrmw

seq_cst

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

  • global

  • 區域

  • 通用

與對應的 atomicrmw acq_rel 相同,但即使對於 OpenCL 也必須產生所有指令。

柵欄

seq_cst

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

none

與對應的柵欄 acq_rel 相同,但即使對於 OpenCL 也必須產生所有指令。

記憶體模型 GFX942

對於 GFX942

  • 每個代理程式有多個著色器陣列 (SA)。

  • 每個 SA 有多個運算單元 (CU)。

  • 每個 CU 有多個執行波前的 SIMD。

  • 單個工作群組的波前在同一個 CU 中執行,但可能由不同的 SIMD 執行。 例外情況是當處於 tgsplit 執行模式時,波前可能由不同 CU 中的不同 SIMD 執行。

  • 每個 CU 都有一個單個 LDS 記憶體,由在其上執行的工作群組的波前共享。 例外情況是當處於 tgsplit 執行模式時,由於同一工作群組的波前可能位於不同的 CU 中,因此不分配 LDS。

  • CU 的所有 LDS 操作都作為波前寬操作以全域順序執行,並且不涉及快取。完成情況以執行順序報告給波前。

  • LDS 記憶體有多個請求佇列,這些佇列由 CU 的 SIMD 共用。因此,工作群組的不同波前執行的 LDS 操作可以彼此重新排序,這可能會導致相對於同一工作群組中其他波前的 LDS 操作重新排序向量記憶體操作的可見性。需要 s_waitcnt lgkmcnt(0) 以確保工作群組的波前之間的 LDS 操作和向量記憶體操作之間同步,而不是同一波前執行的操作之間同步。

  • 向量記憶體操作作為波前寬操作執行,完成情況以執行順序報告給波前。 例外情況是,如果 flat_load/store/atomic 指令存取 LDS 記憶體,則可以報告向量記憶體順序外,如果存取全域記憶體,則可以報告 LDS 操作順序外。

  • 向量記憶體操作存取由 CU 的所有 SIMD 共享的單個向量 L1 快取。 因此

    • 單個波前的通道之間的一致性不需要特殊操作。

    • 同一工作群組中波前之間的一致性不需要特殊操作,因為它們在同一個 CU 上執行。 例外情況是當處於 tgsplit 執行模式時,由於同一工作群組的波前可能位於不同的 CU 中,因此需要 buffer_inv sc0,它將使 L1 快取失效。

    • 在不同工作群組中執行的波前之間的一致性需要 buffer_inv sc0 以使 L1 快取失效,因為它們可能在不同的 CU 上執行。

    • 原子讀取-修改-寫入指令隱式繞過 L1 快取。 因此,它們不使用 sc0 位元進行一致性,而是使用它來指示指令是否傳回正在更新的原始值。 它們確實使用 sc1 來指示系統或代理程式作用域一致性。

  • 純量記憶體操作存取由一組 CU 上所有波前共用的純量 L1 快取。純量和向量 L1 快取不一致。但是,純量操作以受限的方式使用,因此不會影響記憶體模型。請參閱 記憶體空間

  • 向量和純量記憶體操作使用 L2 快取。

    • gfx942 可以配置為多個較小的代理程式,每個代理程式都有一個 L2,由同一代理程式上的所有 CU 共享,或者配置為較少(可能是一個)較大的代理程式,每個代理程式上的 CU 群組各自共享單獨的 L2 快取。

    • L2 快取具有獨立通道,用於服務不相交的虛擬位址範圍。

    • 每個 CU 都有一個單獨的每個通道的請求佇列,用於其關聯的 L2。 因此,由具有不同 L1 快取和相同 L2 快取的波前執行的向量和純量記憶體操作可以相對於彼此重新排序。

    • 需要 s_waitcnt vmcnt(0) 以確保不同 CU 的向量記憶體操作之間的同步。 它確保先前的向量記憶體操作在執行後續的向量記憶體或 LDS 操作之前已完成,因此可以用於滿足取得和釋放的要求。

    • L2 快取可以透過對 L2 本地的記憶體使用 MTYPE RW(讀寫),以及對非 L2 本地的記憶體使用設定 PTE C 位元的 MTYPE NC(非一致性),與其他 L2 快取保持一致性。

      • 由於 PTE C 位元引起的快取探測,任何本地記憶體快取行都將自動被來自與其他 L2 快取關聯的 CU 或來自 CPU 的寫入失效。

      • 來自 CPU 的 XGMI 對本地記憶體的存取可能會在 CPU 上快取。 由於 L2 探測篩選器,來自 GPU 的後續存取將自動使 CPU 快取失效或寫回。

      • 為了確保同一代理程式中具有不同 L1 快取的 CU 的本地記憶體寫入的一致性,需要 buffer_wbl2。 如果代理程式配置為具有單個 L2,它將不執行任何操作,如果配置為具有多個 L2 快取,則將寫回髒 L2 快取行。

      • 為了確保不同代理程式中 CU 的本地記憶體寫入的一致性,需要 buffer_wbl2 sc1。 它將寫回髒 L2 快取行。

      • 為了確保同一代理程式中具有不同 L1 快取的 CU 的本地記憶體讀取的一致性,需要 buffer_inv sc1。 如果代理程式配置為具有單個 L2,它將不執行任何操作,如果配置為具有多個 L2 快取,則將使非本地 L2 快取行失效。

      • 為了確保不同代理程式中 CU 的本地記憶體讀取的一致性,需要 buffer_inv sc0 sc1。 如果配置為具有多個 L2 快取,它將使非本地 L2 快取行失效。

    • 從 GPU 到 CPU 的 PCIe 存取可以透過使用 MTYPE UC(非快取)保持一致性,MTYPE UC(非快取)繞過 L2。

純量記憶體操作僅用於存取在核心調度執行期間證明不會變更的記憶體。 這包括常數位址空間和程式作用域 const 變數的全域位址空間。 因此,核心機器碼不必維護純量快取,以確保它與向量快取一致。 純量快取和向量快取在核心調度之間由 CP 使失效,因為常數位址空間資料可能在核心調度執行之間變更。 請參閱 記憶體空間

一個例外情況是,如果純量寫入用於溢出 SGPR 暫存器。 在這種情況下,AMDGPU 後端確保用於溢出的記憶體位置永遠不會同時被向量記憶體操作存取。 如果使用純量寫入,則在 s_endpgm 之前和函數返回之前插入 s_dcache_wb,因為這些位置可能被未來使用相同暫存區的波前或在相同位址建立框架的函數呼叫用於向量記憶體指令。 不需要 s_dcache_inv,因為所有純量寫入在同一個執行緒中都是先寫後讀。

對於核心參數後備記憶體

  • CP 在每次核心調度開始時使 L1 快取失效。

  • 在透過 XGMI 或 PCIe 的 dGPU 上,核心參數後備記憶體分配在主機記憶體中,以 MTYPE UC(非快取)存取,以避免需要使 L2 快取失效。 這也使其被視為非揮發性,因此不會被 *_vol 失效。

  • 在 APU 上,核心參數後備記憶體以 MTYPE CC(快取一致性)存取,因此 L2 快取將與 CPU 和其他代理程式保持一致性。

暫存後備記憶體(用於私有位址空間)以 MTYPE NC_NV(非一致性非揮發性)存取。 由於私有位址空間僅由單個執行緒存取,並且始終是先寫後讀,因此永遠不需要使 L1 快取中的這些條目失效。 因此,所有快取失效都以 *_vol 完成,僅使揮發性快取行失效。

用於實作 GFX942 記憶體模型的程式碼序列在表 AMDHSA 記憶體模型程式碼序列 GFX942 中定義。

表 81 AMDHSA 記憶體模型程式碼序列 GFX942

LLVM 指令

LLVM 記憶體排序

LLVM 記憶體同步作用域

AMDGPU 位址空間

AMDGPU 機器碼 GFX942

非原子

載入

none

none

  • global

  • 通用

  • private

  • constant

  • !volatile & !nontemporal

    1. buffer/global/flat_load

  • !volatile & nontemporal

    1. buffer/global/flat_load nt=1

  • volatile

    1. buffer/global/flat_load sc0=1 sc1=1

    2. s_waitcnt vmcnt(0)

    • 必須在任何後續的揮發性全域/通用載入/儲存之前發生。

    • 確保對不同位址的揮發性操作不會被硬體重新排序。

載入

none

none

  • 區域

  1. ds_load

儲存

none

none

  • global

  • 通用

  • private

  • constant

  • !volatile & !nontemporal

    1. GFX942

      buffer/global/flat_store

  • !volatile & nontemporal

    1. GFX942

      buffer/global/flat_store nt=1

  • volatile

    1. buffer/global/flat_store sc0=1 sc1=1

    2. s_waitcnt vmcnt(0)

    • 必須在任何後續的揮發性全域/通用載入/儲存之前發生。

    • 確保對不同位址的揮發性操作不會被硬體重新排序。

儲存

none

none

  • 區域

  1. ds_store

無序原子

載入原子

無序

任何

任何

與非原子相同.

儲存原子

無序

任何

任何

與非原子相同.

atomicrmw

無序

任何

任何

與單調原子相同.

單調原子

載入原子

單調

  • singlethread

  • wavefront

  • global

  • 通用

  1. buffer/global/flat_load

載入原子

單調

  • workgroup

  • global

  • 通用

  1. buffer/global/flat_load sc0=1

載入原子

單調

  • singlethread

  • wavefront

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_load

載入原子

單調

  • agent

  • global

  • 通用

  1. buffer/global/flat_load sc1=1

載入原子

單調

  • system

  • global

  • 通用

  1. buffer/global/flat_load sc0=1 sc1=1

儲存原子

單調

  • singlethread

  • wavefront

  • global

  • 通用

  1. buffer/global/flat_store

儲存原子

單調

  • workgroup

  • global

  • 通用

  1. buffer/global/flat_store sc0=1

儲存原子

單調

  • agent

  • global

  • 通用

  1. buffer/global/flat_store sc1=1

儲存原子

單調

  • system

  • global

  • 通用

  1. buffer/global/flat_store sc0=1 sc1=1

儲存原子

單調

  • singlethread

  • wavefront

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_store

atomicrmw

單調

  • singlethread

  • wavefront

  • workgroup

  • agent

  • global

  • 通用

  1. buffer/global/flat_atomic

atomicrmw

單調

  • system

  • global

  • 通用

  1. buffer/global/flat_atomic sc1=1

atomicrmw

單調

  • singlethread

  • wavefront

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_atomic

取得原子

載入原子

取得

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_load

載入原子

取得

  • workgroup

  • global

  1. buffer/global_load sc0=1

  2. s_waitcnt vmcnt(0)

  • 如果不是 TgSplit 執行模式,則省略。

  • 必須在後續的 buffer_inv 之前發生。

  1. buffer_inv sc0=1

  • 如果不是 TgSplit 執行模式,則省略。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的資料。

載入原子

取得

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_load

  2. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL,則省略。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域載入原子值。

載入原子

取得

  • workgroup

  • 通用

  1. flat_load sc0=1

  2. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_inv 以及任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域載入原子值。

  1. buffer_inv sc0=1

  • 如果不是 TgSplit 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

載入原子

取得

  • agent

  • global

  1. buffer/global_load sc1=1

  2. s_waitcnt vmcnt(0)

  • 必須在後續的 buffer_inv 之前發生。

  • 確保載入在使快取失效之前已完成。

  1. buffer_inv sc1=1

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

載入原子

取得

  • system

  • global

  1. buffer/global/flat_load sc0=1 sc1=1

  2. s_waitcnt vmcnt(0)

  • 必須在後續的 buffer_inv 之前發生。

  • 確保載入在使快取失效之前已完成。

  1. buffer_inv sc0=1 sc1=1

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的 MTYPE NC 全域資料。 由於記憶體探測,MTYPE RW 和 CC 記憶體永遠不會過時。

載入原子

取得

  • agent

  • 通用

  1. flat_load sc1=1

  2. s_waitcnt vmcnt(0) & lgkmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_inv 之前發生。

  • 確保 flat_load 在使快取失效之前已完成。

  1. buffer_inv sc1=1

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

載入原子

取得

  • system

  • 通用

  1. flat_load sc0=1 sc1=1

  2. s_waitcnt vmcnt(0) & lgkmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_inv 之前發生。

  • 確保 flat_load 在使快取失效之前已完成。

  1. buffer_inv sc0=1 sc1=1

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的 MTYPE NC 全域資料。 由於記憶體探測,MTYPE RW 和 CC 記憶體永遠不會過時。

atomicrmw

取得

  • singlethread

  • wavefront

  • global

  • 通用

  1. buffer/global/flat_atomic

atomicrmw

取得

  • singlethread

  • wavefront

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_atomic

atomicrmw

取得

  • workgroup

  • global

  1. buffer/global_atomic

  2. s_waitcnt vmcnt(0)

  • 如果不是 TgSplit 執行模式,則省略。

  • 必須在後續的 buffer_inv 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_inv sc0=1

  • 如果不是 TgSplit 執行模式,則省略。

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

atomicrmw

取得

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_atomic

  2. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL,則省略。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域 atomicrmw 值。

atomicrmw

取得

  • workgroup

  • 通用

  1. flat_atomic

  2. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_inv 以及任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域 atomicrmw 值。

  1. buffer_inv sc0=1

  • 如果不是 TgSplit 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得

  • agent

  • global

  1. buffer/global_atomic

  2. s_waitcnt vmcnt(0)

  • 必須在後續的 buffer_inv 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_inv sc1=1

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

atomicrmw

取得

  • system

  • global

  1. buffer/global_atomic sc1=1

  2. s_waitcnt vmcnt(0)

  • 必須在後續的 buffer_inv 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_inv sc0=1 sc1=1

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的 MTYPE NC 全域資料。 由於記憶體探測,MTYPE RW 和 CC 記憶體永遠不會過時。

atomicrmw

取得

  • agent

  • 通用

  1. flat_atomic

  2. s_waitcnt vmcnt(0) & lgkmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_inv 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_inv sc1=1

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

atomicrmw

取得

  • system

  • 通用

  1. flat_atomic sc1=1

  2. s_waitcnt vmcnt(0) & lgkmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_inv 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_inv sc0=1 sc1=1

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的 MTYPE NC 全域資料。 由於記憶體探測,MTYPE RW 和 CC 記憶體永遠不會過時。

柵欄

取得

  • singlethread

  • wavefront

none

none

柵欄

取得

  • workgroup

none

  1. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間是區域的,則省略 vmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入原子/ atomicrmw 之後發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入原子/atomicrmw 之後發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 必須在後續的 buffer_inv 以及任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於柵欄配對原子讀取的值。

  1. buffer_inv sc0=1

  • 如果不是 TgSplit 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

柵欄

取得

  • agent

none

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入原子/atomicrmw 之後發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入原子/atomicrmw 之後發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 必須在後續的 buffer_inv 之前發生。

  • 確保柵欄配對原子在使快取失效之前已完成。 因此,任何後續讀取的位置都不得早於柵欄配對原子讀取的值。

  1. buffer_inv sc1=1

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

柵欄

取得

  • system

none

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入原子/atomicrmw 之後發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入原子/atomicrmw 之後發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 必須在後續的 buffer_inv 之前發生。

  • 確保柵欄配對原子在使快取失效之前已完成。 因此,任何後續讀取的位置都不得早於柵欄配對原子讀取的值。

  1. buffer_inv sc0=1 sc1=1

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

釋放原子

儲存原子

釋放

  • singlethread

  • wavefront

  • global

  • 通用

  1. GFX942

    buffer/global/flat_store

儲存原子

釋放

  • singlethread

  • wavefront

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_store

儲存原子

釋放

  • workgroup

  • global

  • 通用

  1. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/ 載入原子/儲存原子/ atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的儲存之前發生。

  • 確保所有記憶體操作在執行正在釋放的儲存之前已完成。

  1. GFX942

    buffer/global/flat_store sc0=1

儲存原子

釋放

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_store

儲存原子

釋放

  • agent

  • global

  • 通用

  1. buffer_wbl2 sc1=1

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在代理程式作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的儲存之前發生。

  • 確保對記憶體的所有記憶體操作在執行正在釋放的儲存之前已完成。

  1. GFX942

    buffer/global/flat_store sc1=1

儲存原子

釋放

  • system

  • global

  • 通用

  1. buffer_wbl2 sc0=1 sc1=1

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在系統作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的儲存之前發生。

  • 確保對記憶體的所有記憶體操作和 L2 寫回在執行正在釋放的儲存之前已完成。

  1. buffer/global/flat_store sc0=1 sc1=1

atomicrmw

釋放

  • singlethread

  • wavefront

  • global

  • 通用

  1. buffer/global/flat_atomic

atomicrmw

釋放

  • singlethread

  • wavefront

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_atomic

atomicrmw

釋放

  • workgroup

  • global

  • 通用

  1. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/ 載入原子/儲存原子/ atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global/flat_atomic sc0=1

atomicrmw

釋放

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_atomic

atomicrmw

釋放

  • agent

  • global

  • 通用

  1. buffer_wbl2 sc1=1

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在代理程式作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對全域和區域的所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global/flat_atomic sc1=1

atomicrmw

釋放

  • system

  • global

  • 通用

  1. buffer_wbl2 sc0=1 sc1=1

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在系統作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對記憶體的所有記憶體操作和 L2 寫回在執行正在釋放的儲存之前已完成。

  1. buffer/global/flat_atomic sc0=1 sc1=1

柵欄

釋放

  • singlethread

  • wavefront

none

none

柵欄

釋放

  • workgroup

none

  1. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間是區域的,則省略 vmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/ 載入原子/儲存原子/ atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之後發生。

  • 必須在任何後續的儲存原子/atomicrmw 之前發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 確保所有記憶體操作在執行後續的柵欄配對原子之前已完成。

柵欄

釋放

  • agent

none

  1. buffer_wbl2 sc1=1

  • 如果是 OpenCL 且位址空間是區域的,則省略。

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在代理程式作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間是區域的,則省略 vmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在任何後續的儲存原子/atomicrmw 之前發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 確保所有記憶體操作在執行後續的柵欄配對原子之前已完成。

柵欄

釋放

  • system

none

  1. buffer_wbl2 sc0=1 sc1=1

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在系統作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間是區域的,則省略 vmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在任何後續的儲存原子/atomicrmw 之前發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 確保所有記憶體操作在執行後續的柵欄配對原子之前已完成。

取得-釋放原子

atomicrmw

取得_釋放

  • singlethread

  • wavefront

  • global

  • 通用

  1. buffer/global/flat_atomic

atomicrmw

取得_釋放

  • singlethread

  • wavefront

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_atomic

atomicrmw

取得_釋放

  • workgroup

  • global

  1. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/ 載入原子/儲存原子/ atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global_atomic

  2. s_waitcnt vmcnt(0)

  • 如果不是 TgSplit 執行模式,則省略。

  • 必須在後續的 buffer_inv 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的 atomicrmw 值。

  1. buffer_inv sc0=1

  • 如果不是 TgSplit 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得_釋放

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

  1. ds_atomic

  2. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL,則省略。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域載入原子值。

atomicrmw

取得_釋放

  • workgroup

  • 通用

  1. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/ 載入原子/儲存原子/ atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. flat_atomic

  2. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果不是 TgSplit 執行模式,則省略 vmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_inv 以及任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域載入原子值。

  1. buffer_inv sc0=1

  • 如果不是 TgSplit 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得_釋放

  • agent

  • global

  1. buffer_wbl2 sc1=1

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在代理程式作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對全域的所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global_atomic

  2. s_waitcnt vmcnt(0)

  • 必須在後續的 buffer_inv 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_inv sc1=1

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

atomicrmw

取得_釋放

  • system

  • global

  1. buffer_wbl2 sc0=1 sc1=1

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在系統作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對全域的所有記憶體操作和 L2 寫回在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global_atomic sc1=1

  2. s_waitcnt vmcnt(0)

  • 必須在後續的 buffer_inv 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_inv sc0=1 sc1=1

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的 MTYPE NC 全域資料。 由於記憶體探測,MTYPE RW 和 CC 記憶體永遠不會過時。

atomicrmw

取得_釋放

  • agent

  • 通用

  1. buffer_wbl2 sc1=1

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在代理程式作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對全域的所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. flat_atomic

  2. s_waitcnt vmcnt(0) & lgkmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_inv 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_inv sc1=1

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

atomicrmw

取得_釋放

  • system

  • 通用

  1. buffer_wbl2 sc0=1 sc1=1

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在系統作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對全域的所有記憶體操作和 L2 寫回在執行正在釋放的 atomicrmw 之前已完成。

  1. flat_atomic sc1=1

  2. s_waitcnt vmcnt(0) & lgkmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_inv 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_inv sc0=1 sc1=1

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的 MTYPE NC 全域資料。 由於記憶體探測,MTYPE RW 和 CC 記憶體永遠不會過時。

柵欄

取得_釋放

  • singlethread

  • wavefront

none

none

柵欄

取得_釋放

  • workgroup

none

  1. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間是區域的,則省略 vmcnt(0)。

  • 但是,由於 LLVM 目前在柵欄上沒有位址空間,因此需要保守地始終產生(請參閱先前柵欄的註解)。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/ 載入原子/儲存原子/ atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之後發生。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保所有記憶體操作在執行任何後續的全域記憶體操作之前已完成。

  • 確保先前的區域/通用載入原子/atomicrmw,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為取得柵欄配對原子),在後續的全域記憶體操作之前已完成。 這滿足取得的要求。

  • 確保所有先前的記憶體操作在後續的區域/通用儲存原子/atomicrmw 之前已完成,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為釋放柵欄配對原子)。 這滿足釋放的要求。

  • 必須在後續的 buffer_inv 之前發生。

  • 確保取得柵欄配對原子在使快取失效之前已完成。 因此,任何後續讀取的位置都不得早於取得柵欄配對原子讀取的值。

  1. buffer_inv sc0=1

  • 如果不是 TgSplit 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

柵欄

取得_釋放

  • agent

none

  1. buffer_wbl2 sc1=1

  • 如果是 OpenCL 且位址空間是區域的,則省略。

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在代理程式作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 buffer_inv 之前發生。

  • 確保先前的全域/區域/通用載入原子/atomicrmw,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為取得柵欄配對原子),在使快取失效之前已完成。 這滿足取得的要求。

  • 確保所有先前的記憶體操作在後續的全域/區域/通用儲存原子/atomicrmw 之前已完成,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為釋放柵欄配對原子)。 這滿足釋放的要求。

  1. buffer_inv sc1=1

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。 這滿足取得的要求。

柵欄

取得_釋放

  • system

none

  1. buffer_wbl2 sc0=1 sc1=1

  • 如果是 OpenCL 且位址空間是區域的,則省略。

  • 必須在後續的 s_waitcnt 之前發生。

  • 執行 L2 寫回以確保先前的全域/通用儲存/atomicrmw 在系統作用域中可見。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的全域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 buffer_inv 之前發生。

  • 確保先前的全域/區域/通用載入原子/atomicrmw,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為取得柵欄配對原子),在使快取失效之前已完成。 這滿足取得的要求。

  • 確保所有先前的記憶體操作在後續的全域/區域/通用儲存原子/atomicrmw 之前已完成,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為釋放柵欄配對原子)。 這滿足釋放的要求。

  1. buffer_inv sc0=1 sc1=1

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的 MTYPE NC 全域資料。 由於記憶體探測,MTYPE RW 和 CC 記憶體永遠不會過時。

循序一致性原子

載入原子

seq_cst

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

載入原子

seq_cst

  • workgroup

  • global

  • 通用

  1. s_waitcnt lgkm/vmcnt(0)

  • 如果不是 TgSplit 執行模式,則使用 lgkmcnt(0),如果是 TgSplit 執行模式,則使用 vmcnt(0)。

  • s_waitcnt lgkmcnt(0) 必須在先前的區域/通用載入原子/儲存原子/atomicrmw 之後發生,其記憶體排序為 seq_cst,且同步作用域相等或更寬。(請注意,seq_cst 柵欄有自己的 s_waitcnt lgkmcnt(0),因此不需要考慮。)

  • s_waitcnt vmcnt(0) 必須在先前的全域/通用載入原子/儲存原子/atomicrmw 之後發生,其記憶體排序為 seq_cst,且同步作用域相等或更寬。(請注意,seq_cst 柵欄有自己的 s_waitcnt vmcnt(0),因此不需要考慮。)

  • 確保任何先前的循序一致性全域/區域記憶體指令在執行此循序一致性指令之前已完成。 這可以防止重新排序 seq_cst 儲存,然後是 seq_cst 載入。(請注意,seq_cst 比取得/釋放更強,因為釋放的 s_waitcnt 會阻止重新排序載入取得,然後是儲存釋放,但是沒有任何東西阻止儲存釋放,然後是載入取得以無序完成。 s_waitcnt 可以放在 seq_store 之後或 seq_load 之前。 我們選擇載入以使 s_waitcnt 盡可能晚,以便儲存可能已經完成。)

  1. 後續指令與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

載入原子

seq_cst

  • workgroup

  • 區域

如果是 TgSplit 執行模式,則無法使用區域位址空間。

與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

載入原子

seq_cst

  • agent

  • system

  • global

  • 通用

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 如果是 TgSplit 執行模式,則省略 lgkmcnt(0)。

  • 可以拆分為單獨的 s_waitcnt vmcnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt lgkmcnt(0) 必須在先前的全域/通用載入原子/儲存原子/atomicrmw 之後發生,其記憶體排序為 seq_cst,且同步作用域相等或更寬。(請注意,seq_cst 柵欄有自己的 s_waitcnt lgkmcnt(0),因此不需要考慮。)

  • s_waitcnt vmcnt(0) 必須在先前的全域/通用載入原子/儲存原子/atomicrmw 之後發生,其記憶體排序為 seq_cst,且同步作用域相等或更寬。(請注意,seq_cst 柵欄有自己的 s_waitcnt vmcnt(0),因此不需要考慮。)

  • 確保任何先前的循序一致性全域記憶體指令在執行此循序一致性指令之前已完成。 這可以防止重新排序 seq_cst 儲存,然後是 seq_cst 載入。(請注意,seq_cst 比取得/釋放更強,因為釋放的 s_waitcnt 會阻止重新排序載入取得,然後是儲存釋放,但是沒有任何東西阻止儲存釋放,然後是載入取得以無序完成。 s_waitcnt 可以放在 seq_store 之後或 seq_load 之前。 我們選擇載入以使 s_waitcnt 盡可能晚,以便儲存可能已經完成。)

  1. 後續指令與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

儲存原子

seq_cst

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

  • global

  • 區域

  • 通用

與對應的儲存原子釋放相同,但即使對於 OpenCL 也必須產生所有指令。

atomicrmw

seq_cst

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

  • global

  • 區域

  • 通用

與對應的 atomicrmw acq_rel 相同,但即使對於 OpenCL 也必須產生所有指令。

柵欄

seq_cst

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

none

與對應的柵欄 acq_rel 相同,但即使對於 OpenCL 也必須產生所有指令。

記憶體模型 GFX10-GFX11

對於 GFX10-GFX11

  • 每個代理程式有多個著色器陣列 (SA)。

  • 每個 SA 都有多個工作群組處理器 (WGP)。

  • 每個 WGP 都有多個運算單元 (CU)。

  • 每個 CU 有多個執行波前的 SIMD。

  • 單個工作群組的波前在同一個 WGP 中執行。 在 CU 波前執行模式下,波前可能由同一個 CU 中不同的 SIMD 執行。 在 WGP 波前執行模式下,波前可能由同一個 WGP 中不同 CU 中的不同 SIMD 執行。

  • 每個 WGP 都有一個單個 LDS 記憶體,由在其上執行的工作群組的波前共享。

  • WGP 的所有 LDS 操作都作為全波前寬操作以全域順序執行,並且不涉及快取。 完成情況以執行順序報告給波前。

  • LDS 記憶體具有由 WGP 的 SIMD 共享的多個請求佇列。 因此,同一工作群組的不同波前執行的 LDS 操作可以相對於彼此重新排序,這可能會導致相對於同一工作群組中其他波前的 LDS 操作重新排序向量記憶體操作的可見性。 需要 s_waitcnt lgkmcnt(0) 以確保工作群組的波前之間 LDS 操作和向量記憶體操作之間的同步,但不包括同一波前執行的操作之間。

  • 向量記憶體操作作為波前寬操作執行。 載入/儲存/取樣操作的完成情況以該波前執行的其他載入/儲存/取樣操作的執行順序報告給波前。

  • 向量記憶體操作存取向量 L0 快取。 每個 CU 有一個單個 L0 快取。 CU 的每個 SIMD 存取同一個 L0 快取。 因此,單個波前的通道之間的一致性不需要特殊操作。 但是,在同一工作群組中執行的波前之間的一致性需要 buffer_gl0_inv,因為它們可能在存取不同 L0 的不同 CU 的 SIMD 上執行。 在不同工作群組中執行的波前之間的一致性也需要 buffer_gl0_inv,因為它們可能在不同的 WGP 上執行。

  • 純量記憶體操作存取 WGP 上所有波前共享的純量 L0 快取。 純量快取和向量 L0 快取不一致。 但是,純量操作以受限制的方式使用,因此不會影響記憶體模型。 請參閱 記憶體空間

  • 向量和純量記憶體 L0 快取使用由同一個 SA 上的所有 WGP 共享的 L1 快取。 因此,單個工作群組的波前之間的一致性不需要特殊操作。 但是,在不同工作群組中執行的波前之間的一致性需要 buffer_gl1_inv,因為它們可能在存取不同 L1 的不同 SA 上執行。

  • L1 快取具有獨立的象限,用於服務不相交的虛擬位址範圍。

  • 每個 L0 快取都有一個單獨的每個 L1 象限的請求佇列。 因此,由不同波前執行的向量和純量記憶體操作,無論是在同一個還是不同的工作群組中執行(可能在存取不同 L0 的不同 CU 上執行),都可以相對於彼此重新排序。 需要 s_waitcnt vmcnt(0) & vscnt(0) 以確保不同波前的向量記憶體操作之間的同步。 它確保先前的向量記憶體操作在執行後續的向量記憶體或 LDS 操作之前已完成,因此可以用於滿足取得、釋放和循序一致性的要求。

  • L1 快取使用由同一個代理程式上的所有 SA 共享的 L2 快取。

  • L2 快取具有獨立通道,用於服務不相交的虛擬位址範圍。

  • 單個 SA 的每個 L1 象限存取不同的 L2 通道。 每個 L1 象限都有一個單獨的每個 L2 通道的請求佇列。 因此,由不同工作群組(可能在不同 SA 上執行)中的波前執行的向量和純量記憶體操作可以相對於彼此重新排序。 需要 s_waitcnt vmcnt(0) & vscnt(0) 以確保不同 SA 的向量記憶體操作之間的同步。 它確保先前的向量記憶體操作在執行後續的向量記憶體之前已完成,因此可以用於滿足取得、釋放和循序一致性的要求。

  • L2 快取可以與某些目標上的其他代理程式保持一致性,或者可以設定虛擬位址範圍來繞過它,以確保系統一致性。

  • 在 GFX10.3 和 GFX11 上,GPU 記憶體存在附加的最後一層 (MALL) 快取。 MALL 快取與 GPU 記憶體完全一致,並且對系統一致性沒有影響。 所有代理程式(GPU 和 CPU)都透過 MALL 快取存取 GPU 記憶體。

純量記憶體操作僅用於存取在核心調度執行期間證明不會變更的記憶體。 這包括常數位址空間和程式作用域 const 變數的全域位址空間。 因此,核心機器碼不必維護純量快取,以確保它與向量快取一致。 純量快取和向量快取在核心調度之間由 CP 使失效,因為常數位址空間資料可能在核心調度執行之間變更。 請參閱 記憶體空間

一個例外情況是,如果純量寫入用於溢出 SGPR 暫存器。 在這種情況下,AMDGPU 後端確保用於溢出的記憶體位置永遠不會同時被向量記憶體操作存取。 如果使用純量寫入,則在 s_endpgm 之前和函數返回之前插入 s_dcache_wb,因為這些位置可能被未來使用相同暫存區的波前或在相同位址建立框架的函數呼叫用於向量記憶體指令。 不需要 s_dcache_inv,因為所有純量寫入在同一個執行緒中都是先寫後讀。

對於核心參數後備記憶體

  • CP 在每次核心調度開始時使 L0 和 L1 快取失效。

  • 在 dGPU 上,核心參數後備記憶體以 MTYPE UC(非快取)存取,以避免需要使 L2 快取失效。

  • 在 APU 上,核心參數後備記憶體以 MTYPE CC(快取一致性)存取,因此 L2 快取將與 CPU 和其他代理程式保持一致性。

暫存後備記憶體(用於私有位址空間)以 MTYPE NC(非一致性)存取。 由於私有位址空間僅由單個執行緒存取,並且始終是先寫後讀,因此永遠不需要使 L0 或 L1 快取中的這些條目失效。

波前以原生模式執行,並以順序報告載入和取樣指令。 在此模式下,vmcnt 按順序報告載入、帶傳回的原子和取樣指令的完成情況,而 vscnt 按順序報告不帶傳回的儲存和原子的完成情況。 請參閱 GFX6-GFX12 的 compute_pgm_rsrc1 中的 MEM_ORDERED 欄位。

波前可以在 WGP 或 CU 波前執行模式下執行

  • 在 WGP 波前執行模式下,工作群組的波前在 WGP 的兩個 CU 的 SIMD 上執行。 因此,工作群組同步需要顯式管理每個 CU L0 快取。 此外,工作群組作用域中對 L1 的存取需要顯式排序,因為來自不同 CU 的存取是無序的。

  • 在 CU wavefront 執行模式中,work-group 的 wavefronts 會在 WGP 單一 CU 的 SIMD 上執行。因此,work-group 的所有全域記憶體存取都會存取相同的 L0,進而確保 L1 存取是有序的,因此不需要針對 work-group 同步進行快取的明確管理。

請參閱 WGP_MODE 欄位,位於 適用於 GFX6-GFX12 的 compute_pgm_rsrc1目標功能

用於實作 GFX10-GFX11 記憶體模型的程式碼序列定義於表 AMDHSA 記憶體模型程式碼序列 GFX10-GFX11 中。

表 82 AMDHSA 記憶體模型程式碼序列 GFX10-GFX11

LLVM 指令

LLVM 記憶體排序

LLVM 記憶體同步作用域

AMDGPU 位址空間

AMDGPU 機器碼 GFX10-GFX11

非原子

載入

none

none

  • global

  • 通用

  • private

  • constant

  • !volatile & !nontemporal

    1. buffer/global/flat_load

  • !volatile & nontemporal

    1. buffer/global/flat_load slc=1 dlc=1

    • 若為 GFX10,則省略 dlc=1。

  • volatile

    1. buffer/global/flat_load glc=1 dlc=1

    2. s_waitcnt vmcnt(0)

    • 必須在任何後續的揮發性全域/通用載入/儲存之前發生。

    • 確保對不同位址的揮發性操作不會被硬體重新排序。

載入

none

none

  • 區域

  1. ds_load

儲存

none

none

  • global

  • 通用

  • private

  • constant

  • !volatile & !nontemporal

    1. buffer/global/flat_store

  • !volatile & nontemporal

    1. buffer/global/flat_store glc=1 slc=1 dlc=1

    • 若為 GFX10,則省略 dlc=1。

  • volatile

    1. buffer/global/flat_store dlc=1

    • 若為 GFX10,則省略 dlc=1。

    1. s_waitcnt vscnt(0)

    • 必須在任何後續的揮發性全域/通用載入/儲存之前發生。

    • 確保對不同位址的揮發性操作不會被硬體重新排序。

儲存

none

none

  • 區域

  1. ds_store

無序原子

載入原子

無序

任何

任何

與非原子相同.

儲存原子

無序

任何

任何

與非原子相同.

atomicrmw

無序

任何

任何

與單調原子相同.

單調原子

載入原子

單調

  • singlethread

  • wavefront

  • global

  • 通用

  1. buffer/global/flat_load

載入原子

單調

  • workgroup

  • global

  • 通用

  1. buffer/global/flat_load glc=1

  • 若為 CU wavefront 執行模式,則省略 glc=1。

載入原子

單調

  • singlethread

  • wavefront

  • workgroup

  • 區域

  1. ds_load

載入原子

單調

  • agent

  • system

  • global

  • 通用

  1. buffer/global/flat_load glc=1 dlc=1

  • 若為 GFX11,則省略 dlc=1。

儲存原子

單調

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

  • global

  • 通用

  1. buffer/global/flat_store

儲存原子

單調

  • singlethread

  • wavefront

  • workgroup

  • 區域

  1. ds_store

atomicrmw

單調

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

  • global

  • 通用

  1. buffer/global/flat_atomic

atomicrmw

單調

  • singlethread

  • wavefront

  • workgroup

  • 區域

  1. ds_atomic

取得原子

載入原子

取得

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_load

載入原子

取得

  • workgroup

  • global

  1. buffer/global_load glc=1

  • 若為 CU wavefront 執行模式,則省略 glc=1。

  1. s_waitcnt vmcnt(0)

  • 若為 CU wavefront 執行模式,則省略。

  • 必須在後續的 buffer_gl0_inv 之前,以及任何後續的 global/generic load/load atomic/store/store atomic/atomicrmw 之前發生。

  1. buffer_gl0_inv

  • 若為 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

載入原子

取得

  • workgroup

  • 區域

  1. ds_load

  2. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL,則省略。

  • 必須在後續的 buffer_gl0_inv 之前,以及任何後續的 global/generic load/load atomic/store/store atomic/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域載入原子值。

  1. buffer_gl0_inv

  • 若為 CU wavefront 執行模式,則省略。

  • 如果是 OpenCL,則省略。

  • 確保後續的載入不會看到過時的資料。

載入原子

取得

  • workgroup

  • 通用

  1. flat_load glc=1

  • 若為 CU wavefront 執行模式,則省略 glc=1。

  1. s_waitcnt lgkmcnt(0) & vmcnt(0)

  • 若為 CU wavefront 執行模式,則省略 vmcnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_gl0_inv 以及任何後續的 global/generic load/load atomic/store/store atomic/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域載入原子值。

  1. buffer_gl0_inv

  • 若為 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

載入原子

取得

  • agent

  • system

  • global

  1. buffer/global_load glc=1 dlc=1

  • 若為 GFX11,則省略 dlc=1。

  1. s_waitcnt vmcnt(0)

  • 必須在後續的 buffer_gl*_inv 之前發生。

  • 確保在使快取失效之前,載入已完成。

  1. buffer_gl1_inv; buffer_gl0_inv

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

載入原子

取得

  • agent

  • system

  • 通用

  1. flat_load glc=1 dlc=1

  • 若為 GFX11,則省略 dlc=1。

  1. s_waitcnt vmcnt(0) & lgkmcnt(0)

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_gl*_invl 之前發生。

  • 確保 flat_load 在使快取失效之前已完成。

  1. buffer_gl1_inv; buffer_gl0_inv

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

atomicrmw

取得

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_atomic

atomicrmw

取得

  • workgroup

  • global

  1. buffer/global_atomic

  2. s_waitcnt vm/vscnt(0)

  • 若為 CU wavefront 執行模式,則省略。

  • 若為帶有返回值的 atomic,則使用 vmcnt(0),若為不帶返回值的 atomic,則使用 vscnt(0)。

  • 必須在後續的 buffer_gl0_inv 之前,以及任何後續的 global/generic load/load atomic/store/store atomic/atomicrmw 之前發生。

  1. buffer_gl0_inv

  • 若為 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得

  • workgroup

  • 區域

  1. ds_atomic

  2. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL,則省略。

  • 必須在後續的 buffer_gl0_inv 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域 atomicrmw 值。

  1. buffer_gl0_inv

  • 若為 OpenCL,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得

  • workgroup

  • 通用

  1. flat_atomic

  2. s_waitcnt lgkmcnt(0) & vm/vscnt(0)

  • 若為 CU wavefront 執行模式,則省略 vm/vscnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 若為帶有返回值的 atomic,則使用 vmcnt(0),若為不帶返回值的 atomic,則使用 vscnt(0)。

  • 必須在後續的 buffer_gl0_inv 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域 atomicrmw 值。

  1. buffer_gl0_inv

  • 若為 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得

  • agent

  • system

  • global

  1. buffer/global_atomic

  2. s_waitcnt vm/vscnt(0)

  • 若為帶有返回值的 atomic,則使用 vmcnt(0),若為不帶返回值的 atomic,則使用 vscnt(0)。

  • 必須在後續的 buffer_gl*_inv 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_gl1_inv; buffer_gl0_inv

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

atomicrmw

取得

  • agent

  • system

  • 通用

  1. flat_atomic

  2. s_waitcnt vm/vscnt(0) & lgkmcnt(0)

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 若為帶有返回值的 atomic,則使用 vmcnt(0),若為不帶返回值的 atomic,則使用 vscnt(0)。

  • 必須在後續的 buffer_gl*_inv 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_gl1_inv; buffer_gl0_inv

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

柵欄

取得

  • singlethread

  • wavefront

none

none

柵欄

取得

  • workgroup

none

  1. s_waitcnt lgkmcnt(0) & vmcnt(0) & vscnt(0)

  • 若為 CU wavefront 執行模式,則省略 vmcnt(0) 和 vscnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 若為 OpenCL 且位址空間為 local,則省略 vmcnt(0) 和 vscnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為個別的 s_waitcnt vmcnt(0)、s_waitcnt vscnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的 global/generic load atomic/ atomicrmw-with-return-value 之後發生,其同步範圍相等或更寬,且記憶體排序強於 unordered(這稱為 fence-paired-atomic)。

  • s_waitcnt vscnt(0) 必須在任何先前的 global/generic atomicrmw-no-return-value 之後發生,其同步範圍相等或更寬,且記憶體排序強於 unordered(這稱為 fence-paired-atomic)。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入原子/atomicrmw 之後發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 必須在後續的 buffer_gl0_inv 之前發生。

  • 確保柵欄配對原子在使快取失效之前已完成。 因此,任何後續讀取的位置都不得早於柵欄配對原子讀取的值。

  1. buffer_gl0_inv

  • 若為 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

柵欄

取得

  • agent

  • system

none

  1. s_waitcnt lgkmcnt(0) & vmcnt(0) & vscnt(0)

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 若為 OpenCL 且位址空間為 local,則省略 vmcnt(0) 和 vscnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為個別的 s_waitcnt vmcnt(0)、s_waitcnt vscnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的 global/generic load atomic/ atomicrmw-with-return-value 之後發生,其同步範圍相等或更寬,且記憶體排序強於 unordered(這稱為 fence-paired-atomic)。

  • s_waitcnt vscnt(0) 必須在任何先前的 global/generic atomicrmw-no-return-value 之後發生,其同步範圍相等或更寬,且記憶體排序強於 unordered(這稱為 fence-paired-atomic)。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入原子/atomicrmw 之後發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 必須在後續的 buffer_gl*_inv 之前發生。

  • 確保 fence-paired atomic 在使快取失效之前已完成。因此,任何後續讀取的位置都不得早於 fence-paired-atomic 讀取的值。

  1. buffer_gl1_inv; buffer_gl0_inv

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

釋放原子

儲存原子

釋放

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_store

儲存原子

釋放

  • workgroup

  • global

  • 通用

  1. s_waitcnt lgkmcnt(0) & vmcnt(0) & vscnt(0)

  • 若為 CU wavefront 執行模式,則省略 vmcnt(0) 和 vscnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為個別的 s_waitcnt vmcnt(0)、s_waitcnt vscnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_waitcnt vscnt(0) 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的儲存之前發生。

  • 確保所有記憶體操作在執行正在釋放的儲存之前已完成。

  1. buffer/global/flat_store

儲存原子

釋放

  • workgroup

  • 區域

  1. s_waitcnt vmcnt(0) & vscnt(0)

  • 若為 CU wavefront 執行模式,則省略。

  • 如果是 OpenCL,則省略。

  • 可以拆分為個別的 s_waitcnt vmcnt(0) 和 s_waitcnt vscnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_waitcnt vscnt(0) 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • 必須在後續的儲存之前發生。

  • 確保所有全域記憶體操作在執行正在釋放的 store 之前已完成。

  1. ds_store

儲存原子

釋放

  • agent

  • system

  • global

  • 通用

  1. s_waitcnt lgkmcnt(0) & vmcnt(0) & vscnt(0)

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 可以拆分為個別的 s_waitcnt vmcnt(0)、s_waitcnt vscnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_waitcnt vscnt(0) 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的儲存之前發生。

  • 確保所有記憶體操作在執行正在釋放的儲存之前已完成。

  1. buffer/global/flat_store

atomicrmw

釋放

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_atomic

atomicrmw

釋放

  • workgroup

  • global

  • 通用

  1. s_waitcnt lgkmcnt(0) & vmcnt(0) & vscnt(0)

  • 若為 CU wavefront 執行模式,則省略 vmcnt(0) 和 vscnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為個別的 s_waitcnt vmcnt(0)、s_waitcnt vscnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_waitcnt vscnt(0) 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global/flat_atomic

atomicrmw

釋放

  • workgroup

  • 區域

  1. s_waitcnt vmcnt(0) & vscnt(0)

  • 若為 CU wavefront 執行模式,則省略。

  • 如果是 OpenCL,則省略。

  • 可以拆分為個別的 s_waitcnt vmcnt(0) 和 s_waitcnt vscnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_waitcnt vscnt(0) 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • 必須在後續的儲存之前發生。

  • 確保所有全域記憶體操作在執行正在釋放的 store 之前已完成。

  1. ds_atomic

atomicrmw

釋放

  • agent

  • system

  • global

  • 通用

  1. s_waitcnt lgkmcnt(0) &

    vmcnt(0) & vscnt(0)

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為個別的 s_waitcnt vmcnt(0)、s_waitcnt vscnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_waitcnt vscnt(0) 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對全域和區域的所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global/flat_atomic

柵欄

釋放

  • singlethread

  • wavefront

none

none

柵欄

釋放

  • workgroup

none

  1. s_waitcnt lgkmcnt(0) & vmcnt(0) & vscnt(0)

  • 若為 CU wavefront 執行模式,則省略 vmcnt(0) 和 vscnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 若為 OpenCL 且位址空間為 local,則省略 vmcnt(0) 和 vscnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為個別的 s_waitcnt vmcnt(0)、s_waitcnt vscnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_waitcnt vscnt(0) 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的 local/generic load/store/load atomic/store atomic/ atomicrmw 之後發生。

  • 必須在任何後續的儲存原子/atomicrmw 之前發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 確保所有記憶體操作在執行後續的柵欄配對原子之前已完成。

柵欄

釋放

  • agent

  • system

none

  1. s_waitcnt lgkmcnt(0) & vmcnt(0) & vscnt(0)

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 若為 OpenCL 且位址空間為 local,則省略 vmcnt(0) 和 vscnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為個別的 s_waitcnt vmcnt(0)、s_waitcnt vscnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_waitcnt vscnt(0) 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在任何後續的儲存原子/atomicrmw 之前發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 確保所有記憶體操作在執行後續的柵欄配對原子之前已完成。

取得-釋放原子

atomicrmw

取得_釋放

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_atomic

atomicrmw

取得_釋放

  • workgroup

  • global

  1. s_waitcnt lgkmcnt(0) & vmcnt(0) & vscnt(0)

  • 若為 CU wavefront 執行模式,則省略 vmcnt(0) 和 vscnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 可以拆分為個別的 s_waitcnt vmcnt(0)、s_waitcnt vscnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_waitcnt vscnt(0) 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global_atomic

  2. s_waitcnt vm/vscnt(0)

  • 若為 CU wavefront 執行模式,則省略。

  • 若為帶有返回值的 atomic,則使用 vmcnt(0),若為不帶返回值的 atomic,則使用 vscnt(0)。

  • 必須在後續的 buffer_gl0_inv 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的 atomicrmw 值。

  1. buffer_gl0_inv

  • 若為 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得_釋放

  • workgroup

  • 區域

  1. s_waitcnt vmcnt(0) & vscnt(0)

  • 若為 CU wavefront 執行模式,則省略。

  • 如果是 OpenCL,則省略。

  • 可以拆分為個別的 s_waitcnt vmcnt(0) 和 s_waitcnt vscnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_waitcnt vscnt(0) 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • 必須在後續的儲存之前發生。

  • 確保所有全域記憶體操作在執行正在釋放的 store 之前已完成。

  1. ds_atomic

  2. s_waitcnt lgkmcnt(0)

  • 如果是 OpenCL,則省略。

  • 必須在後續的 buffer_gl0_inv 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域載入原子值。

  1. buffer_gl0_inv

  • 若為 CU wavefront 執行模式,則省略。

  • 若為 OpenCL,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得_釋放

  • workgroup

  • 通用

  1. s_waitcnt lgkmcnt(0) & vmcnt(0) & vscnt(0)

  • 若為 CU wavefront 執行模式,則省略 vmcnt(0) 和 vscnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為個別的 s_waitcnt vmcnt(0)、s_waitcnt vscnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_waitcnt vscnt(0) 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. flat_atomic

  2. s_waitcnt lgkmcnt(0) & vmcnt(0) & vscnt(0)

  • 若為 CU wavefront 執行模式,則省略 vmcnt(0) 和 vscnt(0)。

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 必須在後續的 buffer_gl0_inv 之前發生。

  • 確保任何後續讀取的全域資料都不早於正在取得的 load atomic 值。

  1. buffer_gl0_inv

  • 若為 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得_釋放

  • agent

  • system

  • global

  1. s_waitcnt lgkmcnt(0) & vmcnt(0) & vscnt(0)

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為個別的 s_waitcnt vmcnt(0)、s_waitcnt vscnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_waitcnt vscnt(0) 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對全域的所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global_atomic

  2. s_waitcnt vm/vscnt(0)

  • 若為帶有返回值的 atomic,則使用 vmcnt(0),若為不帶返回值的 atomic,則使用 vscnt(0)。

  • 必須在後續的 buffer_gl*_inv 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_gl1_inv; buffer_gl0_inv

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

atomicrmw

取得_釋放

  • agent

  • system

  • 通用

  1. s_waitcnt lgkmcnt(0) & vmcnt(0) & vscnt(0)

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 可以拆分為個別的 s_waitcnt vmcnt(0)、s_waitcnt vscnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的 global/generic load/load atomic atomicrmw-with-return-value 之後發生。

  • s_waitcnt vscnt(0) 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. flat_atomic

  2. s_waitcnt vm/vscnt(0) & lgkmcnt(0)

  • 如果是 OpenCL,則省略 lgkmcnt(0)。

  • 若為帶有返回值的 atomic,則使用 vmcnt(0),若為不帶返回值的 atomic,則使用 vscnt(0)。

  • 必須在後續的 buffer_gl*_inv 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. buffer_gl1_inv; buffer_gl0_inv

  • 必須在任何後續的全域/通用載入/載入原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。

柵欄

取得_釋放

  • singlethread

  • wavefront

none

none

柵欄

取得_釋放

  • workgroup

none

  1. s_waitcnt lgkmcnt(0) & vmcnt(0) & vscnt(0)

  • 若為 CU wavefront 執行模式,則省略 vmcnt(0) 和 vscnt(0)。

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 若為 OpenCL 且位址空間為 local,則省略 vmcnt(0) 和 vscnt(0)。

  • 但是,由於 LLVM 目前在柵欄上沒有位址空間,因此需要保守地始終產生(請參閱先前柵欄的註解)。

  • 可以拆分為個別的 s_waitcnt vmcnt(0)、s_waitcnt vscnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_waitcnt vscnt(0) 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的 local/generic load/store/load atomic/store atomic/ atomicrmw 之後發生。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保所有記憶體操作在執行任何後續的全域記憶體操作之前已完成。

  • 確保先前的區域/通用載入原子/atomicrmw,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為取得柵欄配對原子),在後續的全域記憶體操作之前已完成。 這滿足取得的要求。

  • 確保所有先前的記憶體操作在後續的區域/通用儲存原子/atomicrmw 之前已完成,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為釋放柵欄配對原子)。 這滿足釋放的要求。

  • 必須在後續的 buffer_gl0_inv 之前發生。

  • 確保取得柵欄配對原子在使快取失效之前已完成。 因此,任何後續讀取的位置都不得早於取得柵欄配對原子讀取的值。

  1. buffer_gl0_inv

  • 若為 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

柵欄

取得_釋放

  • agent

  • system

none

  1. s_waitcnt lgkmcnt(0) & vmcnt(0) & vscnt(0)

  • 如果是 OpenCL 且位址空間不是通用的,則省略 lgkmcnt(0)。

  • 若為 OpenCL 且位址空間為 local,則省略 vmcnt(0) 和 vscnt(0)。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 可以拆分為個別的 s_waitcnt vmcnt(0)、s_waitcnt vscnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_waitcnt vscnt(0) 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_waitcnt lgkmcnt(0) 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • 必須在後續的 buffer_gl*_inv 之前發生。

  • 確保先前的 global/local/generic load atomic/atomicrmw (其同步範圍相等或更寬,且記憶體排序強於 unordered,這稱為 acquire-fence-paired-atomic) 在使快取失效之前已完成。這滿足 acquire 的要求。

  • 確保所有先前的記憶體操作在後續的全域/區域/通用儲存原子/atomicrmw 之前已完成,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為釋放柵欄配對原子)。 這滿足釋放的要求。

  1. buffer_gl1_inv; buffer_gl0_inv

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保後續的載入不會看到過時的全域資料。 這滿足取得的要求。

循序一致性原子

載入原子

seq_cst

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

載入原子

seq_cst

  • workgroup

  • global

  • 通用

  1. s_waitcnt lgkmcnt(0) & vmcnt(0) & vscnt(0)

  • 若為 CU wavefront 執行模式,則省略 vmcnt(0) 和 vscnt(0)。

  • 可以拆分為個別的 s_waitcnt vmcnt(0)、s_waitcnt vscnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt lgkmcnt(0) 必須在先前的區域/通用載入原子/儲存原子/atomicrmw 之後發生,其記憶體排序為 seq_cst,且同步作用域相等或更寬。(請注意,seq_cst 柵欄有自己的 s_waitcnt lgkmcnt(0),因此不需要考慮。)

  • s_waitcnt vmcnt(0) 必須在先前的 global/generic load atomic/ atomicrmw-with-return-value 之後發生,其記憶體排序為 seq_cst 且同步範圍相等或更寬。(請注意,seq_cst fences 有自己的 s_waitcnt vmcnt(0),因此無需考慮。)

  • s_waitcnt vscnt(0) 必須在先前的 global/generic store atomic/ atomicrmw-no-return-value 之後發生,其記憶體排序為 seq_cst 且同步範圍相等或更寬。(請注意,seq_cst fences 有自己的 s_waitcnt vscnt(0),因此無需考慮。)

  • 確保任何先前的循序一致性全域/區域記憶體指令在執行此循序一致性指令之前已完成。 這可以防止重新排序 seq_cst 儲存,然後是 seq_cst 載入。(請注意,seq_cst 比取得/釋放更強,因為釋放的 s_waitcnt 會阻止重新排序載入取得,然後是儲存釋放,但是沒有任何東西阻止儲存釋放,然後是載入取得以無序完成。 s_waitcnt 可以放在 seq_store 之後或 seq_load 之前。 我們選擇載入以使 s_waitcnt 盡可能晚,以便儲存可能已經完成。)

  1. 後續指令與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

載入原子

seq_cst

  • workgroup

  • 區域

  1. s_waitcnt vmcnt(0) & vscnt(0)

  • 若為 CU wavefront 執行模式,則省略。

  • 可以拆分為個別的 s_waitcnt vmcnt(0) 和 s_waitcnt vscnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt vmcnt(0) 必須在先前的 global/generic load atomic/ atomicrmw-with-return-value 之後發生,其記憶體排序為 seq_cst 且同步範圍相等或更寬。(請注意,seq_cst fences 有自己的 s_waitcnt vmcnt(0),因此無需考慮。)

  • s_waitcnt vscnt(0) 必須在先前的 global/generic store atomic/ atomicrmw-no-return-value 之後發生,其記憶體排序為 seq_cst 且同步範圍相等或更寬。(請注意,seq_cst fences 有自己的 s_waitcnt vscnt(0),因此無需考慮。)

  • 確保任何先前的循序一致性全域記憶體指令在執行此循序一致性指令之前已完成。 這可以防止重新排序 seq_cst 儲存,然後是 seq_cst 載入。(請注意,seq_cst 比取得/釋放更強,因為釋放的 s_waitcnt 會阻止重新排序載入取得,然後是儲存釋放,但是沒有任何東西阻止儲存釋放,然後是載入取得以無序完成。 s_waitcnt 可以放在 seq_store 之後或 seq_load 之前。 我們選擇載入以使 s_waitcnt 盡可能晚,以便儲存可能已經完成。)

  1. 後續指令與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

載入原子

seq_cst

  • agent

  • system

  • global

  • 通用

  1. s_waitcnt lgkmcnt(0) & vmcnt(0) & vscnt(0)

  • 可以拆分為個別的 s_waitcnt vmcnt(0)、s_waitcnt vscnt(0) 和 s_waitcnt lgkmcnt(0),以允許根據以下規則獨立移動它們。

  • s_waitcnt lgkmcnt(0) 必須在先前的 local load atomic/store atomic/atomicrmw 之後發生,其記憶體排序為 seq_cst 且同步範圍相等或更寬。(請注意,seq_cst fences 有自己的 s_waitcnt lgkmcnt(0),因此無需考慮。)

  • s_waitcnt vmcnt(0) 必須在先前的 global/generic load atomic/ atomicrmw-with-return-value 之後發生,其記憶體排序為 seq_cst 且同步範圍相等或更寬。(請注意,seq_cst fences 有自己的 s_waitcnt vmcnt(0),因此無需考慮。)

  • s_waitcnt vscnt(0) 必須在先前的 global/generic store atomic/ atomicrmw-no-return-value 之後發生,其記憶體排序為 seq_cst 且同步範圍相等或更寬。(請注意,seq_cst fences 有自己的 s_waitcnt vscnt(0),因此無需考慮。)

  • 確保任何先前的循序一致性全域記憶體指令在執行此循序一致性指令之前已完成。 這可以防止重新排序 seq_cst 儲存,然後是 seq_cst 載入。(請注意,seq_cst 比取得/釋放更強,因為釋放的 s_waitcnt 會阻止重新排序載入取得,然後是儲存釋放,但是沒有任何東西阻止儲存釋放,然後是載入取得以無序完成。 s_waitcnt 可以放在 seq_store 之後或 seq_load 之前。 我們選擇載入以使 s_waitcnt 盡可能晚,以便儲存可能已經完成。)

  1. 後續指令與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

儲存原子

seq_cst

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

  • global

  • 區域

  • 通用

與對應的儲存原子釋放相同,但即使對於 OpenCL 也必須產生所有指令。

atomicrmw

seq_cst

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

  • global

  • 區域

  • 通用

與對應的 atomicrmw acq_rel 相同,但即使對於 OpenCL 也必須產生所有指令。

柵欄

seq_cst

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

none

與對應的柵欄 acq_rel 相同,但即使對於 OpenCL 也必須產生所有指令。

記憶體模型 GFX12

適用於 GFX12

  • 每個代理程式有多個著色器陣列 (SA)。

  • 每個 SA 都有多個工作群組處理器 (WGP)。

  • 每個 WGP 都有多個運算單元 (CU)。

  • 每個 CU 有多個執行波前的 SIMD。

  • 單一 work-group 的 wavefronts 在相同的 WGP 中執行。

    • 在 CU wavefront 執行模式中,wavefronts 可能由相同 CU 中不同的 SIMD 執行。

    • 在 WGP wavefront 執行模式中,wavefronts 可能由相同 WGP 中不同 CU 中不同的 SIMD 執行。

  • 每個 WGP 都有一個單個 LDS 記憶體,由在其上執行的工作群組的波前共享。

  • WGP 的所有 LDS 操作都作為全波前寬操作以全域順序執行,並且不涉及快取。 完成情況以執行順序報告給波前。

  • LDS 記憶體具有多個請求佇列,由 WGP 的 SIMD 共用。因此,work-group 不同 wavefronts 執行的 LDS 操作可能會彼此重新排序,這可能會導致向量記憶體操作的可見性相對於相同 work-group 中其他 wavefronts 的 LDS 操作重新排序。需要 s_wait_dscnt 0x0 來確保 work-group wavefronts 之間 LDS 操作和向量記憶體操作之間的同步,但同一 wavefront 執行的操作之間則不需要。

  • 向量記憶體操作作為 wavefront 寬度操作執行。向量記憶體操作分為不同類型。向量記憶體操作的完成會在類型內依序報告給 wavefront,但類型之間可能會亂序。向量記憶體操作的類型(及其相關的 s_wait 指令)為

    • LDS: s_wait_dscnt

    • 載入(global、scratch、flat、buffer 和 image):s_wait_loadcnt

    • 儲存(global、scratch、flat、buffer 和 image):s_wait_storecnt

    • 取樣和 Gather4:s_wait_samplecnt

    • BVH:s_wait_bvhcnt

  • 向量和純量記憶體指令包含一個 SCOPE 欄位,其值對應於每個快取層級。SCOPE 決定快取是否可以在本機完成操作,或者是否需要將操作轉發到下一個快取層級。SCOPE 值為

    • SCOPE_CU:運算單元(注意:不受 CU/WGP 模式影響)

    • SCOPE_SE:Shader Engine

    • SCOPE_DEV:裝置/代理

    • SCOPE_SYS:系統

  • 當具有給定 SCOPE 的記憶體操作到達具有較小 SCOPE 值的快取時,它會被轉發到下一級快取。

  • 當具有給定 SCOPE 的記憶體操作到達具有大於或等於其自身 SCOPE 值的快取時,操作可以繼續進行

    • 讀取可以命中快取

    • 寫入可以在此快取中發生,並且交易會從此快取層級確認。

    • RMW 操作可以在本機完成。

  • global_invglobal_wbglobal_wbinv 指令用於使快取失效、寫回和寫回+失效快取。受影響的快取由指令的 SCOPE: 控制。

  • global_inv 使 scope 嚴格小於指令的快取失效。失效請求不能與擱置或即將到來的記憶體操作重新排序。

  • global_wb 是一個寫回操作,它還額外確保在較低 scope 層級完成的先前記憶體操作已到達 global_wbSCOPE:

    • 對於 gfx120x 中的 SCOPE_SYS 以外的 scope,可以省略 global_wb

  • 向量記憶體操作存取向量 L0 快取。每個 CU 有一個單一 L0 快取。CU 的每個 SIMD 存取相同的 L0 快取。因此,單一 wavefront 的 lanes 之間的同調性不需要特殊操作。為了實現相同 work-group 中執行的 wavefronts 之間的同調性

    • 在 CU wavefront 執行模式中,不需要特殊操作。

    • 在 WGP wavefront 執行模式中,需要 global_inv scope:SCOPE_SE,因為 wavefronts 可能在存取不同 L0 的不同 CU 的 SIMD 上執行。

  • 純量記憶體操作存取 WGP 上所有波前共享的純量 L0 快取。 純量快取和向量 L0 快取不一致。 但是,純量操作以受限制的方式使用,因此不會影響記憶體模型。 請參閱 記憶體空間

  • 向量和純量記憶體 L0 快取使用 L1 buffer,該 buffer 由相同 SA 上的所有 WGP 共用。L1 buffer 作為 SA 內用戶端到 L2 的橋樑。

  • L1 buffers 具有獨立的象限,以服務不相交的虛擬位址範圍。

  • 每個 L0 快取對於每個 L1 象限都有一個單獨的請求佇列。因此,不同 wavefronts 執行的向量和純量記憶體操作(無論是在相同還是不同的 work-groups 中執行,這些 work-groups 可能在存取不同 L0 的不同 CU 上執行)可能會彼此重新排序。以下部分或全部 wait 指令是確保不同 wavefronts 的向量記憶體操作之間同步所必需的。它確保先前的向量記憶體操作已完成,然後再執行後續的向量記憶體或 LDS 操作,因此可以用於滿足 acquire、release 和循序一致性的要求。

    • s_wait_loadcnt 0x0

    • s_wait_samplecnt 0x0

    • s_wait_bvhcnt 0x0

    • s_wait_storecnt 0x0

  • L1 buffers 使用 L2 快取,該快取由相同 agent 上的所有 SA 共用。

  • L2 快取具有獨立通道,用於服務不相交的虛擬位址範圍。

  • 單一 SA 的每個 L1 象限存取不同的 L2 通道。每個 L1 象限對於每個 L2 通道都有一個單獨的請求佇列。因此,在 agent 的不同 work-groups(可能在不同的 SA 上執行)中執行的 wavefronts 所執行的向量和純量記憶體操作可能會彼此重新排序。以下部分或全部 wait 指令是確保不同 SA 的向量記憶體操作之間同步所必需的。它確保先前的向量記憶體操作已完成,然後再執行後續的向量記憶體,因此可以用於滿足 acquire、release 和循序一致性的要求。

    • s_wait_loadcnt 0x0

    • s_wait_samplecnt 0x0

    • s_wait_bvhcnt 0x0

    • s_wait_storecnt 0x0

  • L2 快取可以與其他 agents 保持同調,或者可以設定虛擬位址範圍以繞過它,以確保系統同調性。

  • GPU 記憶體存在記憶體附加的末級 (MALL) 快取。MALL 快取與 GPU 記憶體完全同調,並且對系統同調性沒有影響。所有 agents(GPU 和 CPU)都透過 MALL 快取存取 GPU 記憶體。

純量記憶體操作僅用於存取在核心調度執行期間證明不會變更的記憶體。 這包括常數位址空間和程式作用域 const 變數的全域位址空間。 因此,核心機器碼不必維護純量快取,以確保它與向量快取一致。 純量快取和向量快取在核心調度之間由 CP 使失效,因為常數位址空間資料可能在核心調度執行之間變更。 請參閱 記憶體空間

對於核心參數後備記憶體

  • CP 在每次核心調度開始時使快取失效。

  • 在 dGPU 上,核心參數後備記憶體以 MTYPE UC(非快取)存取,以避免需要使 L2 快取失效。

  • 在 APU 上,核心參數後備記憶體以 MTYPE CC(快取一致性)存取,因此 L2 快取將與 CPU 和其他代理程式保持一致性。

Scratch 後備記憶體(用於私有位址空間)使用 MTYPE NC(非同調)存取。由於私有位址空間僅由單一執行緒存取,並且始終是先寫後讀,因此永遠不需要使 L0 中的這些條目失效。

波前可以在 WGP 或 CU 波前執行模式下執行

  • 在 WGP 波前執行模式下,工作群組的波前在 WGP 的兩個 CU 的 SIMD 上執行。 因此,工作群組同步需要顯式管理每個 CU L0 快取。 此外,工作群組作用域中對 L1 的存取需要顯式排序,因為來自不同 CU 的存取是無序的。

  • 在 CU wavefront 執行模式中,work-group 的 wavefronts 會在 WGP 單一 CU 的 SIMD 上執行。因此,work-group 的所有全域記憶體存取都會存取相同的 L0,進而確保 L1 存取是有序的,因此不需要針對 work-group 同步進行快取的明確管理。

請參閱 WGP_MODE 欄位,位於 適用於 GFX6-GFX12 的 compute_pgm_rsrc1目標功能

用於實作 GFX12 記憶體模型的程式碼序列定義於表 AMDHSA 記憶體模型程式碼序列 GFX12 中。

LLVM IR syncscope 到 GFX12 指令 scope 運算元的對應定義於 AMDHSA 記憶體模型程式碼序列 GFX12 - 指令 Scope 中。

此表僅在 AMDHSA 記憶體模型程式碼序列 GFX12 中的條目直接引用它時適用,並且僅適用於引用該表的程式碼序列中的指令。

表 83 AMDHSA 記憶體模型程式碼序列 GFX12 - 指令 Scope

LLVM syncscope

CU wavefront 執行模式

WGP wavefront 執行模式

none

scope:SCOPE_SYS

scope:SCOPE_SYS

system

scope:SCOPE_SYS

scope:SCOPE_SYS

agent

scope:SCOPE_DEV

scope:SCOPE_DEV

workgroup

none

scope:SCOPE_SE

wavefront

none

none

singlethread

none

none

one-as

scope:SCOPE_SYS

scope:SCOPE_SYS

system-one-as

scope:SCOPE_SYS

scope:SCOPE_SYS

agent-one-as

scope:SCOPE_DEV

scope:SCOPE_DEV

workgroup-one-as

none

scope:SCOPE_SE

wavefront-one-as

none

none

singlethread-one-as

none

none

表 84 AMDHSA 記憶體模型程式碼序列 GFX12

LLVM 指令

LLVM 記憶體排序

LLVM 記憶體同步作用域

AMDGPU 位址空間

AMDGPU 機器碼 GFX12

非原子

載入

none

none

  • global

  • 通用

  • private

  • constant

  • !volatile & !nontemporal

    1. buffer/global/flat_load

  • !volatile & nontemporal

    1. buffer/global/flat_load th:TH_LOAD_NT

  • volatile

    1. buffer/global/flat_load scope:SCOPE_SYS

    2. s_wait_loadcnt 0x0

    • 必須在任何後續的揮發性全域/通用載入/儲存之前發生。

    • 確保對不同位址的揮發性操作不會被硬體重新排序。

載入

none

none

  • 區域

  1. ds_load

儲存

none

none

  • global

  • 通用

  • private

  • constant

  • !volatile & !nontemporal

    1. buffer/global/flat_store

  • !volatile & nontemporal

    1. buffer/global/flat_store th:TH_STORE_NT

  • volatile

    1. buffer/global/flat_store scope:SCOPE_SYS

    2. s_wait_storecnt 0x0

    • 必須在任何後續的揮發性全域/通用載入/儲存之前發生。

    • 確保對不同位址的揮發性操作不會被硬體重新排序。

儲存

none

none

  • 區域

  1. ds_store

無序原子

載入原子

無序

任何

任何

與非原子相同.

儲存原子

無序

任何

任何

與非原子相同.

atomicrmw

無序

任何

任何

與單調原子相同.

單調原子

載入原子

單調

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

  • global

  • 通用

  1. buffer/global/flat_load

載入原子

單調

  • singlethread

  • wavefront

  • workgroup

  • 區域

  1. ds_load

儲存原子

單調

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

  • global

  • 通用

  1. buffer/global/flat_store

儲存原子

單調

  • singlethread

  • wavefront

  • workgroup

  • 區域

  1. ds_store

atomicrmw

單調

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

  • global

  • 通用

  1. buffer/global/flat_atomic

atomicrmw

單調

  • singlethread

  • wavefront

  • workgroup

  • 區域

  1. ds_atomic

取得原子

載入原子

取得

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_load

載入原子

取得

  • workgroup

  • global

  1. buffer/global_load scope:SCOPE_SE

  1. s_wait_loadcnt 0x0

  • 若為 CU wavefront 執行模式,則省略。

  • 必須在後續的 global_inv 之前,以及任何後續的 global/generic load/load atomic/store/store atomic/atomicrmw 之前發生。

  1. global_inv scope:SCOPE_SE

  • 若為 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

載入原子

取得

  • workgroup

  • 區域

  1. ds_load

  2. s_wait_dscnt 0x0

  • 如果是 OpenCL,則省略。

  • 必須在後續的 global_inv 之前,以及任何後續的 global/generic load/load atomic/store/store atomic/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域載入原子值。

  1. global_inv scope:SCOPE_SE

  • 若為 OpenCL 或 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

載入原子

取得

  • workgroup

  • 通用

  1. flat_load

  1. s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
    CU wavefront 執行模式
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 s_wait_dscnt 0x0

  • 必須在後續的 global_inv 以及任何後續的 global/generic load/load atomic/store/store atomic/atomicrmw 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域載入原子值。

  1. global_inv scope:SCOPE_SE

  • 若為 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

載入原子

取得

  • agent

  • system

  • global

  1. buffer/global_load

  1. s_wait_loadcnt 0x0

  • 必須在後續的 global_inv 之前發生。

  • 確保在使快取失效之前,載入已完成。

  1. global_inv

載入原子

取得

  • agent

  • system

  • 通用

  1. flat_load

  1. s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 s_wait_dscnt 0x0

  • 必須在後續的 global_inv 之前發生。

  • 確保 flat_load 在使快取失效之前已完成。

  1. global_inv

atomicrmw

取得

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_atomic

atomicrmw

取得

  • workgroup

  • global

  1. buffer/global_atomic

  1. 帶有返回值的 Atomic
    s_wait_loadcnt 0x0
    不帶返回值的 Atomic
    s_wait_storecnt 0x0
  • 若為 CU wavefront 執行模式,則省略。

  • 必須在後續的 global_inv 之前,以及任何後續的 global/generic load/load atomic/store/store atomic/atomicrmw 之前發生。

  1. global_inv scope:SCOPE_SE

  • 若為 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得

  • workgroup

  • 區域

  1. ds_atomic

  2. s_wait_dscnt 0x0

  • 如果是 OpenCL,則省略。

  • 必須在後續的 global_inv 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域 atomicrmw 值。

  1. global_inv scope:SCOPE_SE

  • 若為 OpenCL,則省略。

  • 若為 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得

  • workgroup

  • 通用

  1. flat_atomic

  1. 帶有返回值的 Atomic
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
    不帶返回值的 Atomic
    s_wait_storecnt 0x0
    s_wait_dscnt 0x0
  • 若為 CU wavefront 執行模式,則對於不帶返回值的 atomics,省略所有內容,對於帶有返回值的 atomics,僅發出 s_wait_dscnt 0x0

  • 若為 OpenCL,則省略 s_wait_dscnt 0x0

  • 必須在後續的 global_inv 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域 atomicrmw 值。

  1. global_inv scope:SCOPE_SE

  • 若為 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得

  • agent

  • system

  • global

  1. buffer/global_atomic

  1. 帶有返回值的 Atomic
    s_wait_loadcnt 0x0
    不帶返回值的 Atomic
    s_wait_storecnt 0x0
  • 必須在後續的 global_inv 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. global_inv

atomicrmw

取得

  • agent

  • system

  • 通用

  1. flat_atomic

  1. 帶有返回值的 Atomic
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
    不帶返回值的 Atomic
    s_wait_storecnt 0x0
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 dscnt

  • 必須在後續的 global_inv 之前發生

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. global_inv

柵欄

取得

  • singlethread

  • wavefront

none

none

柵欄

取得

  • workgroup

none

  1. s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
    CU wavefront 執行模式
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 s_wait_dscnt 0x0

  • 若為 OpenCL 且位址空間為 local,則省略所有內容。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 注意:我們不必使用 s_wait_samplecnt 0x0s_wait_bvhcnt 0x0,因為沒有 fence 可以與之配對的 atomic sample 或 BVH 指令。

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0 必須在任何先前的 global/generic load atomic/ atomicrmw-with-return-value 之後發生,其同步範圍相等或更寬,且記憶體排序強於 unordered(這稱為 fence-paired-atomic)。

  • s_wait_storecnt 0x0 必須在任何先前的 global/generic atomicrmw-no-return-value 之後發生,其同步範圍相等或更寬,且記憶體排序強於 unordered(這稱為 fence-paired-atomic)。

  • s_wait_dscnt 0x0 必須在任何先前的 local/generic load atomic/atomicrmw 之後發生,其同步範圍相等或更寬,且記憶體排序強於 unordered(這稱為 fence-paired-atomic)。

  • 必須在後續的 global_inv 之前發生。

  • 確保柵欄配對原子在使快取失效之前已完成。 因此,任何後續讀取的位置都不得早於柵欄配對原子讀取的值。

  1. global_inv scope:SCOPE_SE

  • 若為 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

柵欄

取得

  • agent

none

  1. s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 s_wait_dscnt 0x0

  • 若為 OpenCL 且位址空間為 local,則省略所有內容。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • 注意:我們不必使用 s_wait_samplecnt 0x0s_wait_bvhcnt 0x0,因為沒有 fence 可以與之配對的 atomic sample 或 BVH 指令。

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0 必須在任何先前的 global/generic load atomic/ atomicrmw-with-return-value 之後發生,其同步範圍相等或更寬,且記憶體排序強於 unordered(這稱為 fence-paired-atomic)。

  • s_wait_storecnt 0x0 必須在任何先前的 global/generic atomicrmw-no-return-value 之後發生,其同步範圍相等或更寬,且記憶體排序強於 unordered(這稱為 fence-paired-atomic)。

  • s_wait_dscnt 0x0 必須在任何先前的 local/generic load atomic/atomicrmw 之後發生,其同步範圍相等或更寬,且記憶體排序強於 unordered(這稱為 fence-paired-atomic)。

  • 必須在後續的 global_inv 之前發生

  • 確保 fence-paired atomic 在使快取失效之前已完成。因此,任何後續讀取的位置都不得早於 fence-paired-atomic 讀取的值。

  1. global_inv

釋放原子

儲存原子

釋放

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_store

儲存原子

釋放

  • workgroup

  • global

  1. s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
    CU wavefront 執行模式
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 s_wait_dscnt 0x0

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_wait_storecnt 0x0 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_wait_dscnt 0x0 必須在任何先前的 local/generic load/store/load atomic/store atomic/atomicrmw 之後發生。

  • 確保所有記憶體操作在執行正在釋放的儲存之前已完成。

  1. buffer/global/flat_store

儲存原子

釋放

  • workgroup

  • 區域

  1. s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
    CU wavefront 執行模式
    s_wait_dscnt 0x0
  • 如果是 OpenCL,則省略。

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_wait_storecnt 0x0 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • 必須在後續的儲存之前發生。

  • 確保所有全域記憶體操作在執行正在釋放的 store 之前已完成。

  1. ds_store

儲存原子

釋放

  • agent

  • system

  • global

  • 通用

  1. global_wb scope:SCOPE_SYS

    • 若為 agent scope,則省略。

  2. s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 s_wait_dscnt 0x0

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_wait_storecnt 0x0 必須在 global_wb (如果存在) 之後,或任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_wait_dscnt 0x0 必須在任何先前的 local/generic load/store/load atomic/store atomic/atomicrmw 之後發生。

  • 必須在後續的儲存之前發生。

  • 確保所有記憶體操作在執行正在釋放的儲存之前已完成。

  1. buffer/global/flat_store

atomicrmw

釋放

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_atomic

atomicrmw

釋放

  • workgroup

  • global

  • 通用

  1. s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
    CU wavefront 執行模式
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 s_wait_dscnt 0x0

  • 若為 OpenCL 且 CU wavefront 執行模式,則省略所有內容。

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_wait_storecnt 0x0 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_wait_dscnt 0x0 必須在任何先前的 local/generic load/store/load atomic/store atomic/atomicrmw 之後發生。

  • 必須在後續的 atomic 之前發生。

  • 確保所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global/flat_atomic

atomicrmw

釋放

  • workgroup

  • 區域

  1. s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
    CU wavefront 執行模式
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略所有內容。

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_wait_storecnt 0x0 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • 必須在後續的 atomic 之前發生。

  • 確保所有全域記憶體操作在執行正在釋放的 store 之前已完成。

  1. ds_atomic

atomicrmw

釋放

  • agent

  • system

  • global

  • 通用

  1. global_wb scope:SCOPE_SYS

  • 若為 agent scope,則省略。

  1. s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 s_wait_dscnt 0x0

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_wait_storecnt 0x0 必須在 global_wb (如果存在) 之後,或任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_wait_dscnt 0x0 必須在任何先前的 local/generic load/store/load atomic/store atomic/atomicrmw 之後發生。

  • 必須在後續的 atomic 之前發生。

  • 確保對全域和區域的所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global/flat_atomic

柵欄

釋放

  • singlethread

  • wavefront

none

none

柵欄

釋放

  • workgroup

none

  1. s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
    CU wavefront 執行模式
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 s_wait_dscnt 0x0

  • 若為 OpenCL 且位址空間為 local,則省略所有內容。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_wait_storecnt 0x0 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_wait_dscnt 0x0 必須在任何先前的 local/generic load/store/load atomic/store atomic/ atomicrmw 之後發生。

  • 必須在任何後續的儲存原子/atomicrmw 之前發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 確保所有記憶體操作在執行後續的柵欄配對原子之前已完成。

柵欄

釋放

  • agent

  • system

none

  1. global_wb scope:SCOPE_SYS

  • 若為 agent scope,則省略。

  1. s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
    OpenCL
    s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
  • 若為 OpenCl,則省略 s_wait_dscnt 0x0

  • 若為 OpenCL 且位址空間為 local,則省略所有內容。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_wait_storecnt 0x0 必須在 global_wb (如果存在) 之後,或任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_wait_dscnt 0x0 必須在任何先前的 local/generic load/store/load atomic/store atomic/atomicrmw 之後發生。

  • 必須在任何後續的儲存原子/atomicrmw 之前發生,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為柵欄配對原子)。

  • 確保所有記憶體操作在執行後續的柵欄配對原子之前已完成。

取得-釋放原子

atomicrmw

取得_釋放

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

  1. buffer/global/ds/flat_atomic

atomicrmw

取得_釋放

  • workgroup

  • global

  1. s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
    CU wavefront 執行模式
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 s_wait_dscnt 0x0

  • 必須在任何先前的區域/通用載入/儲存/載入原子/儲存原子/atomicrmw 之後發生。

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_wait_storecnt 0x0 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_wait_dscnt 0x0 必須在任何先前的 local/generic load/store/load atomic/store atomic/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global_atomic

  1. 帶有返回值的 Atomic
    s_wait_loadcnt 0x0
    不帶返回值的 Atomic
    s_wait_storecnt 0x0
  • 若為 CU wavefront 執行模式,則省略。

  • 必須在後續的 global_inv 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的 atomicrmw 值。

  1. global_inv scope:SCOPE_SE

  • 若為 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得_釋放

  • workgroup

  • 區域

1 | s_wait_bvhcnt 0x0
s_wait_samplecnt 0x0
s_wait_storecnt 0x0
s_wait_loadcnt 0x0
s_wait_dscnt 0x0
CU wavefront 執行模式
s_wait_dscnt 0x0
  • 如果是 OpenCL,則省略。

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_wait_storecnt 0x0 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • 必須在後續的儲存之前發生。

  • 確保所有全域記憶體操作在執行正在釋放的 store 之前已完成。

  1. ds_atomic

  2. s_wait_dscnt 0x0

  • 如果是 OpenCL,則省略。

  • 必須在後續的 global_inv 之前發生。

  • 確保任何後續的全域資料讀取都不會早於正在取得的區域載入原子值。

  1. global_inv scope:SCOPE_SE

  • 若為 CU wavefront 執行模式,則省略。

  • 若為 OpenCL,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得_釋放

  • workgroup

  • 通用

  1. s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
    CU wavefront 執行模式
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 s_wait_loadcnt 0x0

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_wait_storecnt 0x0 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_wait_dscnt 0x0 必須在任何先前的 local/generic load/store/load atomic/store atomic/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. flat_atomic

  1. 不帶返回值的 Atomic
    s_wait_dscnt 0x0
    s_wait_storecnt 0x0
    帶有返回值的 Atomic
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
    CU wavefront 執行模式
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 s_wait_dscnt 0x0

  • 必須在後續的 global_inv 之前發生。

  • 確保任何後續讀取的全域資料都不早於正在取得的 load atomic 值。

  1. global_inv scope:SCOPE_SE

  • 若為 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

atomicrmw

取得_釋放

  • agent

  • system

  • global

  1. global_wb scope:SCOPE_SYS

  • 若為 agent scope,則省略。

  1. s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 s_wait_dscnt 0x0

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_wait_storecnt 0x0 必須在 global_wb (如果存在) 之後,或任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_wait_dscnt 0x0 必須在任何先前的 local/generic load/store/load atomic/store atomic/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保對全域的所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. buffer/global_atomic

  1. 帶有返回值的 Atomic
    s_wait_loadcnt 0x0
    不帶返回值的 Atomic
    s_wait_storecnt 0x0
  • 必須在後續的 global_inv 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. global_inv

atomicrmw

取得_釋放

  • agent

  • system

  • 通用

  1. global_wb scope:SCOPE_SYS

  • 若為 agent scope,則省略。

  1. s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 s_wait_dscnt 0x0

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在任何先前的 global/generic load/load atomic atomicrmw-with-return-value 之後發生。

  • s_wait_storecnt 0x0 必須在 global_wb (如果存在) 之後,或任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_wait_dscnt 0x0 必須在任何先前的 local/generic load/store/load atomic/store atomic/atomicrmw 之後發生。

  • 必須在後續的 atomicrmw 之前發生。

  • 確保所有記憶體操作在執行正在釋放的 atomicrmw 之前已完成。

  1. flat_atomic

  1. 帶有返回值的 Atomic
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
    不帶返回值的 Atomic
    s_wait_storecnt 0x0
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 s_wait_dscnt 0x0

  • 必須在後續的 global_inv 之前發生。

  • 確保 atomicrmw 在使快取失效之前已完成。

  1. global_inv

柵欄

取得_釋放

  • singlethread

  • wavefront

none

none

柵欄

取得_釋放

  • workgroup

none

  1. s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
    CU wavefront 執行模式
    s_wait_dscnt 0x0
  • 若為 OpenCL 且位址空間不是 generic,則省略 s_wait_dscnt 0x0

  • 若為 OpenCL 且位址空間為 local,則省略除 s_wait_dscnt 0x0 之外的所有內容。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_wait_storecnt 0x0 必須在任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_wait_dscnt 0x0 必須在任何先前的 local/generic load/store/load atomic/store atomic/ atomicrmw 之後發生。

  • 必須在任何後續的全域/通用載入/載入原子/儲存/儲存原子/atomicrmw 之前發生。

  • 確保所有記憶體操作在執行任何後續的全域記憶體操作之前已完成。

  • 確保先前的區域/通用載入原子/atomicrmw,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為取得柵欄配對原子),在後續的全域記憶體操作之前已完成。 這滿足取得的要求。

  • 確保所有先前的記憶體操作在後續的區域/通用儲存原子/atomicrmw 之前已完成,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為釋放柵欄配對原子)。 這滿足釋放的要求。

  • 必須在後續的 global_inv 之前發生。

  • 確保取得柵欄配對原子在使快取失效之前已完成。 因此,任何後續讀取的位置都不得早於取得柵欄配對原子讀取的值。

  1. global_inv scope:SCOPE_SE

  • 若為 CU wavefront 執行模式,則省略。

  • 確保後續的載入不會看到過時的資料。

柵欄

取得_釋放

  • agent

  • system

none

  1. global_wb scope:SCOPE_SYS

  • 若為 agent scope,則省略。

  1. s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
  • 若為 OpenCL 且位址空間不是 generic,則省略 s_wait_dscnt 0x0

  • 若為 OpenCL 且位址空間為 local,則省略除 s_wait_dscnt 0x0 之外的所有內容。

  • 有關特定位址空間柵欄的更多詳細資訊,請參閱 柵欄和位址空間

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在任何先前的 global/generic load/load atomic/ atomicrmw-with-return-value 之後發生。

  • s_wait_storecnt 0x0 必須在 global_wb (如果存在) 之後,或任何先前的 global/generic store/store atomic/ atomicrmw-no-return-value 之後發生。

  • s_wait_dscnt 0x0 必須在任何先前的 local/generic load/store/load atomic/store atomic/atomicrmw 之後發生。

  • 必須在後續的 global_inv 之前發生

  • 確保先前的 global/local/generic load atomic/atomicrmw (其同步範圍相等或更寬,且記憶體排序強於 unordered,這稱為 acquire-fence-paired-atomic) 在使快取失效之前已完成。這滿足 acquire 的要求。

  • 確保所有先前的記憶體操作在後續的全域/區域/通用儲存原子/atomicrmw 之前已完成,其同步作用域相等或更寬,且記憶體排序強於無序(這稱為釋放柵欄配對原子)。 這滿足釋放的要求。

  1. global_inv scope:

循序一致性原子

載入原子

seq_cst

  • singlethread

  • wavefront

  • global

  • 區域

  • 通用

與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

載入原子

seq_cst

  • workgroup

  • global

  • 通用

  1. s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
    CU wavefront 執行模式
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 s_wait_dscnt 0x0

  • waits 可以根據以下規則獨立移動

  • s_wait_dscnt 0x0 必須在先前的 local/generic load atomic/store atomic/atomicrmw 之後發生,其記憶體排序為 seq_cst 且同步範圍相等或更寬。(請注意,seq_cst fences 有自己的 s_wait_dscnt 0x0,因此無需考慮。)

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在先前的 global/generic load atomic/ atomicrmw-with-return-value 之後發生,其記憶體排序為 seq_cst 且同步範圍相等或更寬。(請注意,seq_cst fences 有自己的 waits,因此無需考慮。)

  • s_wait_storecnt 0x0 必須在先前的 global/generic store atomic/ atomicrmw-no-return-value 之後發生,其記憶體排序為 seq_cst 且同步範圍相等或更寬。(請注意,seq_cst fences 有自己的 s_wait_storecnt 0x0,因此無需考慮。)

  • 確保任何先前的循序一致性 global/local 記憶體指令在執行此循序一致性指令之前已完成。這可防止重新排序 seq_cst store 後面跟著 seq_cst load。(請注意,seq_cst 比 acquire/release 更強,因為 load acquire 後面跟著 store release 的重新排序受到 release 的 s_waits 的阻止,但沒有任何東西阻止 store release 後面跟著 load acquire 從亂序完成。s_waits 可以放在 seq_store 之後或 seq_load 之前。我們選擇 load 是為了使 s_waits 盡可能晚,以便 store 可能已經完成。)

  1. 後續指令與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

載入原子

seq_cst

  • workgroup

  • 區域

  1. s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
    CU wavefront 執行模式
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略所有內容。

  • waits 可以根據以下規則獨立移動

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在先前的 global/generic load atomic/ atomicrmw-with-return-value 之後發生,其記憶體排序為 seq_cst 且同步範圍相等或更寬。(請注意,seq_cst fences 有自己的 s_waits,因此無需考慮。)

  • s_wait_storecnt 0x0 必須在先前的 global/generic store atomic/ atomicrmw-no-return-value 之後發生,其記憶體排序為 seq_cst 且同步範圍相等或更寬。(請注意,seq_cst fences 有自己的 s_wait_storecnt 0x0,因此無需考慮。)

  • 確保任何先前的循序一致性全域記憶體指令在執行此循序一致性指令之前已完成。這可防止重新排序 seq_cst store 後面跟著 seq_cst load。(請注意,seq_cst 比 acquire/release 更強,因為 load acquire 後面跟著 store release 的重新排序受到 release 的 s_waits 的阻止,但沒有任何東西阻止 store release 後面跟著 load acquire 從亂序完成。s_waitcnt 可以放在 seq_store 之後或 seq_load 之前。我們選擇 load 是為了使 s_waits 盡可能晚,以便 store 可能已經完成。)

  1. 後續指令與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

載入原子

seq_cst

  • agent

  • system

  • global

  • 通用

  1. s_wait_bvhcnt 0x0
    s_wait_samplecnt 0x0
    s_wait_storecnt 0x0
    s_wait_loadcnt 0x0
    s_wait_dscnt 0x0
  • 若為 OpenCL,則省略 s_wait_dscnt 0x0

  • waits 可以根據以下規則獨立移動

  • s_wait_dscnt 0x0 必須在先前的 local load atomic/store atomic/atomicrmw 之後發生,其記憶體排序為 seq_cst 且同步範圍相等或更寬。(請注意,seq_cst fences 有自己的 s_wait_dscnt 0x0,因此無需考慮。)

  • s_wait_loadcnt 0x0s_wait_samplecnt 0x0s_wait_bvhcnt 0x0 必須在先前的 global/generic load atomic/ atomicrmw-with-return-value 之後發生,其記憶體排序為 seq_cst 且同步範圍相等或更寬。(請注意,seq_cst fences 有自己的 s_waits,因此無需考慮。)

  • s_wait_storecnt 0x0 必須在先前的 global/generic store atomic/ atomicrmw-no-return-value 之後發生,其記憶體排序為 seq_cst 且同步範圍相等或更寬。(請注意,seq_cst fences 有自己的 s_wait_storecnt 0x0,因此無需考慮。)

  • 確保任何先前的循序一致性全域記憶體指令在執行此循序一致性指令之前已完成。這可防止重新排序 seq_cst store 後面跟著 seq_cst load。(請注意,seq_cst 比 acquire/release 更強,因為 load acquire 後面跟著 store release 的重新排序受到 release 的 s_waits 的阻止,但沒有任何東西阻止 store release 後面跟著 load acquire 從亂序完成。s_waits 可以放在 seq_store 之後或 seq_load 之前。我們選擇 load 是為了使 s_waits 盡可能晚,以便 store 可能已經完成。)

  1. 後續指令與對應的載入原子取得相同,但即使對於 OpenCL 也必須產生所有指令。

儲存原子

seq_cst

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

  • global

  • 區域

  • 通用

與對應的儲存原子釋放相同,但即使對於 OpenCL 也必須產生所有指令。

atomicrmw

seq_cst

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

  • global

  • 區域

  • 通用

與對應的 atomicrmw acq_rel 相同,但即使對於 OpenCL 也必須產生所有指令。

柵欄

seq_cst

  • singlethread

  • wavefront

  • workgroup

  • agent

  • system

none

與對應的柵欄 acq_rel 相同,但即使對於 OpenCL 也必須產生所有指令。

Trap Handler ABI

對於由 AMDGPU 後端為 HSA [HSA] 相容執行階段產生的程式碼物件(請參閱 AMDGPU 作業系統),執行階段安裝了一個 trap handler,其支援 s_trap 指令。如需用法,請參閱

  • AMDGPU Trap Handler for AMDHSA OS Code Object V2

  • AMDGPU Trap Handler for AMDHSA OS Code Object V3

  • AMDGPU Trap Handler for AMDHSA OS Code Object V4 及更高版本

    表 85 AMDGPU Trap Handler for AMDHSA OS Code Object V2

    用法

    程式碼序列

    Trap Handler 輸入

    描述

    保留

    s_trap 0x00

    硬體保留。

    debugtrap(arg)

    s_trap 0x01

    SGPR0-1:

    queue_ptr

    VGPR0:

    arg

    保留給 Finalizer HSA debugtrap intrinsic(尚未實作)。

    llvm.trap

    s_trap 0x02

    SGPR0-1:

    queue_ptr

    導致 wave 在 trap 指令處的 PC 停止。相關的佇列會發出訊號以將其置於錯誤狀態。當佇列處於錯誤狀態時,在佇列上執行調度的 waves 將會終止。

    llvm.debugtrap

    s_trap 0x03

    none

    • 如果未啟用偵錯器,則行為如同 no-operation。trap handler 會進入並立即返回以繼續執行 wavefront。

    • 如果已啟用偵錯器,則會導致偵錯器報告 debug trap,並且 wavefront 會在指令處的 PC 進入 halt 狀態。偵錯器必須增加 PC 並恢復 wave。

    保留

    s_trap 0x04

    保留。

    保留

    s_trap 0x05

    保留。

    保留

    s_trap 0x06

    保留。

    保留

    s_trap 0x07

    保留。

    保留

    s_trap 0x08

    保留。

    保留

    s_trap 0xfe

    保留。

    保留

    s_trap 0xff

    保留。

表 86 AMDGPU Trap Handler for AMDHSA OS Code Object V3

用法

程式碼序列

Trap Handler 輸入

描述

保留

s_trap 0x00

硬體保留。

偵錯器中斷點

s_trap 0x01

none

保留供偵錯器用於中斷點。導致 wave 在 trap 指令處的 PC 停止。偵錯器負責恢復 wave,包括中斷點覆寫的指令。

llvm.trap

s_trap 0x02

SGPR0-1:

queue_ptr

導致 wave 在 trap 指令處的 PC 停止。相關的佇列會發出訊號以將其置於錯誤狀態。當佇列處於錯誤狀態時,在佇列上執行調度的 waves 將會終止。

llvm.debugtrap

s_trap 0x03

none

  • 如果未啟用偵錯器,則行為如同 no-operation。trap handler 會進入並立即返回以繼續執行 wavefront。

  • 如果已啟用偵錯器,則會導致偵錯器報告 debug trap,並且 wavefront 會在指令處的 PC 進入 halt 狀態。偵錯器必須增加 PC 並恢復 wave。

保留

s_trap 0x04

保留。

保留

s_trap 0x05

保留。

保留

s_trap 0x06

保留。

保留

s_trap 0x07

保留。

保留

s_trap 0x08

保留。

保留

s_trap 0xfe

保留。

保留

s_trap 0xff

保留。

表 87 AMDGPU Trap Handler for AMDHSA OS Code Object V4 及更高版本

用法

程式碼序列

GFX6-GFX8 輸入

GFX9-GFX11 輸入

描述

保留

s_trap 0x00

硬體保留。

偵錯器中斷點

s_trap 0x01

none

none

保留供偵錯器用於中斷點。導致 wave 在 trap 指令處的 PC 停止。偵錯器負責恢復 wave,包括中斷點覆寫的指令。

llvm.trap

s_trap 0x02

SGPR0-1:

queue_ptr

none

導致 wave 在 trap 指令處的 PC 停止。相關的佇列會發出訊號以將其置於錯誤狀態。當佇列處於錯誤狀態時,在佇列上執行調度的 waves 將會終止。

llvm.debugtrap

s_trap 0x03

none

none

  • 如果未啟用偵錯器,則行為如同 no-operation。trap handler 會進入並立即返回以繼續執行 wavefront。

  • 如果已啟用偵錯器,則會導致偵錯器報告 debug trap,並且 wavefront 會在指令處的 PC 進入 halt 狀態。偵錯器必須增加 PC 並恢復 wave。

保留

s_trap 0x04

保留。

保留

s_trap 0x05

保留。

保留

s_trap 0x06

保留。

保留

s_trap 0x07

保留。

保留

s_trap 0x08

保留。

保留

s_trap 0xfe

保留。

保留

s_trap 0xff

保留。

呼叫慣例

注意

本節目前尚未完成且存在不準確之處。這是 WIP,將在確定資訊後更新。

請參閱 位址空間識別碼 以取得關於 swizzled 位址的資訊。Unswizzled 位址是正常的線性位址。

核心函數

本節描述外部核心函數的呼叫慣例 ABI。

請參閱 初始核心執行狀態 以取得核心呼叫慣例。

以下內容不是 AMDGPU 核心呼叫慣例的一部分,但描述了 AMDGPU 如何實作函數呼叫

  1. Clang 決定 kernarg layout 以符合《HSA Programmer’s Language Reference》[HSA]

    • 所有 structs 都直接傳遞。

    • Lambda 值以 TBA 方式傳遞。

  1. 核心在其序言中執行某些設定,如 核心序言 中所述。

非核心函數

本節描述外部核心函數以外的函數的呼叫慣例 ABI。

如果核心具有函數呼叫,則始終會分配 scratch 並將其用於呼叫堆疊,該堆疊使用 swizzled scratch 位址空間從低位址成長到高位址。

在進入函數時

  1. SGPR0-3 包含具有以下屬性的 V#(請參閱 私有區段 Buffer

    • 指向 wavefront scratch 後備記憶體開頭的基準位址。

    • 以 dword 元素大小和 wavefront size 元素步幅進行 swizzled。

  2. 已設定 FLAT_SCRATCH 暫存器對。請參閱 Flat Scratch

  3. GFX6-GFX8:M0 暫存器設定為 LDS 的大小 (以位元組為單位)。請參閱 M0

  4. EXEC 暫存器設定為進入函數時活動的 lanes。

  5. MODE 暫存器:TBD

  6. VGPR0-31 和 SGPR4-29 用於傳遞函數輸入引數,如下所述。

  7. SGPR30-31 返回位址 (RA)。函數完成時必須返回的程式碼位址。如果函數為 no return,則值未定義。

  8. SGPR32 用於堆疊指標 (SP)。它是相對於 wavefront scratch 後備記憶體開頭的 unswizzled scratch 偏移。

    unswizzled SP 可以與 buffer 指令一起使用,作為具有 SGPR0-3 中 scratch V# 的 unswizzled SGPR 偏移,以 swizzled 方式存取堆疊。

    unswizzled SP 值可以透過以下方式轉換為 swizzled SP 值

    swizzled SP = unswizzled SP / wavefront size

    這可以用於取得堆疊物件的私有位址空間位址,並透過新增 flat scratch aperture 基準位址將此位址轉換為 flat 位址。

    對於 r600 架構,swizzled SP 值始終為 4 位元組對齊,對於 amdgcn 架構,則為 16 位元組對齊。

    注意

    amdgcn 值被選擇為避免 OpenCL 語言的動態堆疊對齊,OpenCL 語言將最大基本類型定義為 16 個位元組。

    在進入時,swizzled SP 值是在堆疊上傳遞的第一個函數引數的位址。其他堆疊傳遞的引數是從進入 swizzled SP 值開始的正偏移量。

    函式可能會使用超出最後一個堆疊傳遞引數的正向偏移量,以用於堆疊配置的區域變數和暫存器溢出槽。如有必要,函式可能會將這些對齊到大於 16 位元組的對齊方式。在這些之後,函式可能會動態分配空間,以用於諸如運行時大小的 alloca 區域分配。

    如果函式呼叫另一個函式,它會將任何堆疊配置的引數放置在最後一個區域分配之後,並調整 SGPR32 至最後一個區域分配之後的位址。

  9. 所有其他暫存器皆未指定。

  10. 任何必要的 s_waitcnt 皆已執行,以確保記憶體可供函式使用。

  11. 在 C ABI 中,結構 (struct) 引數請使用傳參考 (pass-by-reference, byref) 而非傳值 (pass-by-value, byval)。被呼叫者 (Callee) 負責分配堆疊記憶體,並在結構被修改時複製結構的值。請注意,後端 (backend) 仍然支援結構引數的傳值 (byval)。

從函式退出時

  1. VGPR0-31 和 SGPR4-29 用於傳遞函式結果引數,如下所述。任何使用的暫存器都被視為被覆寫 (clobbered) 的暫存器。

  2. 以下暫存器會被保留,並具有與進入時相同的值

    • FLAT_SCRATCH

    • EXEC

    • GFX6-GFX8: M0

    • 除了 SGPR4-31 中被覆寫的暫存器之外,所有 SGPR 暫存器。

    • VGPR40-47

    • VGPR56-63

    • VGPR72-79

    • VGPR88-95

    • VGPR104-111

    • VGPR120-127

    • VGPR136-143

    • VGPR152-159

    • VGPR168-175

    • VGPR184-191

    • VGPR200-207

    • VGPR216-223

    • VGPR232-239

    • VGPR248-255

      注意

      除了引數暫存器之外,被覆寫的 VGPR 和被保留的暫存器會以規律的間隔交錯,以便保持相似的比率,且不受已分配 VGPR 數量的影響。

    • GFX90A: 除了 AGPR0-31 中被覆寫的暫存器之外,所有 AGPR 暫存器。

    • 在呼叫點處非作用中之所有 VGPR 的通道 (Lanes)。

      對於 AMDGPU 後端,程序間暫存器分配 (Inter-Procedural Register Allocation, IPRA) 優化可能會將某些被覆寫的 SGPR 和 VGPR 暫存器標記為已保留,如果可以確定被呼叫的函式不會更改它們的值。

  1. PC 會設定為進入時提供的 RA。

  2. MODE 暫存器:待定

  3. 所有其他暫存器皆被覆寫。

  4. 任何必要的 s_waitcnt 皆已執行,以確保函式存取的記憶體可供呼叫者 (caller) 使用。

函式輸入引數由來源語言函式明確宣告的形式引數,以及實作使用的隱含輸入引數組成。

來源語言輸入引數為

  1. 任何來源語言的隱含 thisself 引數都首先以指標類型出現。

  2. 接著是函式的形式引數,依據來源順序由左至右排列。

來源語言結果引數為

  1. 函式結果引數。

小於或等於 16 位元組的來源語言輸入或結果結構類型引數,會遞迴地分解為其基本類型欄位,並且每個欄位都像獨立的引數一樣傳遞。對於輸入引數,如果被呼叫的函式要求結構位於記憶體中,例如因為要取得其位址,則函式主體負責分配堆疊位置,並將欄位引數複製到其中。Clang 將此稱為直接結構 (direct struct)

大於 16 位元組的來源語言輸入結構類型引數,會以傳參考方式傳遞。呼叫者負責分配堆疊位置以建立結構值的副本,並將位址作為輸入引數傳遞。被呼叫的函式負責在存取輸入引數時執行解參考 (dereference)。Clang 將此稱為傳值結構 (by-value struct)

大於 16 位元組的來源語言結果結構類型引數,會以傳參考方式傳回。呼叫者負責分配堆疊位置以保存結果值,並將位址作為最後一個輸入引數 (在隱含輸入引數之前) 傳遞。在這種情況下,沒有結果引數。被呼叫的函式負責在儲存結果值時執行解參考。Clang 將此稱為結構化返回 (structured return, sret)

待辦事項:更正 ``sret`` 定義。

Lambda 引數類型被視為具有實作定義欄位集的結構類型。

對於 AMDGPU 後端,除非標記為 inreg (在這種情況下,它們會在 SGPR 中傳遞),否則所有來源語言引數 (包括分解的結構類型引數) 都會在 VGPR 中傳遞。

AMDGPU 後端從葉節點開始遍歷函式呼叫圖,以確定使用了哪些隱含輸入引數,並傳播到函式的每個呼叫者。已使用的隱含引數會按照以下順序附加到來源語言引數之後的函式引數中

  1. 工作項目 ID (Work-Item ID) (1 個 VGPR)

    X、Y 和 Z 工作項目 ID 被封裝到具有以下佈局的單個 VGRP 中。僅設定函式實際使用的欄位。其他位元未定義。

    這些值來自初始核心執行狀態。請參閱 初始核心執行狀態

    表 88 工作項目隱含引數佈局

    位元

    大小

    欄位名稱

    9:0

    10 位元

    X 工作項目 ID

    19:10

    10 位元

    Y 工作項目 ID

    29:20

    10 位元

    Z 工作項目 ID

    31:30

    2 位元

    未使用

  2. 分派指標 (Dispatch Ptr) (2 個 SGPR)

    該值來自初始核心執行狀態。請參閱 SGPR 暫存器設定順序

  3. 佇列指標 (Queue Ptr) (2 個 SGPR)

    該值來自初始核心執行狀態。請參閱 SGPR 暫存器設定順序

  4. 核心引數區段指標 (Kernarg Segment Ptr) (2 個 SGPR)

    該值來自初始核心執行狀態。請參閱 SGPR 暫存器設定順序

  5. 分派 ID (Dispatch ID) (2 個 SGPR)

    該值來自初始核心執行狀態。請參閱 SGPR 暫存器設定順序

  6. 工作群組 ID X (Work-Group ID X) (1 個 SGPR)

    該值來自初始核心執行狀態。請參閱 SGPR 暫存器設定順序

  7. 工作群組 ID Y (Work-Group ID Y) (1 個 SGPR)

    該值來自初始核心執行狀態。請參閱 SGPR 暫存器設定順序

  8. 工作群組 ID Z (Work-Group ID Z) (1 個 SGPR)

    該值來自初始核心執行狀態。請參閱 SGPR 暫存器設定順序

  9. 隱含引數指標 (Implicit Argument Ptr) (2 個 SGPR)

    該值是透過將偏移量加到核心引數區段指標 (Kernarg Segment Ptr) 來計算,以取得指向第一個核心引數隱含引數的全域位址空間指標。

輸入和結果引數會依以下方式依序分配

注意

以下描述可能存在一些錯誤和遺漏,需要更正。

  • VGPR 引數會分配給從 VGPR0 開始到 VGPR31 的連續 VGPR。

    如果引數數量超過這些暫存器可以容納的數量,則剩餘的引數會依序分配在堆疊上,並位於自然對齊的位址。

  • SGPR 引數會分配給從 SGPR0 開始到 SGPR29 的連續 SGPR。

    如果引數數量超過這些暫存器可以容納的數量,則剩餘的引數會依序分配在堆疊上,並位於自然對齊的位址。

請注意,分解的結構類型引數可能會有部分欄位在暫存器中傳遞,而部分在記憶體中傳遞。

以下內容並非 AMDGPU 函式呼叫慣例的一部分,而是描述 AMDGPU 如何實作函式呼叫

  1. 如有必要,SGPR33 會用作框架指標 (Frame Pointer, FP)。與 SP 類似,它是一個未混合 (unswizzled) 的 scratch 位址。只有在使用運行時大小的 alloca,或基於 SIFrameLowering 中定義的原因時,才需要它。

  2. 支援運行時堆疊對齊。SGPR34 用作基底指標 (Base Pointer, BP),以存取函式中傳入的堆疊引數。只有當函式需要運行時堆疊對齊時,才需要 BP。

  3. 不支援在堆疊上分配 SGPR 引數。

  4. 目前未產生 CFI。請參閱 A.6.4 呼叫框架資訊

    注意

    將會產生 CFI,其將 CFA 定義為未混合 (unswizzled) 位址,該位址相對於最低位址堆疊配置區域變數之未混合私有位址空間中的 wave scratch 基底。

    DW_AT_frame_base 將定義為混合 (swizzled) 私有位址空間中的混合位址,方法是將 CFA 除以 wavefront 大小 (因為 CFA 始終至少是 dword 對齊,這與 scratch 混合元素大小相符)。

    如果未執行動態堆疊對齊,則堆疊配置的引數會作為相對於 DW_AT_frame_base 的負向偏移量存取,而區域變數和暫存器溢出槽會作為相對於 DW_AT_frame_base 的正向偏移量存取。

  5. 函式引數傳遞的實作方式是在進入時將輸入實體暫存器複製到虛擬暫存器。暫存器分配器可以在必要時溢出 (spill)。這些會在呼叫點處複製回實體暫存器。最終結果是,每次函式呼叫都可能在完全不同的位置擁有這些值。IPRA 可以幫助避免混洗 (shuffling) 引數暫存器。

  6. 呼叫點的實作方式是在相對於 SP 的正向偏移量處設定引數。然後,在呼叫之前遞增 SP 以考慮已知的框架大小,並在呼叫之後遞減 SP。

    注意

    CFI 將反映從 SP 計算 CFA 所需的已變更計算。

  7. 堆疊框架中使用 4 位元組的溢出槽。分配一個槽作為緊急溢出槽。緩衝區指令用於堆疊存取,而不是 flat_scratch 指令。

AMDPAL

本節提供目標三元組 (target triple) OS 為 amdpal 時使用的程式碼慣例 (請參閱 目標三元組)。

程式碼物件元資料 (Code Object Metadata)

注意

元資料目前正在開發中,並且可能會進行重大變更。僅支援目前版本。當產生此文件時,版本為 2.6。

程式碼物件元資料由 NT_AMDGPU_METADATA 註記記錄指定 (請參閱 程式碼物件 V3 及更高版本註記記錄)。

元資料表示為 Message Pack 格式化的二進制資料 (請參閱 [MsgPack])。頂層是一個 Message Pack 映射 (map),其中包含表 AMDPAL 程式碼物件元資料映射 和參考表格中定義的鍵 (keys)。

其他資訊可以添加到映射中。為避免衝突,任何金鑰名稱都應以 “vendor-name.” 為前綴,其中 vendor-name 可以是供應商名稱和產生資訊的特定供應商工具的名稱。當前綴出現在由同一 vendor-name 添加的映射中時,前綴簡稱為 “.”。

表 89 AMDPAL 程式碼物件元資料映射

字串金鑰 (String Key)

值類型 (Value Type)

是否必填?

描述

“amdpal.version”

2 個整數的序列 (sequence)

必填

PAL 程式碼物件元資料 (主要、次要) 版本。目前值由 Util::Abi::PipelineMetadata(Major|Minor)Version 定義。

“amdpal.pipelines”

映射序列

必填

每個管線 (pipeline) 的元資料。有關該映射中包含的鍵的定義,請參閱 AMDPAL 程式碼物件管線元資料映射

表 90 AMDPAL 程式碼物件管線元資料映射

字串金鑰 (String Key)

值類型 (Value Type)

是否必填?

描述

“.name” (名稱)

字串

管線的來源名稱。

“.type”

字串

管線類型,例如 VsPs。值包括

  • “VsPs”

  • “Gs”

  • “Cs”

  • “Ngg”

  • “Tess”

  • “GsTess”

  • “NggTess”

“.internal_pipeline_hash”

2 個整數的序列 (sequence)

必填

此管線的內部編譯器雜湊值。較低的 64 位元是雜湊的「穩定」部分,用於例如著色器替換查找。較高的 64 位元是雜湊的「唯一」部分,用於例如管線快取查找。該值由實作定義,並且不能在編譯器的不同建置版本之間依賴。

“.shaders”

映射 (map)

每個 API 著色器 (shader) 的元資料。有關該映射中包含的鍵的定義,請參閱 AMDPAL 程式碼物件著色器映射

“.hardware_stages”

映射 (map)

每個硬體階段 (hardware stage) 的元資料。有關該映射中包含的鍵的定義,請參閱 AMDPAL 程式碼物件硬體階段映射

“.shader_functions”

映射 (map)

每個著色器函式 (shader function) 的元資料。有關該映射中包含的鍵的定義,請參閱 AMDPAL 程式碼物件著色器函式映射

“.registers”

映射 (map)

必填

硬體暫存器配置。有關該映射中包含的鍵的定義,請參閱 AMDPAL 程式碼物件暫存器映射

“.user_data_limit”

整數

此管線存取的使用者資料條目 (user data entries) 數量。

“.spill_threshold”

整數

使用者資料溢出閾值 (user data spill threshold)。0xFFFF 表示 NoUserDataSpilling。

“.uses_viewport_array_index”

布林值

指示管線是否使用視口陣列索引 (viewport array index) 功能。使用此功能的管線可以渲染到所有 16 個視口,而不使用此功能的管線則限制為視口 #0。

“.es_gs_lds_size”

整數

內部用於處理 ES 和 GS 著色器階段之間資料傳遞的 LDS 空間大小 (以位元組為單位)。如果資料是使用晶片外 (off-chip) 緩衝區傳遞的,則此值可以為零。此值應用於程式設計所有標記為 “UserDataMapping::EsGsLdsSize” 的 user-SGPR (通常只有 GS 和 VS HW 階段會有如此標記的 user-SGPR)。

“.nggSubgroupSize”

整數

NGG 著色器的明確最大子群組大小 (subgroup size) (子群組中的最大執行緒數)。

“.num_interpolants”

整數

僅限圖形。PS 插值器 (interpolants) 的數量。

“.mesh_scratch_memory_size”

整數

使用的最大網格著色器 (mesh shader) scratch 記憶體。

“.api”

字串

客戶端圖形 API 的名稱。

“.api_create_info”

二進制 (binary)

圖形 API 著色器建立資訊二進制 blob。如果驅動程式想要能夠在稍後關聯建立期間使用的 API 特定資訊,則可以使用編譯器定義它。

表 91 AMDPAL 程式碼物件著色器映射

字串金鑰 (String Key)

值類型 (Value Type)

描述

  • “.compute”

  • “.vertex”

  • “.hull”

  • “.domain”

  • “.geometry”

  • “.pixel”

映射 (map)

有關該映射中包含的鍵的定義,請參閱 AMDPAL 程式碼物件 API 著色器元資料映射

表 92 AMDPAL 程式碼物件 API 著色器元資料映射

字串金鑰 (String Key)

值類型 (Value Type)

是否必填?

描述

“.api_shader_hash”

2 個整數的序列 (sequence)

必填

輸入著色器雜湊值,通常從客戶端傳入。該值由實作定義,並且不能在編譯器的不同建置版本之間依賴。

“.hardware_mapping”

字串序列

必填

標記,指示此 API 著色器映射到的 HW 階段。值包括

  • “.ls”

  • “.hs”

  • “.es”

  • “.gs”

  • “.vs”

  • “.ps”

  • “.cs”

表 93 AMDPAL 程式碼物件硬體階段映射

字串金鑰 (String Key)

值類型 (Value Type)

描述

  • “.ls”

  • “.hs”

  • “.es”

  • “.gs”

  • “.vs”

  • “.ps”

  • “.cs”

映射 (map)

有關該映射中包含的鍵的定義,請參閱 AMDPAL 程式碼物件硬體階段元資料映射

表 94 AMDPAL 程式碼物件硬體階段元資料映射

字串金鑰 (String Key)

值類型 (Value Type)

是否必填?

描述

“.entry_point”

字串

指向此管線階段進入點的 ELF 符號。

“.scratch_memory_size”

整數

Scratch 記憶體大小,以位元組為單位。

“.lds_size”

整數

本地資料共享 (Local Data Share) 大小,以位元組為單位。

“.perf_data_buffer_size”

整數

效能資料緩衝區大小,以位元組為單位。

“.vgpr_count” (VGPR 數量)

整數

使用的 VGPR 數量。

“.agpr_count” (AGPR 數量)

整數

使用的 AGPR 數量。

“.sgpr_count” (SGPR 數量)

整數

使用的 SGPR 數量。

“.vgpr_limit”

整數

如果非零,則表示著色器在編譯時使用了指令,指示編譯器將 VGPR 使用量限制為小於或等於指定值 (僅在與 HW 預設值不同時設定)。

“.sgpr_limit”

整數

SGPR 計數上限 (僅在與 HW 預設值不同時設定)。

“.threadgroup_dimensions”

3 個整數的序列

執行緒群組 (Thread-group) X/Y/Z 維度 (僅限計算)。

“.wavefront_size” (波前大小)

整數

Wavefront 大小 (僅在與 HW 預設值不同時設定)。

“.uses_uavs”

布林值

著色器讀取或寫入 UAV。

“.uses_rovs”

布林值

著色器讀取或寫入 ROV。

“.writes_uavs”

布林值

著色器寫入一個或多個 UAV。

“.writes_depth”

布林值

著色器寫出深度值。

“.uses_append_consume”

布林值

著色器使用 append 和/或 consume 操作,無論是記憶體還是 GDS。

“.uses_prim_id”

布林值

著色器使用 PrimID。

表 95 AMDPAL 程式碼物件著色器函式映射

字串金鑰 (String Key)

值類型 (Value Type)

描述

符號名稱

映射 (map)

符號名稱 是著色器函式程式碼進入位址的 ELF 符號名稱。該值是函式的元資料。請參閱 AMDPAL 程式碼物件著色器函式元資料映射

表 96 AMDPAL 程式碼物件著色器函式元資料映射

字串金鑰 (String Key)

值類型 (Value Type)

描述

“.api_shader_hash”

2 個整數的序列 (sequence)

輸入著色器雜湊值,通常從客戶端傳入。該值由實作定義,並且不能在編譯器的不同建置版本之間依賴。

“.scratch_memory_size”

整數

著色器使用的 scratch 記憶體大小,以位元組為單位。

“.lds_size”

整數

LDS 記憶體大小,以位元組為單位。

“.vgpr_count” (VGPR 數量)

整數

著色器使用的 VGPR 數量。

“.sgpr_count” (SGPR 數量)

整數

著色器使用的 SGPR 數量。

“.stack_frame_size_in_bytes”

整數

著色器使用的堆疊大小量。

“.shader_subtype”

字串

著色器子類型/種類。值包括

  • “Unknown”

表 97 AMDPAL 程式碼物件暫存器映射

32 位元整數鍵

值類型 (Value Type)

描述

reg offset

32 位元整數

reg offset 是 GRBM 暫存器的 dword 偏移量,位於 GFXIP 暫存器空間中 (即,驅動程式可存取的 GPU 暫存器編號,而非著色器 GPR 暫存器編號)。驅動程式需要在執行此管線時,將每個指定的暫存器程式設計為對應的指定值。通常,reg offsets 是硬體晶片標頭定義的每個暫存器的 uint16_t 偏移量。暫存器會設定為提供的值。但是,指定使用者資料暫存器 (例如,COMPUTE_USER_DATA_0) 的 reg offset 需要特殊處理。有關更多資訊,請參閱 使用者資料 節。

使用者資料 (User Data)

每個硬體階段都有一組 32 位元實體 SPI 使用者資料暫存器 (根據圖形 IP 和階段,可以是 16 個或 32 個),這些暫存器可以從命令緩衝區寫入,然後在透過後續分派或繪圖操作啟動 wave 時載入到 SGPR 中。這是將大多數引數從應用程式/運行時傳遞到硬體著色器的方式。

PAL 透過公開每個管線一組 128 個使用者資料條目來抽象化此功能,客戶端可以使用這些條目將引數從命令緩衝區傳遞到該管線中的一個或多個著色器。ELF 程式碼物件必須指定從虛擬化使用者資料條目到實體使用者資料暫存器的映射,而 PAL 負責實作該映射,包括在需要時將溢出的使用者資料條目溢出到記憶體。

由於使用者資料暫存器是 GRBM 可存取的 SPI 暫存器,因此此映射實際上嵌入在 .registers 元資料條目中。對於大多數暫存器,該映射中的值是一個字面 32 位元值,應由驅動程式寫入到暫存器中。但是,當暫存器是使用者資料暫存器 (任何 USER_DATA 暫存器,例如 SPI_SHADER_USER_DATA_PS_5) 時,該值實際上是一個編碼,告訴驅動程式將使用者資料條目值或幾個驅動程式內部值之一寫入到暫存器中。此編碼在下表中描述

注意

目前,使用者資料暫存器 0 和 1 (例如,SPI_SHADER_USER_DATA_PS_0 和 SPI_SHADER_USER_DATA_PS_1) 已保留。使用者資料暫存器 0 必須始終程式設計為 GlobalTable 的位址,而使用者資料暫存器 1 必須始終程式設計為 PerShaderTable 的位址。

表 98 AMDPAL 使用者資料映射

名稱

描述

0..127

使用者資料條目 (User Data Entry)

透過 CmdSetUserData() 指定的 user_data_entry[N] 的 32 位元值

0x10000000

GlobalTable

指向 GPU 記憶體的 32 位元指標,其中包含全域內部表 (應始終指向使用者資料暫存器 0)。

0x10000001

PerShaderTable

指向 GPU 記憶體的 32 位元指標,其中包含每個著色器的內部表。有關更多詳細資訊,請參閱 每個著色器表 (應始終指向使用者資料暫存器 1)。

0x10000002

SpillTable

指向 GPU 記憶體的 32 位元指標,其中包含使用者資料溢出表。有關更多詳細資訊,請參閱 溢出表

0x10000003

BaseVertex

頂點偏移量 (Vertex offset) (32 位元無號整數)。如果管線未在頂點著色器中參考繪圖索引,則不需要。僅圖形管線的第一階段支援。

0x10000004

BaseInstance

實例偏移量 (Instance offset) (32 位元無號整數)。僅圖形管線的第一階段支援。

0x10000005

DrawIndex

繪圖索引 (Draw index) (32 位元無號整數)。僅圖形管線的第一階段支援。

0x10000006

Workgroup

執行緒群組計數 (Thread group count) (32 位元無號整數)。包含 Compute 分派操作網格維度的緩衝區之 64 位元位址的低半部分。位址的高半部分儲存在下一個循序 user-SGPR 中。僅計算管線支援。

0x1000000A

EsGsLdsSize

指示 PAL 將程式設計此 user-SGPR 以包含用於 ES/GS 偽環形緩衝區的 LDS 空間量,以便在著色器階段之間傳遞資料。

0x1000000B

ViewId

視圖 ID (View id) (32 位元無號整數) 識別圖形管線實例化的視圖。

0x1000000C

StreamOutTable

指向 GPU 記憶體的 32 位元指標,其中包含 stream out 目標 SRD 表。每個管線只能出現一個著色器階段。

0x1000000D

PerShaderPerfData

指向 GPU 記憶體的 32 位元指標,其中包含每個著色器的效能資料緩衝區。

0x1000000F

VertexBufferTable

指向 GPU 記憶體的 32 位元指標,其中包含頂點緩衝區 SRD 表。每個管線只能出現一個著色器階段。

0x10000010

UavExportTable

指向 GPU 記憶體的 32 位元指標,其中包含 UAV 匯出 SRD 表。每個管線只能出現一個著色器階段 (PS)。這些取代顏色目標,並且與著色器使用的任何 UAV 完全分離。這是可選的,僅當使用 UAV 匯出取代顏色目標匯出以優化特定著色器時,才由 PS 使用。

0x10000011

NggCullingData

指向 GPU 記憶體的 64 位元指標,其中包含某些 NGG 管線執行剔除 (culling) 所需的硬體暫存器資料。此值包含提供完整 GPU 位址的兩個連續暫存器中的第一個的位址。

0x10000015

FetchShaderPtr

指向 GPU 記憶體的 64 位元指標,其中包含 fetch shader 副程式。

每個著色器表 (Per-Shader Table)

ELF 的 .data 區段中可選緩衝區的 GPU 位址的低 32 位元。位址的高 32 位元與著色器的程式計數器的高 32 位元相符。

緩衝區可以是著色器編譯器所需的任何內容,並允許每個著色器擁有自己的 .data 區段區域。通常,這可以是緩衝區 SRD 的表和緩衝區 SRD 指向的資料,但也可能是平坦位址 (flat-address) 的記憶體區域。其佈局和用法由著色器編譯器定義。

每個著色器在 .data 區段中的表都由符號 _amdgpu_xs_shdr_intrl_data 參考,其中 xs 對應於資料所屬的硬體著色器階段。例如,計算著色器硬體階段的 _amdgpu_cs_shdr_intrl_data

溢出表 (Spill Table)

硬體著色器可能需要存取比一個或多個硬體著色器階段的使用者資料暫存器中可用槽更多的使用者資料條目。在這種情況下,PAL 運行時預期必要的使用者資料條目會溢出到 GPU 記憶體,並使用一個使用者資料暫存器指向溢出的使用者資料記憶體。然後,使用者資料條目的值必須表示著色器預期讀取表的 GPU 虛擬位址的低 32 位元的位置。溢出表本身表示 PAL 運行時在 GPU 可存取記憶體中管理的一組 32 位元值,這些值可以間接存取硬體著色器。

未指定的 OS (Unspecified OS)

本節提供目標三元組 OS 為空時使用的程式碼慣例 (請參閱 目標三元組)。

陷阱處理常式 ABI (Trap Handler ABI)

對於 AMDGPU 後端為非 amdhsa OS 產生的程式碼物件,運行時不會安裝陷阱處理常式。llvm.trapllvm.debugtrap 指令的處理方式如下

表 99 非 AMDHSA OS 的 AMDGPU 陷阱處理常式

用法

程式碼序列

描述

llvm.trap

s_endpgm

導致 wavefront 終止。

llvm.debugtrap

none

由於未安裝陷阱處理常式,因此發出編譯器警告。

核心檔案格式 (Core file format)

本節描述支援 AMDGPU 的核心檔案格式。AMDGPU 程式的核心轉儲 (core dumps) 可以分為 2 種:分割或統一核心檔案。

分割佈局由一個主機核心檔案 (host core file) 組成,其中包含重建主機進程映像的資訊;以及一個 AMDGPU 核心檔案,其中包含進程中使用的 AMDGPU agent 的資訊。AMDGPU 核心檔案由以下組成

  • 描述進程的 AMDGPU agent、AMDGPU 佇列和 AMDGPU 運行時狀態的註記 (請參閱 核心檔案註記)。

  • 包含 AMDGPU agent 記憶體映像的載入區段 (load segments) 列表 (請參閱 記憶體區段)。

統一核心檔案是分割佈局的兩個檔案中包含的所有資訊 (所有註記和載入區段) 的聯集。它包含重建跨所有 agent 的進程映像所需的所有資訊。

核心檔案標頭

AMDGPU 核心檔案是一種 ELF64 核心檔案。標頭的內容在統一核心檔案佈局和 AMDGPU 核心檔案佈局中有所不同。

分割檔案

在分割檔案佈局中,AMDGPU 核心檔案是一個 ELF64 檔案,其標頭配置如AMDGPU 核心檔案標頭中所述

表 100 AMDGPU 核心檔案標頭

欄位

e_ident[EI_CLASS]

ELFCLASS64 (0x2)

e_ident[EI_DATA]

ELFDATA2LSB (0x1)

e_ident[EI_OSABI]

ELFOSABI_AMDGPU_HSA (0x40)

e_type

ET_CORE``(``0x4)

e_ident[EI_ABIVERSION]

ELFABIVERSION_AMDGPU_HSA_5

e_machine

EM_AMDGPU (0xe0)

統一檔案

在統一核心檔案模式下,ELF64 標頭設定為描述主機架構和程序。

核心檔案註記

AMDGPU 核心檔案必須在 PT_NOTE 段中包含一個快照註記。當使用分割核心檔案佈局時,此註記位於 AMDGPU 檔案中。

註記記錄供應商欄位為 “AMDGPU”,記錄類型為 “NT_AMDGPU_KFD_CORE_STATE”(請參閱程式碼物件 V3 及更高版本的註記記錄

註記的內容在表AMDGPU 快照註記格式 V1中定義

表 101 AMDGPU 快照註記格式 V1

欄位

類型

大小 (位元組)

位元組對齊

註解

version_major

uint32

4

4

KFD_IOCTL_MAJOR_VERSION

version_minor

uint32

4

4

KFD_IOCTL_MINOR_VERSION

runtime_info_size

uint64

8

8

必須是 8 的倍數

n_agents

uint32

4

8

agent_info_entry_size

uint32

4

4

必須是 8 的倍數

n_queues

uint32

4

8

queue_info_entry_size

uint32

4

4

必須是 8 的倍數

runtime_info

kfd_runtime_info

runtime_info_size

8

agents_info

kfd_dbg_device_info_entry[n_agents]

n_agents * agent_info_entry_size

8

queues_info

kfd_queue_snapshot_entry[n_queues]

n_queues * queue_info_entry_size

8

所有 kfd_* 類型的定義都來自 KFD 儲存庫中的 include/uapi/linux/kfd_ioctl.h 標頭檔。它通常安裝在 /usr/include/linux/kfd_ioctl.h 中。使用的 kfd_ioctl.h 檔案版本必須為 KFD_IOCTL_MAJOR_VERSIONKFD_IOCTL_MINOR_VERSION 定義值,以符合註記中的 kfd_version_majorkfd_version_major 值。

記憶體段

AMDGPU 核心檔案必須在載入段(類型為 PT_LOAD)中包含 AMDGPU 代理程式記憶體的映像。這些段必須對應於代理程式記憶體的內容透過 ROCr 執行階段對應到主機程序的記憶體區域(請注意,這些記憶體對應通常對於程序本身是不可讀取的)。

當使用分割核心檔案佈局時,這些段必須包含在 AMDGPU 核心檔案中。

原始碼語言

OpenCL

當語言為 OpenCL 時,會發生以下差異

  1. 使用 OpenCL 記憶體模型(請參閱記憶體模型)。

  2. AMDGPU 後端會為 AMDHSA 作業系統將額外的引數附加到核心的顯式引數中(請參閱為 AMDHSA 作業系統附加的 OpenCL 核心隱式引數)。

  3. 產生額外的元數據(請參閱程式碼物件元數據)。

表 102 為 AMDHSA 作業系統附加的 OpenCL 核心隱式引數

位置

位元組大小

位元組對齊

描述

1

8

8

OpenCL 全域偏移 X

2

8

8

OpenCL 全域偏移 Y

3

8

8

OpenCL 全域偏移 Z

4

8

8

printf 緩衝區的 OpenCL 位址

5

8

8

enqueue_kernel 使用的虛擬佇列的 OpenCL 位址。

6

8

8

enqueue_kernel 使用的 AqlWrap 結構的 OpenCL 位址。

7

8

8

用於多網格同步的指標引數。

HCC

當語言為 HCC 時,會發生以下差異

  1. 使用 HSA 記憶體模型(請參閱記憶體模型)。

組譯器

AMDGPU 後端具有基於 LLVM-MC 的組譯器,目前正在開發中。它支援 AMDGCN GFX6-GFX11。

本節介紹指令和運算元的一般語法。

指令

指令具有以下語法

<opcode> <operand0>, <operand1>,... <modifier0> <modifier1>...

運算元以逗號分隔,而修飾符以空格分隔。

運算元和修飾符的順序是固定的。大多數修飾符是可選的,可以省略。

詳細指令語法描述的連結可以在下表中找到。請注意,開發中的功能不包含在此描述中。

架構

核心 ISA

ISA 變體和擴充功能

GCN 2

GFX7

-

GCN 3, GCN 4

GFX8

-

GCN 5

GFX9

gfx900

gfx902

gfx904

gfx906

gfx909

gfx90c

CDNA 1

GFX9

gfx908

CDNA 2

GFX9

gfx90a

CDNA 3

GFX9

gfx942

RDNA 1

GFX10 RDNA1

gfx1010

gfx1011

gfx1012

gfx1013

RDNA 2

GFX10 RDNA2

gfx1030

gfx1031

gfx1032

gfx1033

gfx1034

gfx1035

gfx1036

RDNA 3

GFX11

gfx1100

gfx1101

gfx1102

gfx1103

有關指令、其語義和支援的運算元組合的更多資訊,請參閱指令集架構手冊[AMD-GCN-GFX6][AMD-GCN-GFX7][AMD-GCN-GFX8][AMD-GCN-GFX900-GFX904-VEGA][AMD-GCN-GFX906-VEGA7NM][AMD-GCN-GFX908-CDNA1][AMD-GCN-GFX90A-CDNA2][AMD-GCN-GFX942-CDNA3][AMD-GCN-GFX10-RDNA1][AMD-GCN-GFX10-RDNA2][AMD-GCN-GFX11-RDNA3][AMD-GCN-GFX11-RDNA3.5]

運算元

運算元的詳細描述可以在此處找到。

修飾符

修飾符的詳細描述可以在此處找到。

指令範例

DS
ds_add_u32 v2, v4 offset:16
ds_write_src2_b64 v2 offset0:4 offset1:8
ds_cmpst_f32 v2, v4, v6
ds_min_rtn_f64 v[8:9], v2, v[4:5]

有關支援指令的完整列表,請參閱 ISA 手冊中的「LDS/GDS 指令」。

FLAT
flat_load_dword v1, v[3:4]
flat_store_dwordx3 v[3:4], v[5:7]
flat_atomic_swap v1, v[3:4], v5 glc
flat_atomic_cmpswap v1, v[3:4], v[5:6] glc slc
flat_atomic_fmax_x2 v[1:2], v[3:4], v[5:6] glc

有關支援指令的完整列表,請參閱 ISA 手冊中的「FLAT 指令」。

MUBUF
buffer_load_dword v1, off, s[4:7], s1
buffer_store_dwordx4 v[1:4], v2, ttmp[4:7], s1 offen offset:4 glc tfe
buffer_store_format_xy v[1:2], off, s[4:7], s1
buffer_wbinvl1
buffer_atomic_inc v1, v2, s[8:11], s4 idxen offset:4 slc

有關支援指令的完整列表,請參閱 ISA 手冊中的「MUBUF 指令」。

SMRD/SMEM
s_load_dword s1, s[2:3], 0xfc
s_load_dwordx8 s[8:15], s[2:3], s4
s_load_dwordx16 s[88:103], s[2:3], s4
s_dcache_inv_vol
s_memtime s[4:5]

有關支援指令的完整列表,請參閱 ISA 手冊中的「純量記憶體操作」。

SOP1
s_mov_b32 s1, s2
s_mov_b64 s[0:1], 0x80000000
s_cmov_b32 s1, 200
s_wqm_b64 s[2:3], s[4:5]
s_bcnt0_i32_b64 s1, s[2:3]
s_swappc_b64 s[2:3], s[4:5]
s_cbranch_join s[4:5]

有關支援指令的完整列表,請參閱 ISA 手冊中的「SOP1 指令」。

SOP2
s_add_u32 s1, s2, s3
s_and_b64 s[2:3], s[4:5], s[6:7]
s_cselect_b32 s1, s2, s3
s_andn2_b32 s2, s4, s6
s_lshr_b64 s[2:3], s[4:5], s6
s_ashr_i32 s2, s4, s6
s_bfm_b64 s[2:3], s4, s6
s_bfe_i64 s[2:3], s[4:5], s6
s_cbranch_g_fork s[4:5], s[6:7]

有關支援指令的完整列表,請參閱 ISA 手冊中的「SOP2 指令」。

SOPC
s_cmp_eq_i32 s1, s2
s_bitcmp1_b32 s1, s2
s_bitcmp0_b64 s[2:3], s4
s_setvskip s3, s5

有關支援指令的完整列表,請參閱 ISA 手冊中的「SOPC 指令」。

SOPP
s_barrier
s_nop 2
s_endpgm
s_waitcnt 0 ; Wait for all counters to be 0
s_waitcnt vmcnt(0) & expcnt(0) & lgkmcnt(0) ; Equivalent to above
s_waitcnt vmcnt(1) ; Wait for vmcnt counter to be 1.
s_sethalt 9
s_sleep 10
s_sendmsg 0x1
s_sendmsg sendmsg(MSG_INTERRUPT)
s_trap 1

有關支援指令的完整列表,請參閱 ISA 手冊中的「SOPP 指令」。

除非另有說明,否則 SOPP 指令的運算元幾乎不進行驗證,因此程式設計人員應熟悉可接受值的範圍。

VALU

對於向量 ALU 指令運算碼(VOP1、VOP2、VOP3、VOPC、VOP_DPP、VOP_SDWA),組譯器將根據其運算元自動使用最佳編碼。若要強制使用特定編碼,可以將後綴添加到指令的運算碼中

  • _e32 用於 32 位元 VOP1/VOP2/VOPC

  • _e64 用於 64 位元 VOP3

  • _dpp 用於 VOP_DPP

  • _e64_dpp 用於帶 DPP 的 VOP3

  • _sdwa 用於 VOP_SDWA

VOP1/VOP2/VOP3/VOPC 範例

v_mov_b32 v1, v2
v_mov_b32_e32 v1, v2
v_nop
v_cvt_f64_i32_e32 v[1:2], v2
v_floor_f32_e32 v1, v2
v_bfrev_b32_e32 v1, v2
v_add_f32_e32 v1, v2, v3
v_mul_i32_i24_e64 v1, v2, 3
v_mul_i32_i24_e32 v1, -3, v3
v_mul_i32_i24_e32 v1, -100, v3
v_addc_u32 v1, s[0:1], v2, v3, s[2:3]
v_max_f16_e32 v1, v2, v3

VOP_DPP 範例

v_mov_b32 v0, v0 quad_perm:[0,2,1,1]
v_sin_f32 v0, v0 row_shl:1 row_mask:0xa bank_mask:0x1 bound_ctrl:0
v_mov_b32 v0, v0 wave_shl:1
v_mov_b32 v0, v0 row_mirror
v_mov_b32 v0, v0 row_bcast:31
v_mov_b32 v0, v0 quad_perm:[1,3,0,1] row_mask:0xa bank_mask:0x1 bound_ctrl:0
v_add_f32 v0, v0, |v0| row_shl:1 row_mask:0xa bank_mask:0x1 bound_ctrl:0
v_max_f16 v1, v2, v3 row_shl:1 row_mask:0xa bank_mask:0x1 bound_ctrl:0

VOP3_DPP 範例(適用於 GFX11+)

v_add_f32_e64_dpp v0, v1, v2 dpp8:[0,1,2,3,4,5,6,7]
v_sqrt_f32_e64_dpp v0, v1 row_shl:1 row_mask:0xa bank_mask:0x1 bound_ctrl:0
v_ldexp_f32 v0, v1, v2 dpp8:[0,1,2,3,4,5,6,7]

VOP_SDWA 範例

v_mov_b32 v1, v2 dst_sel:BYTE_0 dst_unused:UNUSED_PRESERVE src0_sel:DWORD
v_min_u32 v200, v200, v1 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:DWORD
v_sin_f32 v0, v0 dst_unused:UNUSED_PAD src0_sel:WORD_1
v_fract_f32 v0, |v0| dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1
v_cmpx_le_u32 vcc, v1, v2 src0_sel:BYTE_2 src1_sel:WORD_0

有關支援指令的完整列表,請參閱「向量 ALU 指令」。

程式碼物件 V2 預定義符號

警告

此版本的 LLVM 不再支援程式碼物件 V2 生成。

AMDGPU 組譯器會自動定義和更新某些符號。這些符號不會影響程式碼產生。

.option.machine_version_major

設定為正在組譯的目標的 GFX 主要世代編號。例如,當為「GFX9」目標組譯時,這將設定為整數值「9」。可能的 GFX 主要世代編號在處理器中呈現。

.option.machine_version_minor

設定為正在組譯的目標的 GFX 次要世代編號。例如,當為「GFX810」目標組譯時,這將設定為整數值「1」。可能的 GFX 次要世代編號在處理器中呈現。

.option.machine_version_stepping

設定為正在組譯的目標的 GFX 步進世代編號。例如,當為「GFX704」目標組譯時,這將設定為整數值「4」。可能的 GFX 步進世代編號在處理器中呈現。

.kernel.vgpr_count

每次遇到 .amdgpu_hsa_kernel (名稱) 指令時,都會設定為零。在每個指令中,如果此符號的目前值小於或等於該指令中明確引用的最大 VGPR 編號,則符號值會更新為等於該 VGPR 編號加一。

.kernel.sgpr_count

每次遇到 .amdgpu_hsa_kernel (名稱) 指令時,都會設定為零。在每個指令中,如果此符號的目前值小於或等於該指令中明確引用的最大 VGPR 編號,則符號值會更新為等於該 SGPR 編號加一。

程式碼物件 V2 指令

警告

此版本的 LLVM 不再支援程式碼物件 V2 生成。

AMDGPU ABI 在輸出程式碼物件中定義輔助資料。在組譯原始碼中,可以使用組譯器指令指定它們。

.hsa_code_object_version major, minor

majorminor 是整數,用於指定組譯器將產生的 HSA 程式碼物件的版本。

.hsa_code_object_isa [major, minor, stepping, vendor, arch]

majorminorstepping 都是描述組譯程式的指令集架構 (ISA) 版本的整數。

vendorarch 是帶引號的字串。vendor 應始終等於 “AMD”,而 arch 應始終等於 “AMDGPU”。

預設情況下,組譯器將從傳遞給組譯器的 -mcpu 選項的值中衍生 ISA 版本、vendorarch

.amdgpu_hsa_kernel (name)

此指令指定具有給定名稱的符號是核心進入點(標籤),並且物件應包含 STT_AMDGPU_HSA_KERNEL 類型的對應符號。

.amd_kernel_code_t

此指令標記用於指定組譯器將發出的 amd_kernel_code_t 物件的鍵/值對列表的開始。列表必須以 .end_amd_kernel_code_t 指令終止。對於任何未指定的 amd_kernel_code_t 值,將使用預設值。所有鍵的預設值為 0,但以下例外

  • amd_code_version_major 預設為 1。

  • amd_kernel_code_version_minor 預設為 2。

  • amd_machine_kind 預設為 1。

  • amd_machine_version_majormachine_version_minoramd_machine_version_stepping 是從傳遞給組譯器的 -mcpu 選項的值衍生的。

  • kernel_code_entry_byte_offset 預設為 256。

  • wavefront_size 在 GFX10 之前的所有目標預設為 6。對於 GFX10 及更高版本,如果目標功能 wavefrontsize64 已啟用,則預設為 6,否則為 5。請注意,wavefront 大小指定為 2 的冪,因此值 n 表示大小為 2^ n

  • call_convention 預設為 -1。

  • kernarg_segment_alignmentgroup_segment_alignmentprivate_segment_alignment 預設為 4。請注意,對齊方式指定為 2 的冪,因此值 n 表示對齊方式為 2^ n

  • 如果 GFX90A 及更高版本的目標功能 tgsplit 已啟用,則 enable_tg_split 預設為 1。

  • 如果 GFX10 及更高版本的目標功能 cumode 已停用,則 enable_wgp_mode 預設為 1。

  • 對於 GFX10 及更高版本,enable_mem_ordered 預設為 1。

.amd_kernel_code_t 指令必須緊接在函數標籤之後和任何指令之前放置。

有關 amd_kernel_code_t 鍵的完整列表,請參閱 AMDGPU ABI 文件、lib/Target/AMDGPU/AmdKernelCodeT.h 中的註解和 test/CodeGen/AMDGPU/hsa.s。

程式碼物件 V2 範例原始碼

警告

此版本的 LLVM 不再支援程式碼物件 V2 生成。

以下是一個最小組譯原始碼檔案的範例,定義了一個 HSA 核心

 1.hsa_code_object_version 1,0
 2.hsa_code_object_isa
 3
 4.hsatext
 5.globl  hello_world
 6.p2align 8
 7.amdgpu_hsa_kernel hello_world
 8
 9hello_world:
10
11   .amd_kernel_code_t
12      enable_sgpr_kernarg_segment_ptr = 1
13      is_ptr64 = 1
14      compute_pgm_rsrc1_vgprs = 0
15      compute_pgm_rsrc1_sgprs = 0
16      compute_pgm_rsrc2_user_sgpr = 2
17      compute_pgm_rsrc1_wgp_mode = 0
18      compute_pgm_rsrc1_mem_ordered = 0
19      compute_pgm_rsrc1_fwd_progress = 1
20  .end_amd_kernel_code_t
21
22  s_load_dwordx2 s[0:1], s[0:1] 0x0
23  v_mov_b32 v0, 3.14159
24  s_waitcnt lgkmcnt(0)
25  v_mov_b32 v1, s0
26  v_mov_b32 v2, s1
27  flat_store_dword v[1:2], v0
28  s_endpgm
29.Lfunc_end0:
30     .size   hello_world, .Lfunc_end0-hello_world

程式碼物件 V3 及更高版本預定義符號

AMDGPU 組譯器會自動定義和更新某些符號。這些符號不會影響程式碼產生。

.amdgcn.gfx_generation_number

設定為正在組譯的目標的 GFX 主要世代編號。例如,當為「GFX9」目標組譯時,這將設定為整數值「9」。可能的 GFX 主要世代編號在處理器中呈現。

.amdgcn.gfx_generation_minor

設定為正在組譯的目標的 GFX 次要世代編號。例如,當為「GFX810」目標組譯時,這將設定為整數值「1」。可能的 GFX 次要世代編號在處理器中呈現。

.amdgcn.gfx_generation_stepping

設定為正在組譯的目標的 GFX 步進世代編號。例如,當為「GFX704」目標組譯時,這將設定為整數值「4」。可能的 GFX 步進世代編號在處理器中呈現。

.amdgcn.next_free_vgpr

在組譯開始之前設定為零。在每個指令中,如果此符號的目前值小於或等於該指令中明確引用的最大 VGPR 編號,則符號值會更新為等於該 VGPR 編號加一。

可用於設定.amdhsa_next_free_vgpr 指令,請參閱AMDHSA 核心組譯器指令

可以隨時設定,例如在每個核心開始時手動設定為零。

.amdgcn.next_free_sgpr

在組譯開始之前設定為零。在每個指令中,如果此符號的目前值小於或等於該指令中明確引用的最大 SGPR 編號,則符號值會更新為等於該 SGPR 編號加一。

可用於設定.amdhsa_next_free_spgr 指令,請參閱AMDHSA 核心組譯器指令

可以隨時設定,例如在每個核心開始時手動設定為零。

程式碼物件 V3 及更高版本指令

.amdgcn 開頭的指令對於所有 amdgcn 架構處理器都有效,並且與作業系統無關。當指定 amdhsa 作業系統時,以 .amdhsa 開頭的指令特定於 amdgcn 架構處理器。請參閱目標三元組處理器

.amdgcn_target <target-triple> “-” <target-id>

可選指令,用於宣告包含的組譯器原始碼檔案支援的 <target-triple>-<target-id>。組譯器使用它來驗證命令列選項,例如 -triple-mcpu--offload-arch=<target-id>。允許使用非規範目標 ID。請參閱目標三元組目標 ID

注意

用於程式碼物件 V2 到 V3 的此指令的目標 ID 語法與其他地方使用的語法不同。請參閱程式碼物件 V2 到 V3 目標 ID

.amdhsa_code_object_version <version>

可選指令,用於宣告組譯器要產生的程式碼物件版本。如果不存在,將使用預設值。

.amdhsa_kernel <name>

在目前區段的目前位置建立正確對齊的 AMDHSA 核心描述符和符號 <name>.kd。僅當作業系統為 amdhsa 時有效。<name> 必須是標記要執行的第一個指令的符號(標籤),並且不需要預先定義。

標記用於產生核心描述符位元組的指令列表的開始,如核心描述符中所述。此列表中可能出現的指令在AMDHSA 核心組譯器指令中描述。指令可以以任何順序出現,必須對於正在組譯的目標有效,並且不能重複。指令支援核心描述符中它們引用的欄位指定的數值範圍。如果未指定指令,則假定它具有預設值,除非它被標記為「必需」,在這種情況下,省略該指令是錯誤的。此指令列表以 .end_amdhsa_kernel 指令終止。

表 103 AMDHSA 核心組譯器指令

指令

預設值

支援於

描述

.amdhsa_group_segment_fixed_size

0

GFX6-GFX12

控制 程式碼物件 V3 核心描述符中的 GROUP_SEGMENT_FIXED_SIZE。

.amdhsa_private_segment_fixed_size

0

GFX6-GFX12

控制 程式碼物件 V3 核心描述符中的 PRIVATE_SEGMENT_FIXED_SIZE。

.amdhsa_kernarg_size

0

GFX6-GFX12

控制 程式碼物件 V3 核心描述符中的 KERNARG_SIZE。

.amdhsa_user_sgpr_count

0

GFX6-GFX12

控制 COMPUTE_PGM_RSRC2 適用於 GFX6-GFX12 的 compute_pgm_rsrc2 中的 USER_SGPR_COUNT

.amdhsa_user_sgpr_private_segment_buffer

0

GFX6-GFX10 (GFX942 除外)

控制 程式碼物件 V3 核心描述符 中的 ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER。

.amdhsa_user_sgpr_dispatch_ptr

0

GFX6-GFX12

控制 程式碼物件 V3 核心描述符 中的 ENABLE_SGPR_DISPATCH_PTR。

.amdhsa_user_sgpr_queue_ptr

0

GFX6-GFX12

控制 程式碼物件 V3 核心描述符 中的 ENABLE_SGPR_QUEUE_PTR。

.amdhsa_user_sgpr_kernarg_segment_ptr

0

GFX6-GFX12

控制 程式碼物件 V3 核心描述符 中的 ENABLE_SGPR_KERNARG_SEGMENT_PTR。

.amdhsa_user_sgpr_dispatch_id

0

GFX6-GFX12

控制 程式碼物件 V3 核心描述符 中的 ENABLE_SGPR_DISPATCH_ID。

.amdhsa_user_sgpr_flat_scratch_init

0

GFX6-GFX10 (GFX942 除外)

控制 程式碼物件 V3 核心描述符 中的 ENABLE_SGPR_FLAT_SCRATCH_INIT。

.amdhsa_user_sgpr_private_segment_size

0

GFX6-GFX12

控制 程式碼物件 V3 核心描述符 中的 ENABLE_SGPR_PRIVATE_SEGMENT_SIZE。

.amdhsa_wavefront_size32

目標功能特定 (wavefrontsize64)

GFX10-GFX12

控制 程式碼物件 V3 核心描述符 中的 ENABLE_WAVEFRONT_SIZE32。

.amdhsa_uses_dynamic_stack

0

GFX6-GFX12

控制 程式碼物件 V3 核心描述符 中的 USES_DYNAMIC_STACK。

.amdhsa_system_sgpr_private_segment_wavefront_offset

0

GFX6-GFX10 (GFX942 除外)

控制 適用於 GFX6-GFX12 的 compute_pgm_rsrc2 中的 ENABLE_PRIVATE_SEGMENT。

.amdhsa_enable_private_segment

0

GFX942, GFX11-GFX12

控制 適用於 GFX6-GFX12 的 compute_pgm_rsrc2 中的 ENABLE_PRIVATE_SEGMENT。

.amdhsa_system_sgpr_workgroup_id_x

1

GFX6-GFX12

控制 適用於 GFX6-GFX12 的 compute_pgm_rsrc2 中的 ENABLE_SGPR_WORKGROUP_ID_X。

.amdhsa_system_sgpr_workgroup_id_y

0

GFX6-GFX12

控制 適用於 GFX6-GFX12 的 compute_pgm_rsrc2 中的 ENABLE_SGPR_WORKGROUP_ID_Y。

.amdhsa_system_sgpr_workgroup_id_z

0

GFX6-GFX12

控制 適用於 GFX6-GFX12 的 compute_pgm_rsrc2 中的 ENABLE_SGPR_WORKGROUP_ID_Z。

.amdhsa_system_sgpr_workgroup_info

0

GFX6-GFX12

控制 適用於 GFX6-GFX12 的 compute_pgm_rsrc2 中的 ENABLE_SGPR_WORKGROUP_INFO。

.amdhsa_system_vgpr_workitem_id

0

GFX6-GFX12

控制 適用於 GFX6-GFX12 的 compute_pgm_rsrc2 中的 ENABLE_VGPR_WORKITEM_ID。可能的值在系統 VGPR 工作項目 ID 列舉值中定義。

.amdhsa_next_free_vgpr

必填

GFX6-GFX12

明確引用的最大 VGPR 編號,加一。用於計算 適用於 GFX6-GFX12 的 compute_pgm_rsrc1 中的 GRANULATED_WORKITEM_VGPR_COUNT。

.amdhsa_next_free_sgpr

必填

GFX6-GFX12

明確引用的最大 SGPR 編號,加一。用於計算 適用於 GFX6-GFX12 的 compute_pgm_rsrc1 中的 GRANULATED_WAVEFRONT_SGPR_COUNT。

.amdhsa_accum_offset

必填

GFX90A、GFX942

統一暫存器檔案中第一個 AccVGPR 的偏移量。用於計算 適用於 GFX90A、GFX942 的 compute_pgm_rsrc3 中的 ACCUM_OFFSET。

.amdhsa_reserve_vcc

1

GFX6-GFX12

核心是否可以使用特殊的 VCC SGPR。用於計算 適用於 GFX6-GFX12 的 compute_pgm_rsrc1 中的 GRANULATED_WAVEFRONT_SGPR_COUNT。

.amdhsa_reserve_flat_scratch

1

GFX7-GFX10 (GFX942 除外)

核心是否可以使用 flat 指令來存取 scratch 記憶體。用於計算 適用於 GFX6-GFX12 的 compute_pgm_rsrc1 中的 GRANULATED_WAVEFRONT_SGPR_COUNT。

.amdhsa_reserve_xnack_mask

目標功能特定 (xnack)

GFX8-GFX10

核心是否可以觸發 XNACK 重播。用於計算 適用於 GFX6-GFX12 的 compute_pgm_rsrc1 中的 GRANULATED_WAVEFRONT_SGPR_COUNT。

.amdhsa_float_round_mode_32

0

GFX6-GFX12

控制 適用於 GFX6-GFX12 的 compute_pgm_rsrc1 中的 FLOAT_ROUND_MODE_32。可能的值在浮點數捨入模式列舉值中定義。

.amdhsa_float_round_mode_16_64

0

GFX6-GFX12

控制 適用於 GFX6-GFX12 的 compute_pgm_rsrc1 中的 FLOAT_ROUND_MODE_16_64。可能的值在浮點數捨入模式列舉值中定義。

.amdhsa_float_denorm_mode_32

0

GFX6-GFX12

控制 適用於 GFX6-GFX12 的 compute_pgm_rsrc1 中的 FLOAT_DENORM_MODE_32。可能的值在浮點數非正規化模式列舉值中定義。

.amdhsa_float_denorm_mode_16_64

3

GFX6-GFX12

控制 適用於 GFX6-GFX12 的 compute_pgm_rsrc1 中的 FLOAT_DENORM_MODE_16_64。可能的值在浮點數非正規化模式列舉值中定義。

.amdhsa_dx10_clamp

1

GFX6-GFX11

控制 適用於 GFX6-GFX12 的 compute_pgm_rsrc1 中的 ENABLE_DX10_CLAMP。

.amdhsa_ieee_mode

1

GFX6-GFX11

控制 適用於 GFX6-GFX12 的 compute_pgm_rsrc1 中的 ENABLE_IEEE_MODE。

.amdhsa_round_robin_scheduling

0

GFX12

控制 適用於 GFX6-GFX12 的 compute_pgm_rsrc1 中的 ENABLE_WG_RR_EN。

.amdhsa_fp16_overflow

0

GFX9-GFX12

控制 適用於 GFX6-GFX12 的 compute_pgm_rsrc1 中的 FP16_OVFL。

.amdhsa_tg_split

目標功能特定 (tgsplit)

GFX90A, GFX942, GFX11-GFX12

控制 適用於 GFX90A、GFX942 的 compute_pgm_rsrc3 中的 TG_SPLIT。

.amdhsa_workgroup_processor_mode

目標功能特定 (cumode)

GFX10-GFX12

控制 程式碼物件 V3 核心描述符 中的 ENABLE_WGP_MODE。

.amdhsa_memory_ordered

1

GFX10-GFX12

控制 適用於 GFX6-GFX12 的 compute_pgm_rsrc1 中的 MEM_ORDERED。

.amdhsa_forward_progress

0

GFX10-GFX12

控制 適用於 GFX6-GFX12 的 compute_pgm_rsrc1 中的 FWD_PROGRESS。

.amdhsa_shared_vgpr_count

0

GFX10-GFX11

控制 適用於 GFX10-GFX11 的 compute_pgm_rsrc3 中的 SHARED_VGPR_COUNT。

.amdhsa_inst_pref_size

0

GFX11-GFX12

控制 適用於 GFX10-GFX11 的 compute_pgm_rsrc3適用於 GFX12 的 compute_pgm_rsrc3 中的 INST_PREF_SIZE

.amdhsa_exception_fp_ieee_invalid_op

0

GFX6-GFX12

控制 compute_pgm_rsrc2 for GFX6-GFX12 中的 ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION 啟用狀態。

.amdhsa_exception_fp_denorm_src

0

GFX6-GFX12

控制 compute_pgm_rsrc2 for GFX6-GFX12 中的 ENABLE_EXCEPTION_FP_DENORMAL_SOURCE 啟用狀態。

.amdhsa_exception_fp_ieee_div_zero

0

GFX6-GFX12

控制 compute_pgm_rsrc2 for GFX6-GFX12 中的 ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO 啟用狀態。

.amdhsa_exception_fp_ieee_overflow

0

GFX6-GFX12

控制 compute_pgm_rsrc2 for GFX6-GFX12 中的 ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW 啟用狀態。

.amdhsa_exception_fp_ieee_underflow

0

GFX6-GFX12

控制 compute_pgm_rsrc2 for GFX6-GFX12 中的 ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW 啟用狀態。

.amdhsa_exception_fp_ieee_inexact

0

GFX6-GFX12

控制 compute_pgm_rsrc2 for GFX6-GFX12 中的 ENABLE_EXCEPTION_IEEE_754_FP_INEXACT 啟用狀態。

.amdhsa_exception_int_div_zero

0

GFX6-GFX12

控制 compute_pgm_rsrc2 for GFX6-GFX12 中的 ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO 啟用狀態。

.amdhsa_user_sgpr_kernarg_preload_length

0

GFX90A、GFX942

控制 Code Object V3 Kernel Descriptor 中的 KERNARG_PRELOAD_SPEC_LENGTH

.amdhsa_user_sgpr_kernarg_preload_offset

0

GFX90A、GFX942

控制 Code Object V3 Kernel Descriptor 中的 KERNARG_PRELOAD_SPEC_OFFSET

.amdgpu_metadata

選用指示詞,宣告 NT_AMDGPU_METADATA 註記記錄的內容(請參閱AMDGPU Code Object V3 及更高版本的 ELF 註記記錄)。

內容必須為 [YAML] 標記格式,並具有與 Code Object V3 MetadataCode Object V4 MetadataCode Object V5 Metadata 中描述的相同結構和語意。

此指示詞以 .end_amdgpu_metadata 指示詞終止。

Code Object V3 及更高版本範例原始碼

以下是一個最小組譯原始碼檔案的範例,定義了一個 HSA 核心

 1.amdgcn_target "amdgcn-amd-amdhsa--gfx900+xnack" // optional
 2
 3.text
 4.globl hello_world
 5.p2align 8
 6.type hello_world,@function
 7hello_world:
 8  s_load_dwordx2 s[0:1], s[0:1] 0x0
 9  v_mov_b32 v0, 3.14159
10  s_waitcnt lgkmcnt(0)
11  v_mov_b32 v1, s0
12  v_mov_b32 v2, s1
13  flat_store_dword v[1:2], v0
14  s_endpgm
15.Lfunc_end0:
16  .size   hello_world, .Lfunc_end0-hello_world
17
18.rodata
19.p2align 6
20.amdhsa_kernel hello_world
21  .amdhsa_user_sgpr_kernarg_segment_ptr 1
22  .amdhsa_next_free_vgpr .amdgcn.next_free_vgpr
23  .amdhsa_next_free_sgpr .amdgcn.next_free_sgpr
24.end_amdhsa_kernel
25
26.amdgpu_metadata
27---
28amdhsa.version:
29  - 1
30  - 0
31amdhsa.kernels:
32  - .name: hello_world
33    .symbol: hello_world.kd
34    .kernarg_segment_size: 48
35    .group_segment_fixed_size: 0
36    .private_segment_fixed_size: 0
37    .kernarg_segment_align: 4
38    .wavefront_size: 64
39    .sgpr_count: 2
40    .vgpr_count: 3
41    .max_flat_workgroup_size: 256
42    .args:
43      - .size: 8
44        .offset: 0
45        .value_kind: global_buffer
46        .address_space: global
47        .actual_access: write_only
48//...
49.end_amdgpu_metadata

此核心等同於下列 HIP 程式

1__global__ void hello_world(float *p) {
2    *p = 3.14159f;
3}

如果組譯原始碼檔案包含多個核心及/或函式,則可以使用 .set <symbol>, <expression> 指示詞重設 .amdgcn.next_free_vgpr.amdgcn.next_free_sgpr 符號。例如,在兩個核心的情況下,其中 function1 僅從 kernel1 呼叫,將函式與呼叫它的核心分組,並在兩個連線組件之間重設符號就足夠了

 1.amdgcn_target "amdgcn-amd-amdhsa--gfx900+xnack" // optional
 2
 3// gpr tracking symbols are implicitly set to zero
 4
 5.text
 6.globl kern0
 7.p2align 8
 8.type kern0,@function
 9kern0:
10  // ...
11  s_endpgm
12.Lkern0_end:
13  .size   kern0, .Lkern0_end-kern0
14
15.rodata
16.p2align 6
17.amdhsa_kernel kern0
18  // ...
19  .amdhsa_next_free_vgpr .amdgcn.next_free_vgpr
20  .amdhsa_next_free_sgpr .amdgcn.next_free_sgpr
21.end_amdhsa_kernel
22
23// reset symbols to begin tracking usage in func1 and kern1
24.set .amdgcn.next_free_vgpr, 0
25.set .amdgcn.next_free_sgpr, 0
26
27.text
28.hidden func1
29.global func1
30.p2align 2
31.type func1,@function
32func1:
33  // ...
34  s_setpc_b64 s[30:31]
35.Lfunc1_end:
36.size func1, .Lfunc1_end-func1
37
38.globl kern1
39.p2align 8
40.type kern1,@function
41kern1:
42  // ...
43  s_getpc_b64 s[4:5]
44  s_add_u32 s4, s4, func1@rel32@lo+4
45  s_addc_u32 s5, s5, func1@rel32@lo+4
46  s_swappc_b64 s[30:31], s[4:5]
47  // ...
48  s_endpgm
49.Lkern1_end:
50  .size   kern1, .Lkern1_end-kern1
51
52.rodata
53.p2align 6
54.amdhsa_kernel kern1
55  // ...
56  .amdhsa_next_free_vgpr .amdgcn.next_free_vgpr
57  .amdhsa_next_free_sgpr .amdgcn.next_free_sgpr
58.end_amdhsa_kernel

這些符號無法識別連線的組件,以便自動追蹤每個核心的使用情況。然而,在某些情況下,仔細組織原始碼檔案中的核心和函式,表示只需極少的額外工作即可準確計算 GPR 使用量。

其他文件