1.3 计算节点的计算能力描述:HsaNodeProperties

摘要: HsaNodeProperties 是 KFD 拓扑中信息最密集的结构体,包含 30+ 字段描述一个计算节点的完整特征。本文逐字段解析其语义、CPU/GPU 节点的差异、以及各字段对上层运行时决策的影响。

前文讲了KFD中如何获取系统拓扑信息,本节关注一个计算节点的整体信息表达。

1. 结构体全貌

源码位置:libhsakmt/include/hsakmt/hsakmttypes.h

c 复制代码
typedef struct _HsaNodeProperties {
    // ─── 节点类型标识 ───
    HSAuint32       NumCPUCores;            // CPU 物理核心数(>0 即为 CPU 节点)
    HSAuint32       NumFComputeCores;       // GPU SIMD 核心总数(>0 即为 GPU 节点)
    HSAuint32       NumNeuralCores;         // 神经处理单元数(AIE),无则为 0

    // ─── 子资源计数 ───
    HSAuint32       NumMemoryBanks;         // 内存区域数
    HSAuint32       NumCaches;              // 缓存层级数
    HSAuint32       NumIOLinks;             // IO 链路数(含推导的间接链路)

    // ─── 计算引擎标识 ───
    HSAuint32       CComputeIdLo;           // CPU 逻辑处理器起始 ID
    HSAuint32       FComputeIdLo;           // GPU 逻辑处理器起始 ID

    // ─── 能力标志 ───
    HSA_CAPABILITY  Capability;             // 能力标志位(见 §2.7)
    HSA_CAPABILITY2 Capability2;            // 扩展能力标志位

    // ─── GPU 微架构参数 ───
    HSAuint32       MaxWavesPerSIMD;        // 每 SIMD 最大并发 wave 数
    HSAuint32       LDSSizeInKB;            // 每 CU LDS 大小 (KB)
    HSAuint32       GDSSizeInKB;            // Global Data Share 大小 (KB)
    HSAuint32       WaveFrontSize;          // Wave 宽度(通常 64)
    HSAuint32       NumShaderBanks;         // Shader Engine 数 (array_count)
    HSAuint32       NumArrays;              // SIMD 阵列数/SE
    HSAuint32       NumCUPerArray;          // 每阵列 CU 数
    HSAuint32       NumSIMDPerCU;           // 每 CU 的 SIMD 数(通常 4)
    HSAuint32       MaxSlotsScratchCU;      // 每 CU 最大 scratch slot 数

    // ─── 固件/引擎版本 ───
    HSA_ENGINE_ID   EngineId;               // GPU 微引擎版本标识
    HSA_ENGINE_ID   OverrideEngineId;       // 覆盖的引擎版本(可为 0)

    // ─── 设备标识 ───
    HSAuint16       VendorId;               // PCI Vendor ID(0x1002 = AMD)
    HSAuint16       DeviceId;               // PCI Device ID
    HSAuint32       LocationId;             // PCI BDF 编码
    HSAuint64       LocalMemSize;           // 本地显存大小 (bytes)
    HSAuint32       MaxEngineClockMhzFCompute;  // GPU 最大时钟 (MHz)
    HSAuint32       MaxEngineClockMhzCCompute;  // CPU 最大时钟 (MHz)
    HSAint32        DrmRenderMinor;         // /dev/dri/renderDXX 的 minor 号

    // ─── 名称与版本 ───
    HSAuint16       MarketingName[HSA_PUBLIC_NAME_SIZE];  // 设备公开名称 (Unicode)
    HSAuint8        AMDName[HSA_PUBLIC_NAME_SIZE];        // CAL 名称 (ASCII)
    HSA_ENGINE_VERSION uCodeEngineVersions;               // 微码引擎版本
    HSA_DEBUG_PROPERTIES DebugProperties;                 // 调试属性

    // ─── XGMI / Hive ───
    HSAuint64       HiveID;                 // XGMI Hive 标识(PSP 哈希)
    HSAuint32       NumSdmaEngines;         // PCIe 方向 SDMA 引擎数
    HSAuint32       NumSdmaXgmiEngines;     // XGMI 方向 SDMA 引擎数

    // ─── 其他硬件参数 ───
    HSAuint8        NumSdmaQueuesPerEngine; // 每 SDMA 引擎队列数
    HSAuint8        NumCpQueues;            // CP 硬件队列数
    HSAuint8        NumGws;                 // GWS barrier 数
    HSAuint8        Integrated;             // 0=独立 GPU, 1=集成 GPU

    HSAuint32       Domain;                 // PCI 域
    HSAuint64       UniqueID;               // 全局唯一不可变 ID(熔丝写入)

    // ─── 寄存器文件 ───
    HSAuint32       VGPRSizePerCU;          // 每 CU VGPR 大小 (bytes)
    HSAuint32       SGPRSizePerCU;          // 每 CU SGPR 大小 (bytes)

    // ─── 多 XCC 与系统信息 ───
    HSAuint32       NumXcc;                 // XCC(Accelerated Compute Die)数
    HSAuint32       KFDGpuID;               // KFD 生成的 GPU 哈希 ID
    HSAuint32       FamilyID;               // GPU 家族 ID

    // ─── CWSR ───
    HSAuint32       CwsrSize;              // CWSR 区域大小
    HSAuint32       CtlStackSize;          // 控制栈大小

    // ─── Windows 标识 ───
    HSAuint32       LuidLowPart;           // Windows LUID 低 32 位
    HSAuint32       LuidHighPart;          // Windows LUID 高 32 位

    HSAuint64       WallClockKHz;          // 墙钟频率 (KHz)
} HsaNodeProperties;

内容比较多,不用去死记,还是从前文给出的描述HSA系统的几个维度去理解为什么y有这些字段即可。而且ROCm的更新速度很快,我基于的版本可能与你看到的有些小差异。下面从几个维度解释下关键字段。


2. 字段分组详解

2.1 节点类型判断

c 复制代码
bool is_cpu_node = (props.NumCPUCores > 0);
bool is_gpu_node = (props.NumFComputeCores > 0);
场景 NumCPUCores NumFComputeCores 说明
纯 CPU 节点 64 0 典型 EPYC
纯 GPU 节点 0 15360 典型 MI250X
APU >0 >0 CPU 和 iGPU 共存于同一节点(少见,通常拆分为两个 Node)

注意NumFComputeCores 不是 CU 数,而是 SIMD 总数 × WaveFrontSize:

复制代码
NumFComputeCores = NumSIMD × WaveFrontSize
                 = (128 CU × 4 SIMD/CU) × 64
                 = 32768  (MI250X 单 die)

2.2 GPU 微架构参数

这组字段完整描述了 GPU 的计算层次结构:

复制代码
GPU
├── Shader Engine (NumShaderBanks 个)
│   └── SIMD Array (NumArrays 个/SE)
│       └── CU (NumCUPerArray 个)
│           └── SIMD (NumSIMDPerCU 个, 通常 4)
│               └── Wave (MaxWavesPerSIMD 个并发)
│                   └── Lane (WaveFrontSize 个, 通常 64)

sysfs 字段对应关系:

sysfs key 结构体字段 典型值 (MI250X)
array_count NumShaderBanks 8
simd_arrays_per_engine NumArrays 2
cu_per_simd_array NumCUPerArray 8
simd_per_cu NumSIMDPerCU 4
simd_count NumFComputeCores (换算) 512 (SIMD 总数)
max_waves_per_simd MaxWavesPerSIMD 10
wave_front_size WaveFrontSize 64
lds_size_in_kb LDSSizeInKB 64
max_slots_scratch_cu MaxSlotsScratchCU 32

上层用途:ROCr runtime 用这些参数计算 dispatch 的 workgroup 限制、scratch 空间分配、occupancy 等。

2.3 设备标识

字段 说明 示例
VendorId PCI 厂商 ID 0x1002 (AMD)
DeviceId PCI 设备 ID 0x7388 (MI210)
LocationId PCI BDF 编码 0x0300(Bus 3, Dev 0, Func 0)
DrmRenderMinor DRM 渲染节点编号 128 → /dev/dri/renderD128
UniqueId GPU 全局唯一 ID XGMI hive 内区分相同型号的不同 GPU

DrmRenderMinor 的作用

  • libhsakmt 只负责 KFD 接口(/dev/kfd
  • 上层的 amdgpu/DRM 操作需要对应的 render node
  • 通过 DrmRenderMinor 将 KFD 节点映射到 DRM 设备

这就是libhsakmt 看起来是打开了一个/dev/kfd字符设备,但后面是遍历了所有的GPU计算节点,实际上是打开了/dev/dri/renderDXX。这也是一个需要理解的点,有些IOCTL下去后,会走到drm设备上。

UniqueId 的场景

  • XGMI hive 中多个同型号 GPU,DeviceId 相同
  • UniqueId 是物理芯片级别的唯一标识(熔丝写入)
  • 用于多 GPU 通信时精确路由

2.4 LocationId 编码

LocationId 编码了 PCI 拓扑位置:

复制代码
LocationId = (Domain << 32) | (Bus << 8) | (Device << 3) | Function

示例: LocationId = 0x0300
  Bus    = 3
  Device = 0
  Function = 0
  → PCI 地址 0000:03:00.0

上层通过 LocationId 可以:

  • 确定 GPU 挂在哪个 PCIe root complex 下
  • 推断 NUMA 亲和性(同一 root complex 通常对应同一 NUMA node)
  • 关联 /sys/bus/pci/devices/ 下的设备信息

2.5 时钟与内存

字段 说明 单位
MaxEngineClockMhzFCompute GPU 核心最大时钟 MHz
MaxEngineClockMhzCCompute CPU 最大时钟 MHz
LocalMemSize GPU 本地显存 bytes

LocalMemSize 注意事项

  • 这是物理 VRAM 总量,不是可分配量(需减去保留区域)
  • 对 CPU 节点,此字段为 0(CPU 内存通过 MemoryProperties 描述)
  • MI250X 双 die 配置时,每个 Node 报告单 die 的 VRAM(如 64GB/die)

2.6 SDMA 引擎

复制代码
NumSdmaEngines       = 2   (通用 SDMA,用于 CPU↔GPU、GPU local copy)
NumSdmaXgmiEngines   = 3   (XGMI 专用 SDMA,用于 GPU↔GPU 跨 XGMI)

为什么分开

  • XGMI SDMA 直接连接到 XGMI 物理链路,不走 PCIe
  • 通用 SDMA 负责 PCIe 方向的传输
  • 队列分配时需要根据传输方向选择正确的引擎

2.7 Capability 标志位

HSA_CAPABILITY 在源码中定义为 union + bitfield 结构:

c 复制代码
typedef union {
    HSAuint32 Value;
    struct {
        unsigned int HotPluggable        : 1;  // 节点可热插拔
        unsigned int HSAMMUPresent       : 1;  // 存在 IOMMU(ATS/PRI 1.1)
        unsigned int SharedWithGraphics  : 1;  // GPU 同时用于 OS 图形渲染
        unsigned int QueueSizePowerOfTwo : 1;  // 队列大小须为 2 的幂
        unsigned int QueueSize32bit      : 1;  // 队列大小 < 4GB
        unsigned int QueueIdleEvent      : 1;  // 支持队列空闲通知
        unsigned int VALimit             : 1;  // VA 范围受限(如 40bit)
        unsigned int WatchPointsSupported: 1;  // 支持硬件断点
        unsigned int WatchPointsTotalBits: 4;  // 断点数 = 2^value
        unsigned int DoorbellType        : 2;  // Doorbell 版本(0=pre-1.0, 1=1.0, 2=2.0)
        unsigned int AQLQueueDoubleMap   : 1;  // 队列环形缓冲双映射
        unsigned int DebugTrapSupported  : 1;  // GPU 调试陷阱
        unsigned int WaveLaunchTrapOverrideSupported: 1;
        unsigned int WaveLaunchModeSupported: 1;
        unsigned int PreciseMemoryOperationsSupported: 1;
        unsigned int DEPRECATED_SRAM_EDCSupport: 1;
        unsigned int Mem_EDCSupport      : 1;  // HBM ECC 功能
        unsigned int RASEventNotify      : 1;  // RAS 事件通知
        unsigned int ASICRevision        : 4;  // ASIC 版本号
        unsigned int SRAM_EDCSupport     : 1;  // SRAM ECC 功能
        unsigned int SVMAPISupported     : 1;  // SVM API 支持
        unsigned int CoherentHostAccess  : 1;  // 主机可一致性访问设备内存
        unsigned int DebugSupportedFirmware : 1;  // 固件支持 GPU 调试
        unsigned int PreciseALUOperationsSupported : 1;
        unsigned int PerQueueResetSupported : 1;  // 单队列重置
    } ui32;
} HSA_CAPABILITY;

关键标志位分组:

类别 标志位 影响
队列特性 QueueSizePowerOfTwo, AQLQueueDoubleMap, QueueIdleEvent 队列创建与管理
调试支持 DebugTrapSupported, WaveLaunchTrapOverrideSupported, PreciseMemoryOperationsSupported 调试器功能可用性
内存/MMU HSAMMUPresent, VALimit, SVMAPISupported, CoherentHostAccess 内存模型与 SVM 能力
Doorbell DoorbellType 队列通知机制版本
RAS/ECC Mem_EDCSupport, SRAM_EDCSupport, RASEventNotify 错误检测与纠正
硬件版本 ASICRevision 同一 DeviceId 下区分具体 stepping

3. CPU 节点 vs GPU 节点的字段差异

字段 CPU 节点 GPU 节点
NumCPUCores 64 0
NumFComputeCores 0 32768
WaveFrontSize 0 64
LDSSizeInKB 0 64
VendorId 0 0x1002
DeviceId 0 0x7388
DrmRenderMinor 0 128
LocalMemSize 0 17163091968
NumSdmaEngines 0 2
Capability 0 0x3300
MaxEngineClockMhzFCompute 0 1700
MaxEngineClockMhzCCompute 3500 0
NumXcc 0 1 (或多 XCC 时 >1)
Integrated 0 0 (独立) / 1 (集成)

4. 字段与上层决策的关联

上层决策 依赖的字段 决策逻辑
选择目标 GPU DeviceId, LocalMemSize 匹配用户指定的设备或选最大 VRAM
Scratch 分配 MaxSlotsScratchCU, NumCUPerArray 计算每个 wave 的 scratch 上限
队列创建 NumCpQueues, Capability 确定可创建的硬件队列数和类型
SDMA 路径选择 NumSdmaEngines, NumSdmaXgmiEngines PCIe vs XGMI 方向
调试器 attach Capability (bit 13-15) 判断是否支持 GPU 调试
DRM 交互 DrmRenderMinor 打开对应的 /dev/dri/renderDXX
XGMI hive 识别 HiveID, UniqueID 区分 hive 及 hive 内的不同 GPU
Occupancy 计算 MaxWavesPerSIMD, NumSIMDPerCU, LDSSizeInKB 估算 kernel 并发度

5. sysfs 键名与结构体字段的完整映射

sysfs key HsaNodeProperties 字段
cpu_cores_count NumCPUCores
simd_count NumFComputeCores (换算)
mem_banks_count NumMemoryBanks
caches_count NumCaches
io_links_count NumIOLinks
cpu_core_id_base CComputeIdLo
simd_id_base FComputeIdLo
max_waves_per_simd MaxWavesPerSIMD
lds_size_in_kb LDSSizeInKB
gds_size_in_kb GDSSizeInKB
num_gws NumGws
wave_front_size WaveFrontSize
array_count NumShaderBanks
simd_arrays_per_engine NumArrays
cu_per_simd_array NumCUPerArray
simd_per_cu NumSIMDPerCU
max_slots_scratch_cu MaxSlotsScratchCU
vendor_id VendorId
device_id DeviceId
location_id LocationId
domain Domain
drm_render_minor DrmRenderMinor
max_engine_clk_fcompute MaxEngineClockMhzFCompute
max_engine_clk_ccompute MaxEngineClockMhzCCompute
local_mem_size LocalMemSize
fw_version EngineId
capability Capability
capability2 Capability2
unique_id UniqueID
hive_id HiveID
num_sdma_engines NumSdmaEngines
num_sdma_xgmi_engines NumSdmaXgmiEngines
num_sdma_queues_per_engine NumSdmaQueuesPerEngine
num_cp_queues NumCpQueues
num_xcc NumXcc
family_id FamilyID
vgpr_size_per_cu VGPRSizePerCU
sgpr_size_per_cu SGPRSizePerCU

6. 小结

HsaNodeProperties 是理解 KFD 节点能力的一站式数据源。关键认知:

  1. 类型判断靠 NumCPUCores / NumFComputeCores,不是单独的 type 字段
  2. GPU 微架构字段构成层次结构:SE → Array → CU → SIMD → Wave → Lane
  3. 设备标识用于多系统集成:DrmRenderMinor 桥接 KFD 与 DRM,UniqueID 标识物理芯片,HiveID 标识 XGMI hive
  4. Capability 位域决定可用特性:调试、doorbell 版本、队列优化等
  5. SDMA 引擎按传输方向分类:通用 vs XGMI 专用
  6. 多 XCC 支持:NumXcc 标识 chiplet 数量,VGPRSizePerCU/SGPRSizePerCU 描述寄存器资源