CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
7245 lines
299 KiB
Python
7245 lines
299 KiB
Python
# Copyright (C) Advanced Micro Devices. All rights reserved.
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
# this software and associated documentation files (the "Software"), to deal in
|
|
# the Software without restriction, including without limitation the rights to
|
|
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
# the Software, and to permit persons to whom the Software is furnished to do so,
|
|
# subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included in all
|
|
# copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
import ctypes
|
|
import math
|
|
import os
|
|
import re
|
|
import warnings
|
|
from collections.abc import Iterable
|
|
from ctypes import POINTER, c_void_p
|
|
from enum import IntEnum, Enum
|
|
from pathlib import Path
|
|
from time import asctime, localtime, time
|
|
from typing import Any, Dict, List, Tuple, Union
|
|
|
|
from . import amdsmi_wrapper
|
|
from .amdsmi_exception import *
|
|
from .amdsmi_interface_utils import *
|
|
|
|
|
|
### Non Library Specific Constants ###
|
|
KILO = math.pow(10, 3)
|
|
AMDSMI_MAX_UTIL = 0xFFFFFFFF
|
|
AMDSMI_MAX_PPT_LIMIT = 0xFFFFFFFF
|
|
AMDSMI_MAX_RAIL_INDEX = 0xFFFFFFFF
|
|
# Power efficiency mode constants
|
|
AMDSMI_MAX_POWER_EFFICIENCY_UTIL = 0x7F # Maximum UTIL value for balanced core modes (%)
|
|
AMDSMI_MAX_POWER_EFFICIENCY_PPTLIMIT = 0x1FFFFF # Maximum PPT limit for balanced core modes (mW)
|
|
|
|
socket_handle_t = c_void_p
|
|
processor_handle_t = c_void_p
|
|
###############################
|
|
|
|
MAX_NUM_PROCESSES = 1024
|
|
|
|
# gpu metrics macros defined in amdsmi.h
|
|
AMDSMI_NUM_HBM_INSTANCES = 4
|
|
AMDSMI_MAX_NUM_VCN = 4
|
|
AMDSMI_MAX_NUM_CLKS = 4
|
|
AMDSMI_MAX_NUM_XGMI_LINKS = 8
|
|
AMDSMI_MAX_NUM_GFX_CLKS = 8
|
|
AMDSMI_MAX_AID = 4
|
|
AMDSMI_MAX_ENGINES = 8
|
|
AMDSMI_MAX_NUM_JPEG = 32
|
|
AMDSMI_MAX_NUM_XCC = 8
|
|
AMDSMI_MAX_NUM_XCP = 8
|
|
|
|
# max num afids per cper record
|
|
AMDSMI_MAX_NUMBER_OF_AFIDS_PER_RECORD = 12
|
|
|
|
# Max number of DPM policies
|
|
AMDSMI_MAX_NUM_PM_POLICIES = 32
|
|
|
|
# Max supported frequencies
|
|
AMDSMI_MAX_NUM_FREQUENCIES = 33
|
|
|
|
# Max Fan speed (legacy hwmon). For gpu_od GPUs, use amdsmi_get_gpu_fan_speed_max().
|
|
AMDSMI_MAX_FAN_SPEED = 255
|
|
|
|
# Max Votlage Curve Points
|
|
AMDSMI_NUM_VOLTAGE_CURVE_POINTS = 3
|
|
|
|
# Max size definitions
|
|
AMDSMI_MAX_MM_IP_COUNT = 8
|
|
AMDSMI_MAX_STRING_LENGTH = 256
|
|
AMDSMI_MAX_DEVICES = 32
|
|
AMDSMI_MAX_CONTAINER_TYPE = 2
|
|
AMDSMI_MAX_CACHE_TYPES = 10
|
|
AMDSMI_MAX_NUM_XGMI_PHYSICAL_LINK = 64
|
|
AMDSMI_GPU_UUID_SIZE = 38
|
|
_AMDSMI_STRING_LENGTH = 80
|
|
_AMDSMI_MAX_STRING_LENGTH = 256
|
|
AMDSMI_GPU_CUID_SIZE = AMDSMI_GPU_UUID_SIZE
|
|
|
|
|
|
class AmdSmiStatus(IntEnum):
|
|
SUCCESS = amdsmi_wrapper.AMDSMI_STATUS_SUCCESS
|
|
INVAL = amdsmi_wrapper.AMDSMI_STATUS_INVAL
|
|
NOT_SUPPORTED = amdsmi_wrapper.AMDSMI_STATUS_NOT_SUPPORTED
|
|
NOT_YET_IMPLEMENTED = amdsmi_wrapper.AMDSMI_STATUS_NOT_YET_IMPLEMENTED
|
|
FAIL_LOAD_MODULE = amdsmi_wrapper.AMDSMI_STATUS_FAIL_LOAD_MODULE
|
|
FAIL_LOAD_SYMBOL = amdsmi_wrapper.AMDSMI_STATUS_FAIL_LOAD_SYMBOL
|
|
DRM_ERROR = amdsmi_wrapper.AMDSMI_STATUS_DRM_ERROR
|
|
API_FAILED = amdsmi_wrapper.AMDSMI_STATUS_API_FAILED
|
|
TIMEOUT = amdsmi_wrapper.AMDSMI_STATUS_TIMEOUT
|
|
RETRY = amdsmi_wrapper.AMDSMI_STATUS_RETRY
|
|
NO_PERM = amdsmi_wrapper.AMDSMI_STATUS_NO_PERM
|
|
INTERRUPT = amdsmi_wrapper.AMDSMI_STATUS_INTERRUPT
|
|
IO = amdsmi_wrapper.AMDSMI_STATUS_IO
|
|
ADDRESS_FAULT = amdsmi_wrapper.AMDSMI_STATUS_ADDRESS_FAULT
|
|
FILE_ERROR = amdsmi_wrapper.AMDSMI_STATUS_FILE_ERROR
|
|
OUT_OF_RESOURCES = amdsmi_wrapper.AMDSMI_STATUS_OUT_OF_RESOURCES
|
|
INTERNAL_EXCEPTION = amdsmi_wrapper.AMDSMI_STATUS_INTERNAL_EXCEPTION
|
|
INPUT_OUT_OF_BOUNDS = amdsmi_wrapper.AMDSMI_STATUS_INPUT_OUT_OF_BOUNDS
|
|
INIT_ERROR = amdsmi_wrapper.AMDSMI_STATUS_INIT_ERROR
|
|
REFCOUNT_OVERFLOW = amdsmi_wrapper.AMDSMI_STATUS_REFCOUNT_OVERFLOW
|
|
DIRECTORY_NOT_FOUND = amdsmi_wrapper.AMDSMI_STATUS_DIRECTORY_NOT_FOUND
|
|
IPC_ERROR = amdsmi_wrapper.AMDSMI_STATUS_IPC_ERROR
|
|
BUSY = amdsmi_wrapper.AMDSMI_STATUS_BUSY
|
|
NOT_FOUND = amdsmi_wrapper.AMDSMI_STATUS_NOT_FOUND
|
|
NOT_INIT = amdsmi_wrapper.AMDSMI_STATUS_NOT_INIT
|
|
NO_SLOT = amdsmi_wrapper.AMDSMI_STATUS_NO_SLOT
|
|
DRIVER_NOT_LOADED = amdsmi_wrapper.AMDSMI_STATUS_DRIVER_NOT_LOADED
|
|
MORE_DATA = amdsmi_wrapper.AMDSMI_STATUS_MORE_DATA
|
|
NO_DATA = amdsmi_wrapper.AMDSMI_STATUS_NO_DATA
|
|
INSUFFICIENT_SIZE = amdsmi_wrapper.AMDSMI_STATUS_INSUFFICIENT_SIZE
|
|
UNEXPECTED_SIZE = amdsmi_wrapper.AMDSMI_STATUS_UNEXPECTED_SIZE
|
|
UNEXPECTED_DATA = amdsmi_wrapper.AMDSMI_STATUS_UNEXPECTED_DATA
|
|
NON_AMD_CPU = amdsmi_wrapper.AMDSMI_STATUS_NON_AMD_CPU
|
|
NO_ENERGY_DRV = amdsmi_wrapper.AMDSMI_STATUS_NO_ENERGY_DRV
|
|
NO_MSR_DRV = amdsmi_wrapper.AMDSMI_STATUS_NO_MSR_DRV
|
|
NO_HSMP_DRV = amdsmi_wrapper.AMDSMI_STATUS_NO_HSMP_DRV
|
|
NO_HSMP_SUP = amdsmi_wrapper.AMDSMI_STATUS_NO_HSMP_SUP
|
|
NO_HSMP_MSG_SUP = amdsmi_wrapper.AMDSMI_STATUS_NO_HSMP_MSG_SUP
|
|
HSMP_TIMEOUT = amdsmi_wrapper.AMDSMI_STATUS_HSMP_TIMEOUT
|
|
NO_DRV = amdsmi_wrapper.AMDSMI_STATUS_NO_DRV
|
|
FILE_NOT_FOUND = amdsmi_wrapper.AMDSMI_STATUS_FILE_NOT_FOUND
|
|
ARG_PTR_NULL = amdsmi_wrapper.AMDSMI_STATUS_ARG_PTR_NULL
|
|
AMDGPU_RESTART_ERR = amdsmi_wrapper.AMDSMI_STATUS_AMDGPU_RESTART_ERR
|
|
SETTING_UNAVAILABLE = amdsmi_wrapper.AMDSMI_STATUS_SETTING_UNAVAILABLE
|
|
CORRUPTED_EEPROM = amdsmi_wrapper.AMDSMI_STATUS_CORRUPTED_EEPROM
|
|
MAP_ERROR = amdsmi_wrapper.AMDSMI_STATUS_MAP_ERROR
|
|
UNKNOWN_ERROR = amdsmi_wrapper.AMDSMI_STATUS_UNKNOWN_ERROR
|
|
|
|
|
|
class AmdSmiInitFlags(IntEnum):
|
|
INIT_ALL_PROCESSORS = amdsmi_wrapper.AMDSMI_INIT_ALL_PROCESSORS
|
|
INIT_AMD_CPUS = amdsmi_wrapper.AMDSMI_INIT_AMD_CPUS
|
|
INIT_AMD_GPUS = amdsmi_wrapper.AMDSMI_INIT_AMD_GPUS
|
|
INIT_NON_AMD_CPUS = amdsmi_wrapper.AMDSMI_INIT_NON_AMD_CPUS
|
|
INIT_NON_AMD_GPUS = amdsmi_wrapper.AMDSMI_INIT_NON_AMD_GPUS
|
|
INIT_AMD_NICS = amdsmi_wrapper.AMDSMI_INIT_AMD_NICS
|
|
INIT_AMD_APUS = amdsmi_wrapper.AMDSMI_INIT_AMD_APUS
|
|
|
|
|
|
class AmdSmiContainerTypes(IntEnum):
|
|
LXC = amdsmi_wrapper.AMDSMI_CONTAINER_LXC
|
|
DOCKER = amdsmi_wrapper.AMDSMI_CONTAINER_DOCKER
|
|
|
|
|
|
class AmdSmiDeviceType(IntEnum):
|
|
UNKNOWN_DEVICE = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_UNKNOWN
|
|
AMD_GPU_DEVICE = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_AMD_GPU
|
|
AMD_CPU_DEVICE = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_AMD_CPU
|
|
NON_AMD_GPU_DEVICE = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_NON_AMD_GPU
|
|
NON_AMD_CPU_DEVICE = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_NON_AMD_CPU
|
|
AMD_CPU_CORE_DEVICE = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_AMD_CPU_CORE
|
|
AINIC_DEVICE = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_AMD_NIC
|
|
BRCM_NIC_DEVICE = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_BRCM_NIC
|
|
BRCM_SWITCH_DEVICE = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_BRCM_SWITCH
|
|
|
|
|
|
class AmdSmiMmIp(IntEnum):
|
|
UVD = amdsmi_wrapper.AMDSMI_MM_UVD
|
|
VCE = amdsmi_wrapper.AMDSMI_MM_VCE
|
|
VCN = amdsmi_wrapper.AMDSMI_MM_VCN
|
|
|
|
|
|
class AmdSmiFwBlock(IntEnum):
|
|
AMDSMI_FW_ID_SMU = amdsmi_wrapper.AMDSMI_FW_ID_SMU
|
|
AMDSMI_FW_ID_CP_CE = amdsmi_wrapper.AMDSMI_FW_ID_CP_CE
|
|
AMDSMI_FW_ID_CP_PFP = amdsmi_wrapper.AMDSMI_FW_ID_CP_PFP
|
|
AMDSMI_FW_ID_CP_ME = amdsmi_wrapper.AMDSMI_FW_ID_CP_ME
|
|
AMDSMI_FW_ID_CP_MEC_JT1 = amdsmi_wrapper.AMDSMI_FW_ID_CP_MEC_JT1
|
|
AMDSMI_FW_ID_CP_MEC_JT2 = amdsmi_wrapper.AMDSMI_FW_ID_CP_MEC_JT2
|
|
AMDSMI_FW_ID_CP_MEC1 = amdsmi_wrapper.AMDSMI_FW_ID_CP_MEC1
|
|
AMDSMI_FW_ID_CP_MEC2 = amdsmi_wrapper.AMDSMI_FW_ID_CP_MEC2
|
|
AMDSMI_FW_ID_RLC = amdsmi_wrapper.AMDSMI_FW_ID_RLC
|
|
AMDSMI_FW_ID_SDMA0 = amdsmi_wrapper.AMDSMI_FW_ID_SDMA0
|
|
AMDSMI_FW_ID_SDMA1 = amdsmi_wrapper.AMDSMI_FW_ID_SDMA1
|
|
AMDSMI_FW_ID_SDMA2 = amdsmi_wrapper.AMDSMI_FW_ID_SDMA2
|
|
AMDSMI_FW_ID_SDMA3 = amdsmi_wrapper.AMDSMI_FW_ID_SDMA3
|
|
AMDSMI_FW_ID_SDMA4 = amdsmi_wrapper.AMDSMI_FW_ID_SDMA4
|
|
AMDSMI_FW_ID_SDMA5 = amdsmi_wrapper.AMDSMI_FW_ID_SDMA5
|
|
AMDSMI_FW_ID_SDMA6 = amdsmi_wrapper.AMDSMI_FW_ID_SDMA6
|
|
AMDSMI_FW_ID_SDMA7 = amdsmi_wrapper.AMDSMI_FW_ID_SDMA7
|
|
AMDSMI_FW_ID_VCN = amdsmi_wrapper.AMDSMI_FW_ID_VCN
|
|
AMDSMI_FW_ID_UVD = amdsmi_wrapper.AMDSMI_FW_ID_UVD
|
|
AMDSMI_FW_ID_VCE = amdsmi_wrapper.AMDSMI_FW_ID_VCE
|
|
AMDSMI_FW_ID_ISP = amdsmi_wrapper.AMDSMI_FW_ID_ISP
|
|
AMDSMI_FW_ID_DMCU_ERAM = amdsmi_wrapper.AMDSMI_FW_ID_DMCU_ERAM
|
|
AMDSMI_FW_ID_DMCU_ISR = amdsmi_wrapper.AMDSMI_FW_ID_DMCU_ISR
|
|
AMDSMI_FW_ID_RLC_RESTORE_LIST_GPM_MEM = amdsmi_wrapper.AMDSMI_FW_ID_RLC_RESTORE_LIST_GPM_MEM
|
|
AMDSMI_FW_ID_RLC_RESTORE_LIST_SRM_MEM = amdsmi_wrapper.AMDSMI_FW_ID_RLC_RESTORE_LIST_SRM_MEM
|
|
AMDSMI_FW_ID_RLC_RESTORE_LIST_CNTL = amdsmi_wrapper.AMDSMI_FW_ID_RLC_RESTORE_LIST_CNTL
|
|
AMDSMI_FW_ID_RLC_V = amdsmi_wrapper.AMDSMI_FW_ID_RLC_V
|
|
AMDSMI_FW_ID_MMSCH = amdsmi_wrapper.AMDSMI_FW_ID_MMSCH
|
|
AMDSMI_FW_ID_PSP_SYSDRV = amdsmi_wrapper.AMDSMI_FW_ID_PSP_SYSDRV
|
|
AMDSMI_FW_ID_PSP_SOSDRV = amdsmi_wrapper.AMDSMI_FW_ID_PSP_SOSDRV
|
|
AMDSMI_FW_ID_PSP_TOC = amdsmi_wrapper.AMDSMI_FW_ID_PSP_TOC
|
|
AMDSMI_FW_ID_PSP_KEYDB = amdsmi_wrapper.AMDSMI_FW_ID_PSP_KEYDB
|
|
AMDSMI_FW_ID_DFC = amdsmi_wrapper.AMDSMI_FW_ID_DFC
|
|
AMDSMI_FW_ID_PSP_SPL = amdsmi_wrapper.AMDSMI_FW_ID_PSP_SPL
|
|
AMDSMI_FW_ID_DRV_CAP = amdsmi_wrapper.AMDSMI_FW_ID_DRV_CAP
|
|
AMDSMI_FW_ID_MC = amdsmi_wrapper.AMDSMI_FW_ID_MC
|
|
AMDSMI_FW_ID_PSP_BL = amdsmi_wrapper.AMDSMI_FW_ID_PSP_BL
|
|
AMDSMI_FW_ID_CP_PM4 = amdsmi_wrapper.AMDSMI_FW_ID_CP_PM4
|
|
AMDSMI_FW_ID_RLC_P = amdsmi_wrapper.AMDSMI_FW_ID_RLC_P
|
|
AMDSMI_FW_ID_SEC_POLICY_STAGE2 = amdsmi_wrapper.AMDSMI_FW_ID_SEC_POLICY_STAGE2
|
|
AMDSMI_FW_ID_REG_ACCESS_WHITELIST = amdsmi_wrapper.AMDSMI_FW_ID_REG_ACCESS_WHITELIST
|
|
AMDSMI_FW_ID_IMU_DRAM = amdsmi_wrapper.AMDSMI_FW_ID_IMU_DRAM
|
|
AMDSMI_FW_ID_IMU_IRAM = amdsmi_wrapper.AMDSMI_FW_ID_IMU_IRAM
|
|
AMDSMI_FW_ID_SDMA_TH0 = amdsmi_wrapper.AMDSMI_FW_ID_SDMA_TH0
|
|
AMDSMI_FW_ID_SDMA_TH1 = amdsmi_wrapper.AMDSMI_FW_ID_SDMA_TH1
|
|
AMDSMI_FW_ID_CP_MES = amdsmi_wrapper.AMDSMI_FW_ID_CP_MES
|
|
AMDSMI_FW_ID_MES_STACK = amdsmi_wrapper.AMDSMI_FW_ID_MES_STACK
|
|
AMDSMI_FW_ID_MES_THREAD1 = amdsmi_wrapper.AMDSMI_FW_ID_MES_THREAD1
|
|
AMDSMI_FW_ID_MES_THREAD1_STACK = amdsmi_wrapper.AMDSMI_FW_ID_MES_THREAD1_STACK
|
|
AMDSMI_FW_ID_RLX6 = amdsmi_wrapper.AMDSMI_FW_ID_RLX6
|
|
AMDSMI_FW_ID_RLX6_DRAM_BOOT = amdsmi_wrapper.AMDSMI_FW_ID_RLX6_DRAM_BOOT
|
|
AMDSMI_FW_ID_RS64_ME = amdsmi_wrapper.AMDSMI_FW_ID_RS64_ME
|
|
AMDSMI_FW_ID_RS64_ME_P0_DATA = amdsmi_wrapper.AMDSMI_FW_ID_RS64_ME_P0_DATA
|
|
AMDSMI_FW_ID_RS64_ME_P1_DATA = amdsmi_wrapper.AMDSMI_FW_ID_RS64_ME_P1_DATA
|
|
AMDSMI_FW_ID_RS64_PFP = amdsmi_wrapper.AMDSMI_FW_ID_RS64_PFP
|
|
AMDSMI_FW_ID_RS64_PFP_P0_DATA = amdsmi_wrapper.AMDSMI_FW_ID_RS64_PFP_P0_DATA
|
|
AMDSMI_FW_ID_RS64_PFP_P1_DATA = amdsmi_wrapper.AMDSMI_FW_ID_RS64_PFP_P1_DATA
|
|
AMDSMI_FW_ID_RS64_MEC = amdsmi_wrapper.AMDSMI_FW_ID_RS64_MEC
|
|
AMDSMI_FW_ID_RS64_MEC_P0_DATA = amdsmi_wrapper.AMDSMI_FW_ID_RS64_MEC_P0_DATA
|
|
AMDSMI_FW_ID_RS64_MEC_P1_DATA = amdsmi_wrapper.AMDSMI_FW_ID_RS64_MEC_P1_DATA
|
|
AMDSMI_FW_ID_RS64_MEC_P2_DATA = amdsmi_wrapper.AMDSMI_FW_ID_RS64_MEC_P2_DATA
|
|
AMDSMI_FW_ID_RS64_MEC_P3_DATA = amdsmi_wrapper.AMDSMI_FW_ID_RS64_MEC_P3_DATA
|
|
AMDSMI_FW_ID_PPTABLE = amdsmi_wrapper.AMDSMI_FW_ID_PPTABLE
|
|
AMDSMI_FW_ID_PSP_SOC = amdsmi_wrapper.AMDSMI_FW_ID_PSP_SOC
|
|
AMDSMI_FW_ID_PSP_DBG = amdsmi_wrapper.AMDSMI_FW_ID_PSP_DBG
|
|
AMDSMI_FW_ID_PSP_INTF = amdsmi_wrapper.AMDSMI_FW_ID_PSP_INTF
|
|
AMDSMI_FW_ID_RLX6_CORE1 = amdsmi_wrapper.AMDSMI_FW_ID_RLX6_CORE1
|
|
AMDSMI_FW_ID_RLX6_DRAM_BOOT_CORE1 = amdsmi_wrapper.AMDSMI_FW_ID_RLX6_DRAM_BOOT_CORE1
|
|
AMDSMI_FW_ID_RLCV_LX7 = amdsmi_wrapper.AMDSMI_FW_ID_RLCV_LX7
|
|
AMDSMI_FW_ID_RLC_SAVE_RESTORE_LIST = amdsmi_wrapper.AMDSMI_FW_ID_RLC_SAVE_RESTORE_LIST
|
|
AMDSMI_FW_ID_ASD = amdsmi_wrapper.AMDSMI_FW_ID_ASD
|
|
AMDSMI_FW_ID_TA_RAS = amdsmi_wrapper.AMDSMI_FW_ID_TA_RAS
|
|
AMDSMI_FW_ID_TA_XGMI = amdsmi_wrapper.AMDSMI_FW_ID_TA_XGMI
|
|
AMDSMI_FW_ID_RLC_SRLG = amdsmi_wrapper.AMDSMI_FW_ID_RLC_SRLG
|
|
AMDSMI_FW_ID_RLC_SRLS = amdsmi_wrapper.AMDSMI_FW_ID_RLC_SRLS
|
|
AMDSMI_FW_ID_PM = amdsmi_wrapper.AMDSMI_FW_ID_PM
|
|
AMDSMI_FW_ID_DMCU = amdsmi_wrapper.AMDSMI_FW_ID_DMCU
|
|
AMDSMI_FW_ID_PLDM_BUNDLE = amdsmi_wrapper.AMDSMI_FW_ID_PLDM_BUNDLE
|
|
|
|
|
|
class AmdSmiClkType(IntEnum):
|
|
SYS = amdsmi_wrapper.AMDSMI_CLK_TYPE_SYS
|
|
GFX = amdsmi_wrapper.AMDSMI_CLK_TYPE_GFX
|
|
DF = amdsmi_wrapper.AMDSMI_CLK_TYPE_DF
|
|
DCEF = amdsmi_wrapper.AMDSMI_CLK_TYPE_DCEF
|
|
SOC = amdsmi_wrapper.AMDSMI_CLK_TYPE_SOC
|
|
MEM = amdsmi_wrapper.AMDSMI_CLK_TYPE_MEM
|
|
PCIE = amdsmi_wrapper.AMDSMI_CLK_TYPE_PCIE
|
|
VCLK0 = amdsmi_wrapper.AMDSMI_CLK_TYPE_VCLK0
|
|
VCLK1 = amdsmi_wrapper.AMDSMI_CLK_TYPE_VCLK1
|
|
DCLK0 = amdsmi_wrapper.AMDSMI_CLK_TYPE_DCLK0
|
|
DCLK1 = amdsmi_wrapper.AMDSMI_CLK_TYPE_DCLK1
|
|
|
|
|
|
class AmdSmiClkLimitType(IntEnum):
|
|
MIN = amdsmi_wrapper.AMDSMI_CLK_LIMIT_MIN
|
|
MAX = amdsmi_wrapper.AMDSMI_CLK_LIMIT_MAX
|
|
|
|
|
|
class AmdSmiTemperatureType(IntEnum):
|
|
EDGE = amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_EDGE
|
|
HOTSPOT = amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_HOTSPOT
|
|
JUNCTION = amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_JUNCTION
|
|
VRAM = amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_VRAM
|
|
HBM_0 = amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_HBM_0
|
|
HBM_1 = amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_HBM_1
|
|
HBM_2 = amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_HBM_2
|
|
HBM_3 = amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_HBM_3
|
|
PLX = amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_PLX
|
|
|
|
# GPU Board Node temperature
|
|
GPUBOARD_NODE_RETIMER_X = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_NODE_RETIMER_X
|
|
) # Retimer X temperature
|
|
GPUBOARD_NODE_OAM_X_IBC = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_NODE_OAM_X_IBC
|
|
) # OAM X IBC temperature
|
|
GPUBOARD_NODE_OAM_X_IBC_2 = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_NODE_OAM_X_IBC_2
|
|
) # OAM X IBC 2 temperature
|
|
GPUBOARD_NODE_OAM_X_VDD18_VR = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_NODE_OAM_X_VDD18_VR
|
|
) # OAM X VDD 1.8V voltage regulator temperature
|
|
GPUBOARD_NODE_OAM_X_04_HBM_B_VR = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_NODE_OAM_X_04_HBM_B_VR
|
|
) # OAM X 0.4V HBM B voltage regulator temperature
|
|
GPUBOARD_NODE_OAM_X_04_HBM_D_VR = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_NODE_OAM_X_04_HBM_D_VR
|
|
) # OAM X 0.4V HBM D voltage regulator temperature
|
|
GPUBOARD_NODE_LAST = amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_NODE_LAST
|
|
|
|
# GPU Board VR (Voltage Regulator) temperature
|
|
GPUBOARD_VDDCR_VDD0 = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDCR_VDD0
|
|
) # VDDCR VDD0 voltage regulator temperature
|
|
GPUBOARD_VDDCR_VDD1 = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDCR_VDD1
|
|
) # VDDCR VDD1 voltage regulator temperature
|
|
GPUBOARD_VDDCR_VDD2 = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDCR_VDD2
|
|
) # VDDCR VDD2 voltage regulator temperature
|
|
GPUBOARD_VDDCR_VDD3 = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDCR_VDD3
|
|
) # VDDCR VDD3 voltage regulator temperature
|
|
GPUBOARD_VDDCR_SOC_A = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDCR_SOC_A
|
|
) # VDDCR SOC A voltage regulator temperature
|
|
GPUBOARD_VDDCR_SOC_C = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDCR_SOC_C
|
|
) # VDDCR SOC C voltage regulator temperature
|
|
GPUBOARD_VDDCR_SOCIO_A = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDCR_SOCIO_A
|
|
) # VDDCR SOCIO A voltage regulator temperature
|
|
GPUBOARD_VDDCR_SOCIO_C = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDCR_SOCIO_C
|
|
) # VDDCR SOCIO C voltage regulator temperature
|
|
GPUBOARD_VDD_085_HBM = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDD_085_HBM
|
|
) # VDD 0.85V HBM voltage regulator temperature
|
|
GPUBOARD_VDDCR_11_HBM_B = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDCR_11_HBM_B
|
|
) # VDDCR 1.1V HBM B voltage regulator temperature
|
|
GPUBOARD_VDDCR_11_HBM_D = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDCR_11_HBM_D
|
|
) # VDDCR 1.1V HBM D voltage regulator temperature
|
|
GPUBOARD_VDDIO_04_HBM_B = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDIO_04_HBM_B
|
|
) # VDDIO 0.4V HBM B voltage regulator temperature
|
|
GPUBOARD_VDDIO_04_HBM_D = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDIO_04_HBM_D
|
|
) # VDDIO 0.4V HBM D voltage regulator temperature
|
|
GPUBOARD_VDDCR_075_HBM_B = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDCR_075_HBM_B
|
|
) # VDDCR 0.75V HBM B voltage regulator temperature
|
|
GPUBOARD_VDDCR_075_HBM_D = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDCR_075_HBM_D
|
|
) # VDDCR 0.75V HBM D voltage regulator temperature
|
|
GPUBOARD_VDDIO_11_GTA_A = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDIO_11_GTA_A
|
|
) # VDDIO 1.1V GTA A voltage regulator temperature
|
|
GPUBOARD_VDDIO_11_GTA_C = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDIO_11_GTA_C
|
|
) # VDDIO 1.1V GTA C voltage regulator temperature
|
|
GPUBOARD_VDDAN_075_GTA_A = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDAN_075_GTA_A
|
|
) # VDDAN 0.75V GTA A voltage regulator temperature
|
|
GPUBOARD_VDDAN_075_GTA_C = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDAN_075_GTA_C
|
|
) # VDDAN 0.75V GTA C voltage regulator temperature
|
|
GPUBOARD_VDDCR_075_UCIE = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDCR_075_UCIE
|
|
) # VDDCR 0.75V UCIE voltage regulator temperature
|
|
GPUBOARD_VDDIO_065_UCIEAA = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDIO_065_UCIEAA
|
|
) # VDDIO 0.65V UCIEAA voltage regulator temperature
|
|
GPUBOARD_VDDIO_065_UCIEAM_A = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDIO_065_UCIEAM_A
|
|
) # VDDIO 0.65V UCIEAM A voltage regulator temperature
|
|
GPUBOARD_VDDIO_065_UCIEAM_C = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDIO_065_UCIEAM_C
|
|
) # VDDIO 0.65V UCIEAM C voltage regulator temperature
|
|
GPUBOARD_VDDAN_075 = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDAN_075
|
|
) # VDDAN 0.75V voltage regulator temperature
|
|
GPUBOARD_VDD_USR = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDD_USR
|
|
) # VDD USR voltage regulator temperature
|
|
GPUBOARD_VDDIO_11_E32 = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VDDIO_11_E32
|
|
) # VDDIO 1.1V E32 voltage regulator temperature
|
|
GPUBOARD_VR_LAST = amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_GPUBOARD_VR_LAST
|
|
|
|
# Baseboard System temperature
|
|
BASEBOARD_UBB_FPGA = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_UBB_FPGA
|
|
) # UBB FPGA temperature
|
|
BASEBOARD_UBB_FRONT = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_UBB_FRONT
|
|
) # UBB front temperature
|
|
BASEBOARD_UBB_BACK = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_UBB_BACK
|
|
) # UBB back temperature
|
|
BASEBOARD_UBB_OAM7 = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_UBB_OAM7
|
|
) # UBB OAM7 temperature
|
|
BASEBOARD_UBB_IBC = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_UBB_IBC
|
|
) # UBB IBC temperature
|
|
BASEBOARD_UBB_UFPGA = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_UBB_UFPGA
|
|
) # UBB UFPGA temperature
|
|
BASEBOARD_UBB_OAM1 = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_UBB_OAM1
|
|
) # UBB OAM1 temperature
|
|
BASEBOARD_OAM_0_1_HSC = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_OAM_0_1_HSC
|
|
) # OAM 0-1 HSC temperature
|
|
BASEBOARD_OAM_2_3_HSC = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_OAM_2_3_HSC
|
|
) # OAM 2-3 HSC temperature
|
|
BASEBOARD_OAM_4_5_HSC = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_OAM_4_5_HSC
|
|
) # OAM 4-5 HSC temperature
|
|
BASEBOARD_OAM_6_7_HSC = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_OAM_6_7_HSC
|
|
) # OAM 6-7 HSC temperature
|
|
BASEBOARD_UBB_FPGA_0V72_VR = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_UBB_FPGA_0V72_VR
|
|
) # UBB FPGA 0.72V voltage regulator temperature
|
|
BASEBOARD_UBB_FPGA_3V3_VR = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_UBB_FPGA_3V3_VR
|
|
) # UBB FPGA 3.3V voltage regulator temperature
|
|
BASEBOARD_RETIMER_0_1_2_3_1V2_VR = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_RETIMER_0_1_2_3_1V2_VR
|
|
) # Retimer 0-1-2-3 1.2V voltage regulator temperature
|
|
BASEBOARD_RETIMER_4_5_6_7_1V2_VR = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_RETIMER_4_5_6_7_1V2_VR
|
|
) # Retimer 4-5-6-7 1.2V voltage regulator temperature
|
|
BASEBOARD_RETIMER_0_1_0V9_VR = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_RETIMER_0_1_0V9_VR
|
|
) # Retimer 0-1 0.9V voltage regulator temperature
|
|
BASEBOARD_RETIMER_4_5_0V9_VR = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_RETIMER_4_5_0V9_VR
|
|
) # Retimer 4-5 0.9V voltage regulator temperature
|
|
BASEBOARD_RETIMER_2_3_0V9_VR = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_RETIMER_2_3_0V9_VR
|
|
) # Retimer 2-3 0.9V voltage regulator temperature
|
|
BASEBOARD_RETIMER_6_7_0V9_VR = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_RETIMER_6_7_0V9_VR
|
|
) # Retimer 6-7 0.9V voltage regulator temperature
|
|
BASEBOARD_OAM_0_1_2_3_3V3_VR = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_OAM_0_1_2_3_3V3_VR
|
|
) # OAM 0-1-2-3 3.3V voltage regulator temperature
|
|
BASEBOARD_OAM_4_5_6_7_3V3_VR = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_OAM_4_5_6_7_3V3_VR
|
|
) # OAM 4-5-6-7 3.3V voltage regulator temperature
|
|
BASEBOARD_IBC_HSC = (
|
|
amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_IBC_HSC
|
|
) # IBC HSC temperature
|
|
BASEBOARD_IBC = amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_IBC # IBC temperature
|
|
BASEBOARD_LAST = amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE_BASEBOARD_LAST
|
|
BASEBOARD__MAX = amdsmi_wrapper.AMDSMI_TEMPERATURE_TYPE__MAX # Maximum per GPU temperature type
|
|
|
|
|
|
class AmdSmiDevPerfLevel(IntEnum):
|
|
AUTO = amdsmi_wrapper.AMDSMI_DEV_PERF_LEVEL_AUTO
|
|
LOW = amdsmi_wrapper.AMDSMI_DEV_PERF_LEVEL_LOW
|
|
HIGH = amdsmi_wrapper.AMDSMI_DEV_PERF_LEVEL_HIGH
|
|
MANUAL = amdsmi_wrapper.AMDSMI_DEV_PERF_LEVEL_MANUAL
|
|
STABLE_STD = amdsmi_wrapper.AMDSMI_DEV_PERF_LEVEL_STABLE_STD
|
|
STABLE_PEAK = amdsmi_wrapper.AMDSMI_DEV_PERF_LEVEL_STABLE_PEAK
|
|
STABLE_MIN_MCLK = amdsmi_wrapper.AMDSMI_DEV_PERF_LEVEL_STABLE_MIN_MCLK
|
|
STABLE_MIN_SCLK = amdsmi_wrapper.AMDSMI_DEV_PERF_LEVEL_STABLE_MIN_SCLK
|
|
DETERMINISM = amdsmi_wrapper.AMDSMI_DEV_PERF_LEVEL_DETERMINISM
|
|
UNKNOWN = amdsmi_wrapper.AMDSMI_DEV_PERF_LEVEL_UNKNOWN
|
|
|
|
|
|
class AmdSmiEventGroup(IntEnum):
|
|
XGMI = amdsmi_wrapper.AMDSMI_EVNT_GRP_XGMI
|
|
XGMI_DATA_OUT = amdsmi_wrapper.AMDSMI_EVNT_GRP_XGMI_DATA_OUT
|
|
GRP_INVALID = amdsmi_wrapper.AMDSMI_EVNT_GRP_INVALID
|
|
|
|
|
|
class AmdSmiEventType(IntEnum):
|
|
XGMI_0_NOP_TX = amdsmi_wrapper.AMDSMI_EVNT_XGMI_0_NOP_TX
|
|
XGMI_0_REQUEST_TX = amdsmi_wrapper.AMDSMI_EVNT_XGMI_0_REQUEST_TX
|
|
XGMI_0_RESPONSE_TX = amdsmi_wrapper.AMDSMI_EVNT_XGMI_0_RESPONSE_TX
|
|
XGMI_0_BEATS_TX = amdsmi_wrapper.AMDSMI_EVNT_XGMI_0_BEATS_TX
|
|
XGMI_1_NOP_TX = amdsmi_wrapper.AMDSMI_EVNT_XGMI_1_NOP_TX
|
|
XGMI_1_REQUEST_TX = amdsmi_wrapper.AMDSMI_EVNT_XGMI_1_REQUEST_TX
|
|
XGMI_1_RESPONSE_TX = amdsmi_wrapper.AMDSMI_EVNT_XGMI_1_RESPONSE_TX
|
|
XGMI_1_BEATS_TX = amdsmi_wrapper.AMDSMI_EVNT_XGMI_1_BEATS_TX
|
|
XGMI_DATA_OUT_0 = amdsmi_wrapper.AMDSMI_EVNT_XGMI_DATA_OUT_0
|
|
XGMI_DATA_OUT_1 = amdsmi_wrapper.AMDSMI_EVNT_XGMI_DATA_OUT_1
|
|
XGMI_DATA_OUT_2 = amdsmi_wrapper.AMDSMI_EVNT_XGMI_DATA_OUT_2
|
|
XGMI_DATA_OUT_3 = amdsmi_wrapper.AMDSMI_EVNT_XGMI_DATA_OUT_3
|
|
XGMI_DATA_OUT_4 = amdsmi_wrapper.AMDSMI_EVNT_XGMI_DATA_OUT_4
|
|
XGMI_DATA_OUT_5 = amdsmi_wrapper.AMDSMI_EVNT_XGMI_DATA_OUT_5
|
|
|
|
|
|
class AmdSmiCounterCommand(IntEnum):
|
|
CMD_START = amdsmi_wrapper.AMDSMI_CNTR_CMD_START
|
|
CMD_STOP = amdsmi_wrapper.AMDSMI_CNTR_CMD_STOP
|
|
|
|
|
|
class AmdSmiEvtNotificationType(IntEnum):
|
|
NONE = amdsmi_wrapper.AMDSMI_EVT_NOTIF_NONE
|
|
VMFAULT = amdsmi_wrapper.AMDSMI_EVT_NOTIF_VMFAULT
|
|
THERMAL_THROTTLE = amdsmi_wrapper.AMDSMI_EVT_NOTIF_THERMAL_THROTTLE
|
|
GPU_PRE_RESET = amdsmi_wrapper.AMDSMI_EVT_NOTIF_GPU_PRE_RESET
|
|
GPU_POST_RESET = amdsmi_wrapper.AMDSMI_EVT_NOTIF_GPU_POST_RESET
|
|
MIGRATE_START = amdsmi_wrapper.AMDSMI_EVT_NOTIF_MIGRATE_START
|
|
MIGRATE_END = amdsmi_wrapper.AMDSMI_EVT_NOTIF_MIGRATE_END
|
|
PAGE_FAULT_START = amdsmi_wrapper.AMDSMI_EVT_NOTIF_PAGE_FAULT_START
|
|
PAGE_FAULT_END = amdsmi_wrapper.AMDSMI_EVT_NOTIF_PAGE_FAULT_END
|
|
QUEUE_EVICTION = amdsmi_wrapper.AMDSMI_EVT_NOTIF_QUEUE_EVICTION
|
|
QUEUE_RESTORE = amdsmi_wrapper.AMDSMI_EVT_NOTIF_QUEUE_RESTORE
|
|
UNMAP_FROM_GPU = amdsmi_wrapper.AMDSMI_EVT_NOTIF_UNMAP_FROM_GPU
|
|
PROCESS_START = amdsmi_wrapper.AMDSMI_EVT_NOTIF_PROCESS_START
|
|
PROCESS_END = amdsmi_wrapper.AMDSMI_EVT_NOTIF_PROCESS_END
|
|
|
|
|
|
class AmdSmiTemperatureMetric(IntEnum):
|
|
CURRENT = amdsmi_wrapper.AMDSMI_TEMP_CURRENT
|
|
MAX = amdsmi_wrapper.AMDSMI_TEMP_MAX
|
|
MIN = amdsmi_wrapper.AMDSMI_TEMP_MIN
|
|
MAX_HYST = amdsmi_wrapper.AMDSMI_TEMP_MAX_HYST
|
|
MIN_HYST = amdsmi_wrapper.AMDSMI_TEMP_MIN_HYST
|
|
CRITICAL = amdsmi_wrapper.AMDSMI_TEMP_CRITICAL
|
|
CRITICAL_HYST = amdsmi_wrapper.AMDSMI_TEMP_CRITICAL_HYST
|
|
EMERGENCY = amdsmi_wrapper.AMDSMI_TEMP_EMERGENCY
|
|
EMERGENCY_HYST = amdsmi_wrapper.AMDSMI_TEMP_EMERGENCY_HYST
|
|
CRIT_MIN = amdsmi_wrapper.AMDSMI_TEMP_CRIT_MIN
|
|
CRIT_MIN_HYST = amdsmi_wrapper.AMDSMI_TEMP_CRIT_MIN_HYST
|
|
OFFSET = amdsmi_wrapper.AMDSMI_TEMP_OFFSET
|
|
LOWEST = amdsmi_wrapper.AMDSMI_TEMP_LOWEST
|
|
HIGHEST = amdsmi_wrapper.AMDSMI_TEMP_HIGHEST
|
|
|
|
|
|
class AmdSmiVoltageMetric(IntEnum):
|
|
CURRENT = amdsmi_wrapper.AMDSMI_VOLT_CURRENT
|
|
MAX = amdsmi_wrapper.AMDSMI_VOLT_MAX
|
|
MIN_CRIT = amdsmi_wrapper.AMDSMI_VOLT_MIN_CRIT
|
|
MIN = amdsmi_wrapper.AMDSMI_VOLT_MIN
|
|
MAX_CRIT = amdsmi_wrapper.AMDSMI_VOLT_MAX_CRIT
|
|
AVERAGE = amdsmi_wrapper.AMDSMI_VOLT_AVERAGE
|
|
LOWEST = amdsmi_wrapper.AMDSMI_VOLT_LOWEST
|
|
HIGHEST = amdsmi_wrapper.AMDSMI_VOLT_HIGHEST
|
|
|
|
|
|
class AmdSmiVoltageType(IntEnum):
|
|
VDDGFX = amdsmi_wrapper.AMDSMI_VOLT_TYPE_VDDGFX
|
|
VDDBOARD = amdsmi_wrapper.AMDSMI_VOLT_TYPE_VDDBOARD
|
|
INVALID = amdsmi_wrapper.AMDSMI_VOLT_TYPE_INVALID
|
|
|
|
|
|
class AmdSmiAcceleratorPartitionResourceType(IntEnum):
|
|
XCC = amdsmi_wrapper.AMDSMI_ACCELERATOR_XCC
|
|
ENCODER = amdsmi_wrapper.AMDSMI_ACCELERATOR_ENCODER
|
|
DECODER = amdsmi_wrapper.AMDSMI_ACCELERATOR_DECODER
|
|
DMA = amdsmi_wrapper.AMDSMI_ACCELERATOR_DMA
|
|
JPEG = amdsmi_wrapper.AMDSMI_ACCELERATOR_JPEG
|
|
MAX = amdsmi_wrapper.AMDSMI_ACCELERATOR_MAX
|
|
|
|
|
|
class AmdSmiAcceleratorPartitionType(IntEnum):
|
|
SPX = amdsmi_wrapper.AMDSMI_ACCELERATOR_PARTITION_SPX
|
|
DPX = amdsmi_wrapper.AMDSMI_ACCELERATOR_PARTITION_DPX
|
|
TPX = amdsmi_wrapper.AMDSMI_ACCELERATOR_PARTITION_TPX
|
|
QPX = amdsmi_wrapper.AMDSMI_ACCELERATOR_PARTITION_QPX
|
|
CPX = amdsmi_wrapper.AMDSMI_ACCELERATOR_PARTITION_CPX
|
|
INVALID = amdsmi_wrapper.AMDSMI_ACCELERATOR_PARTITION_INVALID
|
|
|
|
|
|
# This class is deprecated, use AmdSmiAcceleratorPartitionType instead
|
|
class AmdSmiComputePartitionType(IntEnum):
|
|
SPX = amdsmi_wrapper.AMDSMI_COMPUTE_PARTITION_SPX
|
|
DPX = amdsmi_wrapper.AMDSMI_COMPUTE_PARTITION_DPX
|
|
TPX = amdsmi_wrapper.AMDSMI_COMPUTE_PARTITION_TPX
|
|
QPX = amdsmi_wrapper.AMDSMI_COMPUTE_PARTITION_QPX
|
|
CPX = amdsmi_wrapper.AMDSMI_COMPUTE_PARTITION_CPX
|
|
INVALID = amdsmi_wrapper.AMDSMI_COMPUTE_PARTITION_INVALID
|
|
|
|
|
|
# This class is deprecated, use AmdSmiAcceleratorPartitionMemAllocModeType instead
|
|
class AmdSmiComputePartitionMemAllocModeType(IntEnum):
|
|
INVALID = amdsmi_wrapper.AMDSMI_COMPUTE_PARTITION_MEM_ALLOC_INVALID
|
|
CAPPING = amdsmi_wrapper.AMDSMI_COMPUTE_PARTITION_MEM_ALLOC_CAPPING
|
|
ALL = amdsmi_wrapper.AMDSMI_COMPUTE_PARTITION_MEM_ALLOC_ALL
|
|
|
|
|
|
class AmdSmiAcceleratorPartitionMemAllocModeType(IntEnum):
|
|
INVALID = amdsmi_wrapper.AMDSMI_ACCELERATOR_PARTITION_MEM_ALLOC_INVALID
|
|
CAPPING = amdsmi_wrapper.AMDSMI_ACCELERATOR_PARTITION_MEM_ALLOC_CAPPING
|
|
ALL = amdsmi_wrapper.AMDSMI_ACCELERATOR_PARTITION_MEM_ALLOC_ALL
|
|
|
|
|
|
class AmdSmiMemoryPartitionType(IntEnum):
|
|
NPS1 = amdsmi_wrapper.AMDSMI_MEMORY_PARTITION_NPS1
|
|
NPS2 = amdsmi_wrapper.AMDSMI_MEMORY_PARTITION_NPS2
|
|
NPS4 = amdsmi_wrapper.AMDSMI_MEMORY_PARTITION_NPS4
|
|
NPS8 = amdsmi_wrapper.AMDSMI_MEMORY_PARTITION_NPS8
|
|
UNKNOWN = amdsmi_wrapper.AMDSMI_MEMORY_PARTITION_UNKNOWN
|
|
|
|
|
|
class AmdSmiPowerProfilePresetMasks(IntEnum):
|
|
CUSTOM_MASK = amdsmi_wrapper.AMDSMI_PWR_PROF_PRST_CUSTOM_MASK
|
|
VIDEO_MASK = amdsmi_wrapper.AMDSMI_PWR_PROF_PRST_VIDEO_MASK
|
|
POWER_SAVING_MASK = amdsmi_wrapper.AMDSMI_PWR_PROF_PRST_POWER_SAVING_MASK
|
|
COMPUTE_MASK = amdsmi_wrapper.AMDSMI_PWR_PROF_PRST_COMPUTE_MASK
|
|
VR_MASK = amdsmi_wrapper.AMDSMI_PWR_PROF_PRST_VR_MASK
|
|
THREE_D_FULL_SCR_MASK = amdsmi_wrapper.AMDSMI_PWR_PROF_PRST_3D_FULL_SCR_MASK
|
|
BOOTUP_DEFAULT = amdsmi_wrapper.AMDSMI_PWR_PROF_PRST_BOOTUP_DEFAULT
|
|
INVALID = amdsmi_wrapper.AMDSMI_PWR_PROF_PRST_INVALID
|
|
|
|
|
|
class AmdSmiGpuBlock(IntEnum):
|
|
INVALID = amdsmi_wrapper.AMDSMI_GPU_BLOCK_INVALID
|
|
UMC = amdsmi_wrapper.AMDSMI_GPU_BLOCK_UMC
|
|
SDMA = amdsmi_wrapper.AMDSMI_GPU_BLOCK_SDMA
|
|
GFX = amdsmi_wrapper.AMDSMI_GPU_BLOCK_GFX
|
|
MMHUB = amdsmi_wrapper.AMDSMI_GPU_BLOCK_MMHUB
|
|
ATHUB = amdsmi_wrapper.AMDSMI_GPU_BLOCK_ATHUB
|
|
PCIE_BIF = amdsmi_wrapper.AMDSMI_GPU_BLOCK_PCIE_BIF
|
|
HDP = amdsmi_wrapper.AMDSMI_GPU_BLOCK_HDP
|
|
XGMI_WAFL = amdsmi_wrapper.AMDSMI_GPU_BLOCK_XGMI_WAFL
|
|
DF = amdsmi_wrapper.AMDSMI_GPU_BLOCK_DF
|
|
SMN = amdsmi_wrapper.AMDSMI_GPU_BLOCK_SMN
|
|
SEM = amdsmi_wrapper.AMDSMI_GPU_BLOCK_SEM
|
|
MP0 = amdsmi_wrapper.AMDSMI_GPU_BLOCK_MP0
|
|
MP1 = amdsmi_wrapper.AMDSMI_GPU_BLOCK_MP1
|
|
FUSE = amdsmi_wrapper.AMDSMI_GPU_BLOCK_FUSE
|
|
MCA = amdsmi_wrapper.AMDSMI_GPU_BLOCK_MCA
|
|
VCN = amdsmi_wrapper.AMDSMI_GPU_BLOCK_VCN
|
|
JPEG = amdsmi_wrapper.AMDSMI_GPU_BLOCK_JPEG
|
|
IH = amdsmi_wrapper.AMDSMI_GPU_BLOCK_IH
|
|
MPIO = amdsmi_wrapper.AMDSMI_GPU_BLOCK_MPIO
|
|
RESERVED = amdsmi_wrapper.AMDSMI_GPU_BLOCK_RESERVED
|
|
|
|
|
|
class AmdSmiRasErrState(IntEnum):
|
|
NONE = amdsmi_wrapper.AMDSMI_RAS_ERR_STATE_NONE
|
|
DISABLED = amdsmi_wrapper.AMDSMI_RAS_ERR_STATE_DISABLED
|
|
PARITY = amdsmi_wrapper.AMDSMI_RAS_ERR_STATE_PARITY
|
|
SING_C = amdsmi_wrapper.AMDSMI_RAS_ERR_STATE_SING_C
|
|
MULT_UC = amdsmi_wrapper.AMDSMI_RAS_ERR_STATE_MULT_UC
|
|
POISON = amdsmi_wrapper.AMDSMI_RAS_ERR_STATE_POISON
|
|
ENABLED = amdsmi_wrapper.AMDSMI_RAS_ERR_STATE_ENABLED
|
|
INVALID = amdsmi_wrapper.AMDSMI_RAS_ERR_STATE_INVALID
|
|
|
|
|
|
class AmdSmiCperNotifyType(Enum):
|
|
CMC = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_CMC
|
|
CPE = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_CPE
|
|
MCE = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_MCE
|
|
PCIE = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_PCIE
|
|
INIT = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_INIT
|
|
NMI = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_NMI
|
|
BOOT = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_BOOT
|
|
DMAr = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_DMAR
|
|
SEA = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_SEA
|
|
SEI = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_SEI
|
|
PEI = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_PEI
|
|
CXL_COMPONENT = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_CXL_COMPONENT
|
|
|
|
|
|
class AmdSmiMemoryType(IntEnum):
|
|
VRAM = amdsmi_wrapper.AMDSMI_MEM_TYPE_VRAM
|
|
VIS_VRAM = amdsmi_wrapper.AMDSMI_MEM_TYPE_VIS_VRAM
|
|
GTT = amdsmi_wrapper.AMDSMI_MEM_TYPE_GTT
|
|
|
|
|
|
class AmdSmiFreqInd(IntEnum):
|
|
MIN = amdsmi_wrapper.AMDSMI_FREQ_IND_MIN
|
|
MAX = amdsmi_wrapper.AMDSMI_FREQ_IND_MAX
|
|
INVALID = amdsmi_wrapper.AMDSMI_FREQ_IND_INVALID
|
|
|
|
|
|
class AmdSmiXgmiStatus(IntEnum):
|
|
NO_ERRORS = amdsmi_wrapper.AMDSMI_XGMI_STATUS_NO_ERRORS
|
|
ERROR = amdsmi_wrapper.AMDSMI_XGMI_STATUS_ERROR
|
|
MULTIPLE_ERRORS = amdsmi_wrapper.AMDSMI_XGMI_STATUS_MULTIPLE_ERRORS
|
|
|
|
|
|
class AmdSmiMemoryPageStatus(IntEnum):
|
|
RESERVED = amdsmi_wrapper.AMDSMI_MEM_PAGE_STATUS_RESERVED
|
|
PENDING = amdsmi_wrapper.AMDSMI_MEM_PAGE_STATUS_PENDING
|
|
UNRESERVABLE = amdsmi_wrapper.AMDSMI_MEM_PAGE_STATUS_UNRESERVABLE
|
|
|
|
|
|
class AmdSmiLinkType(IntEnum):
|
|
AMDSMI_LINK_TYPE_INTERNAL = amdsmi_wrapper.AMDSMI_LINK_TYPE_INTERNAL
|
|
AMDSMI_LINK_TYPE_XGMI = amdsmi_wrapper.AMDSMI_LINK_TYPE_XGMI
|
|
AMDSMI_LINK_TYPE_PCIE = amdsmi_wrapper.AMDSMI_LINK_TYPE_PCIE
|
|
AMDSMI_LINK_TYPE_NOT_APPLICABLE = amdsmi_wrapper.AMDSMI_LINK_TYPE_NOT_APPLICABLE
|
|
AMDSMI_LINK_TYPE_UNKNOWN = amdsmi_wrapper.AMDSMI_LINK_TYPE_UNKNOWN
|
|
|
|
|
|
class AmdSmiUtilizationCounterType(IntEnum):
|
|
COARSE_GRAIN_GFX_ACTIVITY = amdsmi_wrapper.AMDSMI_COARSE_GRAIN_GFX_ACTIVITY
|
|
COARSE_GRAIN_MEM_ACTIVITY = amdsmi_wrapper.AMDSMI_COARSE_GRAIN_MEM_ACTIVITY
|
|
COARSE_DECODER_ACTIVITY = amdsmi_wrapper.AMDSMI_COARSE_DECODER_ACTIVITY
|
|
FINE_GRAIN_GFX_ACTIVITY = amdsmi_wrapper.AMDSMI_FINE_GRAIN_GFX_ACTIVITY
|
|
FINE_GRAIN_MEM_ACTIVITY = amdsmi_wrapper.AMDSMI_FINE_GRAIN_MEM_ACTIVITY
|
|
FINE_DECODER_ACTIVITY = amdsmi_wrapper.AMDSMI_FINE_DECODER_ACTIVITY
|
|
UTILIZATION_COUNTER_FIRST = amdsmi_wrapper.AMDSMI_UTILIZATION_COUNTER_FIRST
|
|
UTILIZATION_COUNTER_LAST = amdsmi_wrapper.AMDSMI_UTILIZATION_COUNTER_LAST
|
|
|
|
|
|
class AmdSmiProcessorType(IntEnum):
|
|
UNKNOWN = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_UNKNOWN
|
|
AMD_GPU = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_AMD_GPU
|
|
AMD_CPU = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_AMD_CPU
|
|
NON_AMD_GPU = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_NON_AMD_GPU
|
|
NON_AMD_CPU = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_NON_AMD_CPU
|
|
AMD_CPU_CORE = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_AMD_CPU_CORE
|
|
AMD_APU = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_AMD_APU
|
|
AMD_AINIC = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_AMD_NIC
|
|
AMD_BRCM_NIC = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_BRCM_NIC
|
|
AMD_BRCM_SWITCH = amdsmi_wrapper.AMDSMI_PROCESSOR_TYPE_BRCM_SWITCH
|
|
|
|
|
|
class AmdSmiRegType(IntEnum):
|
|
XGMI = amdsmi_wrapper.AMDSMI_REG_XGMI
|
|
WAFL = amdsmi_wrapper.AMDSMI_REG_WAFL
|
|
PCIE = amdsmi_wrapper.AMDSMI_REG_PCIE
|
|
USR = amdsmi_wrapper.AMDSMI_REG_USR
|
|
USR1 = amdsmi_wrapper.AMDSMI_REG_USR1
|
|
|
|
|
|
class AmdSmiVirtualizationMode(IntEnum):
|
|
UNKNOWN = amdsmi_wrapper.AMDSMI_VIRTUALIZATION_MODE_UNKNOWN
|
|
BAREMETAL = amdsmi_wrapper.AMDSMI_VIRTUALIZATION_MODE_BAREMETAL
|
|
HOST = amdsmi_wrapper.AMDSMI_VIRTUALIZATION_MODE_HOST
|
|
GUEST = amdsmi_wrapper.AMDSMI_VIRTUALIZATION_MODE_GUEST
|
|
PASSTHROUGH = amdsmi_wrapper.AMDSMI_VIRTUALIZATION_MODE_PASSTHROUGH
|
|
|
|
|
|
class AmdSmiVramType(IntEnum):
|
|
UNKNOWN = amdsmi_wrapper.AMDSMI_VRAM_TYPE_UNKNOWN
|
|
HBM = amdsmi_wrapper.AMDSMI_VRAM_TYPE_HBM
|
|
HBM2 = amdsmi_wrapper.AMDSMI_VRAM_TYPE_HBM2
|
|
HBM2E = amdsmi_wrapper.AMDSMI_VRAM_TYPE_HBM2E
|
|
HBM3 = amdsmi_wrapper.AMDSMI_VRAM_TYPE_HBM3
|
|
DDR2 = amdsmi_wrapper.AMDSMI_VRAM_TYPE_DDR2
|
|
DDR3 = amdsmi_wrapper.AMDSMI_VRAM_TYPE_DDR3
|
|
DDR4 = amdsmi_wrapper.AMDSMI_VRAM_TYPE_DDR4
|
|
GDDR1 = amdsmi_wrapper.AMDSMI_VRAM_TYPE_GDDR1
|
|
GDDR2 = amdsmi_wrapper.AMDSMI_VRAM_TYPE_GDDR2
|
|
GDDR3 = amdsmi_wrapper.AMDSMI_VRAM_TYPE_GDDR3
|
|
GDDR4 = amdsmi_wrapper.AMDSMI_VRAM_TYPE_GDDR4
|
|
GDDR5 = amdsmi_wrapper.AMDSMI_VRAM_TYPE_GDDR5
|
|
GDDR6 = amdsmi_wrapper.AMDSMI_VRAM_TYPE_GDDR6
|
|
GDDR7 = amdsmi_wrapper.AMDSMI_VRAM_TYPE_GDDR7
|
|
MAX = amdsmi_wrapper.AMDSMI_VRAM_TYPE__MAX
|
|
|
|
|
|
class AmdSmiAffinityScope(IntEnum):
|
|
NUMA_SCOPE = amdsmi_wrapper.AMDSMI_AFFINITY_SCOPE_NODE
|
|
SOCKET_SCOPE = amdsmi_wrapper.AMDSMI_AFFINITY_SCOPE_SOCKET
|
|
|
|
|
|
class AmdSmiPtlData(IntEnum):
|
|
I8 = amdsmi_wrapper.AMDSMI_PTL_DATA_FORMAT_I8
|
|
F16 = amdsmi_wrapper.AMDSMI_PTL_DATA_FORMAT_F16
|
|
BF16 = amdsmi_wrapper.AMDSMI_PTL_DATA_FORMAT_BF16
|
|
F32 = amdsmi_wrapper.AMDSMI_PTL_DATA_FORMAT_F32
|
|
F64 = amdsmi_wrapper.AMDSMI_PTL_DATA_FORMAT_F64
|
|
F8 = amdsmi_wrapper.AMDSMI_PTL_DATA_FORMAT_F8
|
|
VECTOR = amdsmi_wrapper.AMDSMI_PTL_DATA_FORMAT_VECTOR
|
|
INVALID = amdsmi_wrapper.AMDSMI_PTL_DATA_FORMAT_INVALID
|
|
|
|
|
|
class AmdSmiPowerCapType(IntEnum):
|
|
PPT0 = amdsmi_wrapper.AMDSMI_POWER_CAP_TYPE_PPT0
|
|
PPT1 = amdsmi_wrapper.AMDSMI_POWER_CAP_TYPE_PPT1
|
|
|
|
|
|
class AmdSmiEventReader:
|
|
def __init__(
|
|
self, processor_handle: processor_handle_t, event_types: List[AmdSmiEvtNotificationType]
|
|
):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(event_types, Iterable):
|
|
raise AmdSmiParameterException(event_types, Iterable)
|
|
|
|
for event_type in event_types:
|
|
if not isinstance(event_type, AmdSmiEvtNotificationType):
|
|
raise AmdSmiParameterException(event_type, AmdSmiEvtNotificationType)
|
|
|
|
self.processor_handle = processor_handle
|
|
mask = 0
|
|
for event_type in event_types:
|
|
if event_type != AmdSmiEvtNotificationType.NONE:
|
|
mask |= 1 << (int(event_type) - 1)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_init_gpu_event_notification(processor_handle))
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_gpu_event_notification_mask(
|
|
processor_handle, ctypes.c_uint64(mask)
|
|
)
|
|
)
|
|
|
|
def read(self, timestamp, num_elem=10):
|
|
c_count = ctypes.c_uint32(num_elem)
|
|
event_info = (amdsmi_wrapper.amdsmi_evt_notification_data_t * num_elem)()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_event_notification(
|
|
ctypes.c_int(timestamp), ctypes.byref(c_count), event_info
|
|
)
|
|
)
|
|
|
|
ret = []
|
|
for i in range(c_count.value):
|
|
unique_event_values = set(event.value for event in AmdSmiEvtNotificationType)
|
|
if event_info[i].event in unique_event_values:
|
|
if AmdSmiEvtNotificationType(event_info[i].event).name != "NONE":
|
|
processor_handle = amdsmi_wrapper.amdsmi_processor_handle(
|
|
event_info[i].processor_handle
|
|
)
|
|
ret.append(
|
|
{
|
|
"processor_handle": processor_handle,
|
|
"event": AmdSmiEvtNotificationType(event_info[i].event).name,
|
|
"message": event_info[i].message.decode("utf-8"),
|
|
}
|
|
)
|
|
|
|
return ret
|
|
|
|
def stop(self):
|
|
_check_res(amdsmi_wrapper.amdsmi_stop_gpu_event_notification(self.processor_handle))
|
|
|
|
def __enter__(self):
|
|
return self
|
|
|
|
def __exit__(self, exc_type, exc_value, traceback):
|
|
self.stop()
|
|
|
|
|
|
def _apu_metrics_na_dict() -> dict:
|
|
"""Return a dict of all APU metrics keys set to N/A."""
|
|
return {
|
|
"apu_metrics.temperature_gfx": "N/A",
|
|
"apu_metrics.temperature_soc": "N/A",
|
|
"apu_metrics.temperature_core": "N/A",
|
|
"apu_metrics.temperature_l3": "N/A",
|
|
"apu_metrics.temperature_skin": "N/A",
|
|
"apu_metrics.average_gfx_activity": "N/A",
|
|
"apu_metrics.average_mm_activity": "N/A",
|
|
"apu_metrics.average_vcn_activity": "N/A",
|
|
"apu_metrics.average_ipu_activity": "N/A",
|
|
"apu_metrics.average_core_c0_activity": "N/A",
|
|
"apu_metrics.average_dram_reads": "N/A",
|
|
"apu_metrics.average_dram_writes": "N/A",
|
|
"apu_metrics.average_ipu_reads": "N/A",
|
|
"apu_metrics.average_ipu_writes": "N/A",
|
|
"apu_metrics.average_socket_power": "N/A",
|
|
"apu_metrics.average_cpu_power": "N/A",
|
|
"apu_metrics.average_soc_power": "N/A",
|
|
"apu_metrics.average_gfx_power": "N/A",
|
|
"apu_metrics.average_core_power": "N/A",
|
|
"apu_metrics.average_ipu_power": "N/A",
|
|
"apu_metrics.average_apu_power": "N/A",
|
|
"apu_metrics.average_dgpu_power": "N/A",
|
|
"apu_metrics.average_all_core_power": "N/A",
|
|
"apu_metrics.average_sys_power": "N/A",
|
|
"apu_metrics.stapm_power_limit": "N/A",
|
|
"apu_metrics.current_stapm_power_limit": "N/A",
|
|
"apu_metrics.average_gfxclk_frequency": "N/A",
|
|
"apu_metrics.average_socclk_frequency": "N/A",
|
|
"apu_metrics.average_uclk_frequency": "N/A",
|
|
"apu_metrics.average_fclk_frequency": "N/A",
|
|
"apu_metrics.average_vclk_frequency": "N/A",
|
|
"apu_metrics.average_dclk_frequency": "N/A",
|
|
"apu_metrics.average_vpeclk_frequency": "N/A",
|
|
"apu_metrics.average_ipuclk_frequency": "N/A",
|
|
"apu_metrics.average_mpipu_frequency": "N/A",
|
|
"apu_metrics.current_gfxclk": "N/A",
|
|
"apu_metrics.current_socclk": "N/A",
|
|
"apu_metrics.current_uclk": "N/A",
|
|
"apu_metrics.current_fclk": "N/A",
|
|
"apu_metrics.current_vclk": "N/A",
|
|
"apu_metrics.current_dclk": "N/A",
|
|
"apu_metrics.current_coreclk": "N/A",
|
|
"apu_metrics.current_l3clk": "N/A",
|
|
"apu_metrics.current_core_maxfreq": "N/A",
|
|
"apu_metrics.current_gfx_maxfreq": "N/A",
|
|
"apu_metrics.throttle_status": "N/A",
|
|
"apu_metrics.indep_throttle_status": "N/A",
|
|
"apu_metrics.throttle_residency_prochot": "N/A",
|
|
"apu_metrics.throttle_residency_spl": "N/A",
|
|
"apu_metrics.throttle_residency_fppt": "N/A",
|
|
"apu_metrics.throttle_residency_sppt": "N/A",
|
|
"apu_metrics.throttle_residency_thm_core": "N/A",
|
|
"apu_metrics.throttle_residency_thm_gfx": "N/A",
|
|
"apu_metrics.throttle_residency_thm_soc": "N/A",
|
|
"apu_metrics.fan_pwm": "N/A",
|
|
"apu_metrics.average_temperature_gfx": "N/A",
|
|
"apu_metrics.average_temperature_soc": "N/A",
|
|
"apu_metrics.average_temperature_core": "N/A",
|
|
"apu_metrics.average_temperature_l3": "N/A",
|
|
"apu_metrics.average_cpu_voltage": "N/A",
|
|
"apu_metrics.average_soc_voltage": "N/A",
|
|
"apu_metrics.average_gfx_voltage": "N/A",
|
|
"apu_metrics.average_cpu_current": "N/A",
|
|
"apu_metrics.average_soc_current": "N/A",
|
|
"apu_metrics.average_gfx_current": "N/A",
|
|
"apu_metrics.time_filter_alphavalue": "N/A",
|
|
}
|
|
|
|
|
|
def _convert_apu_unit(value, divisor):
|
|
"""Convert a validated APU metrics value by the given divisor.
|
|
|
|
Handles scalars, lists, and "N/A" pass-through.
|
|
"""
|
|
if value == "N/A":
|
|
return "N/A"
|
|
if isinstance(value, list):
|
|
return [round(v / divisor, 2) if v != "N/A" else "N/A" for v in value]
|
|
return round(value / divisor, 2)
|
|
|
|
|
|
def _populate_apu_metrics(apu):
|
|
"""Build the apu_metrics.* dict from an AmdSmiApuMetrics ctypes struct.
|
|
|
|
Unit conversions applied here:
|
|
- temperatures : centidegrees -> degrees C (/ 100)
|
|
- power : milliwatts -> watts (/ 1000)
|
|
- clocks : already MHz (no conversion)
|
|
- activity : already % (no conversion)
|
|
"""
|
|
return {
|
|
# --- temperatures (centidegrees -> C) ---
|
|
"apu_metrics.temperature_gfx": _convert_apu_unit(
|
|
_validate_if_max_uint(apu.temperature_gfx, MaxUIntegerTypes.UINT16_T), 100
|
|
),
|
|
"apu_metrics.temperature_soc": _convert_apu_unit(
|
|
_validate_if_max_uint(apu.temperature_soc, MaxUIntegerTypes.UINT16_T), 100
|
|
),
|
|
"apu_metrics.temperature_core": _convert_apu_unit(
|
|
_validate_if_max_uint(list(apu.temperature_core), MaxUIntegerTypes.UINT16_T), 100
|
|
),
|
|
"apu_metrics.temperature_l3": _convert_apu_unit(
|
|
_validate_if_max_uint(list(apu.temperature_l3), MaxUIntegerTypes.UINT16_T), 100
|
|
),
|
|
"apu_metrics.temperature_skin": _convert_apu_unit(
|
|
_validate_if_max_uint(apu.temperature_skin, MaxUIntegerTypes.UINT16_T), 100
|
|
),
|
|
"apu_metrics.average_temperature_gfx": _convert_apu_unit(
|
|
_validate_if_max_uint(apu.average_temperature_gfx, MaxUIntegerTypes.UINT16_T), 100
|
|
),
|
|
"apu_metrics.average_temperature_soc": _convert_apu_unit(
|
|
_validate_if_max_uint(apu.average_temperature_soc, MaxUIntegerTypes.UINT16_T), 100
|
|
),
|
|
"apu_metrics.average_temperature_core": _convert_apu_unit(
|
|
_validate_if_max_uint(list(apu.average_temperature_core), MaxUIntegerTypes.UINT16_T),
|
|
100,
|
|
),
|
|
"apu_metrics.average_temperature_l3": _convert_apu_unit(
|
|
_validate_if_max_uint(list(apu.average_temperature_l3), MaxUIntegerTypes.UINT16_T), 100
|
|
),
|
|
# --- activities (already %) ---
|
|
"apu_metrics.average_gfx_activity": _validate_if_max_uint(
|
|
apu.average_gfx_activity, MaxUIntegerTypes.UINT16_T, isActivity=True
|
|
),
|
|
"apu_metrics.average_mm_activity": _validate_if_max_uint(
|
|
apu.average_mm_activity, MaxUIntegerTypes.UINT16_T, isActivity=True
|
|
),
|
|
"apu_metrics.average_vcn_activity": _validate_if_max_uint(
|
|
apu.average_vcn_activity, MaxUIntegerTypes.UINT16_T, isActivity=True
|
|
),
|
|
"apu_metrics.average_ipu_activity": _validate_if_max_uint(
|
|
list(apu.average_ipu_activity), MaxUIntegerTypes.UINT16_T, isActivity=True
|
|
),
|
|
"apu_metrics.average_core_c0_activity": _validate_if_max_uint(
|
|
list(apu.average_core_c0_activity), MaxUIntegerTypes.UINT16_T, isActivity=True
|
|
),
|
|
"apu_metrics.average_dram_reads": _validate_if_max_uint(
|
|
apu.average_dram_reads, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.average_dram_writes": _validate_if_max_uint(
|
|
apu.average_dram_writes, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.average_ipu_reads": _validate_if_max_uint(
|
|
apu.average_ipu_reads, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.average_ipu_writes": _validate_if_max_uint(
|
|
apu.average_ipu_writes, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
# --- power (mW -> W) ---
|
|
"apu_metrics.average_socket_power": _convert_apu_unit(
|
|
_validate_if_max_uint(apu.average_socket_power, MaxUIntegerTypes.UINT32_T), 1000
|
|
),
|
|
"apu_metrics.average_cpu_power": _convert_apu_unit(
|
|
_validate_if_max_uint(apu.average_cpu_power, MaxUIntegerTypes.UINT16_T), 1000
|
|
),
|
|
"apu_metrics.average_soc_power": _convert_apu_unit(
|
|
_validate_if_max_uint(apu.average_soc_power, MaxUIntegerTypes.UINT16_T), 1000
|
|
),
|
|
"apu_metrics.average_gfx_power": _convert_apu_unit(
|
|
_validate_if_max_uint(apu.average_gfx_power, MaxUIntegerTypes.UINT32_T), 1000
|
|
),
|
|
"apu_metrics.average_core_power": _convert_apu_unit(
|
|
_validate_if_max_uint(list(apu.average_core_power), MaxUIntegerTypes.UINT16_T), 1000
|
|
),
|
|
"apu_metrics.average_ipu_power": _convert_apu_unit(
|
|
_validate_if_max_uint(apu.average_ipu_power, MaxUIntegerTypes.UINT16_T), 1000
|
|
),
|
|
"apu_metrics.average_apu_power": _convert_apu_unit(
|
|
_validate_if_max_uint(apu.average_apu_power, MaxUIntegerTypes.UINT32_T), 1000
|
|
),
|
|
"apu_metrics.average_dgpu_power": _convert_apu_unit(
|
|
_validate_if_max_uint(apu.average_dgpu_power, MaxUIntegerTypes.UINT32_T), 1000
|
|
),
|
|
"apu_metrics.average_all_core_power": _convert_apu_unit(
|
|
_validate_if_max_uint(apu.average_all_core_power, MaxUIntegerTypes.UINT32_T), 1000
|
|
),
|
|
"apu_metrics.average_sys_power": _convert_apu_unit(
|
|
_validate_if_max_uint(apu.average_sys_power, MaxUIntegerTypes.UINT16_T), 1000
|
|
),
|
|
"apu_metrics.stapm_power_limit": _convert_apu_unit(
|
|
_validate_if_max_uint(apu.stapm_power_limit, MaxUIntegerTypes.UINT16_T), 1000
|
|
),
|
|
"apu_metrics.current_stapm_power_limit": _convert_apu_unit(
|
|
_validate_if_max_uint(apu.current_stapm_power_limit, MaxUIntegerTypes.UINT16_T), 1000
|
|
),
|
|
# --- clocks (already MHz) ---
|
|
"apu_metrics.average_gfxclk_frequency": _validate_if_max_uint(
|
|
apu.average_gfxclk_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.average_socclk_frequency": _validate_if_max_uint(
|
|
apu.average_socclk_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.average_uclk_frequency": _validate_if_max_uint(
|
|
apu.average_uclk_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.average_fclk_frequency": _validate_if_max_uint(
|
|
apu.average_fclk_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.average_vclk_frequency": _validate_if_max_uint(
|
|
apu.average_vclk_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.average_dclk_frequency": _validate_if_max_uint(
|
|
apu.average_dclk_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.average_vpeclk_frequency": _validate_if_max_uint(
|
|
apu.average_vpeclk_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.average_ipuclk_frequency": _validate_if_max_uint(
|
|
apu.average_ipuclk_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.average_mpipu_frequency": _validate_if_max_uint(
|
|
apu.average_mpipu_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.current_gfxclk": _validate_if_max_uint(
|
|
apu.current_gfxclk, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.current_socclk": _validate_if_max_uint(
|
|
apu.current_socclk, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.current_uclk": _validate_if_max_uint(
|
|
apu.current_uclk, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.current_fclk": _validate_if_max_uint(
|
|
apu.current_fclk, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.current_vclk": _validate_if_max_uint(
|
|
apu.current_vclk, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.current_dclk": _validate_if_max_uint(
|
|
apu.current_dclk, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.current_coreclk": _validate_if_max_uint(
|
|
list(apu.current_coreclk), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.current_l3clk": _validate_if_max_uint(
|
|
list(apu.current_l3clk), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.current_core_maxfreq": _validate_if_max_uint(
|
|
apu.current_core_maxfreq, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.current_gfx_maxfreq": _validate_if_max_uint(
|
|
apu.current_gfx_maxfreq, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
# --- voltages/currents (already mV/mA) ---
|
|
"apu_metrics.average_cpu_voltage": _validate_if_max_uint(
|
|
apu.average_cpu_voltage, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.average_soc_voltage": _validate_if_max_uint(
|
|
apu.average_soc_voltage, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.average_gfx_voltage": _validate_if_max_uint(
|
|
apu.average_gfx_voltage, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.average_cpu_current": _validate_if_max_uint(
|
|
apu.average_cpu_current, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.average_soc_current": _validate_if_max_uint(
|
|
apu.average_soc_current, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"apu_metrics.average_gfx_current": _validate_if_max_uint(
|
|
apu.average_gfx_current, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
# --- throttle ---
|
|
"apu_metrics.throttle_status": _validate_if_max_uint(
|
|
apu.throttle_status, MaxUIntegerTypes.UINT32_T, isBool=True
|
|
),
|
|
"apu_metrics.indep_throttle_status": _validate_if_max_uint(
|
|
apu.indep_throttle_status, MaxUIntegerTypes.UINT64_T, isBool=True
|
|
),
|
|
"apu_metrics.throttle_residency_prochot": _validate_if_max_uint(
|
|
apu.throttle_residency_prochot, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
"apu_metrics.throttle_residency_spl": _validate_if_max_uint(
|
|
apu.throttle_residency_spl, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
"apu_metrics.throttle_residency_fppt": _validate_if_max_uint(
|
|
apu.throttle_residency_fppt, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
"apu_metrics.throttle_residency_sppt": _validate_if_max_uint(
|
|
apu.throttle_residency_sppt, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
"apu_metrics.throttle_residency_thm_core": _validate_if_max_uint(
|
|
apu.throttle_residency_thm_core, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
"apu_metrics.throttle_residency_thm_gfx": _validate_if_max_uint(
|
|
apu.throttle_residency_thm_gfx, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
"apu_metrics.throttle_residency_thm_soc": _validate_if_max_uint(
|
|
apu.throttle_residency_thm_soc, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
# --- fan ---
|
|
"apu_metrics.fan_pwm": _validate_if_max_uint(apu.fan_pwm, MaxUIntegerTypes.UINT16_T),
|
|
# --- other ---
|
|
"apu_metrics.time_filter_alphavalue": _validate_if_max_uint(
|
|
apu.time_filter_alphavalue, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
}
|
|
|
|
|
|
def amdsmi_get_socket_handles() -> List[c_void_p]:
|
|
"""
|
|
Function that gets socket handles. Wraps the same named function call.
|
|
|
|
Parameters:
|
|
`None`.
|
|
|
|
Returns:
|
|
`List`: List containing all of the found socket handles.
|
|
"""
|
|
socket_count = ctypes.c_uint32(0)
|
|
null_ptr = POINTER(amdsmi_wrapper.amdsmi_socket_handle)()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_socket_handles(ctypes.byref(socket_count), null_ptr))
|
|
socket_handles = (amdsmi_wrapper.amdsmi_socket_handle * socket_count.value)()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_socket_handles(ctypes.byref(socket_count), socket_handles))
|
|
sockets = [
|
|
amdsmi_wrapper.amdsmi_socket_handle(socket_handles[sock_idx])
|
|
for sock_idx in range(socket_count.value)
|
|
]
|
|
|
|
return sockets
|
|
|
|
|
|
def amdsmi_get_cpu_handles() -> Dict[str, Any]:
|
|
"""
|
|
Function that gets cpu socket handles. Wraps the same named function call.
|
|
|
|
Parameters:
|
|
`None`.
|
|
|
|
Returns:
|
|
`Dict[str, Any]`: Dictionary with keys:
|
|
- ``cpu_count`` (`int`): Number of CPU socket handles found.
|
|
- ``processor_handles`` (`List[c_void_p]`): List of CPU socket handles.
|
|
"""
|
|
cpu_count = ctypes.c_uint32(0)
|
|
null_ptr = POINTER(amdsmi_wrapper.amdsmi_processor_handle)()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_handles(ctypes.byref(cpu_count), null_ptr))
|
|
proc_handles = (amdsmi_wrapper.amdsmi_processor_handle * cpu_count.value)()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_handles(ctypes.byref(cpu_count), proc_handles))
|
|
cpu_handles = [
|
|
amdsmi_wrapper.amdsmi_processor_handle(proc_handles[sock_idx])
|
|
for sock_idx in range(cpu_count.value)
|
|
]
|
|
return {"cpu_count": len(cpu_handles), "processor_handles": cpu_handles}
|
|
|
|
|
|
def amdsmi_get_socket_info(socket_handle):
|
|
if not isinstance(socket_handle, amdsmi_wrapper.amdsmi_socket_handle):
|
|
raise AmdSmiParameterException(socket_handle, amdsmi_wrapper.amdsmi_socket_handle)
|
|
socket_info = ctypes.create_string_buffer(128)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_socket_info(socket_handle, ctypes.c_size_t(128), socket_info)
|
|
)
|
|
|
|
return socket_info.value.decode()
|
|
|
|
|
|
def amdsmi_get_processor_info(processor_handle):
|
|
"""
|
|
Get a string identifier for the given processor. Wraps the same named function call.
|
|
|
|
The returned string is the processor's index as a string (for example
|
|
"0", "1", "2"): its zero-based position in the library's processor list, the
|
|
same order used by ``amdsmi_get_processor_handles``.
|
|
|
|
Parameters:
|
|
`processor_handle`: Handle of the processor to query.
|
|
|
|
Returns:
|
|
`str`: The processor index as a string.
|
|
"""
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
processor_info = ctypes.create_string_buffer(128)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_processor_info(
|
|
processor_handle, ctypes.c_size_t(128), processor_info
|
|
)
|
|
)
|
|
|
|
return processor_info.value.decode()
|
|
|
|
|
|
def amdsmi_get_processor_handles() -> List[c_void_p]:
|
|
socket_handles = amdsmi_get_socket_handles()
|
|
devices = []
|
|
for socket in socket_handles:
|
|
device_count = ctypes.c_uint32()
|
|
null_ptr = POINTER(amdsmi_wrapper.amdsmi_processor_handle)()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_processor_handles(
|
|
socket, ctypes.byref(device_count), null_ptr
|
|
)
|
|
)
|
|
processor_handles = (amdsmi_wrapper.amdsmi_processor_handle * device_count.value)()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_processor_handles(
|
|
socket, ctypes.byref(device_count), processor_handles
|
|
)
|
|
)
|
|
devices.extend(
|
|
[
|
|
amdsmi_wrapper.amdsmi_processor_handle(processor_handles[dev_idx])
|
|
for dev_idx in range(device_count.value)
|
|
]
|
|
)
|
|
|
|
return devices
|
|
|
|
|
|
def amdsmi_get_cpucore_handles() -> List[c_void_p]:
|
|
cores_count = ctypes.c_uint32(0)
|
|
null_ptr = POINTER(amdsmi_wrapper.amdsmi_processor_handle)()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpucore_handles(ctypes.byref(cores_count), null_ptr))
|
|
proc_handles = (amdsmi_wrapper.amdsmi_processor_handle * cores_count.value)()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpucore_handles(ctypes.byref(cores_count), proc_handles))
|
|
core_handles = [
|
|
amdsmi_wrapper.amdsmi_processor_handle(proc_handles[sock_idx])
|
|
for sock_idx in range(cores_count.value)
|
|
]
|
|
|
|
return core_handles
|
|
|
|
|
|
def amdsmi_get_cpu_hsmp_proto_ver(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
proto_ver = ctypes.c_uint32()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_hsmp_proto_ver(processor_handle, ctypes.byref(proto_ver))
|
|
)
|
|
|
|
return proto_ver.value
|
|
|
|
|
|
def amdsmi_get_cpu_smu_fw_version(processor_handle: processor_handle_t) -> Dict[str, int]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
smu_fw = amdsmi_wrapper.amdsmi_smu_fw_version_t()
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_smu_fw_version(processor_handle, smu_fw))
|
|
|
|
return {
|
|
"smu_fw_debug_ver_num": smu_fw.debug,
|
|
"smu_fw_minor_ver_num": smu_fw.minor,
|
|
"smu_fw_major_ver_num": smu_fw.major,
|
|
}
|
|
|
|
|
|
def amdsmi_get_cpu_hsmp_driver_version(processor_handle: processor_handle_t) -> Dict[str, int]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
hsmp_driver_version = amdsmi_wrapper.amdsmi_hsmp_driver_version_t()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_hsmp_driver_version(processor_handle, hsmp_driver_version)
|
|
)
|
|
|
|
return {
|
|
"hsmp_driver_major_ver_num": hsmp_driver_version.major,
|
|
"hsmp_driver_minor_ver_num": hsmp_driver_version.minor,
|
|
}
|
|
|
|
|
|
def amdsmi_get_cpu_core_energy(processor_handle: processor_handle_t) -> str:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
penergy = ctypes.c_uint64()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_core_energy(processor_handle, ctypes.byref(penergy)))
|
|
|
|
return f"{float(penergy.value * pow(10, -6))} J"
|
|
|
|
|
|
def amdsmi_get_cpu_core_ccd_power(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
power = ctypes.c_uint32()
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_core_ccd_power(processor_handle, ctypes.byref(power)))
|
|
|
|
return power.value # in mW
|
|
|
|
|
|
def amdsmi_get_cpu_socket_energy(processor_handle: processor_handle_t) -> str:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
penergy = ctypes.c_uint64()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_socket_energy(processor_handle, ctypes.byref(penergy)))
|
|
|
|
return f"{float(penergy.value * pow(10, -6))} J"
|
|
|
|
|
|
def amdsmi_get_threads_per_core():
|
|
threads_per_core = ctypes.c_uint32()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_threads_per_core(ctypes.byref(threads_per_core)))
|
|
|
|
return threads_per_core.value
|
|
|
|
|
|
def amdsmi_get_cpu_prochot_status(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
prochot = ctypes.c_uint32()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_prochot_status(processor_handle, ctypes.byref(prochot))
|
|
)
|
|
|
|
return prochot.value
|
|
|
|
|
|
def amdsmi_get_cpu_fclk_mclk(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
fclk = ctypes.c_uint32()
|
|
mclk = ctypes.c_uint32()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_fclk_mclk(
|
|
processor_handle, ctypes.byref(fclk), ctypes.byref(mclk)
|
|
)
|
|
)
|
|
|
|
return {"fclk": f"{fclk.value} MHz", "mclk": f"{mclk.value} MHz"}
|
|
|
|
|
|
def amdsmi_get_cpu_cclk_limit(processor_handle: processor_handle_t) -> str:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
cclk = ctypes.c_uint32()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_cclk_limit(processor_handle, ctypes.byref(cclk)))
|
|
|
|
return f"{cclk.value} MHz"
|
|
|
|
|
|
def amdsmi_get_cpu_socket_current_active_freq_limit(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
amdsmi_wrapper.amdsmi_get_cpu_socket_current_active_freq_limit.argtypes = [
|
|
amdsmi_wrapper.amdsmi_processor_handle,
|
|
POINTER(ctypes.c_uint16),
|
|
POINTER(ctypes.c_char_p * len(amdsmi_wrapper.amdsmi_hsmp_freqlimit_src_names)),
|
|
]
|
|
freq = ctypes.c_uint16()
|
|
src_type = (ctypes.c_char_p * len(amdsmi_wrapper.amdsmi_hsmp_freqlimit_src_names))()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_socket_current_active_freq_limit(
|
|
processor_handle, ctypes.byref(freq), src_type
|
|
)
|
|
)
|
|
|
|
freq_src = []
|
|
for names in src_type:
|
|
if names is not None:
|
|
freq_src.append(names.decode("utf-8"))
|
|
|
|
return {"freq": f"{freq.value} MHz", "freq_src": f"{freq_src}"}
|
|
|
|
|
|
def amdsmi_get_cpu_socket_freq_range(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
freq_max = ctypes.c_uint16()
|
|
freq_min = ctypes.c_uint16()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_socket_freq_range(
|
|
processor_handle, ctypes.byref(freq_max), ctypes.byref(freq_min)
|
|
)
|
|
)
|
|
|
|
return {"max_socket_freq": f"{freq_max.value} MHz", "min_socket_freq": f"{freq_min.value} MHz"}
|
|
|
|
|
|
def amdsmi_get_cpu_core_current_freq_limit(processor_handle: processor_handle_t) -> str:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
freq = ctypes.c_uint32()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_core_current_freq_limit(processor_handle, ctypes.byref(freq))
|
|
)
|
|
|
|
return f"{freq.value} MHz"
|
|
|
|
|
|
def amdsmi_get_cpu_socket_power(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
ppower = ctypes.c_uint32()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_socket_power(processor_handle, ctypes.byref(ppower)))
|
|
|
|
return ppower.value # in mW
|
|
|
|
|
|
def amdsmi_get_cpu_socket_power_cap(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
pcap = ctypes.c_uint32()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_socket_power_cap(processor_handle, ctypes.byref(pcap)))
|
|
|
|
return pcap.value # in mW
|
|
|
|
|
|
def amdsmi_get_cpu_socket_power_cap_max(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
pmax = ctypes.c_uint32()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_socket_power_cap_max(processor_handle, ctypes.byref(pmax))
|
|
)
|
|
|
|
return pmax.value # in mW
|
|
|
|
|
|
def amdsmi_get_cpu_pwr_svi_telemetry_all_rails(processor_handle: processor_handle_t) -> str:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
power = ctypes.c_uint32()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_pwr_svi_telemetry_all_rails(
|
|
processor_handle, ctypes.byref(power)
|
|
)
|
|
)
|
|
|
|
return f"{power.value} mW"
|
|
|
|
|
|
def amdsmi_set_cpu_socket_power_cap(processor_handle: processor_handle_t, power_cap: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(power_cap, int):
|
|
raise AmdSmiParameterException(power_cap, int)
|
|
|
|
power_cap_32 = ctypes.c_uint32(power_cap)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_set_cpu_socket_power_cap(processor_handle, power_cap_32))
|
|
|
|
|
|
def amdsmi_set_cpu_pwr_efficiency_mode(
|
|
processor_handle: processor_handle_t,
|
|
mode: int,
|
|
util: int = AMDSMI_MAX_UTIL,
|
|
ppt_limit: int = AMDSMI_MAX_PPT_LIMIT,
|
|
) -> tuple:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(mode, int):
|
|
raise AmdSmiParameterException(mode, int)
|
|
if not isinstance(util, int):
|
|
raise AmdSmiParameterException(util, int)
|
|
if not isinstance(ppt_limit, int):
|
|
raise AmdSmiParameterException(ppt_limit, int)
|
|
|
|
mode_8 = ctypes.c_uint8(mode)
|
|
util_32 = ctypes.c_uint32(util)
|
|
ppt_limit_32 = ctypes.c_uint32(ppt_limit)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_cpu_pwr_efficiency_mode(
|
|
processor_handle, mode_8, ctypes.byref(util_32), ctypes.byref(ppt_limit_32)
|
|
)
|
|
)
|
|
|
|
return (util_32.value, ppt_limit_32.value)
|
|
|
|
|
|
def amdsmi_get_cpu_pwr_efficiency_mode(processor_handle: processor_handle_t) -> tuple:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
mode = ctypes.c_uint32()
|
|
util = ctypes.c_uint32()
|
|
ppt_limit = ctypes.c_uint32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_pwr_efficiency_mode(
|
|
processor_handle, ctypes.byref(mode), ctypes.byref(util), ctypes.byref(ppt_limit)
|
|
)
|
|
)
|
|
|
|
return (mode.value, util.value, ppt_limit.value)
|
|
|
|
|
|
def amdsmi_get_cpu_core_boostlimit(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
boostlimit = ctypes.c_uint32()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_core_boostlimit(processor_handle, ctypes.byref(boostlimit))
|
|
)
|
|
|
|
# In MHz"
|
|
return boostlimit.value
|
|
|
|
|
|
def amdsmi_get_cpu_socket_c0_residency(processor_handle: processor_handle_t) -> str:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
c0_residency = ctypes.c_uint32()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_socket_c0_residency(
|
|
processor_handle, ctypes.byref(c0_residency)
|
|
)
|
|
)
|
|
|
|
return f"{c0_residency.value} %"
|
|
|
|
|
|
def amdsmi_set_cpu_core_boostlimit(processor_handle: processor_handle_t, boostlimit: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(boostlimit, int):
|
|
raise AmdSmiParameterException(boostlimit, int)
|
|
boostlimit_32 = ctypes.c_uint32(boostlimit)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_set_cpu_core_boostlimit(processor_handle, boostlimit_32))
|
|
|
|
|
|
def amdsmi_set_cpu_socket_boostlimit(processor_handle: processor_handle_t, boostlimit: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(boostlimit, int):
|
|
raise AmdSmiParameterException(boostlimit, int)
|
|
boostlimit_32 = ctypes.c_uint32(boostlimit)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_set_cpu_socket_boostlimit(processor_handle, boostlimit_32))
|
|
|
|
|
|
def amdsmi_get_cpu_ddr_bw(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
ddr_bw = amdsmi_wrapper.amdsmi_ddr_bw_metrics_t()
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_ddr_bw(processor_handle, ddr_bw))
|
|
|
|
return {
|
|
"ddr_bw_max_bw": f"{ddr_bw.max_bw} Gbps",
|
|
"ddr_bw_utilized_bw": f"{ddr_bw.utilized_bw} Gbps",
|
|
"ddr_bw_utilized_pct": f"{ddr_bw.utilized_pct} %",
|
|
}
|
|
|
|
|
|
def amdsmi_get_cpu_socket_temperature(processor_handle: processor_handle_t) -> str:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
ptmon = ctypes.c_uint32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_socket_temperature(processor_handle, ctypes.byref(ptmon))
|
|
)
|
|
|
|
return f"{ptmon.value} Degrees C"
|
|
|
|
|
|
def amdsmi_get_cpu_dimm_temp_range_and_refresh_rate(
|
|
processor_handle: processor_handle_t, dimm_addr: int
|
|
):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(dimm_addr, int):
|
|
raise AmdSmiParameterException(dimm_addr, int)
|
|
|
|
dimm_addr_8 = ctypes.c_uint8(dimm_addr)
|
|
dimm = amdsmi_wrapper.amdsmi_temp_range_refresh_rate_t()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_dimm_temp_range_and_refresh_rate(
|
|
processor_handle, dimm_addr_8, ctypes.byref(dimm)
|
|
)
|
|
)
|
|
|
|
return {"dimm_temperature_range": dimm.range, "dimm_refresh_rate": dimm.ref_rate}
|
|
|
|
|
|
def amdsmi_get_cpu_dimm_power_consumption(processor_handle: processor_handle_t, dimm_addr: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(dimm_addr, int):
|
|
raise AmdSmiParameterException(dimm_addr, int)
|
|
|
|
dimm_addr_8 = ctypes.c_uint8(dimm_addr)
|
|
dimm = amdsmi_wrapper.amdsmi_dimm_power_t()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_dimm_power_consumption(
|
|
processor_handle, dimm_addr_8, ctypes.byref(dimm)
|
|
)
|
|
)
|
|
|
|
return {
|
|
"dimm_power_consumed": f"{dimm.power} mW",
|
|
"dimm_power_update_rate": f"{dimm.update_rate} ms",
|
|
"dimm_dimm_addr": dimm.dimm_addr,
|
|
}
|
|
|
|
|
|
def amdsmi_get_cpu_dimm_thermal_sensor(processor_handle: processor_handle_t, dimm_addr: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(dimm_addr, int):
|
|
raise AmdSmiParameterException(dimm_addr, int)
|
|
|
|
dimm_addr_8 = ctypes.c_uint8(dimm_addr)
|
|
dimm_thermal = amdsmi_wrapper.amdsmi_dimm_thermal_t()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_dimm_thermal_sensor(
|
|
processor_handle, dimm_addr_8, ctypes.byref(dimm_thermal)
|
|
)
|
|
)
|
|
|
|
return {
|
|
"dimm_thermal_sensor_value": dimm_thermal.sensor,
|
|
"dimm_thermal_update_rate": f"{dimm_thermal.update_rate} ms",
|
|
"dimm_thermal_dimm_addr": dimm_thermal.dimm_addr,
|
|
"dimm_thermal_temperature": f"{dimm_thermal.temp} Degrees C",
|
|
}
|
|
|
|
|
|
def amdsmi_set_cpu_xgmi_width(processor_handle: processor_handle_t, min_width: int, max_width: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(min_width, int):
|
|
raise AmdSmiParameterException(min_width, int)
|
|
if not isinstance(max_width, int):
|
|
raise AmdSmiParameterException(max_width, int)
|
|
|
|
min_width_8 = ctypes.c_uint8(min_width)
|
|
max_width_8 = ctypes.c_uint8(max_width)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_set_cpu_xgmi_width(processor_handle, min_width_8, max_width_8))
|
|
|
|
|
|
def amdsmi_set_cpu_gmi3_link_width_range(
|
|
processor_handle: processor_handle_t, min_link_width: int, max_link_width: int
|
|
):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(min_link_width, int):
|
|
raise AmdSmiParameterException(min_link_width, int)
|
|
if not isinstance(max_link_width, int):
|
|
raise AmdSmiParameterException(max_link_width, int)
|
|
|
|
min_link_width_8 = ctypes.c_uint8(min_link_width)
|
|
max_link_width_8 = ctypes.c_uint8(max_link_width)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_cpu_gmi3_link_width_range(
|
|
processor_handle, min_link_width_8, max_link_width_8
|
|
)
|
|
)
|
|
|
|
|
|
def amdsmi_cpu_apb_enable(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_cpu_apb_enable(processor_handle))
|
|
|
|
|
|
def amdsmi_cpu_apb_disable(processor_handle: processor_handle_t, pstate: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(pstate, int):
|
|
raise AmdSmiParameterException(pstate, int)
|
|
|
|
pstate_8 = ctypes.c_uint8(pstate)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_cpu_apb_disable(processor_handle, pstate_8))
|
|
|
|
|
|
def amdsmi_set_cpu_socket_lclk_dpm_level(
|
|
processor_handle: processor_handle_t, nbio_id: int, min_val: int, max_val: int
|
|
):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(nbio_id, int):
|
|
raise AmdSmiParameterException(nbio_id, int)
|
|
if not isinstance(min_val, int):
|
|
raise AmdSmiParameterException(min_val, int)
|
|
if not isinstance(max_val, int):
|
|
raise AmdSmiParameterException(max_val, int)
|
|
|
|
nbio_id_8 = ctypes.c_uint8(nbio_id)
|
|
min_val_8 = ctypes.c_uint8(min_val)
|
|
max_val_8 = ctypes.c_uint8(max_val)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_cpu_socket_lclk_dpm_level(
|
|
processor_handle, nbio_id_8, min_val_8, max_val_8
|
|
)
|
|
)
|
|
|
|
|
|
def amdsmi_get_cpu_socket_lclk_dpm_level(processor_handle: processor_handle_t, nbio_id: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(nbio_id, int):
|
|
raise AmdSmiParameterException(nbio_id, int)
|
|
|
|
nbio_id_8 = ctypes.c_uint8(nbio_id)
|
|
dpm_level = amdsmi_wrapper.amdsmi_dpm_level_t()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_socket_lclk_dpm_level(processor_handle, nbio_id_8, dpm_level)
|
|
)
|
|
|
|
return {
|
|
"nbio_max_dpm_level": dpm_level.max_dpm_level,
|
|
"nbio_min_dpm_level": dpm_level.min_dpm_level,
|
|
}
|
|
|
|
|
|
def amdsmi_set_cpu_pcie_link_rate(processor_handle: processor_handle_t, rate_ctrl: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(rate_ctrl, int):
|
|
raise AmdSmiParameterException(rate_ctrl, int)
|
|
|
|
rate_ctrl_8 = ctypes.c_uint8(rate_ctrl)
|
|
prev_mode_8 = ctypes.c_uint8()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_cpu_pcie_link_rate(
|
|
processor_handle, rate_ctrl_8, ctypes.byref(prev_mode_8)
|
|
)
|
|
)
|
|
|
|
return f"{prev_mode_8.value}"
|
|
|
|
|
|
def amdsmi_set_cpu_df_pstate_range(
|
|
processor_handle: processor_handle_t, min_pstate: int, max_pstate: int
|
|
):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(min_pstate, int):
|
|
raise AmdSmiParameterException(min_pstate, int)
|
|
if not isinstance(max_pstate, int):
|
|
raise AmdSmiParameterException(max_pstate, int)
|
|
|
|
min_pstate_8 = ctypes.c_uint8(min_pstate)
|
|
max_pstate_8 = ctypes.c_uint8(max_pstate)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_cpu_df_pstate_range(processor_handle, min_pstate_8, max_pstate_8)
|
|
)
|
|
|
|
|
|
def amdsmi_get_cpu_current_io_bandwidth(
|
|
processor_handle: processor_handle_t, encoding: int, link_name: str
|
|
):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(encoding, int):
|
|
raise AmdSmiParameterException(encoding, int)
|
|
if not isinstance(link_name, str):
|
|
raise AmdSmiParameterException(link_name, str)
|
|
|
|
link = amdsmi_wrapper.amdsmi_link_id_bw_type_t()
|
|
link.bw_type = ctypes.c_uint32(encoding)
|
|
link.link_name = ctypes.create_string_buffer(link_name.encode("utf-8"))
|
|
io_bw = ctypes.c_uint32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_current_io_bandwidth(
|
|
processor_handle, link, ctypes.byref(io_bw)
|
|
)
|
|
)
|
|
|
|
return f"{io_bw.value} Mbps"
|
|
|
|
|
|
def amdsmi_get_cpu_current_xgmi_bw(
|
|
processor_handle: processor_handle_t, encoding: int, link_name: str
|
|
):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(encoding, int):
|
|
raise AmdSmiParameterException(encoding, int)
|
|
if not isinstance(link_name, str):
|
|
raise AmdSmiParameterException(link_name, str)
|
|
|
|
link = amdsmi_wrapper.amdsmi_link_id_bw_type_t()
|
|
link.bw_type = ctypes.c_uint32(encoding)
|
|
link.link_name = ctypes.create_string_buffer(link_name.encode("utf-8"))
|
|
xgmi_bw = ctypes.c_uint32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_current_xgmi_bw(processor_handle, link, ctypes.byref(xgmi_bw))
|
|
)
|
|
|
|
return f"{xgmi_bw.value} Mbps"
|
|
|
|
|
|
def amdsmi_get_hsmp_metrics_table_version(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
metric_tbl_version = ctypes.c_uint32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_hsmp_metrics_table_version(
|
|
processor_handle, ctypes.byref(metric_tbl_version)
|
|
)
|
|
)
|
|
|
|
return metric_tbl_version.value
|
|
|
|
|
|
def amdsmi_set_cpu_xgmi_pstate_range(
|
|
processor_handle: processor_handle_t, min_pstate: int, max_pstate: int
|
|
):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(min_pstate, int):
|
|
raise AmdSmiParameterException(min_pstate, int)
|
|
if not isinstance(max_pstate, int):
|
|
raise AmdSmiParameterException(max_pstate, int)
|
|
|
|
min_pstate_8 = ctypes.c_uint8(min_pstate)
|
|
max_pstate_8 = ctypes.c_uint8(max_pstate)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_cpu_xgmi_pstate_range(
|
|
processor_handle, min_pstate_8, max_pstate_8
|
|
)
|
|
)
|
|
|
|
|
|
def amdsmi_get_cpu_xgmi_pstate_range(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
min_pstate = ctypes.c_uint8()
|
|
max_pstate = ctypes.c_uint8()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_xgmi_pstate_range(
|
|
processor_handle, ctypes.byref(min_pstate), ctypes.byref(max_pstate)
|
|
)
|
|
)
|
|
|
|
return {"min_pstate": min_pstate.value, "max_pstate": max_pstate.value}
|
|
|
|
|
|
def amdsmi_set_cpu_rail_isofreq_policy(processor_handle: processor_handle_t, value: int) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(value, int):
|
|
raise AmdSmiParameterException(value, int)
|
|
|
|
value_bool = ctypes.c_bool(value)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_cpu_rail_isofreq_policy(
|
|
processor_handle, ctypes.byref(value_bool)
|
|
)
|
|
)
|
|
|
|
value = int(value_bool.value)
|
|
return value
|
|
|
|
|
|
def amdsmi_get_cpu_rail_isofreq_policy(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
cpurailiso = ctypes.c_uint8()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_rail_isofreq_policy(
|
|
processor_handle, ctypes.byref(cpurailiso)
|
|
)
|
|
)
|
|
|
|
value = int(cpurailiso.value)
|
|
return value
|
|
|
|
|
|
def amdsmi_set_cpu_dfc_ctrl(processor_handle: processor_handle_t, value: int) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(value, int):
|
|
raise AmdSmiParameterException(value, int)
|
|
|
|
value_8 = ctypes.c_uint8(value)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_set_cpu_dfc_ctrl(processor_handle, ctypes.byref(value_8)))
|
|
|
|
return value_8.value
|
|
|
|
|
|
def amdsmi_get_cpu_dfc_ctrl(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
dfc_ctrl = ctypes.c_uint8()
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_dfc_ctrl(processor_handle, ctypes.byref(dfc_ctrl)))
|
|
|
|
return dfc_ctrl.value
|
|
|
|
|
|
def amdsmi_set_cpu_pc6_enable(processor_handle: processor_handle_t, value: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(value, int):
|
|
raise AmdSmiParameterException(value, int)
|
|
|
|
value_8 = ctypes.c_uint8(value)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_set_cpu_pc6_enable(processor_handle, value_8))
|
|
|
|
|
|
def amdsmi_get_cpu_pc6_enable(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
pc6_enable = ctypes.c_uint8()
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_pc6_enable(processor_handle, ctypes.byref(pc6_enable)))
|
|
|
|
return pc6_enable.value
|
|
|
|
|
|
def amdsmi_set_cpu_cc6_enable(processor_handle: processor_handle_t, value: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(value, int):
|
|
raise AmdSmiParameterException(value, int)
|
|
|
|
value_8 = ctypes.c_uint8(value)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_set_cpu_cc6_enable(processor_handle, value_8))
|
|
|
|
|
|
def amdsmi_get_cpu_cc6_enable(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
cc6_enable = ctypes.c_uint8()
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_cc6_enable(processor_handle, ctypes.byref(cc6_enable)))
|
|
|
|
return cc6_enable.value
|
|
|
|
|
|
def amdsmi_get_cpu_dimm_sb_reg(
|
|
processor_handle: processor_handle_t, dimm_addr: int, lid: int, reg_offset: int, reg_space: int
|
|
):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(dimm_addr, int):
|
|
raise AmdSmiParameterException(dimm_addr, int)
|
|
if not isinstance(lid, int):
|
|
raise AmdSmiParameterException(lid, int)
|
|
if not isinstance(reg_offset, int):
|
|
raise AmdSmiParameterException(reg_offset, int)
|
|
if not isinstance(reg_space, int):
|
|
raise AmdSmiParameterException(reg_space, int)
|
|
|
|
dimm_addr_32 = ctypes.c_uint32(dimm_addr)
|
|
lid_32 = ctypes.c_uint32(lid)
|
|
reg_offset_32 = ctypes.c_uint32(reg_offset)
|
|
reg_space_32 = ctypes.c_uint32(reg_space)
|
|
data = ctypes.c_uint32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_dimm_sb_reg(
|
|
processor_handle, dimm_addr_32, lid_32, reg_offset_32, reg_space_32, ctypes.byref(data)
|
|
)
|
|
)
|
|
|
|
return data.value
|
|
|
|
|
|
def amdsmi_set_cpu_dimm_sb_reg(
|
|
processor_handle: processor_handle_t,
|
|
dimm_addr: int,
|
|
lid: int,
|
|
reg_offset: int,
|
|
reg_space: int,
|
|
write_data: int,
|
|
):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(dimm_addr, int):
|
|
raise AmdSmiParameterException(dimm_addr, int)
|
|
if not isinstance(lid, int):
|
|
raise AmdSmiParameterException(lid, int)
|
|
if not isinstance(reg_offset, int):
|
|
raise AmdSmiParameterException(reg_offset, int)
|
|
if not isinstance(reg_space, int):
|
|
raise AmdSmiParameterException(reg_space, int)
|
|
if not isinstance(write_data, int):
|
|
raise AmdSmiParameterException(write_data, int)
|
|
|
|
dimm_addr_32 = ctypes.c_uint32(dimm_addr)
|
|
lid_32 = ctypes.c_uint32(lid)
|
|
reg_offset_32 = ctypes.c_uint32(reg_offset)
|
|
reg_space_32 = ctypes.c_uint32(reg_space)
|
|
write_data_32 = ctypes.c_uint32(write_data)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_cpu_dimm_sb_reg(
|
|
processor_handle, dimm_addr_32, lid_32, reg_offset_32, reg_space_32, write_data_32
|
|
)
|
|
)
|
|
|
|
|
|
def amdsmi_get_cpu_tdelta(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
tdelta = ctypes.c_uint8()
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_tdelta(processor_handle, ctypes.byref(tdelta)))
|
|
|
|
return tdelta.value
|
|
|
|
|
|
def amdsmi_get_cpu_svi3_vr_controller_temp(
|
|
processor_handle: processor_handle_t,
|
|
rail_selection: int,
|
|
rail_index: int = AMDSMI_MAX_RAIL_INDEX,
|
|
) -> dict:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(rail_selection, int):
|
|
raise AmdSmiParameterException(rail_selection, int)
|
|
if not isinstance(rail_index, int):
|
|
raise AmdSmiParameterException(rail_index, int)
|
|
|
|
rail_selection_32 = ctypes.c_uint32(rail_selection)
|
|
rail_index_32 = ctypes.c_uint32(rail_index)
|
|
temperature_32 = ctypes.c_uint32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_svi3_vr_controller_temp(
|
|
processor_handle,
|
|
ctypes.byref(rail_selection_32),
|
|
ctypes.byref(rail_index_32),
|
|
ctypes.byref(temperature_32),
|
|
)
|
|
)
|
|
|
|
return {
|
|
"rail_selection": rail_selection_32.value,
|
|
"rail_index": rail_index_32.value,
|
|
"temperature": temperature_32.value,
|
|
}
|
|
|
|
|
|
def amdsmi_get_cpu_enabled_commands(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
# First call for read commands
|
|
mask = ctypes.c_bool(True)
|
|
read_mask0_u32 = ctypes.c_uint32()
|
|
read_mask1_u32 = ctypes.c_uint32()
|
|
read_mask2_u32 = ctypes.c_uint32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_enabled_commands(
|
|
processor_handle,
|
|
ctypes.byref(mask),
|
|
ctypes.byref(read_mask0_u32),
|
|
ctypes.byref(read_mask1_u32),
|
|
ctypes.byref(read_mask2_u32),
|
|
)
|
|
)
|
|
|
|
# Second call for write commands
|
|
mask = ctypes.c_bool(False)
|
|
write_mask0_u32 = ctypes.c_uint32()
|
|
write_mask1_u32 = ctypes.c_uint32()
|
|
write_mask2_u32 = ctypes.c_uint32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_enabled_commands(
|
|
processor_handle,
|
|
ctypes.byref(mask),
|
|
ctypes.byref(write_mask0_u32),
|
|
ctypes.byref(write_mask1_u32),
|
|
ctypes.byref(write_mask2_u32),
|
|
)
|
|
)
|
|
|
|
return {
|
|
"ReadEnabledCommandsBitMask0": read_mask0_u32.value,
|
|
"ReadEnabledCommandsBitMask1": read_mask1_u32.value,
|
|
"ReadEnabledCommandsBitMask2": read_mask2_u32.value,
|
|
"WriteEnabledCommandsBitMask0": write_mask0_u32.value,
|
|
"WriteEnabledCommandsBitMask1": write_mask1_u32.value,
|
|
"WriteEnabledCommandsBitMask2": write_mask2_u32.value,
|
|
}
|
|
|
|
|
|
def amdsmi_get_cpu_core_floor_freq_limit(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
floorlimit = ctypes.c_uint32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_core_floor_freq_limit(
|
|
processor_handle, ctypes.byref(floorlimit)
|
|
)
|
|
)
|
|
|
|
# In MHz
|
|
return floorlimit.value
|
|
|
|
|
|
def amdsmi_get_cpu_floor_freq_limit(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
floorlimit = ctypes.c_uint32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_floor_freq_limit(processor_handle, ctypes.byref(floorlimit))
|
|
)
|
|
|
|
# In MHz
|
|
return floorlimit.value
|
|
|
|
|
|
def amdsmi_get_cpu_core_eff_floor_freq_limit(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
eff_floor_freq_limit = ctypes.c_uint32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_core_eff_floor_freq_limit(
|
|
processor_handle, ctypes.byref(eff_floor_freq_limit)
|
|
)
|
|
)
|
|
|
|
# In MHz
|
|
return eff_floor_freq_limit.value
|
|
|
|
|
|
def amdsmi_get_cpu_eff_floor_freq_limit(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
eff_floor_freq_limit = ctypes.c_uint32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_eff_floor_freq_limit(
|
|
processor_handle, ctypes.byref(eff_floor_freq_limit)
|
|
)
|
|
)
|
|
|
|
# In MHz
|
|
return eff_floor_freq_limit.value
|
|
|
|
|
|
def amdsmi_set_cpu_core_floor_freq_limit(processor_handle: processor_handle_t, floorlimit: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(floorlimit, int):
|
|
raise AmdSmiParameterException(floorlimit, int)
|
|
|
|
floorlimit_32 = ctypes.c_uint32(floorlimit)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_set_cpu_core_floor_freq_limit(processor_handle, floorlimit_32))
|
|
|
|
|
|
def amdsmi_set_cpu_floor_freq_limit(processor_handle: processor_handle_t, floorlimit: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(floorlimit, int):
|
|
raise AmdSmiParameterException(floorlimit, int)
|
|
|
|
floorlimit_32 = ctypes.c_uint32(floorlimit)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_set_cpu_floor_freq_limit(processor_handle, floorlimit_32))
|
|
|
|
|
|
def amdsmi_set_cpu_msr_floor_freq_limit(processor_handle: processor_handle_t, msrfloorlimit: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(msrfloorlimit, int):
|
|
raise AmdSmiParameterException(msrfloorlimit, int)
|
|
|
|
msrfloorlimit_32 = ctypes.c_uint32(msrfloorlimit)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_cpu_msr_floor_freq_limit(processor_handle, msrfloorlimit_32)
|
|
)
|
|
|
|
|
|
def amdsmi_set_cpu_core_msr_floor_freq_limit(
|
|
processor_handle: processor_handle_t, msrfloorlimit: int
|
|
):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(msrfloorlimit, int):
|
|
raise AmdSmiParameterException(msrfloorlimit, int)
|
|
|
|
msrfloorlimit_32 = ctypes.c_uint32(msrfloorlimit)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_cpu_core_msr_floor_freq_limit(processor_handle, msrfloorlimit_32)
|
|
)
|
|
|
|
|
|
def amdsmi_get_cpu_freq_range() -> Dict[str, int]:
|
|
|
|
fmax = ctypes.c_uint32()
|
|
fmin = ctypes.c_uint32()
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_freq_range(ctypes.byref(fmax), ctypes.byref(fmin)))
|
|
|
|
# In MHz
|
|
return {"fmax": fmax.value, "fmin": fmin.value}
|
|
|
|
|
|
def amdsmi_set_cpu_sdps_limit(processor_handle: processor_handle_t, sdps_limit: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(sdps_limit, int):
|
|
raise AmdSmiParameterException(sdps_limit, int)
|
|
|
|
sdps_limit_32 = ctypes.c_uint32(sdps_limit)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_set_cpu_sdps_limit(processor_handle, sdps_limit_32))
|
|
|
|
|
|
def amdsmi_get_cpu_sdps_limit(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
sdps_limit = ctypes.c_uint32()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_sdps_limit(processor_handle, ctypes.byref(sdps_limit)))
|
|
|
|
return sdps_limit.value # in mW
|
|
|
|
|
|
def amdsmi_get_hsmp_metrics_table(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
mtbl = amdsmi_wrapper.amdsmi_hsmp_metrics_table_t()
|
|
|
|
# Encodings for the metric table defined for hsmp
|
|
fraction_q10 = 1 / math.pow(2, 10)
|
|
fraction_uq10 = fraction_q10
|
|
fraction_uq16 = 1 / math.pow(2, 16)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_hsmp_metrics_table(processor_handle, mtbl))
|
|
|
|
rawtime = int(mtbl.timestamp)
|
|
rawtime = time()
|
|
timeinfo = localtime(rawtime)
|
|
|
|
return {
|
|
"mtbl_accumulation_counter": mtbl.accumulation_counter,
|
|
"mtbl_max_socket_temperature": f"{round(_check_msb_32(mtbl.max_socket_temperature) * fraction_q10, 3)} °C",
|
|
"mtbl_max_vr_temperature": f"{round(_check_msb_32(mtbl.max_vr_temperature) * fraction_q10, 3)} °C",
|
|
"mtbl_max_hbm_temperature": f"{round(_check_msb_32(mtbl.max_hbm_temperature) * fraction_q10, 3)} °C",
|
|
"mtbl_max_socket_temperature_acc": f"{round(_check_msb_64(mtbl.max_socket_temperature_acc) * fraction_q10, 3)} °C",
|
|
"mtbl_max_vr_temperature_acc": f"{round(_check_msb_64(mtbl.max_vr_temperature_acc) * fraction_q10, 3)} °C",
|
|
"mtbl_max_hbm_temperature_acc": f"{round(_check_msb_64(mtbl.max_hbm_temperature_acc) * fraction_q10, 3)} °C",
|
|
"mtbl_socket_power_limit": f"{round(mtbl.socket_power_limit * fraction_uq10, 3)} W",
|
|
"mtbl_max_socket_power_limit": f"{round(mtbl.max_socket_power_limit * fraction_uq10, 3)} W",
|
|
"mtbl_socket_power": f"{round(mtbl.socket_power * fraction_uq10, 3)} W",
|
|
"mtbl_timestamp_raw": mtbl.timestamp,
|
|
"mtbl_timestamp_readable": f"{asctime(timeinfo)}",
|
|
"mtbl_socket_energy_acc": f"{round((mtbl.socket_energy_acc * fraction_uq16) / KILO, 3)} kJ",
|
|
"mtbl_ccd_energy_acc": f"{round((mtbl.ccd_energy_acc * fraction_uq16) / KILO, 3)} kJ",
|
|
"mtbl_xcd_energy_acc": f"{round((mtbl.xcd_energy_acc * fraction_uq16) / KILO, 3)} kJ",
|
|
"mtbl_aid_energy_acc": f"{round((mtbl.aid_energy_acc * fraction_uq16) / KILO, 3)} kJ",
|
|
"mtbl_hbm_energy_acc": f"{round((mtbl.hbm_energy_acc * fraction_uq16) / KILO, 3)} kJ",
|
|
"mtbl_cclk_frequency_limit": f"{round(mtbl.cclk_frequency_limit * fraction_uq10, 3)} GHz",
|
|
"mtbl_gfxclk_frequency_limit": f"{round(mtbl.gfxclk_frequency_limit * fraction_uq10, 3)} MHz",
|
|
"mtbl_fclk_frequency": f"{round(mtbl.fclk_frequency * fraction_uq10, 3)} MHz",
|
|
"mtbl_uclk_frequency": f"{round(mtbl.uclk_frequency * fraction_uq10, 3)} MHz",
|
|
"mtbl_socclk_frequency": f"{[round(x * fraction_uq10, 3) for x in list(mtbl.socclk_frequency)]} MHz",
|
|
"mtbl_vclk_frequency": f"{[round(x * fraction_uq10, 3) for x in list(mtbl.vclk_frequency)]} MHz",
|
|
"mtbl_dclk_frequency": f"{[round(x * fraction_uq10, 3) for x in list(mtbl.dclk_frequency)]} MHz",
|
|
"mtbl_lclk_frequency": f"{[round(x * fraction_uq10, 3) for x in list(mtbl.lclk_frequency)]} MHz",
|
|
"mtbl_fclk_frequency_table": f"{[round(x * fraction_uq10, 3) for x in list(mtbl.fclk_frequency_table)]} MHz",
|
|
"mtbl_uclk_frequency_table": f"{[round(x * fraction_uq10, 3) for x in list(mtbl.uclk_frequency_table)]} MHz",
|
|
"mtbl_socclk_frequency_table": f"{[round(x * fraction_uq10, 3) for x in list(mtbl.socclk_frequency_table)]} MHz",
|
|
"mtbl_vclk_frequency_table": f"{[round(x * fraction_uq10, 3) for x in list(mtbl.vclk_frequency_table)]} MHz",
|
|
"mtbl_dclk_frequency_table": f"{[round(x * fraction_uq10, 3) for x in list(mtbl.dclk_frequency_table)]} MHz",
|
|
"mtbl_lclk_frequency_table": f"{[round(x * fraction_uq10, 3) for x in list(mtbl.lclk_frequency_table)]} MHz",
|
|
"mtbl_cclk_frequency_acc": f"{[round(x * fraction_uq10, 3) for x in list(mtbl.cclk_frequency_acc)]} GHz",
|
|
"mtbl_gfxclk_frequency_acc": f"{[round(x * fraction_uq10, 3) for x in list(mtbl.gfxclk_frequency_acc)]} MHz",
|
|
"mtbl_gfxclk_frequency": f"{[round(x * fraction_uq10, 3) for x in list(mtbl.gfxclk_frequency)]} MHz",
|
|
"mtbl_max_cclk_frequency": f"{round(mtbl.max_cclk_frequency * fraction_uq10, 3)} GHz",
|
|
"mtbl_min_cclk_frequency": f"{round(mtbl.min_cclk_frequency * fraction_uq10, 3)} GHz",
|
|
"mtbl_max_gfxclk_frequency": f"{round(mtbl.max_gfxclk_frequency * fraction_uq10, 3)} MHz",
|
|
"mtbl_min_gfxclk_frequency": f"{round(mtbl.min_gfxclk_frequency * fraction_uq10, 3)} MHz",
|
|
"mtbl_max_lclk_dpm_range": mtbl.max_lclk_dpm_range,
|
|
"mtbl_min_lclk_dpm_range": mtbl.min_lclk_dpm_range,
|
|
"mtbl_xgmi_width": round(mtbl.xgmi_width * fraction_uq10, 3),
|
|
"mtbl_xgmi_bitrate": f"{round(mtbl.xgmi_bitrate * fraction_uq10, 3)} Gbps",
|
|
"mtbl_xgmi_read_bandwidth_acc": f"{[round(x * fraction_uq10, 3) for x in list(mtbl.xgmi_read_bandwidth_acc)]} Gbps",
|
|
"mtbl_xgmi_write_bandwidth_acc": f"{[round(x * fraction_uq10, 3) for x in list(mtbl.xgmi_write_bandwidth_acc)]} Gbps",
|
|
"mtbl_socket_c0_residency": f"{round(mtbl.socket_c0_residency * fraction_uq10, 3)} %",
|
|
"mtbl_socket_gfx_busy": f"{round(mtbl.socket_gfx_busy * fraction_uq10, 3)} %",
|
|
"mtbl_hbm_bandwidth_utilization": f"{round(mtbl.dram_bandwidth_utilization * fraction_uq10, 3)} %",
|
|
"mtbl_socket_c0_residency_acc": round(mtbl.socket_c0_residency_acc * fraction_uq10, 3),
|
|
"mtbl_socket_gfx_busy_acc": round(mtbl.socket_gfx_busy_acc * fraction_uq10, 3),
|
|
"mtbl_hbm_bandwidth_acc": f"{round(mtbl.dram_bandwidth_acc * fraction_uq10, 3)} Gbps",
|
|
"mtbl_max_hbm_bandwidth": f"{round(mtbl.max_dram_bandwidth * fraction_uq10, 3)} Gbps",
|
|
"mtbl_dram_bandwidth_utilization_acc": round(
|
|
mtbl.dram_bandwidth_utilization_acc * fraction_uq10, 3
|
|
),
|
|
"mtbl_pcie_bandwidth_acc": f"{[round(x * fraction_uq10, 3) for x in list(mtbl.pcie_bandwidth_acc)]} Gbps",
|
|
"mtbl_prochot_residency_acc": mtbl.prochot_residency_acc,
|
|
"mtbl_ppt_residency_acc": mtbl.ppt_residency_acc,
|
|
"mtbl_socket_thm_residency_acc": mtbl.socket_thm_residency_acc,
|
|
"mtbl_vr_thm_residency_acc": mtbl.vr_thm_residency_acc,
|
|
"mtbl_hbm_thm_residency_acc": mtbl.hbm_thm_residency_acc,
|
|
}
|
|
|
|
|
|
def amdsmi_first_online_core_on_cpu_socket(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
pcore_ind = ctypes.c_uint32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_first_online_core_on_cpu_socket(
|
|
processor_handle, ctypes.byref(pcore_ind)
|
|
)
|
|
)
|
|
|
|
return pcore_ind.value
|
|
|
|
|
|
def amdsmi_get_cpu_family():
|
|
family = ctypes.c_uint32()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_family(ctypes.byref(family)))
|
|
return family.value
|
|
|
|
|
|
def amdsmi_get_cpu_model():
|
|
model = ctypes.c_uint32()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_model(ctypes.byref(model)))
|
|
return model.value
|
|
|
|
|
|
def amdsmi_get_cpu_model_name(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
cpu_info = amdsmi_wrapper.amdsmi_cpu_info_t()
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_model_name(processor_handle, cpu_info))
|
|
return f"{cpu_info.model_name}"
|
|
|
|
|
|
def amdsmi_get_cpu_cores_per_socket(sock_count: ctypes.c_uint32):
|
|
cps = amdsmi_wrapper.amdsmi_sock_info_t()
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_cores_per_socket(sock_count, cps))
|
|
return {"socket_id": cps.socket_id, "cores_per_socket": cps.cores_per_socket}
|
|
|
|
|
|
def amdsmi_get_cpu_socket_count():
|
|
sock_count = ctypes.c_uint32()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_cpu_socket_count(ctypes.byref(sock_count)))
|
|
return sock_count.value
|
|
|
|
|
|
def amdsmi_init(flag=AmdSmiInitFlags.INIT_AMD_GPUS):
|
|
if not _amdsmi_init_enum_flag_is_valid(flag):
|
|
raise AmdSmiParameterException(flag, AmdSmiInitFlags)
|
|
_check_res(amdsmi_wrapper.amdsmi_init(flag))
|
|
|
|
|
|
def amdsmi_shut_down():
|
|
_check_res(amdsmi_wrapper.amdsmi_shut_down())
|
|
|
|
|
|
def amdsmi_get_processor_type(processor_handle: processor_handle_t) -> Dict[str, str]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
dev_type = amdsmi_wrapper.amdsmi_processor_type_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_processor_type(processor_handle, ctypes.byref(dev_type)))
|
|
|
|
return {"processor_type": AmdSmiProcessorType(dev_type.value).name}
|
|
|
|
|
|
def amdsmi_get_gpu_device_bdf(processor_handle: processor_handle_t) -> str:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
bdf_info = amdsmi_wrapper.amdsmi_bdf_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_device_bdf(processor_handle, ctypes.byref(bdf_info)))
|
|
|
|
return _format_bdf(bdf_info)
|
|
|
|
|
|
def amdsmi_get_gpu_device_bdf_bdf(
|
|
processor_handle: amdsmi_wrapper.amdsmi_processor_handle,
|
|
) -> amdsmi_wrapper.amdsmi_bdf_t:
|
|
"""Deprecated: use amdsmi_get_gpu_device_bdf() and format the returned BDF string instead.
|
|
|
|
Returns the raw amdsmi_bdf_t struct for a GPU. The same data is available as a
|
|
formatted string from amdsmi_get_gpu_device_bdf().
|
|
"""
|
|
|
|
warnings.warn(
|
|
"amdsmi_get_gpu_device_bdf_bdf() is deprecated, use amdsmi_get_gpu_device_bdf() "
|
|
"and format the returned BDF string instead",
|
|
DeprecationWarning,
|
|
stacklevel=2,
|
|
)
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
bdf_info = amdsmi_wrapper.amdsmi_bdf_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_device_bdf(processor_handle, ctypes.byref(bdf_info)))
|
|
|
|
return bdf_info
|
|
|
|
|
|
def amdsmi_get_nic_info(processor_handle: amdsmi_wrapper.amdsmi_processor_handle) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
return None # disabled feature
|
|
|
|
|
|
def amdsmi_get_ainic_info_summary(nic_info):
|
|
return {
|
|
"bdf": _format_bdf(nic_info.bus.bdf),
|
|
"UUID": nic_info.asic.permanent_address.decode("utf-8"),
|
|
"Permanent Address": nic_info.asic.permanent_address.decode("utf-8"),
|
|
# "Device Name": nic_info.asic.product_name.decode('utf-8'),
|
|
"Product Name": nic_info.asic.product_name.decode("utf-8"),
|
|
"Part Number": nic_info.asic.part_number.decode("utf-8"),
|
|
"Serial Number": nic_info.asic.serial_number.decode("utf-8"),
|
|
"Vendor Name": nic_info.asic.vendor_name.decode("utf-8"),
|
|
# "Firmware_Version": nic_info.versions.running.fw.decode('utf-8'),
|
|
}
|
|
|
|
|
|
def amdsmi_get_ainic_info_detail(ainic_info_struct):
|
|
ainic_info = {
|
|
"ASIC": {
|
|
"VENDOR_ID": hex(ainic_info_struct.asic.vendor_id),
|
|
"SUBVENDOR_ID": hex(ainic_info_struct.asic.subvendor_id),
|
|
"DEVICE_ID": hex(ainic_info_struct.asic.device_id),
|
|
"SUBSYSTEM_ID": hex(ainic_info_struct.asic.subsystem_id),
|
|
"REVISION": hex(ainic_info_struct.asic.revision),
|
|
"PERMANENT_ADDRESS": ainic_info_struct.asic.permanent_address.decode("utf-8"),
|
|
"PRODUCT_NAME": ainic_info_struct.asic.product_name.decode("utf-8"),
|
|
"PART_NUMBER": ainic_info_struct.asic.part_number.decode("utf-8"),
|
|
"SERIAL_NUMBER": ainic_info_struct.asic.serial_number.decode("utf-8"),
|
|
"VENDOR_NAME": ainic_info_struct.asic.vendor_name.decode("utf-8"),
|
|
},
|
|
"BUS": {
|
|
"bdf": _format_bdf(ainic_info_struct.bus.bdf),
|
|
"MAX_PCIE_WIDTH": int(ainic_info_struct.bus.max_pcie_width),
|
|
"MAX_PCIE_SPEED": ainic_info_struct.bus.max_pcie_speed,
|
|
"PCIE_INTERFACE_VERSION": ainic_info_struct.bus.pcie_interface_version.decode("utf-8"),
|
|
"SLOT_TYPE": ainic_info_struct.bus.slot_type.decode("utf-8"),
|
|
},
|
|
"DRIVER": {
|
|
"NAME": ainic_info_struct.driver.name.decode("utf-8"),
|
|
"VERSION": ainic_info_struct.driver.version.decode("utf-8"),
|
|
},
|
|
"NUMA": {
|
|
"NODE": ainic_info_struct.numa.node,
|
|
"AFFINITY": ainic_info_struct.numa.affinity.decode("utf-8"),
|
|
},
|
|
"FW": {
|
|
"FW_0": ainic_info_struct.driver.name.decode("utf-8"),
|
|
"FW_HEARTBEAT": ainic_info_struct.driver.version.decode("utf-8"),
|
|
},
|
|
"PORTS": {},
|
|
"RDMA_DEVICES": {},
|
|
}
|
|
port_num = 0
|
|
total_rdma_dev_num = 0
|
|
for port_info in ainic_info_struct.port.ports:
|
|
if port_num == ainic_info_struct.port.num_ports:
|
|
break
|
|
ainic_info["PORTS"][f"PORT_{port_num}"] = {
|
|
"TYPE": port_info.type.decode("utf-8"),
|
|
"FLAVOUR": port_info.flavour.decode("utf-8"),
|
|
"NETDEV": port_info.netdev.decode("utf-8"),
|
|
"IFINDEX": port_info.ifindex,
|
|
"MAC_ADDRESS": port_info.mac_address.decode("utf-8"),
|
|
"CARRIER": port_info.carrier,
|
|
"MTU": f"{port_info.mtu}B",
|
|
"LINK_STATE": port_info.link_state.decode("utf-8"),
|
|
"LINK_SPEED": f"{port_info.link_speed} Mb/s",
|
|
"ACTIVE_FEC": f"{port_info.active_fec}",
|
|
"AUTONEG": port_info.autoneg.decode("utf-8"),
|
|
"PAUSE_AUTONEG": port_info.pause_autoneg.decode("utf-8"),
|
|
"PAUSE_RX": port_info.pause_rx.decode("utf-8"),
|
|
"PAUSE_TX": port_info.pause_tx.decode("utf-8"),
|
|
}
|
|
rdma_dev_num = 0
|
|
for dev in ainic_info_struct.rdma_dev.rdma_dev_info:
|
|
if rdma_dev_num == ainic_info_struct.rdma_dev.num_rdma_dev:
|
|
break
|
|
ainic_info["RDMA_DEVICES"][f"RDMA_DEVICE_{total_rdma_dev_num}"] = {
|
|
"NAME": dev.rdma_dev.decode("utf-8"),
|
|
"NODE_GUID": dev.node_guid.decode("utf-8"),
|
|
"NODE_TYPE": dev.node_type.decode("utf-8"),
|
|
"SYS_IMAGE_GUID": dev.sys_image_guid.decode("utf-8"),
|
|
"FW_VER": dev.fw_ver.decode("utf-8"),
|
|
}
|
|
rdma_port_num = 0
|
|
for rdma_port in dev.rdma_port_info:
|
|
if (
|
|
rdma_port_num
|
|
== ainic_info_struct.rdma_dev.rdma_dev_info[rdma_dev_num].num_rdma_ports
|
|
):
|
|
break
|
|
max_mtu = rdma_port.max_mtu
|
|
max_uint16_t = (1 << 16) - 1
|
|
if max_mtu == max_uint16_t:
|
|
max_mtu = "N/A"
|
|
active_mtu = rdma_port.active_mtu
|
|
if active_mtu == max_uint16_t:
|
|
active_mtu = "N/A"
|
|
ainic_info["RDMA_DEVICES"][f"RDMA_DEVICE_{total_rdma_dev_num}"][
|
|
f"PORT_{rdma_port_num}"
|
|
] = {
|
|
"NETDEV": rdma_port.netdev.decode("utf-8"),
|
|
"PORT_NUM": rdma_port.rdma_port,
|
|
"STATE": rdma_port.state.decode("utf-8"),
|
|
"MAX_MTU": max_mtu,
|
|
"ACTIVE_MTU": active_mtu,
|
|
}
|
|
rdma_port_num = rdma_port_num + 1
|
|
rdma_dev_num = rdma_dev_num + 1
|
|
total_rdma_dev_num = total_rdma_dev_num + 1
|
|
port_num = port_num + 1
|
|
return ainic_info
|
|
|
|
|
|
class ainic_info_t:
|
|
def __init__(self, processor_handle):
|
|
self.asic = amdsmi_wrapper.amdsmi_nic_asic_info_t()
|
|
self.bus = amdsmi_wrapper.amdsmi_nic_bus_info_t()
|
|
self.driver = amdsmi_wrapper.amdsmi_nic_driver_info_t()
|
|
self.numa = amdsmi_wrapper.amdsmi_nic_numa_info_t()
|
|
self.port = amdsmi_wrapper.amdsmi_nic_port_info_t()
|
|
self.rdma_dev = amdsmi_wrapper.amdsmi_nic_rdma_devices_info_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_nic_asic_info(processor_handle, ctypes.byref(self.asic))
|
|
)
|
|
_check_res(amdsmi_wrapper.amdsmi_get_nic_bus_info(processor_handle, ctypes.byref(self.bus)))
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_nic_driver_info(processor_handle, ctypes.byref(self.driver))
|
|
)
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_nic_numa_info(processor_handle, ctypes.byref(self.numa))
|
|
)
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_nic_port_info(processor_handle, ctypes.byref(self.port))
|
|
)
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_nic_rdma_dev_info(
|
|
processor_handle, ctypes.byref(self.rdma_dev)
|
|
)
|
|
)
|
|
|
|
|
|
def amdsmi_get_ainic_info(
|
|
processor_handle: amdsmi_wrapper.amdsmi_processor_handle, detail=False
|
|
) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
nic_info = ainic_info_t(processor_handle)
|
|
if detail:
|
|
return amdsmi_get_ainic_info_detail(nic_info)
|
|
else:
|
|
return amdsmi_get_ainic_info_summary(nic_info)
|
|
|
|
|
|
def amdsmi_get_switch_device_bdf(processor_handle: amdsmi_wrapper.amdsmi_processor_handle) -> str:
|
|
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
bdf_info = amdsmi_wrapper.amdsmi_bdf_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_switch_device_bdf(processor_handle, ctypes.byref(bdf_info))
|
|
)
|
|
|
|
return _format_bdf(bdf_info)
|
|
|
|
|
|
def amdsmi_get_nic_temp_info(
|
|
processor_handle: amdsmi_wrapper.amdsmi_processor_handle,
|
|
) -> Dict[str, ctypes.c_uint32]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
temp_measure = amdsmi_wrapper.amdsmi_brcm_nic_temperature_metric_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_nic_temp_info(processor_handle, ctypes.byref(temp_measure))
|
|
)
|
|
|
|
temp_info_dict = {
|
|
"NIC_TEMP_CURRENT": math.trunc(temp_measure.nic_temp_input / 1000),
|
|
"NIC_TEMP_CRIT_ALARM": temp_measure.nic_temp_crit_alarm,
|
|
"NIC_TEMP_EMERGENCY_ALARM": temp_measure.nic_temp_emergency_alarm,
|
|
"NIC_TEMP_SHUTDOWN_ALARM": temp_measure.nic_temp_shutdown_alarm,
|
|
"NIC_TEMP_MAX_ALARM": temp_measure.nic_temp_max_alarm,
|
|
}
|
|
for key, value in temp_info_dict.items():
|
|
if value == 0xFFFF:
|
|
temp_info_dict[key] = "N/A"
|
|
|
|
return temp_info_dict
|
|
|
|
|
|
def amdsmi_get_nic_fw_info(
|
|
processor_handle: amdsmi_wrapper.amdsmi_processor_handle,
|
|
) -> Dict[str, ctypes.c_uint32]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
fw_info = amdsmi_wrapper.struct_amdsmi_brcm_nic_firmware_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_nic_fw_info(processor_handle, ctypes.byref(fw_info)))
|
|
|
|
fw_info_dict = {
|
|
"Package Version": fw_info.nic_fw_pkg_version.decode("utf-8"),
|
|
"EFI Version": fw_info.nic_fw_efi_version.decode("utf-8"),
|
|
"Firmware Version": fw_info.nic_fw_version.decode("utf-8"),
|
|
"NCSI Version": fw_info.nic_fw_ncsi_version.decode("utf-8"),
|
|
"RoCE Version": fw_info.nic_fw_roce_version.decode("utf-8"),
|
|
}
|
|
for key, value in fw_info_dict.items():
|
|
if value == "":
|
|
fw_info_dict[key] = "N/A"
|
|
|
|
return fw_info_dict
|
|
|
|
|
|
def amdsmi_get_switch_link_info(
|
|
processor_handle: amdsmi_wrapper.amdsmi_processor_handle,
|
|
) -> Dict[str, ctypes.c_uint32]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
link_measure = amdsmi_wrapper.struct_amdsmi_brcm_switch_link_metric_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_switch_link_info(processor_handle, ctypes.byref(link_measure))
|
|
)
|
|
|
|
link_info_dict = {
|
|
"CURRENT_LINK_SPEED": link_measure.current_link_speed,
|
|
"MAX_LINK_SPEED": link_measure.max_link_speed,
|
|
"CURRENT_LINK_WIDTH": link_measure.current_link_width,
|
|
"MAX_LINK_WIDTH": link_measure.max_link_width,
|
|
}
|
|
for key, value in link_info_dict.items():
|
|
if value == 0xFFFF:
|
|
link_info_dict[key] = "N/A"
|
|
|
|
return link_info_dict
|
|
|
|
|
|
def amdsmi_get_root_switch(amdsmi_bdf: Union[str, amdsmi_wrapper.amdsmi_bdf_t]) -> str:
|
|
# An empty BDF means the caller has no device to resolve (e.g. NIC info
|
|
# unavailable); report it as N/A instead of forcing callers to guard.
|
|
if isinstance(amdsmi_bdf, str):
|
|
if not amdsmi_bdf:
|
|
return "N/A"
|
|
parsed_bdf = _parse_bdf(amdsmi_bdf)
|
|
if parsed_bdf is None:
|
|
raise AmdSmiBdfFormatException(amdsmi_bdf)
|
|
amdsmi_bdf = _make_amdsmi_bdf_from_list(parsed_bdf)
|
|
elif not isinstance(amdsmi_bdf, amdsmi_wrapper.amdsmi_bdf_t):
|
|
raise AmdSmiParameterException(amdsmi_bdf, amdsmi_wrapper.amdsmi_bdf_t)
|
|
|
|
switch_bdf_info = amdsmi_wrapper.amdsmi_bdf_t()
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_root_switch(amdsmi_bdf, ctypes.byref(switch_bdf_info)))
|
|
|
|
return _format_bdf(switch_bdf_info)
|
|
|
|
|
|
def amdsmi_get_gpu_device_uuid(processor_handle: processor_handle_t) -> str:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
uuid = ctypes.create_string_buffer(AMDSMI_GPU_UUID_SIZE)
|
|
|
|
uuid_length = ctypes.c_uint32()
|
|
uuid_length.value = AMDSMI_GPU_UUID_SIZE
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_device_uuid(processor_handle, ctypes.byref(uuid_length), uuid)
|
|
)
|
|
|
|
return uuid.value.decode("utf-8")
|
|
|
|
|
|
def amdsmi_get_gpu_enumeration_info(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
"""
|
|
Retrieves GPU enumeration information including DRM card ID, DRM render ID, HIP ID, and HIP UUID.
|
|
|
|
Parameters:
|
|
processor_handle (amdsmi_processor_handle_t): The processor handle.
|
|
|
|
Returns:
|
|
Dict[str, Any]: A dictionary containing the retrieved enumeration information.
|
|
|
|
Raises:
|
|
AmdSmiParameterException: If the input parameters are invalid.
|
|
"""
|
|
# Validate the processor handle
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
# Create an instance of the enumeration info struct
|
|
enumeration_info = amdsmi_wrapper.amdsmi_enumeration_info_t()
|
|
|
|
# Call the C function to populate the struct
|
|
status = amdsmi_wrapper.amdsmi_get_gpu_enumeration_info(
|
|
processor_handle, ctypes.byref(enumeration_info)
|
|
)
|
|
|
|
# Validate the status result
|
|
_check_res(status)
|
|
|
|
# Convert the struct fields into a dictionary and return
|
|
enumeration_info = {
|
|
"drm_render": _validate_if_max_uint(enumeration_info.drm_render, MaxUIntegerTypes.UINT32_T),
|
|
"drm_card": _validate_if_max_uint(enumeration_info.drm_card, MaxUIntegerTypes.UINT32_T),
|
|
"hsa_id": _validate_if_max_uint(enumeration_info.hsa_id, MaxUIntegerTypes.UINT32_T),
|
|
"hip_id": _validate_if_max_uint(enumeration_info.hip_id, MaxUIntegerTypes.UINT32_T),
|
|
"hip_uuid": enumeration_info.hip_uuid.decode("utf-8"),
|
|
"oam_id": _validate_if_max_uint(enumeration_info.oam_id, MaxUIntegerTypes.UINT32_T),
|
|
}
|
|
|
|
return enumeration_info
|
|
|
|
|
|
def amdsmi_get_cpu_affinity_with_scope(
|
|
processor_handle: processor_handle_t, scope: AmdSmiAffinityScope
|
|
) -> List[int]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(scope, AmdSmiAffinityScope):
|
|
raise AmdSmiParameterException(scope, AmdSmiAffinityScope)
|
|
|
|
socket_count = amdsmi_get_cpu_socket_count()
|
|
sock_info = amdsmi_get_cpu_cores_per_socket(socket_count)
|
|
core_count = sock_info["cores_per_socket"]
|
|
|
|
size = ctypes.c_uint32(0)
|
|
size = (socket_count * core_count) / (ctypes.sizeof(ctypes.c_uint64) * 8)
|
|
size = int(math.ceil(size))
|
|
size = ctypes.c_uint32(size)
|
|
cpu_set = (ctypes.c_uint64 * size.value)()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_cpu_affinity_with_scope(processor_handle, size, cpu_set, scope)
|
|
)
|
|
return cpu_set
|
|
|
|
|
|
def amdsmi_get_gpu_asic_info(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
asic_info_struct = amdsmi_wrapper.amdsmi_asic_info_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_asic_info(processor_handle, ctypes.byref(asic_info_struct))
|
|
)
|
|
|
|
market_name = _pad_hex_value(asic_info_struct.market_name.decode("utf-8"), 4)
|
|
target_graphics_version = hex(asic_info_struct.target_graphics_version)[2:]
|
|
subsystem_id = _validate_if_max_uint(asic_info_struct.subsystem_id, MaxUIntegerTypes.UINT32_T)
|
|
subvendor_id = _validate_if_max_uint(asic_info_struct.subvendor_id, MaxUIntegerTypes.UINT32_T)
|
|
if isinstance(subsystem_id, int):
|
|
subsystem_id = _pad_hex_value(hex(subsystem_id), 4)
|
|
if isinstance(subvendor_id, int):
|
|
subvendor_id = _pad_hex_value(hex(subvendor_id), 4)
|
|
asic_info = {
|
|
"market_name": market_name,
|
|
"vendor_id": asic_info_struct.vendor_id,
|
|
"vendor_name": asic_info_struct.vendor_name.decode("utf-8"),
|
|
"subvendor_id": subvendor_id,
|
|
"device_id": asic_info_struct.device_id,
|
|
"rev_id": _pad_hex_value(hex(asic_info_struct.rev_id), 2),
|
|
"asic_serial": asic_info_struct.asic_serial.decode("utf-8"),
|
|
"oam_id": _validate_if_max_uint(asic_info_struct.oam_id, MaxUIntegerTypes.UINT32_T),
|
|
"num_compute_units": _validate_if_max_uint(
|
|
asic_info_struct.num_of_compute_units, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
"target_graphics_version": "gfx" + target_graphics_version,
|
|
"subsystem_id": subsystem_id,
|
|
"flags": asic_info_struct.flags,
|
|
}
|
|
|
|
string_values = ["market_name", "vendor_name"]
|
|
for value in string_values:
|
|
if not asic_info[value]:
|
|
asic_info[value] = "N/A"
|
|
|
|
hex_values = ["vendor_id", "device_id"]
|
|
for value in hex_values:
|
|
if asic_info[value]:
|
|
asic_info[value] = hex(asic_info[value])
|
|
else:
|
|
asic_info[value] = "N/A"
|
|
|
|
# Convert asic serial (hex string) to hex output format
|
|
if asic_info["asic_serial"]:
|
|
asic_serial_string = asic_info["asic_serial"]
|
|
asic_serial_hex = int(asic_serial_string, base=16)
|
|
# Check if asic_serial is available
|
|
if asic_serial_hex == MaxUIntegerTypes.UINT64_T:
|
|
asic_info["asic_serial"] = "N/A"
|
|
else:
|
|
asic_info["asic_serial"] = str.format("0x{:016X}", asic_serial_hex)
|
|
else:
|
|
asic_info["asic_serial"] = "N/A"
|
|
|
|
# Remove commas from vendor name for clean output
|
|
asic_info["vendor_name"] = asic_info["vendor_name"].replace(",", "")
|
|
|
|
return asic_info
|
|
|
|
|
|
def amdsmi_get_gpu_kfd_info(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
kfd_info_struct = amdsmi_wrapper.amdsmi_kfd_info_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_kfd_info(processor_handle, ctypes.byref(kfd_info_struct))
|
|
)
|
|
|
|
kfd_info = {
|
|
"kfd_id": _validate_if_max_uint(kfd_info_struct.kfd_id, MaxUIntegerTypes.UINT64_T),
|
|
"node_id": _validate_if_max_uint(kfd_info_struct.node_id, MaxUIntegerTypes.UINT32_T),
|
|
"current_partition_id": _validate_if_max_uint(
|
|
kfd_info_struct.current_partition_id, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
}
|
|
|
|
return kfd_info
|
|
|
|
|
|
def amdsmi_get_supported_power_cap(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
CONST_AMDSMI_MAX_POWER_SENSORS = 2
|
|
|
|
sensor_count = ctypes.c_uint32()
|
|
sensor_ind = (ctypes.c_uint32 * CONST_AMDSMI_MAX_POWER_SENSORS)()
|
|
sensor_types = (amdsmi_wrapper.amdsmi_power_cap_type_t * CONST_AMDSMI_MAX_POWER_SENSORS)()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_supported_power_cap(
|
|
processor_handle, ctypes.byref(sensor_count), sensor_ind, sensor_types
|
|
)
|
|
)
|
|
|
|
return {
|
|
"sensor_inds": [sensor_ind[i] for i in range(sensor_count.value)],
|
|
"sensor_types": [AmdSmiPowerCapType(sensor_types[i]) for i in range(sensor_count.value)],
|
|
}
|
|
|
|
|
|
def amdsmi_get_power_cap_info(
|
|
processor_handle: processor_handle_t, sensor_ind: int = AmdSmiPowerCapType.PPT0
|
|
) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
power_cap_info = amdsmi_wrapper.amdsmi_power_cap_info_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_power_cap_info(
|
|
processor_handle, sensor_ind, ctypes.byref(power_cap_info)
|
|
)
|
|
)
|
|
|
|
return {
|
|
"power_cap": power_cap_info.power_cap,
|
|
"default_power_cap": power_cap_info.default_power_cap,
|
|
"dpm_cap": power_cap_info.dpm_cap,
|
|
"min_power_cap": power_cap_info.min_power_cap,
|
|
"max_power_cap": power_cap_info.max_power_cap,
|
|
}
|
|
|
|
|
|
def amdsmi_get_gpu_pm_metrics_info(processor_handle: processor_handle_t) -> List[Dict[str, Any]]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
pm_metrics = POINTER(amdsmi_wrapper.amdsmi_name_value_t)()
|
|
num_mets = ctypes.c_uint32(0)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_pm_metrics_info(
|
|
processor_handle, ctypes.byref(pm_metrics), ctypes.byref(num_mets)
|
|
)
|
|
)
|
|
|
|
results = _get_name_value(num_mets, pm_metrics)
|
|
|
|
# Free the allocated memory
|
|
amdsmi_wrapper.amdsmi_free_name_value_pairs(pm_metrics)
|
|
|
|
return results
|
|
|
|
|
|
def amdsmi_get_gpu_reg_table_info(
|
|
processor_handle: processor_handle_t, reg_type: AmdSmiRegType
|
|
) -> List[Dict[str, Any]]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(reg_type, AmdSmiRegType):
|
|
raise AmdSmiParameterException(reg_type, AmdSmiRegType)
|
|
|
|
reg_metrics = POINTER(amdsmi_wrapper.amdsmi_name_value_t)()
|
|
num_regs = ctypes.c_uint32(0)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_reg_table_info(
|
|
processor_handle, reg_type, ctypes.byref(reg_metrics), ctypes.byref(num_regs)
|
|
)
|
|
)
|
|
|
|
results = _get_name_value(num_regs, reg_metrics)
|
|
|
|
# Free the allocated memory
|
|
amdsmi_wrapper.amdsmi_free_name_value_pairs(reg_metrics)
|
|
|
|
return results
|
|
|
|
|
|
def amdsmi_get_gpu_vram_info(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
vram_info = amdsmi_wrapper.amdsmi_vram_info_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_vram_info(processor_handle, ctypes.byref(vram_info)))
|
|
return {
|
|
"vram_type": vram_info.vram_type,
|
|
"vram_vendor": vram_info.vram_vendor.decode("utf-8"),
|
|
"vram_size": vram_info.vram_size,
|
|
"vram_bit_width": _validate_if_max_uint(
|
|
vram_info.vram_bit_width, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
"vram_max_bandwidth": _validate_if_max_uint(
|
|
vram_info.vram_max_bandwidth, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
}
|
|
|
|
|
|
def amdsmi_get_gpu_xgmi_link_status(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
status_info = amdsmi_wrapper.amdsmi_xgmi_link_status_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_xgmi_link_status(processor_handle, ctypes.byref(status_info))
|
|
)
|
|
|
|
link_status = []
|
|
count = 0
|
|
for link in status_info.status:
|
|
if count == status_info.total_links:
|
|
break
|
|
if (
|
|
amdsmi_wrapper.amdsmi_xgmi_link_status_type_t__enumvalues[link]
|
|
== "AMDSMI_XGMI_LINK_DISABLE"
|
|
): # XGMI link is disabled
|
|
link_status.append("X")
|
|
elif (
|
|
amdsmi_wrapper.amdsmi_xgmi_link_status_type_t__enumvalues[link] == "AMDSMI_XGMI_LINK_UP"
|
|
): # XGMI Link is up
|
|
link_status.append("U")
|
|
elif (
|
|
amdsmi_wrapper.amdsmi_xgmi_link_status_type_t__enumvalues[link]
|
|
== "AMDSMI_XGMI_LINK_DOWN"
|
|
): # XGMI Link is down
|
|
link_status.append("D")
|
|
else:
|
|
link_status.append("N/A")
|
|
count += 1
|
|
|
|
return_dict = {"status": link_status, "total_links": status_info.total_links}
|
|
return return_dict
|
|
|
|
|
|
def amdsmi_get_gpu_cache_info(processor_handle: processor_handle_t) -> Dict[str, List]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
cache_info_struct = amdsmi_wrapper.amdsmi_gpu_cache_info_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_cache_info(processor_handle, ctypes.byref(cache_info_struct))
|
|
)
|
|
|
|
cache_info_list = []
|
|
for cache_index in range(cache_info_struct.num_cache_types):
|
|
# Put cache_properties at the start of the dictionary for readability
|
|
cache_dict = {
|
|
"cache_properties": [], # This will be a list of strings
|
|
"cache_size": cache_info_struct.cache[cache_index].cache_size,
|
|
"cache_level": cache_info_struct.cache[cache_index].cache_level,
|
|
"max_num_cu_shared": cache_info_struct.cache[cache_index].max_num_cu_shared,
|
|
"num_cache_instance": cache_info_struct.cache[cache_index].num_cache_instance,
|
|
}
|
|
|
|
# Check against cache properties bitmask
|
|
cache_properties = cache_info_struct.cache[cache_index].cache_properties
|
|
data_cache = cache_properties & amdsmi_wrapper.AMDSMI_CACHE_PROPERTY_DATA_CACHE
|
|
inst_cache = cache_properties & amdsmi_wrapper.AMDSMI_CACHE_PROPERTY_INST_CACHE
|
|
cpu_cache = cache_properties & amdsmi_wrapper.AMDSMI_CACHE_PROPERTY_CPU_CACHE
|
|
simd_cache = cache_properties & amdsmi_wrapper.AMDSMI_CACHE_PROPERTY_SIMD_CACHE
|
|
|
|
cache_properties_status = [data_cache, inst_cache, cpu_cache, simd_cache]
|
|
cache_property_list = []
|
|
for cache_property in cache_properties_status:
|
|
if cache_property:
|
|
property_name = amdsmi_wrapper.amdsmi_cache_property_type_t__enumvalues[
|
|
cache_property
|
|
]
|
|
property_name = property_name.replace("AMDSMI_CACHE_PROPERTY_", "")
|
|
cache_property_list.append(property_name)
|
|
|
|
cache_dict["cache_properties"] = cache_property_list
|
|
cache_info_list.append(cache_dict)
|
|
|
|
if not cache_info_list:
|
|
raise AmdSmiLibraryException(amdsmi_wrapper.AMDSMI_STATUS_NO_DATA)
|
|
|
|
return {"cache": cache_info_list}
|
|
|
|
|
|
def amdsmi_get_gpu_vbios_info(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
vbios_info = amdsmi_wrapper.amdsmi_vbios_info_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_vbios_info(processor_handle, ctypes.byref(vbios_info)))
|
|
|
|
boot_firmware = vbios_info.boot_firmware.decode("utf-8")
|
|
if boot_firmware == "":
|
|
boot_firmware = "N/A"
|
|
|
|
return {
|
|
"name": vbios_info.name.decode("utf-8"),
|
|
"build_date": vbios_info.build_date.decode("utf-8"),
|
|
"part_number": vbios_info.part_number.decode("utf-8"),
|
|
"version": vbios_info.version.decode("utf-8"),
|
|
"boot_firmware": boot_firmware,
|
|
}
|
|
|
|
|
|
def amdsmi_get_gpu_activity(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
engine_usage = amdsmi_wrapper.amdsmi_engine_usage_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_activity(processor_handle, ctypes.byref(engine_usage)))
|
|
|
|
activity_dict = {
|
|
"gfx_activity": engine_usage.gfx_activity,
|
|
"umc_activity": engine_usage.umc_activity,
|
|
"mm_activity": engine_usage.mm_activity,
|
|
}
|
|
|
|
for key, value in activity_dict.items():
|
|
if value == 0xFFFF:
|
|
activity_dict[key] = "N/A"
|
|
|
|
return activity_dict
|
|
|
|
|
|
def amdsmi_get_clock_info(
|
|
processor_handle: processor_handle_t, clock_type: AmdSmiClkType
|
|
) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(clock_type, AmdSmiClkType):
|
|
raise AmdSmiParameterException(clock_type, AmdSmiClkType)
|
|
|
|
clock_measure = amdsmi_wrapper.amdsmi_clk_info_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_clock_info(
|
|
processor_handle, clock_type, ctypes.byref(clock_measure)
|
|
)
|
|
)
|
|
|
|
dict_ret = {
|
|
"clk": _validate_if_max_uint(clock_measure.clk, MaxUIntegerTypes.UINT32_T),
|
|
"min_clk": _validate_if_max_uint(clock_measure.min_clk, MaxUIntegerTypes.UINT32_T),
|
|
"max_clk": _validate_if_max_uint(clock_measure.max_clk, MaxUIntegerTypes.UINT32_T),
|
|
"clk_locked": _validate_if_max_uint(
|
|
clock_measure.clk_locked, MaxUIntegerTypes.UINT8_T, isBool=True
|
|
),
|
|
"clk_deep_sleep": _validate_if_max_uint(
|
|
clock_measure.clk_deep_sleep, MaxUIntegerTypes.UINT8_T
|
|
),
|
|
}
|
|
return dict_ret
|
|
|
|
|
|
def amdsmi_get_gpu_bad_page_info(processor_handle: processor_handle_t) -> List[Dict[str, Any]]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
num_pages = ctypes.c_uint32()
|
|
nullptr = POINTER(amdsmi_wrapper.amdsmi_retired_page_record_t)()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_bad_page_info(
|
|
processor_handle, ctypes.byref(num_pages), nullptr
|
|
)
|
|
)
|
|
|
|
if num_pages.value == 0:
|
|
return []
|
|
|
|
bad_pages_array_type = amdsmi_wrapper.amdsmi_retired_page_record_t * num_pages.value
|
|
bad_pages = bad_pages_array_type()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_bad_page_info(
|
|
processor_handle, ctypes.byref(num_pages), bad_pages
|
|
)
|
|
)
|
|
|
|
return _format_bad_page_info(bad_pages, num_pages)
|
|
|
|
|
|
def amdsmi_get_gpu_bad_page_threshold(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
threshold = ctypes.c_uint32()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_bad_page_threshold(processor_handle, ctypes.byref(threshold))
|
|
)
|
|
|
|
return threshold.value
|
|
|
|
|
|
def amdsmi_get_violation_status(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
violation_status = amdsmi_wrapper.amdsmi_violation_status_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_violation_status(processor_handle, ctypes.byref(violation_status))
|
|
)
|
|
|
|
dict_return = {
|
|
"reference_timestamp": _validate_if_max_uint(
|
|
violation_status.reference_timestamp, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"violation_timestamp": _validate_if_max_uint(
|
|
violation_status.violation_timestamp, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"acc_counter": _validate_if_max_uint(
|
|
violation_status.acc_counter, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"acc_prochot_thrm": _validate_if_max_uint(
|
|
violation_status.acc_prochot_thrm, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"acc_ppt_pwr": _validate_if_max_uint(
|
|
violation_status.acc_ppt_pwr, MaxUIntegerTypes.UINT64_T
|
|
), # PVIOL
|
|
"acc_socket_thrm": _validate_if_max_uint(
|
|
violation_status.acc_socket_thrm, MaxUIntegerTypes.UINT64_T
|
|
), # TVIOL
|
|
"acc_vr_thrm": _validate_if_max_uint(
|
|
violation_status.acc_vr_thrm, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"acc_hbm_thrm": _validate_if_max_uint(
|
|
violation_status.acc_hbm_thrm, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"acc_gfx_clk_below_host_limit": _validate_if_max_uint(
|
|
violation_status.acc_gfx_clk_below_host_limit, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"acc_gfx_clk_below_host_limit_pwr": list(violation_status.acc_gfx_clk_below_host_limit_pwr),
|
|
"acc_gfx_clk_below_host_limit_thm": list(violation_status.acc_gfx_clk_below_host_limit_thm),
|
|
"acc_gfx_clk_below_host_limit_total": list(
|
|
violation_status.acc_gfx_clk_below_host_limit_total
|
|
),
|
|
"acc_low_utilization": list(violation_status.acc_low_utilization),
|
|
"per_prochot_thrm": _validate_if_max_uint(
|
|
violation_status.per_prochot_thrm, MaxUIntegerTypes.UINT64_T, isActivity=True
|
|
),
|
|
"per_ppt_pwr": _validate_if_max_uint(
|
|
violation_status.per_ppt_pwr, MaxUIntegerTypes.UINT64_T, isActivity=True
|
|
), # PVIOL
|
|
"per_socket_thrm": _validate_if_max_uint(
|
|
violation_status.per_socket_thrm, MaxUIntegerTypes.UINT64_T, isActivity=True
|
|
), # TVIOL
|
|
"per_vr_thrm": _validate_if_max_uint(
|
|
violation_status.per_vr_thrm, MaxUIntegerTypes.UINT64_T, isActivity=True
|
|
),
|
|
"per_hbm_thrm": _validate_if_max_uint(
|
|
violation_status.per_hbm_thrm, MaxUIntegerTypes.UINT64_T, isActivity=True
|
|
),
|
|
"per_gfx_clk_below_host_limit": _validate_if_max_uint(
|
|
violation_status.per_gfx_clk_below_host_limit,
|
|
MaxUIntegerTypes.UINT64_T,
|
|
isActivity=True,
|
|
),
|
|
"per_gfx_clk_below_host_limit_pwr": list(violation_status.per_gfx_clk_below_host_limit_pwr),
|
|
"per_gfx_clk_below_host_limit_thm": list(violation_status.per_gfx_clk_below_host_limit_thm),
|
|
"per_gfx_clk_below_host_limit_total": list(
|
|
violation_status.per_gfx_clk_below_host_limit_total
|
|
),
|
|
"per_low_utilization": list(violation_status.per_low_utilization),
|
|
"active_prochot_thrm": _validate_if_max_uint(
|
|
violation_status.active_prochot_thrm, MaxUIntegerTypes.UINT8_T, isBool=True
|
|
),
|
|
"active_ppt_pwr": _validate_if_max_uint(
|
|
violation_status.active_ppt_pwr, MaxUIntegerTypes.UINT8_T, isBool=True
|
|
), # PVIOL
|
|
"active_socket_thrm": _validate_if_max_uint(
|
|
violation_status.active_socket_thrm, MaxUIntegerTypes.UINT8_T, isBool=True
|
|
), # TVIOL
|
|
"active_vr_thrm": _validate_if_max_uint(
|
|
violation_status.active_vr_thrm, MaxUIntegerTypes.UINT8_T, isBool=True
|
|
),
|
|
"active_hbm_thrm": _validate_if_max_uint(
|
|
violation_status.active_hbm_thrm, MaxUIntegerTypes.UINT8_T, isBool=True
|
|
),
|
|
"active_gfx_clk_below_host_limit": _validate_if_max_uint(
|
|
violation_status.active_gfx_clk_below_host_limit, MaxUIntegerTypes.UINT8_T, isBool=True
|
|
),
|
|
"active_gfx_clk_below_host_limit_pwr": list(
|
|
violation_status.active_gfx_clk_below_host_limit_pwr
|
|
),
|
|
"active_gfx_clk_below_host_limit_thm": list(
|
|
violation_status.active_gfx_clk_below_host_limit_thm
|
|
),
|
|
"active_gfx_clk_below_host_limit_total": list(
|
|
violation_status.active_gfx_clk_below_host_limit_total
|
|
),
|
|
"active_low_utilization": list(violation_status.active_low_utilization),
|
|
}
|
|
|
|
# Create 2d array with each XCD's stats
|
|
if "acc_gfx_clk_below_host_limit_pwr" in dict_return:
|
|
for xcp_index, xcp_metrics in enumerate(dict_return["acc_gfx_clk_below_host_limit_pwr"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T))
|
|
dict_return["acc_gfx_clk_below_host_limit_pwr"][xcp_index] = xcp_detail
|
|
if "acc_gfx_clk_below_host_limit_thm" in dict_return:
|
|
for xcp_index, xcp_metrics in enumerate(dict_return["acc_gfx_clk_below_host_limit_thm"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T))
|
|
dict_return["acc_gfx_clk_below_host_limit_thm"][xcp_index] = xcp_detail
|
|
if "acc_low_utilization" in dict_return:
|
|
for xcp_index, xcp_metrics in enumerate(dict_return["acc_low_utilization"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T))
|
|
dict_return["acc_low_utilization"][xcp_index] = xcp_detail
|
|
if "acc_gfx_clk_below_host_limit_total" in dict_return:
|
|
for xcp_index, xcp_metrics in enumerate(dict_return["acc_gfx_clk_below_host_limit_total"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T))
|
|
dict_return["acc_gfx_clk_below_host_limit_total"][xcp_index] = xcp_detail
|
|
|
|
if "per_gfx_clk_below_host_limit_pwr" in dict_return:
|
|
for xcp_index, xcp_metrics in enumerate(dict_return["per_gfx_clk_below_host_limit_pwr"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics:
|
|
xcp_detail.append(
|
|
_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T, isActivity=True)
|
|
)
|
|
dict_return["per_gfx_clk_below_host_limit_pwr"][xcp_index] = xcp_detail
|
|
if "per_gfx_clk_below_host_limit_thm" in dict_return:
|
|
for xcp_index, xcp_metrics in enumerate(dict_return["per_gfx_clk_below_host_limit_thm"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics:
|
|
xcp_detail.append(
|
|
_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T, isActivity=True)
|
|
)
|
|
dict_return["per_gfx_clk_below_host_limit_thm"][xcp_index] = xcp_detail
|
|
if "per_low_utilization" in dict_return:
|
|
for xcp_index, xcp_metrics in enumerate(dict_return["per_low_utilization"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics:
|
|
xcp_detail.append(
|
|
_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T, isActivity=True)
|
|
)
|
|
dict_return["per_low_utilization"][xcp_index] = xcp_detail
|
|
if "per_gfx_clk_below_host_limit_total" in dict_return:
|
|
for xcp_index, xcp_metrics in enumerate(dict_return["per_gfx_clk_below_host_limit_total"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics:
|
|
xcp_detail.append(
|
|
_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T, isActivity=True)
|
|
)
|
|
dict_return["per_gfx_clk_below_host_limit_total"][xcp_index] = xcp_detail
|
|
|
|
if "active_gfx_clk_below_host_limit_pwr" in dict_return:
|
|
for xcp_index, xcp_metrics in enumerate(dict_return["active_gfx_clk_below_host_limit_pwr"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT8_T, isBool=True))
|
|
dict_return["active_gfx_clk_below_host_limit_pwr"][xcp_index] = xcp_detail
|
|
if "active_gfx_clk_below_host_limit_thm" in dict_return:
|
|
for xcp_index, xcp_metrics in enumerate(dict_return["active_gfx_clk_below_host_limit_thm"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT8_T, isBool=True))
|
|
dict_return["active_gfx_clk_below_host_limit_thm"][xcp_index] = xcp_detail
|
|
if "active_low_utilization" in dict_return:
|
|
for xcp_index, xcp_metrics in enumerate(dict_return["active_low_utilization"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT8_T, isBool=True))
|
|
dict_return["active_low_utilization"][xcp_index] = xcp_detail
|
|
if "active_gfx_clk_below_host_limit_total" in dict_return:
|
|
for xcp_index, xcp_metrics in enumerate(
|
|
dict_return["active_gfx_clk_below_host_limit_total"]
|
|
):
|
|
xcp_detail = []
|
|
for val in xcp_metrics:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT8_T, isBool=True))
|
|
dict_return["active_gfx_clk_below_host_limit_total"][xcp_index] = xcp_detail
|
|
|
|
return dict_return
|
|
|
|
|
|
def amdsmi_get_gpu_total_ecc_count(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
ec = amdsmi_wrapper.amdsmi_error_count_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_total_ecc_count(processor_handle, ctypes.byref(ec)))
|
|
|
|
return {
|
|
"correctable_count": ec.correctable_count,
|
|
"uncorrectable_count": ec.uncorrectable_count,
|
|
"deferred_count": ec.deferred_count,
|
|
}
|
|
|
|
|
|
def amdsmi_get_gpu_cper_entries(
|
|
device_handle: Union[amdsmi_wrapper.amdsmi_processor_handle, Path],
|
|
severity_mask: int,
|
|
buffer_size: int = 4 * 1048576,
|
|
cursor: int = 0,
|
|
) -> Tuple[Dict[str, Any], int, List[Dict[str, Any]], int]:
|
|
|
|
if isinstance(device_handle, Path):
|
|
if not os.path.isfile(device_handle):
|
|
raise AmdSmiParameterException(device_handle, str)
|
|
device_handle = ctypes.c_char_p(str(device_handle).encode("utf-8"))
|
|
elif not isinstance(device_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(device_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(severity_mask, int):
|
|
raise AmdSmiParameterException(severity_mask, int)
|
|
if not isinstance(buffer_size, int):
|
|
raise AmdSmiParameterException(buffer_size, int)
|
|
if not isinstance(cursor, int):
|
|
raise AmdSmiParameterException(cursor, int)
|
|
|
|
# Allocate a buffer for CPER data.
|
|
buf = ctypes.create_string_buffer(buffer_size)
|
|
buf_size = ctypes.c_uint64(buffer_size)
|
|
num_cper_hdrs = 20
|
|
entry_count = ctypes.c_uint64(num_cper_hdrs)
|
|
cur = ctypes.c_uint64(cursor)
|
|
|
|
# Allocate a pointer for the CPER header array.
|
|
cper_hdrs_array = (ctypes.POINTER(amdsmi_wrapper.amdsmi_cper_hdr_t) * num_cper_hdrs)()
|
|
cper_hdrs = ctypes.cast(
|
|
cper_hdrs_array, ctypes.POINTER(ctypes.POINTER(amdsmi_wrapper.amdsmi_cper_hdr_t))
|
|
)
|
|
|
|
# Call the underlying AMD-SMI API.
|
|
status_code = amdsmi_wrapper.amdsmi_get_gpu_cper_entries(
|
|
device_handle,
|
|
ctypes.c_uint32(severity_mask),
|
|
buf,
|
|
ctypes.byref(buf_size),
|
|
cper_hdrs,
|
|
ctypes.byref(entry_count),
|
|
ctypes.byref(cur),
|
|
)
|
|
if status_code not in {
|
|
amdsmi_wrapper.AMDSMI_STATUS_SUCCESS,
|
|
amdsmi_wrapper.AMDSMI_STATUS_MORE_DATA,
|
|
}:
|
|
raise AmdSmiLibraryException(status_code)
|
|
|
|
entries = {}
|
|
cper_data = []
|
|
offset = 0
|
|
|
|
# Iterate over each entry using its variable record_length.
|
|
for i in range(entry_count.value):
|
|
entry_address = ctypes.addressof(buf) + offset
|
|
entry_ptr = ctypes.cast(entry_address, POINTER(amdsmi_wrapper.amdsmi_cper_hdr_t))
|
|
|
|
# Extract the raw bytes and size of the entry.
|
|
cper_data.append(
|
|
{
|
|
"bytes": list(
|
|
(entry_ptr.contents.record_length * ctypes.c_byte).from_address(entry_address)
|
|
),
|
|
"size": entry_ptr.contents.record_length,
|
|
}
|
|
)
|
|
|
|
# Extract the timestamp fields.
|
|
year = entry_ptr.contents.timestamp.year
|
|
if year < 100: # Adjust the year if it's less than 100.
|
|
year += 2000
|
|
formatted_timestamp = (
|
|
f"{year:04d}/"
|
|
f"{entry_ptr.contents.timestamp.month:02d}/"
|
|
f"{entry_ptr.contents.timestamp.day:02d} "
|
|
f"{entry_ptr.contents.timestamp.hours:02d}:"
|
|
f"{entry_ptr.contents.timestamp.minutes:02d}:"
|
|
f"{entry_ptr.contents.timestamp.seconds:02d}"
|
|
)
|
|
|
|
serial_number = ""
|
|
if isinstance(device_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
try:
|
|
board_info = amdsmi_get_gpu_board_info(device_handle)
|
|
serial_number = board_info.get("product_serial", "")
|
|
except Exception:
|
|
serial_number = ""
|
|
# Create a dictionary for the CPER entry.
|
|
cper_entry = {
|
|
"error_severity": amdsmi_wrapper.amdsmi_cper_sev_t__enumvalues.get(
|
|
entry_ptr.contents.error_severity, "AMDSMI_CPER_SEV_UNUSED"
|
|
)
|
|
.replace("AMDSMI_CPER_SEV_", "")
|
|
.lower(),
|
|
"notify_type": _notifyTypeToString(entry_ptr.contents.notify_type.b),
|
|
"timestamp": formatted_timestamp,
|
|
"signature": entry_ptr.contents.signature,
|
|
"revision": entry_ptr.contents.revision,
|
|
"signature_end": hex(entry_ptr.contents.signature_end),
|
|
"sec_cnt": entry_ptr.contents.sec_cnt,
|
|
"record_length": entry_ptr.contents.record_length,
|
|
"serial_number": serial_number,
|
|
"platform_id": entry_ptr.contents.platform_id,
|
|
"creator_id": entry_ptr.contents.creator_id,
|
|
"record_id": entry_ptr.contents.record_id,
|
|
"flags": entry_ptr.contents.flags,
|
|
"persistence_info": entry_ptr.contents.persistence_info,
|
|
# "reserved" : entry_ptr.contents.reserved
|
|
# "cper_valid_bit" : entry_ptr.contents.cper_valid_bits,
|
|
# "partition_id" : entry_ptr.contents.partition_id,
|
|
}
|
|
|
|
entries[i] = cper_entry.copy()
|
|
offset += (
|
|
entry_ptr.contents.record_length
|
|
) # Use the actual record length to advance the offset.
|
|
|
|
return entries, cur.value, cper_data, status_code
|
|
|
|
|
|
def amdsmi_get_afids_from_cper(cper_afid_data: bytes) -> Tuple[List[int], int]:
|
|
"""
|
|
Extract AFIDs from a CPER blob.
|
|
|
|
Args:
|
|
cper_afid_data: raw bytes of a single CPER record.
|
|
|
|
Returns:
|
|
Tuple[List[int], int]: A tuple containing:
|
|
- A list of extracted AFIDs.
|
|
- The total count of AFIDs.
|
|
"""
|
|
cper_records = []
|
|
# Normalize single blob into a list of records
|
|
if isinstance(cper_afid_data, bytes):
|
|
cper_records = [{"bytes": list(cper_afid_data), "size": len(cper_afid_data)}]
|
|
elif isinstance(cper_afid_data, List[Dict[str, Any]]):
|
|
cper_records = cper_afid_data
|
|
else:
|
|
raise AmdSmiParameterException(cper_afid_data, bytes)
|
|
|
|
all_afids: List[int] = []
|
|
|
|
for record in cper_records:
|
|
if isinstance(record, dict) and "bytes" in record and "size" in record:
|
|
raw_bytes = bytes(record["bytes"])
|
|
record_size = record["size"]
|
|
else:
|
|
raise AmdSmiParameterException(
|
|
record, "dict with keys 'bytes' and 'size' or bytes/bytearray"
|
|
)
|
|
# Wrap as char*
|
|
buf = ctypes.create_string_buffer(raw_bytes, record_size)
|
|
buf_ptr = ctypes.cast(buf, POINTER(ctypes.c_char))
|
|
|
|
afid_array = (ctypes.c_uint64 * AMDSMI_MAX_NUMBER_OF_AFIDS_PER_RECORD)()
|
|
num_afids_ct = ctypes.c_uint32(AMDSMI_MAX_NUMBER_OF_AFIDS_PER_RECORD)
|
|
|
|
# Call the wrapper function
|
|
status = amdsmi_wrapper.amdsmi_get_afids_from_cper(
|
|
buf_ptr, ctypes.c_uint32(record_size), afid_array, ctypes.byref(num_afids_ct)
|
|
)
|
|
if status != amdsmi_wrapper.AMDSMI_STATUS_SUCCESS:
|
|
raise AmdSmiLibraryException(status)
|
|
|
|
# Collect exactly the decoded AFIDs
|
|
count = num_afids_ct.value
|
|
all_afids.extend(afid_array[i] for i in range(count))
|
|
|
|
return all_afids, len(all_afids)
|
|
|
|
|
|
def amdsmi_get_gpu_board_info(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
board_info = amdsmi_wrapper.amdsmi_board_info_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_board_info(processor_handle, ctypes.byref(board_info)))
|
|
|
|
board_info_dict = {
|
|
"model_number": _pad_hex_value(board_info.model_number.decode("utf-8").strip(), 4),
|
|
"product_serial": board_info.product_serial.decode("utf-8").strip(),
|
|
"fru_id": board_info.fru_id.decode("utf-8").strip(),
|
|
"product_name": _pad_hex_value(board_info.product_name.decode("utf-8").strip(), 4),
|
|
"manufacturer_name": board_info.manufacturer_name.decode("utf-8").strip(),
|
|
}
|
|
|
|
for key, value in board_info_dict.items():
|
|
if value == "":
|
|
board_info_dict[key] = "N/A"
|
|
return board_info_dict
|
|
|
|
|
|
def amdsmi_get_gpu_ras_feature_info(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
ras_feature = amdsmi_wrapper.amdsmi_ras_feature_t()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_ras_feature_info(processor_handle, ctypes.byref(ras_feature))
|
|
)
|
|
|
|
return {
|
|
"eeprom_version": hex(ras_feature.ras_eeprom_version),
|
|
"parity_schema": bool(ras_feature.ecc_correction_schema_flag & 1),
|
|
"single_bit_schema": bool(ras_feature.ecc_correction_schema_flag & 2),
|
|
"double_bit_schema": bool(ras_feature.ecc_correction_schema_flag & 4),
|
|
"poison_schema": bool(ras_feature.ecc_correction_schema_flag & 8),
|
|
}
|
|
|
|
|
|
def amdsmi_get_gpu_ras_block_features_enabled(
|
|
processor_handle: processor_handle_t,
|
|
) -> List[Dict[str, Any]]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
ras_state = amdsmi_wrapper.amdsmi_ras_err_state_t()
|
|
ras_states = []
|
|
for gpu_block in AmdSmiGpuBlock:
|
|
if gpu_block.name == "RESERVED" or gpu_block.name == "INVALID":
|
|
continue
|
|
gpu_block_name = gpu_block.name
|
|
if gpu_block.name == "LAST":
|
|
gpu_block_name = "MPIO"
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_ras_block_features_enabled(
|
|
processor_handle,
|
|
amdsmi_wrapper.amdsmi_gpu_block_t(gpu_block.value),
|
|
ctypes.byref(ras_state),
|
|
)
|
|
)
|
|
ras_states.append(
|
|
{"block": gpu_block_name, "status": AmdSmiRasErrState(ras_state.value).name}
|
|
)
|
|
|
|
return ras_states
|
|
|
|
|
|
def amdsmi_get_gpu_process_list(
|
|
processor_handle: processor_handle_t,
|
|
) -> List[amdsmi_wrapper.amdsmi_proc_info_t]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
# This will get populated with the number of processes found
|
|
max_processes = ctypes.c_uint32(MAX_NUM_PROCESSES)
|
|
|
|
process_list = (amdsmi_wrapper.amdsmi_proc_info_t * max_processes.value)()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_process_list(
|
|
processor_handle, ctypes.byref(max_processes), process_list
|
|
)
|
|
)
|
|
|
|
self_pid = os.getpid()
|
|
|
|
result = []
|
|
for index in range(max_processes.value):
|
|
pid = int(process_list[index].pid)
|
|
|
|
# Skip the amd-smi CLI process itself so it doesn't show up in output
|
|
if pid == self_pid:
|
|
continue
|
|
|
|
process_name = process_list[index].name.decode("utf-8").strip()
|
|
if process_name == "":
|
|
process_name = "N/A"
|
|
result.append(
|
|
{
|
|
"name": process_name,
|
|
"pid": process_list[index].pid,
|
|
"mem": process_list[index].mem,
|
|
"engine_usage": {
|
|
"gfx": process_list[index].engine_usage.gfx,
|
|
"enc": process_list[index].engine_usage.enc,
|
|
},
|
|
"memory_usage": {
|
|
"gtt_mem": process_list[index].memory_usage.gtt_mem,
|
|
"cpu_mem": process_list[index].memory_usage.cpu_mem,
|
|
"vram_mem": process_list[index].memory_usage.vram_mem,
|
|
},
|
|
"cu_occupancy": _validate_if_max_uint(
|
|
process_list[index].cu_occupancy, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
"sdma_usage": _validate_if_max_uint(
|
|
process_list[index].sdma_usage, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"evicted_time": _validate_if_max_uint(
|
|
process_list[index].evicted_time, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
}
|
|
)
|
|
|
|
return result
|
|
|
|
|
|
def amdsmi_get_gpu_process_list_by_pid(processor_handles: list) -> list:
|
|
"""Get process list grouped by PID across multiple GPUs.
|
|
|
|
Args:
|
|
processor_handles: List of processor handles to query.
|
|
|
|
Returns:
|
|
List of dicts with keys: pid, name, container_name, gpus.
|
|
Each gpu entry has: gpu_index, mem, engine_usage, memory_usage,
|
|
cu_occupancy, sdma_usage, evicted_time.
|
|
"""
|
|
for h in processor_handles:
|
|
if not isinstance(h, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(h, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
num = len(processor_handles)
|
|
handle_array = (amdsmi_wrapper.amdsmi_processor_handle * num)(*processor_handles)
|
|
|
|
max_processes = ctypes.c_uint32(MAX_NUM_PROCESSES)
|
|
process_list = (amdsmi_wrapper.amdsmi_proc_info_by_pid_t * max_processes.value)()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_process_list_by_pid(
|
|
handle_array, num, process_list, ctypes.byref(max_processes)
|
|
)
|
|
)
|
|
|
|
self_pid = os.getpid()
|
|
result = []
|
|
for i in range(max_processes.value):
|
|
entry = process_list[i]
|
|
pid = int(entry.pid)
|
|
if pid == self_pid:
|
|
continue
|
|
|
|
process_name = entry.name.decode("utf-8").strip()
|
|
if process_name == "":
|
|
process_name = "N/A"
|
|
|
|
gpus = []
|
|
for g in range(entry.num_gpus):
|
|
ge = entry.gpus[g]
|
|
gpus.append(
|
|
{
|
|
"gpu_index": ge.gpu_index,
|
|
"mem": ge.mem,
|
|
"engine_usage": {"gfx": ge.engine_usage.gfx, "enc": ge.engine_usage.enc},
|
|
"memory_usage": {
|
|
"gtt_mem": ge.memory_usage.gtt_mem,
|
|
"cpu_mem": ge.memory_usage.cpu_mem,
|
|
"vram_mem": ge.memory_usage.vram_mem,
|
|
},
|
|
"cu_occupancy": _validate_if_max_uint(
|
|
ge.cu_occupancy, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
"sdma_usage": _validate_if_max_uint(ge.sdma_usage, MaxUIntegerTypes.UINT64_T),
|
|
"evicted_time": _validate_if_max_uint(
|
|
ge.evicted_time, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
}
|
|
)
|
|
|
|
result.append(
|
|
{
|
|
"pid": pid,
|
|
"name": process_name,
|
|
"container_name": entry.container_name.decode("utf-8").strip(),
|
|
"gpus": gpus,
|
|
}
|
|
)
|
|
|
|
return result
|
|
|
|
|
|
def amdsmi_get_nic_fw_version(processor_handle: amdsmi_wrapper.amdsmi_processor_handle) -> str:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
uuid = ctypes.create_string_buffer(AMDSMI_MAX_STRING_LENGTH)
|
|
|
|
uuid_length = ctypes.c_uint32()
|
|
uuid_length.value = AMDSMI_MAX_STRING_LENGTH
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_nic_fw_version(processor_handle, ctypes.byref(uuid_length), uuid)
|
|
)
|
|
return uuid.value.decode("utf-8")
|
|
|
|
|
|
def amdsmi_get_nic_device_uuid(processor_handle: amdsmi_wrapper.amdsmi_processor_handle) -> str:
|
|
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
uuid = ctypes.create_string_buffer(AMDSMI_GPU_UUID_SIZE)
|
|
|
|
uuid_length = ctypes.c_uint32()
|
|
uuid_length.value = AMDSMI_GPU_UUID_SIZE
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_nic_device_uuid(processor_handle, ctypes.byref(uuid_length), uuid)
|
|
)
|
|
|
|
return uuid.value.decode("utf-8")
|
|
|
|
|
|
def amdsmi_get_switch_device_uuid(processor_handle: amdsmi_wrapper.amdsmi_processor_handle) -> str:
|
|
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
uuid = ctypes.create_string_buffer(AMDSMI_GPU_UUID_SIZE)
|
|
|
|
uuid_length = ctypes.c_uint32()
|
|
uuid_length.value = AMDSMI_GPU_UUID_SIZE
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_switch_device_uuid(
|
|
processor_handle, ctypes.byref(uuid_length), uuid
|
|
)
|
|
)
|
|
|
|
return uuid.value.decode("utf-8")
|
|
|
|
|
|
def amdsmi_get_gpu_driver_info(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
info = amdsmi_wrapper.amdsmi_driver_info_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_driver_info(processor_handle, ctypes.byref(info)))
|
|
|
|
# Not including os_kernel_version here due to it just being os.uname().release
|
|
driver_info = {
|
|
"driver_name": info.driver_name.decode("utf-8"),
|
|
"driver_version": info.driver_version.decode("utf-8"),
|
|
"driver_date": info.driver_date.decode("utf-8"),
|
|
}
|
|
|
|
for key, value in driver_info.items():
|
|
if value == "":
|
|
driver_info[key] = "N/A"
|
|
|
|
return driver_info
|
|
|
|
|
|
def amdsmi_get_power_info(processor_handle: processor_handle_t) -> Dict[str, ctypes.c_uint32]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
power_info = amdsmi_wrapper.amdsmi_power_info_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_power_info(processor_handle, ctypes.byref(power_info)))
|
|
|
|
power_info_dict = {
|
|
"socket_power": power_info.socket_power,
|
|
"current_socket_power": power_info.current_socket_power,
|
|
"average_socket_power": power_info.average_socket_power,
|
|
"gfx_voltage": power_info.gfx_voltage,
|
|
"soc_voltage": power_info.soc_voltage,
|
|
"mem_voltage": power_info.mem_voltage,
|
|
"power_limit": power_info.power_limit,
|
|
"ubb_power": power_info.ubb_power,
|
|
}
|
|
|
|
for key, value in power_info_dict.items():
|
|
if value in (
|
|
MaxUIntegerTypes.UINT8_T,
|
|
MaxUIntegerTypes.UINT16_T,
|
|
MaxUIntegerTypes.UINT32_T,
|
|
MaxUIntegerTypes.UINT64_T,
|
|
):
|
|
power_info_dict[key] = "N/A"
|
|
|
|
return power_info_dict
|
|
|
|
|
|
def amdsmi_is_gpu_power_management_enabled(processor_handle: processor_handle_t) -> bool:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
is_power_management_enabled = ctypes.c_bool()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_is_gpu_power_management_enabled(
|
|
processor_handle, ctypes.byref(is_power_management_enabled)
|
|
)
|
|
)
|
|
|
|
return is_power_management_enabled.value
|
|
|
|
|
|
def amdsmi_get_fw_info(processor_handle: processor_handle_t) -> Dict[str, List[Dict[str, str]]]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
fw_info = amdsmi_wrapper.amdsmi_fw_info_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_fw_info(processor_handle, ctypes.byref(fw_info)))
|
|
|
|
# Certain FW blocks are padded with 0s in the front intentionally
|
|
# But the C library converts the hex to an integer which trims the leading 0s
|
|
# Nor do we have a flag that defines the expected format for each FW block
|
|
# We can expect the following blocks to have a padded value and a specified format
|
|
|
|
hex_format_fw = [
|
|
AmdSmiFwBlock.AMDSMI_FW_ID_PSP_SOSDRV,
|
|
AmdSmiFwBlock.AMDSMI_FW_ID_TA_RAS,
|
|
AmdSmiFwBlock.AMDSMI_FW_ID_TA_XGMI,
|
|
AmdSmiFwBlock.AMDSMI_FW_ID_UVD,
|
|
AmdSmiFwBlock.AMDSMI_FW_ID_VCE,
|
|
AmdSmiFwBlock.AMDSMI_FW_ID_VCN,
|
|
]
|
|
|
|
# PM(AKA: SMC) firmware's hex value looks like 0x12345678
|
|
# However, they are parsed as: int(0x12).int(0x34).int(0x56).int(0x78)
|
|
# Which results in the following: 12.34.56.78
|
|
dec_format_fw = [AmdSmiFwBlock.AMDSMI_FW_ID_PM, AmdSmiFwBlock.AMDSMI_FW_ID_PLDM_BUNDLE]
|
|
|
|
firmwares = []
|
|
for i in range(0, fw_info.num_fw_info):
|
|
fw_name = AmdSmiFwBlock(fw_info.fw_info_list[i].fw_id)
|
|
fw_version = fw_info.fw_info_list[i].fw_version # This is in int format (base 10)
|
|
|
|
if fw_name in hex_format_fw:
|
|
# Convert the fw_version from a int to a hex string padded leading 0s
|
|
fw_version_string = hex(fw_version)[2:].zfill(8)
|
|
|
|
# Join every two hex digits with a dot
|
|
fw_version_string = ".".join(re.findall("..?", fw_version_string))
|
|
elif fw_name in dec_format_fw:
|
|
# Convert the fw_version from a int to a hex string padded leading 0s
|
|
fw_version_string = hex(fw_version)[2:].zfill(8)
|
|
|
|
# Convert every two hex digits to decimal and join them with a dot
|
|
dec_version_string = ""
|
|
for index, _ in enumerate(fw_version_string):
|
|
if index % 2 != 0:
|
|
continue
|
|
hex_digits = f"0x{fw_version_string[index : index + 2]}"
|
|
dec_version_string += str(int(hex_digits, 16)).zfill(2) + "."
|
|
fw_version_string = dec_version_string.strip(".")
|
|
else:
|
|
fw_version_string = str(fw_version)
|
|
|
|
firmwares.append({"fw_name": fw_name, "fw_version": fw_version_string.upper()})
|
|
return {"fw_list": firmwares}
|
|
|
|
|
|
def amdsmi_get_gpu_vram_usage(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
vram_usage = amdsmi_wrapper.amdsmi_vram_usage_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_vram_usage(processor_handle, ctypes.byref(vram_usage)))
|
|
|
|
return {"vram_total": vram_usage.vram_total, "vram_used": vram_usage.vram_used}
|
|
|
|
|
|
def amdsmi_get_pcie_info(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
pcie_info = amdsmi_wrapper.amdsmi_pcie_info_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_pcie_info(processor_handle, ctypes.byref(pcie_info)))
|
|
|
|
pcie_info_dict = {
|
|
"pcie_static": {
|
|
"max_pcie_width": _validate_if_max_uint(
|
|
pcie_info.pcie_static.max_pcie_width, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"max_pcie_speed": _validate_if_max_uint(
|
|
pcie_info.pcie_static.max_pcie_speed, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
"pcie_interface_version": _validate_if_max_uint(
|
|
pcie_info.pcie_static.pcie_interface_version, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
"slot_type": pcie_info.pcie_static.slot_type,
|
|
},
|
|
"pcie_metric": {
|
|
"pcie_width": _validate_if_max_uint(
|
|
pcie_info.pcie_metric.pcie_width, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"pcie_speed": _validate_if_max_uint(
|
|
pcie_info.pcie_metric.pcie_speed, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
"pcie_bandwidth": _validate_if_max_uint(
|
|
pcie_info.pcie_metric.pcie_bandwidth, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
"pcie_replay_count": _validate_if_max_uint(
|
|
pcie_info.pcie_metric.pcie_replay_count, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"pcie_l0_to_recovery_count": _validate_if_max_uint(
|
|
pcie_info.pcie_metric.pcie_l0_to_recovery_count, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"pcie_replay_roll_over_count": _validate_if_max_uint(
|
|
pcie_info.pcie_metric.pcie_replay_roll_over_count, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"pcie_nak_sent_count": _validate_if_max_uint(
|
|
pcie_info.pcie_metric.pcie_nak_sent_count, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"pcie_nak_received_count": _validate_if_max_uint(
|
|
pcie_info.pcie_metric.pcie_nak_received_count, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"pcie_lc_perf_other_end_recovery_count": _validate_if_max_uint(
|
|
pcie_info.pcie_metric.pcie_lc_perf_other_end_recovery_count,
|
|
MaxUIntegerTypes.UINT32_T,
|
|
),
|
|
},
|
|
}
|
|
|
|
slot_type = pcie_info_dict["pcie_static"]["slot_type"]
|
|
if isinstance(slot_type, int):
|
|
slot_types = amdsmi_wrapper.amdsmi_card_form_factor_t__enumvalues
|
|
if slot_type in slot_types:
|
|
pcie_info_dict["pcie_static"]["slot_type"] = slot_types[slot_type].replace(
|
|
"AMDSMI_CARD_FORM_FACTOR_", ""
|
|
)
|
|
else:
|
|
pcie_info_dict["pcie_static"]["slot_type"] = "Unknown"
|
|
else:
|
|
pcie_info_dict["pcie_static"]["slot_type"] = "N/A"
|
|
|
|
return pcie_info_dict
|
|
|
|
|
|
def amdsmi_get_gpu_xcd_counter(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
xcd_counter = ctypes.c_uint16()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_xcd_counter(processor_handle, ctypes.byref(xcd_counter))
|
|
)
|
|
|
|
return xcd_counter.value
|
|
|
|
|
|
def amdsmi_get_processor_handle_from_bdf(bdf: Union[str, amdsmi_wrapper.amdsmi_bdf_t]):
|
|
if isinstance(bdf, amdsmi_wrapper.amdsmi_bdf_t):
|
|
amdsmi_bdf = bdf
|
|
else:
|
|
parsed_bdf = _parse_bdf(bdf)
|
|
if parsed_bdf is None:
|
|
raise AmdSmiBdfFormatException(bdf)
|
|
amdsmi_bdf = _make_amdsmi_bdf_from_list(parsed_bdf)
|
|
processor_handle = amdsmi_wrapper.amdsmi_processor_handle()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_processor_handle_from_bdf(
|
|
amdsmi_bdf, ctypes.byref(processor_handle)
|
|
)
|
|
)
|
|
return processor_handle
|
|
|
|
|
|
def amdsmi_get_gpu_vendor_name(processor_handle: processor_handle_t) -> str:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
length = ctypes.c_uint64()
|
|
length.value = AMDSMI_MAX_STRING_LENGTH
|
|
|
|
vendor_name = ctypes.create_string_buffer(AMDSMI_MAX_STRING_LENGTH)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_vendor_name(processor_handle, vendor_name, length))
|
|
|
|
return vendor_name.value.decode("utf-8")
|
|
|
|
|
|
def amdsmi_get_gpu_vram_vendor(processor_handle: processor_handle_t):
|
|
"""Deprecated: use amdsmi_get_gpu_vram_info() instead.
|
|
|
|
This API is slated for removal in a future ROCm release.
|
|
"""
|
|
warnings.warn(
|
|
"amdsmi_get_gpu_vram_vendor() is deprecated, use amdsmi_get_gpu_vram_info() instead",
|
|
DeprecationWarning,
|
|
stacklevel=2,
|
|
)
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
length = ctypes.c_uint32()
|
|
length.value = AMDSMI_MAX_STRING_LENGTH
|
|
|
|
vram_vendor = ctypes.create_string_buffer(AMDSMI_MAX_STRING_LENGTH)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_vram_vendor(processor_handle, vram_vendor, length))
|
|
|
|
return vram_vendor.value.decode("utf-8")
|
|
|
|
|
|
def amdsmi_get_gpu_id(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
gpu_id_16 = ctypes.c_uint16()
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_id(processor_handle, ctypes.byref(gpu_id_16)))
|
|
|
|
return gpu_id_16.value
|
|
|
|
|
|
def amdsmi_get_gpu_subsystem_id(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
subsystem_id_16 = ctypes.c_uint16()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_subsystem_id(processor_handle, ctypes.byref(subsystem_id_16))
|
|
)
|
|
|
|
return _pad_hex_value(hex(subsystem_id_16.value), 4)
|
|
|
|
|
|
def amdsmi_get_gpu_subsystem_name(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
length = ctypes.c_uint64()
|
|
length.value = AMDSMI_MAX_STRING_LENGTH
|
|
|
|
name = ctypes.create_string_buffer(AMDSMI_MAX_STRING_LENGTH)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_subsystem_name(processor_handle, name, length))
|
|
|
|
return name.value.decode("utf-8")
|
|
|
|
|
|
def amdsmi_get_lib_version():
|
|
version = amdsmi_wrapper.amdsmi_version_t()
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_lib_version(ctypes.byref(version)))
|
|
|
|
return {
|
|
"major": version.major,
|
|
"minor": version.minor,
|
|
"release": version.release,
|
|
"build": version.build.contents.value.decode("utf-8"),
|
|
}
|
|
|
|
|
|
def amdsmi_topo_get_numa_node_number(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
numa_node_number = ctypes.c_uint32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_topo_get_numa_node_number(
|
|
processor_handle, ctypes.byref(numa_node_number)
|
|
)
|
|
)
|
|
|
|
return numa_node_number.value
|
|
|
|
|
|
def amdsmi_topo_get_link_weight(
|
|
processor_handle_src: processor_handle_t, processor_handle_dst: processor_handle_t
|
|
):
|
|
"""Return the qualitative link weight between two GPUs.
|
|
|
|
The weight is a cost metric derived from the KFD io_link weight property
|
|
(lower = closer/faster), analogous to numactl NUMA distances:
|
|
|
|
- xGMI: 15 per physical hop (e.g. a single-hop xGMI link has weight 15).
|
|
- PCIe: segments are summed (GPU→CPU + CPU→CPU + CPU→GPU). Each
|
|
GPU-to-CPU segment is typically 20. The CPU-to-CPU segment uses the
|
|
actual io_link weight when available; if that weight cannot be read, a
|
|
fallback of 10 is used for that segment.
|
|
|
|
Both handles must be GPU processor handles.
|
|
|
|
Returns:
|
|
int: The link weight.
|
|
"""
|
|
if not isinstance(processor_handle_src, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle_src, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(processor_handle_dst, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle_dst, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
weight = ctypes.c_uint64()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_topo_get_link_weight(
|
|
processor_handle_src, processor_handle_dst, ctypes.byref(weight)
|
|
)
|
|
)
|
|
|
|
return weight.value
|
|
|
|
|
|
def amdsmi_get_minmax_bandwidth_between_processors(
|
|
processor_handle_src: processor_handle_t, processor_handle_dst: processor_handle_t
|
|
):
|
|
if not isinstance(processor_handle_src, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle_src, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(processor_handle_dst, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle_dst, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
min_bandwidth = ctypes.c_uint64()
|
|
max_bandwidth = ctypes.c_uint64()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_minmax_bandwidth_between_processors(
|
|
processor_handle_src,
|
|
processor_handle_dst,
|
|
ctypes.byref(min_bandwidth),
|
|
ctypes.byref(max_bandwidth),
|
|
)
|
|
)
|
|
|
|
return {"min_bandwidth": min_bandwidth.value, "max_bandwidth": max_bandwidth.value}
|
|
|
|
|
|
def amdsmi_get_link_metrics(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
link_metrics = amdsmi_wrapper.amdsmi_link_metrics_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_link_metrics(processor_handle, ctypes.byref(link_metrics)))
|
|
|
|
links = []
|
|
for i in range(AMDSMI_MAX_NUM_XGMI_LINKS):
|
|
link = link_metrics.links[i]
|
|
links.append(
|
|
{
|
|
"bdf": _format_bdf(link.bdf),
|
|
"bit_rate": _validate_if_max_uint(link.bit_rate, MaxUIntegerTypes.UINT32_T),
|
|
"max_bandwidth": _validate_if_max_uint(
|
|
link.max_bandwidth, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
"link_type": link.link_type,
|
|
"read": link.read,
|
|
"write": link.write,
|
|
}
|
|
)
|
|
|
|
return {"num_links": link_metrics.num_links, "links": links}
|
|
|
|
|
|
def amdsmi_topo_get_link_type(
|
|
processor_handle_src: processor_handle_t, processor_handle_dst: processor_handle_t
|
|
):
|
|
"""Return the abstracted hop count and link type between two GPUs.
|
|
|
|
Both handles must be GPU processor handles. The hop count is an abstracted
|
|
topology step count, not the number of physical xGMI links traversed:
|
|
|
|
- 1: The two GPUs are reachable over xGMI, regardless of the number of
|
|
physical xGMI links on the route.
|
|
- 2: The two GPUs communicate over PCIe within the same CPU NUMA node.
|
|
- 3: The two GPUs communicate over PCIe across different CPU NUMA nodes.
|
|
- 4: Fallback when the inter-CPU io_link weight cannot be read.
|
|
|
|
Two GPUs on the same xGMI fabric always report 1 even when data physically
|
|
crosses multiple xGMI links. For the literal physical xGMI hop count, read
|
|
``/sys/class/drm/card*/device/xgmi_num_hops`` from the amdgpu driver.
|
|
|
|
Returns:
|
|
dict: ``{"hops": int, "type": int}`` where ``type`` is a value of
|
|
:class:`amdsmi_link_type_t`.
|
|
"""
|
|
if not isinstance(processor_handle_src, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle_src, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(processor_handle_dst, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle_dst, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
hops_64 = ctypes.c_uint64()
|
|
type_32 = ctypes.c_uint32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_topo_get_link_type(
|
|
processor_handle_src, processor_handle_dst, ctypes.byref(hops_64), ctypes.byref(type_32)
|
|
)
|
|
)
|
|
|
|
return {"hops": hops_64.value, "type": type_32.value}
|
|
|
|
|
|
def amdsmi_topo_get_p2p_status(
|
|
processor_handle_src: processor_handle_t, processor_handle_dst: processor_handle_t
|
|
):
|
|
if not isinstance(processor_handle_src, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle_src, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(processor_handle_dst, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle_dst, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
type_32 = ctypes.c_uint32()
|
|
cap = amdsmi_wrapper.struct_amdsmi_p2p_capability_t()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_topo_get_p2p_status(
|
|
processor_handle_src, processor_handle_dst, ctypes.byref(type_32), ctypes.byref(cap)
|
|
)
|
|
)
|
|
|
|
return {
|
|
"type": type_32.value,
|
|
"cap": {
|
|
"is_iolink_coherent": cap.is_iolink_coherent,
|
|
"is_iolink_atomics_32bit": cap.is_iolink_atomics_32bit,
|
|
"is_iolink_atomics_64bit": cap.is_iolink_atomics_64bit,
|
|
"is_iolink_dma": cap.is_iolink_dma,
|
|
"is_iolink_bi_directional": cap.is_iolink_bi_directional,
|
|
},
|
|
}
|
|
|
|
|
|
def amdsmi_is_P2P_accessible(
|
|
processor_handle_src: processor_handle_t, processor_handle_dst: processor_handle_t
|
|
):
|
|
if not isinstance(processor_handle_src, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle_src, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(processor_handle_dst, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle_dst, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
accessible = ctypes.c_bool()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_is_P2P_accessible(
|
|
processor_handle_src, processor_handle_dst, ctypes.byref(accessible)
|
|
)
|
|
)
|
|
|
|
return accessible.value
|
|
|
|
|
|
def amdsmi_get_gpu_compute_partition(processor_handle: processor_handle_t):
|
|
"""Deprecated: use amdsmi_get_gpu_accelerator_partition_profile() instead."""
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
warnings.warn(
|
|
"amdsmi_get_gpu_compute_partition() is deprecated, "
|
|
"use amdsmi_get_gpu_accelerator_partition_profile() instead",
|
|
DeprecationWarning,
|
|
stacklevel=2,
|
|
)
|
|
|
|
length = ctypes.c_uint32()
|
|
length.value = AMDSMI_MAX_STRING_LENGTH
|
|
|
|
compute_partition = ctypes.create_string_buffer(AMDSMI_MAX_STRING_LENGTH)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_compute_partition(processor_handle, compute_partition, length)
|
|
)
|
|
|
|
return compute_partition.value.decode("utf-8")
|
|
|
|
|
|
def amdsmi_set_gpu_compute_partition(
|
|
processor_handle: processor_handle_t, compute_partition: AmdSmiComputePartitionType
|
|
):
|
|
"""Deprecated: use amdsmi_set_gpu_accelerator_partition_profile() instead."""
|
|
|
|
warnings.warn(
|
|
"amdsmi_set_gpu_compute_partition() is deprecated, "
|
|
"use amdsmi_set_gpu_accelerator_partition_profile() instead",
|
|
DeprecationWarning,
|
|
stacklevel=2,
|
|
)
|
|
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(compute_partition, AmdSmiComputePartitionType):
|
|
raise AmdSmiParameterException(compute_partition, AmdSmiComputePartitionType)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_set_gpu_compute_partition(processor_handle, compute_partition))
|
|
|
|
|
|
def amdsmi_get_gpu_compute_partition_mem_alloc_mode(processor_handle: processor_handle_t):
|
|
"""Deprecated: use amdsmi_get_gpu_accelerator_partition_mem_alloc_mode() instead."""
|
|
|
|
warnings.warn(
|
|
"amdsmi_get_gpu_compute_partition_mem_alloc_mode() is deprecated, "
|
|
"use amdsmi_get_gpu_accelerator_partition_mem_alloc_mode() instead",
|
|
DeprecationWarning,
|
|
stacklevel=2,
|
|
)
|
|
name = amdsmi_get_gpu_accelerator_partition_mem_alloc_mode(processor_handle)
|
|
return name
|
|
|
|
|
|
def amdsmi_get_gpu_accelerator_partition_mem_alloc_mode(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
mode = amdsmi_wrapper.amdsmi_accelerator_partition_mem_alloc_mode_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_accelerator_partition_mem_alloc_mode(
|
|
processor_handle, ctypes.byref(mode)
|
|
)
|
|
)
|
|
return AmdSmiAcceleratorPartitionMemAllocModeType(mode.value).name
|
|
|
|
|
|
def amdsmi_set_gpu_compute_partition_mem_alloc_mode(
|
|
processor_handle: processor_handle_t, mode: AmdSmiComputePartitionMemAllocModeType
|
|
):
|
|
"""Deprecated: use amdsmi_set_gpu_accelerator_partition_mem_alloc_mode() instead."""
|
|
|
|
warnings.warn(
|
|
"amdsmi_set_gpu_compute_partition_mem_alloc_mode() is deprecated, "
|
|
"use amdsmi_set_gpu_accelerator_partition_mem_alloc_mode() instead",
|
|
DeprecationWarning,
|
|
stacklevel=2,
|
|
)
|
|
acc_mode = AmdSmiAcceleratorPartitionMemAllocModeType(mode)
|
|
amdsmi_set_gpu_accelerator_partition_mem_alloc_mode(processor_handle, acc_mode)
|
|
|
|
|
|
def amdsmi_set_gpu_accelerator_partition_mem_alloc_mode(
|
|
processor_handle: processor_handle_t, mode: AmdSmiAcceleratorPartitionMemAllocModeType
|
|
):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(mode, AmdSmiAcceleratorPartitionMemAllocModeType):
|
|
raise AmdSmiParameterException(mode, AmdSmiAcceleratorPartitionMemAllocModeType)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_gpu_accelerator_partition_mem_alloc_mode(processor_handle, mode)
|
|
)
|
|
|
|
|
|
def amdsmi_set_gpu_accelerator_partition_profile(
|
|
processor_handle: processor_handle_t, profile_index: int
|
|
):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(profile_index, int):
|
|
raise AmdSmiParameterException(profile_index, int)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_gpu_accelerator_partition_profile(processor_handle, profile_index)
|
|
)
|
|
|
|
|
|
def amdsmi_get_gpu_memory_partition(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
length = ctypes.c_uint32()
|
|
length.value = AMDSMI_MAX_STRING_LENGTH
|
|
|
|
memory_partition = ctypes.create_string_buffer(AMDSMI_MAX_STRING_LENGTH)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_memory_partition(processor_handle, memory_partition, length)
|
|
)
|
|
|
|
return memory_partition.value.decode("utf-8")
|
|
|
|
|
|
def amdsmi_get_gpu_memory_partition_config(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
config = amdsmi_wrapper.amdsmi_memory_partition_config_t()
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_memory_partition_config(processor_handle, config))
|
|
mem_caps_list = []
|
|
if config.partition_caps.nps_flags.nps1_cap == 1:
|
|
mem_caps_list.append("NPS1")
|
|
if config.partition_caps.nps_flags.nps2_cap == 1:
|
|
mem_caps_list.append("NPS2")
|
|
if config.partition_caps.nps_flags.nps4_cap == 1:
|
|
mem_caps_list.append("NPS4")
|
|
if config.partition_caps.nps_flags.nps8_cap == 1:
|
|
mem_caps_list.append("NPS8")
|
|
if (
|
|
config.partition_caps.nps_flags.nps1_cap == 0
|
|
and config.partition_caps.nps_flags.nps2_cap == 0
|
|
and config.partition_caps.nps_flags.nps4_cap == 0
|
|
and config.partition_caps.nps_flags.nps8_cap == 0
|
|
):
|
|
mem_caps_list.append("N/A")
|
|
|
|
return_dict = {
|
|
"partition_caps": mem_caps_list,
|
|
"mp_mode": amdsmi_wrapper.amdsmi_memory_partition_type_t__enumvalues[config.mp_mode]
|
|
.replace("AMDSMI_MEMORY_PARTITION_", "")
|
|
.replace("UNKNOWN", "N/A"),
|
|
"num_numa_ranges": "N/A",
|
|
"numa_range": "N/A",
|
|
}
|
|
return return_dict
|
|
|
|
|
|
def amdsmi_set_gpu_memory_partition(
|
|
processor_handle: processor_handle_t, memory_partition: AmdSmiMemoryPartitionType
|
|
):
|
|
"""Deprecated: Use amdsmi_set_gpu_memory_partition_mode() instead. Will be deprecated in future ROCM release"""
|
|
|
|
warnings.warn(
|
|
"amdsmi_set_gpu_memory_partition() is deprecated, use amdsmi_set_gpu_memory_partition_mode() instead",
|
|
DeprecationWarning,
|
|
stacklevel=2,
|
|
)
|
|
amdsmi_set_gpu_memory_partition_mode(processor_handle, memory_partition)
|
|
|
|
|
|
def amdsmi_set_gpu_memory_partition_mode(
|
|
processor_handle: processor_handle_t, memory_partition: AmdSmiMemoryPartitionType
|
|
):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(memory_partition, AmdSmiMemoryPartitionType):
|
|
raise AmdSmiParameterException(memory_partition, AmdSmiMemoryPartitionType)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_gpu_memory_partition_mode(processor_handle, memory_partition)
|
|
)
|
|
|
|
|
|
def amdsmi_get_gpu_accelerator_partition_profile(
|
|
processor_handle: processor_handle_t,
|
|
) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
exception_caught = False
|
|
return_dictionary = {}
|
|
length = 8
|
|
partition_id = [0, 0, 0, 0, 0, 0, 0, 0]
|
|
partition_id_list = (ctypes.c_uint32 * length)(*partition_id)
|
|
profile = amdsmi_wrapper.amdsmi_accelerator_partition_profile_t()
|
|
partition_ids = []
|
|
kPOSITION_OF_PARTITION_ID = 0
|
|
|
|
ret = amdsmi_wrapper.amdsmi_get_gpu_accelerator_partition_profile(
|
|
processor_handle, ctypes.byref(profile), partition_id_list
|
|
)
|
|
if ret == amdsmi_wrapper.AMDSMI_STATUS_NOT_SUPPORTED:
|
|
# partition_id[0] will contain the partition id of each device
|
|
# BM/Guest will include this logic. Host will only display primary partition ids.
|
|
partition_ids.append(partition_id_list[kPOSITION_OF_PARTITION_ID])
|
|
|
|
try:
|
|
_check_res(ret)
|
|
except AmdSmiException as e:
|
|
partition_profile_dict = {
|
|
"profile_type": "N/A",
|
|
"num_partitions": "N/A",
|
|
"profile_index": "N/A",
|
|
"memory_caps": "N/A",
|
|
"num_resources": "N/A",
|
|
"resources": "N/A",
|
|
}
|
|
return_dictionary = {
|
|
"partition_id": partition_ids,
|
|
"partition_profile": partition_profile_dict,
|
|
}
|
|
if ret == amdsmi_wrapper.AMDSMI_STATUS_NOT_SUPPORTED:
|
|
exception_caught = True
|
|
else:
|
|
_check_res(
|
|
ret
|
|
) # re-raise the exception if error is anything other than AMDSMI_STATUS_NOT_SUPPORTED
|
|
# this ensures we can get partition ID even if the profile is not supported.
|
|
finally:
|
|
if not exception_caught:
|
|
profile_type_ret = amdsmi_wrapper.amdsmi_accelerator_partition_type_t__enumvalues[
|
|
profile.profile_type
|
|
].replace("AMDSMI_ACCELERATOR_PARTITION_", "")
|
|
profile_type_ret = profile_type_ret.replace("INVALID", "N/A")
|
|
length = profile.num_partitions
|
|
# partition_id[0] will contain the partition id of each device
|
|
# BM/Guest will include this logic. Host will only display primary partition ids.
|
|
partition_ids.append(partition_id_list[kPOSITION_OF_PARTITION_ID])
|
|
mem_caps_list = []
|
|
if profile.memory_caps.nps_flags.nps1_cap == 1:
|
|
mem_caps_list.append("NPS1")
|
|
if profile.memory_caps.nps_flags.nps2_cap == 1:
|
|
mem_caps_list.append("NPS2")
|
|
if profile.memory_caps.nps_flags.nps4_cap == 1:
|
|
mem_caps_list.append("NPS4")
|
|
if profile.memory_caps.nps_flags.nps8_cap == 1:
|
|
mem_caps_list.append("NPS8")
|
|
if (
|
|
profile.memory_caps.nps_flags.nps1_cap == 0
|
|
and profile.memory_caps.nps_flags.nps2_cap == 0
|
|
and profile.memory_caps.nps_flags.nps4_cap == 0
|
|
and profile.memory_caps.nps_flags.nps8_cap == 0
|
|
):
|
|
mem_caps_list.append("N/A")
|
|
partition_profile_dict = {
|
|
"profile_type": profile_type_ret,
|
|
"num_partitions": profile.num_partitions,
|
|
"profile_index": profile.profile_index,
|
|
"memory_caps": mem_caps_list,
|
|
"num_resources": profile.num_resources,
|
|
"resources": "N/A",
|
|
}
|
|
return_dictionary = {
|
|
"partition_id": partition_ids,
|
|
"partition_profile": partition_profile_dict,
|
|
}
|
|
return return_dictionary
|
|
|
|
|
|
def amdsmi_get_gpu_accelerator_partition_profile_config(
|
|
processor_handle: processor_handle_t,
|
|
) -> Dict:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
config = amdsmi_wrapper.amdsmi_accelerator_partition_profile_config_t()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_accelerator_partition_profile_config(
|
|
processor_handle, ctypes.byref(config)
|
|
)
|
|
)
|
|
|
|
profiles = []
|
|
resources = []
|
|
resource_idx = 0
|
|
for i in range(config.num_profiles):
|
|
profile = config.profiles[i]
|
|
profile_type_ret = amdsmi_wrapper.amdsmi_accelerator_partition_type_t__enumvalues[
|
|
config.profiles[i].profile_type
|
|
].replace("AMDSMI_ACCELERATOR_PARTITION_", "")
|
|
profile_type_ret = profile_type_ret.replace("INVALID", "N/A")
|
|
|
|
mem_caps_list = []
|
|
if profile.memory_caps.nps_flags.nps1_cap == 1:
|
|
mem_caps_list.append("NPS1")
|
|
if profile.memory_caps.nps_flags.nps2_cap == 1:
|
|
mem_caps_list.append("NPS2")
|
|
if profile.memory_caps.nps_flags.nps4_cap == 1:
|
|
mem_caps_list.append("NPS4")
|
|
if profile.memory_caps.nps_flags.nps8_cap == 1:
|
|
mem_caps_list.append("NPS8")
|
|
if (
|
|
profile.memory_caps.nps_flags.nps1_cap == 0
|
|
and profile.memory_caps.nps_flags.nps2_cap == 0
|
|
and profile.memory_caps.nps_flags.nps4_cap == 0
|
|
and profile.memory_caps.nps_flags.nps8_cap == 0
|
|
):
|
|
mem_caps_list.append("N/A")
|
|
|
|
resources = []
|
|
for _ in range(config.num_resource_profiles):
|
|
res_profile = config.resource_profiles[resource_idx]
|
|
resource_profiles_ret = (
|
|
amdsmi_wrapper.amdsmi_accelerator_partition_resource_type_t__enumvalues[
|
|
res_profile.resource_type
|
|
].replace("AMDSMI_ACCELERATOR_", "")
|
|
)
|
|
resource_profile_dict = {
|
|
"profile_index": res_profile.profile_index,
|
|
"resource_type": resource_profiles_ret,
|
|
"partition_resource": res_profile.partition_resource,
|
|
"num_partitions_share_resource": res_profile.num_partitions_share_resource,
|
|
}
|
|
resources.append(resource_profile_dict)
|
|
resource_idx += 1
|
|
|
|
profile_dict = {
|
|
"profile_type": profile_type_ret,
|
|
"num_partitions": profile.num_partitions,
|
|
"profile_index": profile.profile_index,
|
|
"memory_caps": mem_caps_list,
|
|
"num_resources": profile.num_resources,
|
|
"resources": resources,
|
|
}
|
|
profiles.append(profile_dict)
|
|
|
|
config_dict = {
|
|
"num_profiles": config.num_profiles,
|
|
"num_resource_profiles": config.num_resource_profiles,
|
|
"resource_profiles": resources,
|
|
"default_profile_index": config.default_profile_index,
|
|
"profiles": profiles,
|
|
}
|
|
|
|
return config_dict
|
|
|
|
|
|
def amdsmi_get_xgmi_info(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
xgmi_info = amdsmi_wrapper.amdsmi_xgmi_info_t()
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_xgmi_info(processor_handle, xgmi_info))
|
|
|
|
return {
|
|
"xgmi_lanes": xgmi_info.xgmi_lanes,
|
|
"xgmi_hive_id": xgmi_info.xgmi_hive_id,
|
|
"xgmi_node_id": xgmi_info.xgmi_node_id,
|
|
"index": xgmi_info.index,
|
|
}
|
|
|
|
|
|
def amdsmi_gpu_counter_group_supported(
|
|
processor_handle: processor_handle_t, event_group: AmdSmiEventGroup
|
|
):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(event_group, AmdSmiEventGroup):
|
|
raise AmdSmiParameterException(event_group, AmdSmiEventGroup)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_gpu_counter_group_supported(processor_handle, event_group))
|
|
|
|
|
|
def amdsmi_gpu_create_counter(
|
|
processor_handle: processor_handle_t, event_type: AmdSmiEventType
|
|
) -> amdsmi_wrapper.amdsmi_event_handle_t:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(event_type, AmdSmiEventType):
|
|
raise AmdSmiParameterException(event_type, AmdSmiEventType)
|
|
|
|
event_handle = amdsmi_wrapper.amdsmi_event_handle_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_gpu_create_counter(
|
|
processor_handle, event_type, ctypes.byref(event_handle)
|
|
)
|
|
)
|
|
|
|
return event_handle
|
|
|
|
|
|
def amdsmi_gpu_destroy_counter(event_handle: amdsmi_wrapper.amdsmi_event_handle_t) -> None:
|
|
if not isinstance(event_handle, amdsmi_wrapper.amdsmi_event_handle_t):
|
|
raise AmdSmiParameterException(event_handle, amdsmi_wrapper.amdsmi_event_handle_t)
|
|
_check_res(amdsmi_wrapper.amdsmi_gpu_destroy_counter(event_handle))
|
|
|
|
|
|
def amdsmi_gpu_control_counter(
|
|
event_handle: amdsmi_wrapper.amdsmi_event_handle_t, counter_command: AmdSmiCounterCommand
|
|
):
|
|
if not isinstance(event_handle, amdsmi_wrapper.amdsmi_event_handle_t):
|
|
raise AmdSmiParameterException(event_handle, amdsmi_wrapper.amdsmi_event_handle_t)
|
|
if not isinstance(counter_command, AmdSmiCounterCommand):
|
|
raise AmdSmiParameterException(counter_command, AmdSmiCounterCommand)
|
|
|
|
event_handle_value = amdsmi_wrapper.amdsmi_event_handle_t(event_handle.value)
|
|
command_args = ctypes.c_void_p()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_gpu_control_counter(event_handle_value, counter_command, command_args)
|
|
)
|
|
|
|
|
|
def amdsmi_gpu_read_counter(event_handle: amdsmi_wrapper.amdsmi_event_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(event_handle, amdsmi_wrapper.amdsmi_event_handle_t):
|
|
raise AmdSmiParameterException(event_handle, amdsmi_wrapper.amdsmi_event_handle_t)
|
|
|
|
counter_value = amdsmi_wrapper.amdsmi_counter_value_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_gpu_read_counter(event_handle, ctypes.byref(counter_value)))
|
|
|
|
return {
|
|
"value": counter_value.value,
|
|
"time_enabled": counter_value.time_enabled,
|
|
"time_running": counter_value.time_running,
|
|
}
|
|
|
|
|
|
def amdsmi_get_gpu_available_counters(
|
|
processor_handle: processor_handle_t, event_group: AmdSmiEventGroup
|
|
) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(event_group, AmdSmiEventGroup):
|
|
raise AmdSmiParameterException(event_group, AmdSmiEventGroup)
|
|
available = ctypes.c_uint32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_available_counters(
|
|
processor_handle, event_group, ctypes.byref(available)
|
|
)
|
|
)
|
|
|
|
return available.value
|
|
|
|
|
|
def amdsmi_set_gpu_perf_level(processor_handle: processor_handle_t, perf_level: AmdSmiDevPerfLevel):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(perf_level, AmdSmiDevPerfLevel):
|
|
raise AmdSmiParameterException(perf_level, AmdSmiDevPerfLevel)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_set_gpu_perf_level(processor_handle, perf_level))
|
|
|
|
|
|
def amdsmi_reset_gpu(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_reset_gpu(processor_handle))
|
|
|
|
|
|
def amdsmi_set_gpu_fan_speed(processor_handle: processor_handle_t, sensor_idx: int, fan_speed: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(sensor_idx, int):
|
|
raise AmdSmiParameterException(sensor_idx, int)
|
|
if not isinstance(fan_speed, int):
|
|
raise AmdSmiParameterException(fan_speed, int)
|
|
sensor_idx_32 = ctypes.c_uint32(sensor_idx)
|
|
fan_speed_64 = ctypes.c_uint64(fan_speed)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_gpu_fan_speed(processor_handle, sensor_idx_32, fan_speed_64)
|
|
)
|
|
|
|
|
|
def amdsmi_reset_gpu_fan(processor_handle: processor_handle_t, sensor_idx: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(sensor_idx, int):
|
|
raise AmdSmiParameterException(sensor_idx, int)
|
|
sensor_idx_32 = ctypes.c_uint32(sensor_idx)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_reset_gpu_fan(processor_handle, sensor_idx_32))
|
|
|
|
|
|
def amdsmi_set_clk_freq(processor_handle: processor_handle_t, clk_type: str, freq_bitmask: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(clk_type, str):
|
|
raise AmdSmiParameterException(clk_type, str)
|
|
if not isinstance(freq_bitmask, int):
|
|
raise AmdSmiParameterException(freq_bitmask, int)
|
|
|
|
if clk_type.lower() == "sclk":
|
|
clk_type_conversion = AmdSmiClkType.SYS
|
|
elif clk_type.lower() == "mclk":
|
|
clk_type_conversion = AmdSmiClkType.MEM
|
|
elif clk_type.lower() == "fclk":
|
|
clk_type_conversion = AmdSmiClkType.DF
|
|
elif clk_type.lower() == "socclk":
|
|
clk_type_conversion = AmdSmiClkType.SOC
|
|
else:
|
|
clk_type_conversion = "N/A"
|
|
if not isinstance(clk_type_conversion, AmdSmiClkType):
|
|
raise AmdSmiParameterException(clk_type_conversion, AmdSmiClkType)
|
|
|
|
freq_bitmask_64 = ctypes.c_uint64(freq_bitmask)
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_clk_freq(processor_handle, clk_type_conversion, freq_bitmask_64)
|
|
)
|
|
|
|
|
|
def amdsmi_set_soc_pstate(processor_handle: processor_handle_t, policy_id: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(policy_id, int):
|
|
raise AmdSmiParameterException(policy_id, int)
|
|
_check_res(amdsmi_wrapper.amdsmi_set_soc_pstate(processor_handle, policy_id))
|
|
|
|
|
|
def amdsmi_set_xgmi_plpd(processor_handle: processor_handle_t, policy_id: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(policy_id, int):
|
|
raise AmdSmiParameterException(policy_id, int)
|
|
_check_res(amdsmi_wrapper.amdsmi_set_xgmi_plpd(processor_handle, policy_id))
|
|
return
|
|
|
|
|
|
def amdsmi_set_gpu_process_isolation(processor_handle: processor_handle_t, pisolate: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(pisolate, int):
|
|
raise AmdSmiParameterException(pisolate, int)
|
|
_check_res(amdsmi_wrapper.amdsmi_set_gpu_process_isolation(processor_handle, pisolate))
|
|
|
|
|
|
def amdsmi_clean_gpu_local_data(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
_check_res(amdsmi_wrapper.amdsmi_clean_gpu_local_data(processor_handle))
|
|
|
|
|
|
def amdsmi_set_gpu_overdrive_level(processor_handle: processor_handle_t, overdrive_value: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(overdrive_value, int):
|
|
raise AmdSmiParameterException(overdrive_value, int)
|
|
overdrive_value_32 = ctypes.c_uint32(overdrive_value)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_set_gpu_overdrive_level(processor_handle, overdrive_value_32))
|
|
|
|
|
|
def amdsmi_get_gpu_bdf_id(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
bdfid = ctypes.c_uint64()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_bdf_id(processor_handle, ctypes.byref(bdfid)))
|
|
|
|
return bdfid.value
|
|
|
|
|
|
def amdsmi_set_gpu_pci_bandwidth(processor_handle: processor_handle_t, bitmask: int) -> None:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(bitmask, int):
|
|
raise AmdSmiParameterException(bitmask, int)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_gpu_pci_bandwidth(processor_handle, ctypes.c_uint64(bitmask))
|
|
)
|
|
|
|
|
|
def amdsmi_get_gpu_pci_bandwidth(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
bandwidth = amdsmi_wrapper.amdsmi_pcie_bandwidth_t()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_pci_bandwidth(processor_handle, ctypes.byref(bandwidth))
|
|
)
|
|
|
|
transfer_rate = _format_transfer_rate(bandwidth.transfer_rate)
|
|
|
|
return {"transfer_rate": transfer_rate, "lanes": list(bandwidth.lanes)}
|
|
|
|
|
|
def amdsmi_get_gpu_pci_throughput(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
sent = ctypes.c_uint64()
|
|
received = ctypes.c_uint64()
|
|
max_pkt_sz = ctypes.c_uint64()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_pci_throughput(
|
|
processor_handle, ctypes.byref(sent), ctypes.byref(received), ctypes.byref(max_pkt_sz)
|
|
)
|
|
)
|
|
|
|
return {"sent": sent.value, "received": received.value, "max_pkt_sz": max_pkt_sz.value}
|
|
|
|
|
|
def amdsmi_get_gpu_pci_replay_counter(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
counter = ctypes.c_uint64()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_pci_replay_counter(processor_handle, ctypes.byref(counter))
|
|
)
|
|
|
|
return counter.value
|
|
|
|
|
|
def amdsmi_get_gpu_topo_numa_affinity(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
numa_node = ctypes.c_int32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_topo_numa_affinity(processor_handle, ctypes.byref(numa_node))
|
|
)
|
|
|
|
return numa_node.value
|
|
|
|
|
|
def amdsmi_get_nic_topo_numa_affinity(processor_handle: amdsmi_wrapper.amdsmi_processor_handle):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
numa_node = ctypes.c_int32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_nic_topo_numa_affinity(processor_handle, ctypes.byref(numa_node))
|
|
)
|
|
|
|
return numa_node.value
|
|
|
|
|
|
def amdsmi_get_switch_topo_numa_affinity(processor_handle: amdsmi_wrapper.amdsmi_processor_handle):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
numa_node = ctypes.c_int32()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_switch_topo_numa_affinity(
|
|
processor_handle, ctypes.byref(numa_node)
|
|
)
|
|
)
|
|
|
|
return numa_node.value
|
|
|
|
|
|
def amdsmi_get_gpu_topo_cpu_affinity(processor_handle: amdsmi_wrapper.amdsmi_processor_handle):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
gpucpuaffid = ctypes.create_string_buffer(AMDSMI_MAX_STRING_LENGTH)
|
|
|
|
gpucpuaffid_length = ctypes.c_uint32()
|
|
gpucpuaffid_length.value = AMDSMI_MAX_STRING_LENGTH
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_topo_cpu_affinity(
|
|
processor_handle, ctypes.byref(gpucpuaffid_length), gpucpuaffid
|
|
)
|
|
)
|
|
return gpucpuaffid.value.decode("utf-8")
|
|
|
|
|
|
def amdsmi_get_nic_topo_cpu_affinity(processor_handle: amdsmi_wrapper.amdsmi_processor_handle):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
niccpuaffid = ctypes.create_string_buffer(AMDSMI_MAX_STRING_LENGTH)
|
|
|
|
niccpuaffid_length = ctypes.c_uint32()
|
|
niccpuaffid_length.value = AMDSMI_MAX_STRING_LENGTH
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_nic_topo_cpu_affinity(
|
|
processor_handle, ctypes.byref(niccpuaffid_length), niccpuaffid
|
|
)
|
|
)
|
|
return niccpuaffid.value.decode("utf-8")
|
|
|
|
|
|
def amdsmi_get_switch_topo_cpu_affinity(processor_handle: amdsmi_wrapper.amdsmi_processor_handle):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
switchcpuaffid = ctypes.create_string_buffer(AMDSMI_MAX_STRING_LENGTH)
|
|
|
|
switchcpuaffid_length = ctypes.c_uint32()
|
|
switchcpuaffid_length.value = AMDSMI_MAX_STRING_LENGTH
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_switch_topo_cpu_affinity(
|
|
processor_handle, ctypes.byref(switchcpuaffid_length), switchcpuaffid
|
|
)
|
|
)
|
|
return switchcpuaffid.value.decode("utf-8")
|
|
|
|
|
|
def amdsmi_get_nic_gpu_topo_info(
|
|
processor_handle_src: amdsmi_wrapper.amdsmi_processor_handle,
|
|
processor_handle_dst: amdsmi_wrapper.amdsmi_processor_handle,
|
|
):
|
|
|
|
if not isinstance(processor_handle_src, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle_src, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(processor_handle_dst, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle_dst, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
niccgpuinfo = ctypes.create_string_buffer(AMDSMI_MAX_STRING_LENGTH)
|
|
|
|
niccgpuinfo_length = ctypes.c_uint32()
|
|
niccgpuinfo_length.value = AMDSMI_MAX_STRING_LENGTH
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_nic_gpu_topo_info(
|
|
processor_handle_src,
|
|
processor_handle_dst,
|
|
ctypes.byref(niccgpuinfo_length),
|
|
niccgpuinfo,
|
|
)
|
|
)
|
|
return niccgpuinfo.value.decode("utf-8")
|
|
|
|
|
|
def amdsmi_set_power_cap(processor_handle: processor_handle_t, sensor_ind: int, cap: int) -> None:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(sensor_ind, int):
|
|
raise AmdSmiParameterException(sensor_ind, int)
|
|
|
|
if not isinstance(cap, int):
|
|
raise AmdSmiParameterException(cap, int)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_power_cap(
|
|
processor_handle, ctypes.c_uint32(sensor_ind), ctypes.c_uint64(cap)
|
|
)
|
|
)
|
|
|
|
|
|
def amdsmi_set_gpu_power_profile(
|
|
processor_handle: processor_handle_t, reserved: int, profile: AmdSmiPowerProfilePresetMasks
|
|
) -> None:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(reserved, int):
|
|
raise AmdSmiParameterException(reserved, int)
|
|
|
|
if not isinstance(profile, AmdSmiPowerProfilePresetMasks):
|
|
raise AmdSmiParameterException(profile, AmdSmiPowerProfilePresetMasks)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_gpu_power_profile(
|
|
processor_handle, ctypes.c_uint32(reserved), profile
|
|
)
|
|
)
|
|
|
|
|
|
def amdsmi_get_energy_count(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
energy_accumulator = ctypes.c_uint64()
|
|
counter_resolution = ctypes.c_float()
|
|
timestamp = ctypes.c_uint64()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_energy_count(
|
|
processor_handle,
|
|
ctypes.byref(energy_accumulator),
|
|
ctypes.byref(counter_resolution),
|
|
ctypes.byref(timestamp),
|
|
)
|
|
)
|
|
|
|
return {
|
|
"energy_accumulator": energy_accumulator.value,
|
|
"counter_resolution": counter_resolution.value,
|
|
"timestamp": timestamp.value,
|
|
}
|
|
|
|
|
|
def amdsmi_set_gpu_clk_limit(
|
|
processor_handle: processor_handle_t, clk_type: str, limit_type: str, value: int
|
|
) -> None:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(clk_type, str):
|
|
raise AmdSmiParameterException(clk_type, str)
|
|
if not isinstance(limit_type, str):
|
|
raise AmdSmiParameterException(limit_type, str)
|
|
if not isinstance(value, int):
|
|
raise AmdSmiParameterException(value, int)
|
|
if clk_type.lower() == "sclk":
|
|
clk_type_conversion = amdsmi_wrapper.AMDSMI_CLK_TYPE_SYS
|
|
elif clk_type.lower() == "mclk":
|
|
clk_type_conversion = amdsmi_wrapper.AMDSMI_CLK_TYPE_MEM
|
|
elif clk_type.lower() == "fclk":
|
|
clk_type_conversion = amdsmi_wrapper.AMDSMI_CLK_TYPE_DF
|
|
else:
|
|
raise AmdSmiParameterException(f"Unsupported clock type: {clk_type}", str)
|
|
|
|
if limit_type.lower() == "min":
|
|
limit_type_conversion = amdsmi_wrapper.AMDSMI_CLK_LIMIT_MIN
|
|
elif limit_type.lower() == "max":
|
|
limit_type_conversion = amdsmi_wrapper.AMDSMI_CLK_LIMIT_MAX
|
|
else:
|
|
raise AmdSmiParameterException(f"Unsupported limit type: {limit_type}", str)
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_gpu_clk_limit(
|
|
processor_handle, clk_type_conversion, limit_type_conversion, ctypes.c_uint64(value)
|
|
)
|
|
)
|
|
|
|
|
|
def amdsmi_get_gpu_memory_total(processor_handle: processor_handle_t, mem_type: AmdSmiMemoryType):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(mem_type, AmdSmiMemoryType):
|
|
raise AmdSmiParameterException(mem_type, AmdSmiMemoryType)
|
|
|
|
total = ctypes.c_uint64()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_memory_total(processor_handle, mem_type, ctypes.byref(total))
|
|
)
|
|
|
|
return total.value
|
|
|
|
|
|
def amdsmi_set_gpu_od_clk_info(
|
|
processor_handle: processor_handle_t, level: AmdSmiFreqInd, value: int, clk_type: AmdSmiClkType
|
|
) -> None:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(level, AmdSmiFreqInd):
|
|
raise AmdSmiParameterException(level, AmdSmiFreqInd)
|
|
|
|
if not isinstance(value, int):
|
|
raise AmdSmiParameterException(value, int)
|
|
|
|
if not isinstance(clk_type, AmdSmiClkType):
|
|
raise AmdSmiParameterException(clk_type, AmdSmiClkType)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_gpu_od_clk_info(
|
|
processor_handle, level, ctypes.c_uint64(value), clk_type
|
|
)
|
|
)
|
|
|
|
|
|
def amdsmi_get_gpu_memory_usage(processor_handle: processor_handle_t, mem_type: AmdSmiMemoryType):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(mem_type, AmdSmiMemoryType):
|
|
raise AmdSmiParameterException(mem_type, AmdSmiMemoryType)
|
|
|
|
used = ctypes.c_uint64()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_memory_usage(processor_handle, mem_type, ctypes.byref(used))
|
|
)
|
|
|
|
return used.value
|
|
|
|
|
|
def amdsmi_set_gpu_od_volt_info(
|
|
processor_handle: processor_handle_t, vpoint: int, clk_value: int, volt_value: int
|
|
) -> None:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(vpoint, int):
|
|
raise AmdSmiParameterException(vpoint, int)
|
|
|
|
if not isinstance(clk_value, int):
|
|
raise AmdSmiParameterException(clk_value, int)
|
|
|
|
if not isinstance(volt_value, int):
|
|
raise AmdSmiParameterException(volt_value, int)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_set_gpu_od_volt_info(
|
|
processor_handle,
|
|
ctypes.c_uint32(vpoint),
|
|
ctypes.c_uint64(clk_value),
|
|
ctypes.c_uint64(volt_value),
|
|
)
|
|
)
|
|
|
|
|
|
def amdsmi_get_gpu_fan_rpms(processor_handle: processor_handle_t, sensor_idx: int) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(sensor_idx, int):
|
|
raise AmdSmiParameterException(sensor_idx, int)
|
|
fan_speed = ctypes.c_int64()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_fan_rpms(
|
|
processor_handle, sensor_idx, ctypes.byref(fan_speed)
|
|
)
|
|
)
|
|
|
|
return fan_speed.value
|
|
|
|
|
|
def amdsmi_get_gpu_fan_speed(processor_handle: processor_handle_t, sensor_idx: int) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(sensor_idx, int):
|
|
raise AmdSmiParameterException(sensor_idx, int)
|
|
fan_speed = ctypes.c_int64()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_fan_speed(
|
|
processor_handle, sensor_idx, ctypes.byref(fan_speed)
|
|
)
|
|
)
|
|
|
|
return fan_speed.value
|
|
|
|
|
|
def amdsmi_get_gpu_fan_speed_max(processor_handle: processor_handle_t, sensor_idx: int) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(sensor_idx, int):
|
|
raise AmdSmiParameterException(sensor_idx, int)
|
|
fan_speed = ctypes.c_uint64()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_fan_speed_max(
|
|
processor_handle, sensor_idx, ctypes.byref(fan_speed)
|
|
)
|
|
)
|
|
|
|
return fan_speed.value
|
|
|
|
|
|
def amdsmi_get_node_handle(processor_handle):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
node_handle = amdsmi_wrapper.amdsmi_node_handle()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_node_handle(processor_handle, ctypes.byref(node_handle)))
|
|
|
|
return node_handle
|
|
|
|
|
|
def amdsmi_get_npm_info(node_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(node_handle, amdsmi_wrapper.amdsmi_node_handle):
|
|
raise AmdSmiParameterException(node_handle, amdsmi_wrapper.amdsmi_node_handle)
|
|
|
|
npm_info = amdsmi_wrapper.amdsmi_npm_info_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_npm_info(node_handle, ctypes.byref(npm_info)))
|
|
|
|
dict_ret = {
|
|
"limit": _validate_if_max_uint(npm_info.limit, MaxUIntegerTypes.UINT64_T),
|
|
"status": npm_info.status,
|
|
"ubb_power_threshold": _validate_if_max_uint(
|
|
npm_info.ubb_power_threshold, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
}
|
|
|
|
return dict_ret
|
|
|
|
|
|
def amdsmi_get_temp_metric(
|
|
processor_handle: processor_handle_t,
|
|
sensor_type: AmdSmiTemperatureType,
|
|
metric: AmdSmiTemperatureMetric,
|
|
) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(sensor_type, AmdSmiTemperatureType):
|
|
raise AmdSmiParameterException(sensor_type, AmdSmiTemperatureType)
|
|
if not isinstance(metric, AmdSmiTemperatureMetric):
|
|
raise AmdSmiParameterException(metric, AmdSmiTemperatureMetric)
|
|
|
|
temp_value = ctypes.c_int64()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_temp_metric(
|
|
processor_handle, sensor_type, metric, ctypes.byref(temp_value)
|
|
)
|
|
)
|
|
|
|
return temp_value.value
|
|
|
|
|
|
def amdsmi_get_gpu_volt_metric(
|
|
processor_handle: processor_handle_t,
|
|
sensor_type: AmdSmiVoltageType,
|
|
metric: AmdSmiVoltageMetric,
|
|
) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(sensor_type, AmdSmiVoltageType):
|
|
raise AmdSmiParameterException(sensor_type, AmdSmiVoltageType)
|
|
if not isinstance(metric, AmdSmiVoltageMetric):
|
|
raise AmdSmiParameterException(metric, AmdSmiVoltageMetric)
|
|
|
|
voltage = ctypes.c_int64()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_volt_metric(
|
|
processor_handle, sensor_type, metric, ctypes.byref(voltage)
|
|
)
|
|
)
|
|
|
|
return voltage.value
|
|
|
|
|
|
def amdsmi_get_utilization_count(
|
|
processor_handle: processor_handle_t, counter_types: List[AmdSmiUtilizationCounterType]
|
|
) -> List[Dict[str, Any]]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
# Enforce List typing
|
|
if not isinstance(counter_types, list):
|
|
counter_types = [counter_types]
|
|
|
|
counter_types = list(set(counter_types))
|
|
|
|
# Validate Inputs
|
|
if len(counter_types) == 0:
|
|
raise AmdSmiLibraryException(amdsmi_wrapper.AMDSMI_STATUS_INVAL)
|
|
counters = []
|
|
for counter_type in counter_types:
|
|
if not isinstance(counter_type, AmdSmiUtilizationCounterType):
|
|
raise AmdSmiParameterException(counter_type, AmdSmiUtilizationCounterType)
|
|
counter = amdsmi_wrapper.amdsmi_utilization_counter_t()
|
|
counter.type = counter_type
|
|
counters.append(counter)
|
|
|
|
count = ctypes.c_uint32(len(counters))
|
|
timestamp = ctypes.c_uint64()
|
|
util_counter_list = (amdsmi_wrapper.amdsmi_utilization_counter_t * len(counters))(*counters)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_utilization_count(
|
|
processor_handle, util_counter_list, count, ctypes.byref(timestamp)
|
|
)
|
|
)
|
|
if count.value != len(counters):
|
|
raise AmdSmiLibraryException(amdsmi_wrapper.AMDSMI_STATUS_API_FAILED)
|
|
|
|
result = []
|
|
result.append({"timestamp": timestamp.value})
|
|
for index in range(count.value):
|
|
counter_type = amdsmi_wrapper.amdsmi_utilization_counter_type_t__enumvalues[
|
|
util_counter_list[index].type
|
|
]
|
|
if counter_type == "AMDSMI_UTILIZATION_COUNTER_FIRST":
|
|
counter_type = "AMDSMI_COARSE_GRAIN_GPU_ACTIVITY"
|
|
if counter_type == "AMDSMI_UTILIZATION_COUNTER_LAST":
|
|
counter_type = "AMDSMI_FINE_DECODER_ACTIVITY"
|
|
counter_value = _validate_if_max_uint(
|
|
util_counter_list[index].value, MaxUIntegerTypes.UINT64_T
|
|
)
|
|
result.append({"type": counter_type, "value": counter_value})
|
|
|
|
return result
|
|
|
|
|
|
def amdsmi_get_gpu_perf_level(processor_handle: processor_handle_t) -> str:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
perf = amdsmi_wrapper.amdsmi_dev_perf_level_t()
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_perf_level(processor_handle, ctypes.byref(perf)))
|
|
|
|
result = amdsmi_wrapper.amdsmi_dev_perf_level_t__enumvalues[perf.value]
|
|
if result == "AMDSMI_DEV_PERF_LEVEL_FIRST":
|
|
result = "AMDSMI_DEV_PERF_LEVEL_AUTO"
|
|
if result == "AMDSMI_DEV_PERF_LEVEL_LAST":
|
|
result = "AMDSMI_DEV_PERF_LEVEL_DETERMINISM"
|
|
|
|
return result
|
|
|
|
|
|
def amdsmi_set_gpu_perf_determinism_mode(
|
|
processor_handle: processor_handle_t, clkvalue: int
|
|
) -> None:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(clkvalue, int):
|
|
raise AmdSmiParameterException(clkvalue, int)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_set_gpu_perf_determinism_mode(processor_handle, clkvalue))
|
|
|
|
|
|
def amdsmi_get_gpu_overdrive_level(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
od_level = ctypes.c_uint32()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_overdrive_level(processor_handle, ctypes.byref(od_level))
|
|
)
|
|
|
|
return od_level.value
|
|
|
|
|
|
def amdsmi_get_gpu_mem_overdrive_level(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
mem_od_level = ctypes.c_uint32()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_mem_overdrive_level(
|
|
processor_handle, ctypes.byref(mem_od_level)
|
|
)
|
|
)
|
|
|
|
return mem_od_level.value
|
|
|
|
|
|
def amdsmi_get_clk_freq(
|
|
processor_handle: processor_handle_t, clk_type: AmdSmiClkType
|
|
) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(clk_type, AmdSmiClkType):
|
|
raise AmdSmiParameterException(clk_type, AmdSmiClkType)
|
|
|
|
freq = amdsmi_wrapper.amdsmi_frequencies_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_clk_freq(processor_handle, clk_type, ctypes.byref(freq)))
|
|
|
|
dict_ret = {
|
|
"num_supported": freq.num_supported,
|
|
"current": freq.current,
|
|
"frequency": list(freq.frequency)[: freq.num_supported],
|
|
}
|
|
return dict_ret
|
|
|
|
|
|
def amdsmi_get_soc_pstate(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
policy = amdsmi_wrapper.amdsmi_dpm_policy_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_soc_pstate(processor_handle, ctypes.byref(policy)))
|
|
|
|
polices = []
|
|
for i in range(0, policy.num_supported):
|
|
policy_id = policy.policies[i].policy_id
|
|
desc = policy.policies[i].policy_description
|
|
polices.append({"policy_id": policy_id, "policy_description": desc.decode()})
|
|
current_id = policy.policies[policy.current].policy_id
|
|
|
|
return {"num_supported": policy.num_supported, "current_id": current_id, "policies": polices}
|
|
|
|
|
|
def amdsmi_get_xgmi_plpd(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
policy = amdsmi_wrapper.amdsmi_dpm_policy_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_xgmi_plpd(processor_handle, ctypes.byref(policy)))
|
|
|
|
policies = []
|
|
for i in range(0, policy.num_supported):
|
|
try:
|
|
policy_id = policy.policies[i].policy_id
|
|
desc = policy.policies[i].policy_description
|
|
policies.append({"policy_id": policy_id, "policy_description": desc.decode()})
|
|
except (UnicodeDecodeError, AttributeError, ValueError):
|
|
# Fallback for problematic entries
|
|
policies.append({"policy_id": 0, "policy_description": ""})
|
|
|
|
if policy.current < policy.num_supported:
|
|
current_id = policy.policies[policy.current].policy_id
|
|
else:
|
|
current_id = 0
|
|
|
|
return {
|
|
"num_supported": policy.num_supported,
|
|
"current_id": current_id,
|
|
"policies": policies, # Correct field name
|
|
}
|
|
|
|
|
|
def amdsmi_get_gpu_process_isolation(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
pisolate = ctypes.c_uint32()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_process_isolation(processor_handle, ctypes.byref(pisolate))
|
|
)
|
|
|
|
return pisolate.value
|
|
|
|
|
|
def amdsmi_get_gpu_od_volt_info(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
freq_data = amdsmi_wrapper.amdsmi_od_volt_freq_data_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_od_volt_info(processor_handle, ctypes.byref(freq_data))
|
|
)
|
|
|
|
sclk_lower = freq_data.curr_sclk_range.lower_bound
|
|
sclk_upper = freq_data.curr_sclk_range.upper_bound
|
|
mclk_lower = freq_data.curr_mclk_range.lower_bound
|
|
mclk_upper = freq_data.curr_mclk_range.upper_bound
|
|
|
|
if sclk_lower == MaxUIntegerTypes.UINT64_T:
|
|
sclk_lower = "N/A"
|
|
if sclk_upper == MaxUIntegerTypes.UINT64_T:
|
|
sclk_upper = "N/A"
|
|
if mclk_lower == MaxUIntegerTypes.UINT64_T:
|
|
mclk_lower = "N/A"
|
|
if mclk_upper == MaxUIntegerTypes.UINT64_T:
|
|
mclk_upper = "N/A"
|
|
|
|
return {
|
|
"curr_sclk_range": {"lower_bound": sclk_lower, "upper_bound": sclk_upper},
|
|
"curr_mclk_range": {"lower_bound": mclk_lower, "upper_bound": mclk_upper},
|
|
"sclk_freq_limits": {
|
|
"lower_bound": freq_data.sclk_freq_limits.lower_bound,
|
|
"upper_bound": freq_data.sclk_freq_limits.upper_bound,
|
|
},
|
|
"mclk_freq_limits": {
|
|
"lower_bound": freq_data.mclk_freq_limits.lower_bound,
|
|
"upper_bound": freq_data.mclk_freq_limits.upper_bound,
|
|
},
|
|
"curve.vc_points": [
|
|
{
|
|
"frequency": freq_data.curve.vc_points[0].frequency,
|
|
"voltage": freq_data.curve.vc_points[0].voltage,
|
|
},
|
|
{
|
|
"frequency": freq_data.curve.vc_points[1].frequency,
|
|
"voltage": freq_data.curve.vc_points[1].voltage,
|
|
},
|
|
{
|
|
"frequency": freq_data.curve.vc_points[2].frequency,
|
|
"voltage": freq_data.curve.vc_points[2].voltage,
|
|
},
|
|
],
|
|
"num_regions": freq_data.num_regions,
|
|
}
|
|
|
|
|
|
def amdsmi_get_gpu_metrics_info(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
gpu_metrics = amdsmi_wrapper.amdsmi_gpu_metrics_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_metrics_info(processor_handle, ctypes.byref(gpu_metrics))
|
|
)
|
|
|
|
gpu_metrics_output = {
|
|
"common_header.structure_size": _validate_if_max_uint(
|
|
gpu_metrics.common_header.structure_size, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"common_header.format_revision": _validate_if_max_uint(
|
|
gpu_metrics.common_header.format_revision, MaxUIntegerTypes.UINT8_T
|
|
),
|
|
"common_header.content_revision": _validate_if_max_uint(
|
|
gpu_metrics.common_header.content_revision, MaxUIntegerTypes.UINT8_T
|
|
),
|
|
"temperature_edge": _validate_if_max_uint(
|
|
gpu_metrics.temperature_edge, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"temperature_hotspot": _validate_if_max_uint(
|
|
gpu_metrics.temperature_hotspot, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"temperature_mem": _validate_if_max_uint(
|
|
gpu_metrics.temperature_mem, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"temperature_vrgfx": _validate_if_max_uint(
|
|
gpu_metrics.temperature_vrgfx, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"temperature_vrsoc": _validate_if_max_uint(
|
|
gpu_metrics.temperature_vrsoc, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"temperature_vrmem": _validate_if_max_uint(
|
|
gpu_metrics.temperature_vrmem, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"average_gfx_activity": _validate_if_max_uint(
|
|
gpu_metrics.average_gfx_activity, MaxUIntegerTypes.UINT16_T, isActivity=True
|
|
),
|
|
"average_umc_activity": _validate_if_max_uint(
|
|
gpu_metrics.average_umc_activity, MaxUIntegerTypes.UINT16_T, isActivity=True
|
|
),
|
|
"average_mm_activity": _validate_if_max_uint(
|
|
gpu_metrics.average_mm_activity, MaxUIntegerTypes.UINT16_T, isActivity=True
|
|
),
|
|
"average_socket_power": _validate_if_max_uint(
|
|
gpu_metrics.average_socket_power, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"energy_accumulator": _validate_if_max_uint(
|
|
gpu_metrics.energy_accumulator, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"system_clock_counter": _validate_if_max_uint(
|
|
gpu_metrics.system_clock_counter, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"average_gfxclk_frequency": _validate_if_max_uint(
|
|
gpu_metrics.average_gfxclk_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"average_socclk_frequency": _validate_if_max_uint(
|
|
gpu_metrics.average_socclk_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"average_uclk_frequency": _validate_if_max_uint(
|
|
gpu_metrics.average_uclk_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"average_vclk0_frequency": _validate_if_max_uint(
|
|
gpu_metrics.average_vclk0_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"average_dclk0_frequency": _validate_if_max_uint(
|
|
gpu_metrics.average_dclk0_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"average_vclk1_frequency": _validate_if_max_uint(
|
|
gpu_metrics.average_vclk1_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"average_dclk1_frequency": _validate_if_max_uint(
|
|
gpu_metrics.average_dclk1_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_gfxclk": _validate_if_max_uint(
|
|
gpu_metrics.current_gfxclk, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_socclk": _validate_if_max_uint(
|
|
gpu_metrics.current_socclk, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_uclk": _validate_if_max_uint(gpu_metrics.current_uclk, MaxUIntegerTypes.UINT16_T),
|
|
"current_vclk0": _validate_if_max_uint(
|
|
gpu_metrics.current_vclk0, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_dclk0": _validate_if_max_uint(
|
|
gpu_metrics.current_dclk0, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_vclk1": _validate_if_max_uint(
|
|
gpu_metrics.current_vclk1, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_dclk1": _validate_if_max_uint(
|
|
gpu_metrics.current_dclk1, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"throttle_status": _validate_if_max_uint(
|
|
gpu_metrics.throttle_status, MaxUIntegerTypes.UINT32_T, isBool=True
|
|
),
|
|
"current_fan_speed": _validate_if_max_uint(
|
|
gpu_metrics.current_fan_speed, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"pcie_link_width": _validate_if_max_uint(
|
|
gpu_metrics.pcie_link_width, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"pcie_link_speed": _validate_if_max_uint(
|
|
gpu_metrics.pcie_link_speed, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"gfx_activity_acc": _validate_if_max_uint(
|
|
gpu_metrics.gfx_activity_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"mem_activity_acc": _validate_if_max_uint(
|
|
gpu_metrics.mem_activity_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"temperature_hbm": _validate_if_max_uint(
|
|
list(gpu_metrics.temperature_hbm), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"firmware_timestamp": _validate_if_max_uint(
|
|
gpu_metrics.firmware_timestamp, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"voltage_soc": _validate_if_max_uint(gpu_metrics.voltage_soc, MaxUIntegerTypes.UINT16_T),
|
|
"voltage_gfx": _validate_if_max_uint(gpu_metrics.voltage_gfx, MaxUIntegerTypes.UINT16_T),
|
|
"voltage_mem": _validate_if_max_uint(gpu_metrics.voltage_mem, MaxUIntegerTypes.UINT16_T),
|
|
"indep_throttle_status": _validate_if_max_uint(
|
|
gpu_metrics.indep_throttle_status, MaxUIntegerTypes.UINT64_T, isBool=True
|
|
),
|
|
"current_socket_power": _validate_if_max_uint(
|
|
gpu_metrics.current_socket_power, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"vcn_activity": _validate_if_max_uint(
|
|
list(gpu_metrics.vcn_activity), MaxUIntegerTypes.UINT16_T, isActivity=True
|
|
),
|
|
"gfxclk_lock_status": _validate_if_max_uint(
|
|
gpu_metrics.gfxclk_lock_status, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
"xgmi_link_width": _validate_if_max_uint(
|
|
gpu_metrics.xgmi_link_width, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"xgmi_link_speed": _validate_if_max_uint(
|
|
gpu_metrics.xgmi_link_speed, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"pcie_bandwidth_acc": _validate_if_max_uint(
|
|
gpu_metrics.pcie_bandwidth_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"pcie_bandwidth_inst": _validate_if_max_uint(
|
|
gpu_metrics.pcie_bandwidth_inst, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"pcie_l0_to_recov_count_acc": _validate_if_max_uint(
|
|
gpu_metrics.pcie_l0_to_recov_count_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"pcie_replay_count_acc": _validate_if_max_uint(
|
|
gpu_metrics.pcie_replay_count_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"pcie_replay_rover_count_acc": _validate_if_max_uint(
|
|
gpu_metrics.pcie_replay_rover_count_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"xgmi_read_data_acc": _validate_if_max_uint(
|
|
list(gpu_metrics.xgmi_read_data_acc), MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"xgmi_write_data_acc": _validate_if_max_uint(
|
|
list(gpu_metrics.xgmi_write_data_acc), MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"current_gfxclks": _validate_if_max_uint(
|
|
list(gpu_metrics.current_gfxclks), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_socclks": _validate_if_max_uint(
|
|
list(gpu_metrics.current_socclks), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_vclk0s": _validate_if_max_uint(
|
|
list(gpu_metrics.current_vclk0s), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_dclk0s": _validate_if_max_uint(
|
|
list(gpu_metrics.current_dclk0s), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"jpeg_activity": _validate_if_max_uint(
|
|
list(gpu_metrics.jpeg_activity), MaxUIntegerTypes.UINT16_T, isActivity=True
|
|
),
|
|
"pcie_nak_sent_count_acc": _validate_if_max_uint(
|
|
gpu_metrics.pcie_nak_sent_count_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"pcie_nak_rcvd_count_acc": _validate_if_max_uint(
|
|
gpu_metrics.pcie_nak_rcvd_count_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"accumulation_counter": _validate_if_max_uint(
|
|
gpu_metrics.accumulation_counter, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"prochot_residency_acc": _validate_if_max_uint(
|
|
gpu_metrics.prochot_residency_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"ppt_residency_acc": _validate_if_max_uint(
|
|
gpu_metrics.ppt_residency_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"socket_thm_residency_acc": _validate_if_max_uint(
|
|
gpu_metrics.socket_thm_residency_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"vr_thm_residency_acc": _validate_if_max_uint(
|
|
gpu_metrics.vr_thm_residency_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"hbm_thm_residency_acc": _validate_if_max_uint(
|
|
gpu_metrics.hbm_thm_residency_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"num_partition": _validate_if_max_uint(
|
|
gpu_metrics.num_partition, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"xcp_stats.gfx_busy_inst": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.jpeg_busy": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.vcn_busy": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.gfx_busy_acc": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.gfx_below_host_limit_acc": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.gfx_below_host_limit_ppt_acc": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.gfx_below_host_limit_thm_acc": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.gfx_low_utilization_acc": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.gfx_below_host_limit_total_acc": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.temperature_xcd": list(gpu_metrics.xcp_stats),
|
|
"pcie_lc_perf_other_end_recovery": _validate_if_max_uint(
|
|
gpu_metrics.pcie_lc_perf_other_end_recovery, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"vram_max_bandwidth": _validate_if_max_uint(
|
|
gpu_metrics.vram_max_bandwidth, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"xgmi_link_status": _validate_if_max_uint(
|
|
list(gpu_metrics.xgmi_link_status), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"temperature_hbm_stacks": _validate_if_max_uint(
|
|
list(gpu_metrics.temperature_hbm_stacks), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"temperature_mid": _validate_if_max_uint(
|
|
list(gpu_metrics.temperature_mid), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"temperature_aid": _validate_if_max_uint(
|
|
list(gpu_metrics.temperature_aid), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_uclk_aid": _validate_if_max_uint(
|
|
list(gpu_metrics.current_uclk_aid), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_socclks_mid": _validate_if_max_uint(
|
|
list(gpu_metrics.current_socclks_mid), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
}
|
|
|
|
# Create 2d array with each XCD's stats
|
|
if "xcp_stats.gfx_busy_inst" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(gpu_metrics_output["xcp_stats.gfx_busy_inst"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.gfx_busy_inst:
|
|
xcp_detail.append(
|
|
_validate_if_max_uint(val, MaxUIntegerTypes.UINT32_T, isActivity=True)
|
|
)
|
|
gpu_metrics_output["xcp_stats.gfx_busy_inst"][xcp_index] = xcp_detail
|
|
|
|
if "xcp_stats.jpeg_busy" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(gpu_metrics_output["xcp_stats.jpeg_busy"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.jpeg_busy:
|
|
xcp_detail.append(
|
|
_validate_if_max_uint(val, MaxUIntegerTypes.UINT16_T, isActivity=True)
|
|
)
|
|
gpu_metrics_output["xcp_stats.jpeg_busy"][xcp_index] = xcp_detail
|
|
|
|
if "xcp_stats.vcn_busy" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(gpu_metrics_output["xcp_stats.vcn_busy"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.vcn_busy:
|
|
xcp_detail.append(
|
|
_validate_if_max_uint(val, MaxUIntegerTypes.UINT16_T, isActivity=True)
|
|
)
|
|
gpu_metrics_output["xcp_stats.vcn_busy"][xcp_index] = xcp_detail
|
|
|
|
if "xcp_stats.gfx_busy_acc" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(gpu_metrics_output["xcp_stats.gfx_busy_acc"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.gfx_busy_acc:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T))
|
|
gpu_metrics_output["xcp_stats.gfx_busy_acc"][xcp_index] = xcp_detail
|
|
|
|
if "xcp_stats.gfx_below_host_limit_acc" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(
|
|
gpu_metrics_output["xcp_stats.gfx_below_host_limit_acc"]
|
|
):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.gfx_below_host_limit_acc:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T))
|
|
gpu_metrics_output["xcp_stats.gfx_below_host_limit_acc"][xcp_index] = xcp_detail
|
|
# new for gpu metrics v1.8
|
|
if "xcp_stats.gfx_below_host_limit_ppt_acc" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(
|
|
gpu_metrics_output["xcp_stats.gfx_below_host_limit_ppt_acc"]
|
|
):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.gfx_below_host_limit_ppt_acc:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T))
|
|
gpu_metrics_output["xcp_stats.gfx_below_host_limit_ppt_acc"][xcp_index] = xcp_detail
|
|
if "xcp_stats.gfx_below_host_limit_thm_acc" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(
|
|
gpu_metrics_output["xcp_stats.gfx_below_host_limit_thm_acc"]
|
|
):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.gfx_below_host_limit_thm_acc:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T))
|
|
gpu_metrics_output["xcp_stats.gfx_below_host_limit_thm_acc"][xcp_index] = xcp_detail
|
|
if "xcp_stats.gfx_low_utilization_acc" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(
|
|
gpu_metrics_output["xcp_stats.gfx_low_utilization_acc"]
|
|
):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.gfx_low_utilization_acc:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T))
|
|
gpu_metrics_output["xcp_stats.gfx_low_utilization_acc"][xcp_index] = xcp_detail
|
|
if "xcp_stats.gfx_below_host_limit_total_acc" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(
|
|
gpu_metrics_output["xcp_stats.gfx_below_host_limit_total_acc"]
|
|
):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.gfx_below_host_limit_total_acc:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T))
|
|
gpu_metrics_output["xcp_stats.gfx_below_host_limit_total_acc"][xcp_index] = xcp_detail
|
|
|
|
if "xcp_stats.temperature_xcd" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(gpu_metrics_output["xcp_stats.temperature_xcd"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.temperature_xcd:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT16_T))
|
|
gpu_metrics_output["xcp_stats.temperature_xcd"][xcp_index] = xcp_detail
|
|
|
|
# APU metrics integration
|
|
gpu_metrics_output["is_apu"] = bool(gpu_metrics.apu_metrics)
|
|
if gpu_metrics.apu_metrics:
|
|
apu = gpu_metrics.apu_metrics.contents
|
|
gpu_metrics_output.update(_populate_apu_metrics(apu))
|
|
else:
|
|
gpu_metrics_output.update(_apu_metrics_na_dict())
|
|
|
|
return gpu_metrics_output
|
|
|
|
|
|
def amdsmi_get_gpu_partition_metrics_info(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
gpu_metrics = amdsmi_wrapper.amdsmi_gpu_metrics_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_partition_metrics_info(
|
|
processor_handle, ctypes.byref(gpu_metrics)
|
|
)
|
|
)
|
|
|
|
gpu_metrics_output = {
|
|
"common_header.structure_size": _validate_if_max_uint(
|
|
gpu_metrics.common_header.structure_size, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"common_header.format_revision": _validate_if_max_uint(
|
|
gpu_metrics.common_header.format_revision, MaxUIntegerTypes.UINT8_T
|
|
),
|
|
"common_header.content_revision": _validate_if_max_uint(
|
|
gpu_metrics.common_header.content_revision, MaxUIntegerTypes.UINT8_T
|
|
),
|
|
"temperature_edge": _validate_if_max_uint(
|
|
gpu_metrics.temperature_edge, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"temperature_hotspot": _validate_if_max_uint(
|
|
gpu_metrics.temperature_hotspot, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"temperature_mem": _validate_if_max_uint(
|
|
gpu_metrics.temperature_mem, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"temperature_vrgfx": _validate_if_max_uint(
|
|
gpu_metrics.temperature_vrgfx, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"temperature_vrsoc": _validate_if_max_uint(
|
|
gpu_metrics.temperature_vrsoc, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"temperature_vrmem": _validate_if_max_uint(
|
|
gpu_metrics.temperature_vrmem, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"average_gfx_activity": _validate_if_max_uint(
|
|
gpu_metrics.average_gfx_activity, MaxUIntegerTypes.UINT16_T, isActivity=True
|
|
),
|
|
"average_umc_activity": _validate_if_max_uint(
|
|
gpu_metrics.average_umc_activity, MaxUIntegerTypes.UINT16_T, isActivity=True
|
|
),
|
|
"average_mm_activity": _validate_if_max_uint(
|
|
gpu_metrics.average_mm_activity, MaxUIntegerTypes.UINT16_T, isActivity=True
|
|
),
|
|
"average_socket_power": _validate_if_max_uint(
|
|
gpu_metrics.average_socket_power, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"energy_accumulator": _validate_if_max_uint(
|
|
gpu_metrics.energy_accumulator, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"system_clock_counter": _validate_if_max_uint(
|
|
gpu_metrics.system_clock_counter, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"average_gfxclk_frequency": _validate_if_max_uint(
|
|
gpu_metrics.average_gfxclk_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"average_socclk_frequency": _validate_if_max_uint(
|
|
gpu_metrics.average_socclk_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"average_uclk_frequency": _validate_if_max_uint(
|
|
gpu_metrics.average_uclk_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"average_vclk0_frequency": _validate_if_max_uint(
|
|
gpu_metrics.average_vclk0_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"average_dclk0_frequency": _validate_if_max_uint(
|
|
gpu_metrics.average_dclk0_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"average_vclk1_frequency": _validate_if_max_uint(
|
|
gpu_metrics.average_vclk1_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"average_dclk1_frequency": _validate_if_max_uint(
|
|
gpu_metrics.average_dclk1_frequency, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_gfxclk": _validate_if_max_uint(
|
|
gpu_metrics.current_gfxclk, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_socclk": _validate_if_max_uint(
|
|
gpu_metrics.current_socclk, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_uclk": _validate_if_max_uint(gpu_metrics.current_uclk, MaxUIntegerTypes.UINT16_T),
|
|
"current_vclk0": _validate_if_max_uint(
|
|
gpu_metrics.current_vclk0, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_dclk0": _validate_if_max_uint(
|
|
gpu_metrics.current_dclk0, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_vclk1": _validate_if_max_uint(
|
|
gpu_metrics.current_vclk1, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_dclk1": _validate_if_max_uint(
|
|
gpu_metrics.current_dclk1, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"throttle_status": _validate_if_max_uint(
|
|
gpu_metrics.throttle_status, MaxUIntegerTypes.UINT32_T, isBool=True
|
|
),
|
|
"current_fan_speed": _validate_if_max_uint(
|
|
gpu_metrics.current_fan_speed, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"pcie_link_width": _validate_if_max_uint(
|
|
gpu_metrics.pcie_link_width, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"pcie_link_speed": _validate_if_max_uint(
|
|
gpu_metrics.pcie_link_speed, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"gfx_activity_acc": _validate_if_max_uint(
|
|
gpu_metrics.gfx_activity_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"mem_activity_acc": _validate_if_max_uint(
|
|
gpu_metrics.mem_activity_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"temperature_hbm": _validate_if_max_uint(
|
|
list(gpu_metrics.temperature_hbm), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"firmware_timestamp": _validate_if_max_uint(
|
|
gpu_metrics.firmware_timestamp, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"voltage_soc": _validate_if_max_uint(gpu_metrics.voltage_soc, MaxUIntegerTypes.UINT16_T),
|
|
"voltage_gfx": _validate_if_max_uint(gpu_metrics.voltage_gfx, MaxUIntegerTypes.UINT16_T),
|
|
"voltage_mem": _validate_if_max_uint(gpu_metrics.voltage_mem, MaxUIntegerTypes.UINT16_T),
|
|
"indep_throttle_status": _validate_if_max_uint(
|
|
gpu_metrics.indep_throttle_status, MaxUIntegerTypes.UINT64_T, isBool=True
|
|
),
|
|
"current_socket_power": _validate_if_max_uint(
|
|
gpu_metrics.current_socket_power, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"vcn_activity": _validate_if_max_uint(
|
|
list(gpu_metrics.vcn_activity), MaxUIntegerTypes.UINT16_T, isActivity=True
|
|
),
|
|
"gfxclk_lock_status": _validate_if_max_uint(
|
|
gpu_metrics.gfxclk_lock_status, MaxUIntegerTypes.UINT32_T
|
|
),
|
|
"xgmi_link_width": _validate_if_max_uint(
|
|
gpu_metrics.xgmi_link_width, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"xgmi_link_speed": _validate_if_max_uint(
|
|
gpu_metrics.xgmi_link_speed, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"pcie_bandwidth_acc": _validate_if_max_uint(
|
|
gpu_metrics.pcie_bandwidth_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"pcie_bandwidth_inst": _validate_if_max_uint(
|
|
gpu_metrics.pcie_bandwidth_inst, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"pcie_l0_to_recov_count_acc": _validate_if_max_uint(
|
|
gpu_metrics.pcie_l0_to_recov_count_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"pcie_replay_count_acc": _validate_if_max_uint(
|
|
gpu_metrics.pcie_replay_count_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"pcie_replay_rover_count_acc": _validate_if_max_uint(
|
|
gpu_metrics.pcie_replay_rover_count_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"xgmi_read_data_acc": _validate_if_max_uint(
|
|
list(gpu_metrics.xgmi_read_data_acc), MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"xgmi_write_data_acc": _validate_if_max_uint(
|
|
list(gpu_metrics.xgmi_write_data_acc), MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"current_gfxclks": _validate_if_max_uint(
|
|
list(gpu_metrics.current_gfxclks), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_socclks": _validate_if_max_uint(
|
|
list(gpu_metrics.current_socclks), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_vclk0s": _validate_if_max_uint(
|
|
list(gpu_metrics.current_vclk0s), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_dclk0s": _validate_if_max_uint(
|
|
list(gpu_metrics.current_dclk0s), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"jpeg_activity": _validate_if_max_uint(
|
|
list(gpu_metrics.jpeg_activity), MaxUIntegerTypes.UINT16_T, isActivity=True
|
|
),
|
|
"pcie_nak_sent_count_acc": _validate_if_max_uint(
|
|
gpu_metrics.pcie_nak_sent_count_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"pcie_nak_rcvd_count_acc": _validate_if_max_uint(
|
|
gpu_metrics.pcie_nak_rcvd_count_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"accumulation_counter": _validate_if_max_uint(
|
|
gpu_metrics.accumulation_counter, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"prochot_residency_acc": _validate_if_max_uint(
|
|
gpu_metrics.prochot_residency_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"ppt_residency_acc": _validate_if_max_uint(
|
|
gpu_metrics.ppt_residency_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"socket_thm_residency_acc": _validate_if_max_uint(
|
|
gpu_metrics.socket_thm_residency_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"vr_thm_residency_acc": _validate_if_max_uint(
|
|
gpu_metrics.vr_thm_residency_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"hbm_thm_residency_acc": _validate_if_max_uint(
|
|
gpu_metrics.hbm_thm_residency_acc, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"num_partition": _validate_if_max_uint(
|
|
gpu_metrics.num_partition, MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"xcp_stats.gfx_busy_inst": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.jpeg_busy": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.vcn_busy": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.gfx_busy_acc": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.gfx_below_host_limit_acc": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.gfx_below_host_limit_ppt_acc": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.gfx_below_host_limit_thm_acc": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.gfx_low_utilization_acc": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.gfx_below_host_limit_total_acc": list(gpu_metrics.xcp_stats),
|
|
"xcp_stats.temperature_xcd": list(gpu_metrics.xcp_stats),
|
|
"pcie_lc_perf_other_end_recovery": _validate_if_max_uint(
|
|
gpu_metrics.pcie_lc_perf_other_end_recovery, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"vram_max_bandwidth": _validate_if_max_uint(
|
|
gpu_metrics.vram_max_bandwidth, MaxUIntegerTypes.UINT64_T
|
|
),
|
|
"xgmi_link_status": _validate_if_max_uint(
|
|
list(gpu_metrics.xgmi_link_status), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"temperature_hbm_stacks": _validate_if_max_uint(
|
|
list(gpu_metrics.temperature_hbm_stacks), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"temperature_mid": _validate_if_max_uint(
|
|
list(gpu_metrics.temperature_mid), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"temperature_aid": _validate_if_max_uint(
|
|
list(gpu_metrics.temperature_aid), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_uclk_aid": _validate_if_max_uint(
|
|
list(gpu_metrics.current_uclk_aid), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
"current_socclks_mid": _validate_if_max_uint(
|
|
list(gpu_metrics.current_socclks_mid), MaxUIntegerTypes.UINT16_T
|
|
),
|
|
}
|
|
|
|
# Create 2d array with each XCD's stats
|
|
if "xcp_stats.gfx_busy_inst" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(gpu_metrics_output["xcp_stats.gfx_busy_inst"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.gfx_busy_inst:
|
|
xcp_detail.append(
|
|
_validate_if_max_uint(val, MaxUIntegerTypes.UINT32_T, isActivity=True)
|
|
)
|
|
gpu_metrics_output["xcp_stats.gfx_busy_inst"][xcp_index] = xcp_detail
|
|
|
|
if "xcp_stats.jpeg_busy" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(gpu_metrics_output["xcp_stats.jpeg_busy"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.jpeg_busy:
|
|
xcp_detail.append(
|
|
_validate_if_max_uint(val, MaxUIntegerTypes.UINT16_T, isActivity=True)
|
|
)
|
|
gpu_metrics_output["xcp_stats.jpeg_busy"][xcp_index] = xcp_detail
|
|
|
|
if "xcp_stats.vcn_busy" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(gpu_metrics_output["xcp_stats.vcn_busy"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.vcn_busy:
|
|
xcp_detail.append(
|
|
_validate_if_max_uint(val, MaxUIntegerTypes.UINT16_T, isActivity=True)
|
|
)
|
|
gpu_metrics_output["xcp_stats.vcn_busy"][xcp_index] = xcp_detail
|
|
|
|
if "xcp_stats.gfx_busy_acc" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(gpu_metrics_output["xcp_stats.gfx_busy_acc"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.gfx_busy_acc:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T))
|
|
gpu_metrics_output["xcp_stats.gfx_busy_acc"][xcp_index] = xcp_detail
|
|
|
|
if "xcp_stats.gfx_below_host_limit_acc" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(
|
|
gpu_metrics_output["xcp_stats.gfx_below_host_limit_acc"]
|
|
):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.gfx_below_host_limit_acc:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T))
|
|
gpu_metrics_output["xcp_stats.gfx_below_host_limit_acc"][xcp_index] = xcp_detail
|
|
# new for gpu metrics v1.8
|
|
if "xcp_stats.gfx_below_host_limit_ppt_acc" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(
|
|
gpu_metrics_output["xcp_stats.gfx_below_host_limit_ppt_acc"]
|
|
):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.gfx_below_host_limit_ppt_acc:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T))
|
|
gpu_metrics_output["xcp_stats.gfx_below_host_limit_ppt_acc"][xcp_index] = xcp_detail
|
|
if "xcp_stats.gfx_below_host_limit_thm_acc" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(
|
|
gpu_metrics_output["xcp_stats.gfx_below_host_limit_thm_acc"]
|
|
):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.gfx_below_host_limit_thm_acc:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T))
|
|
gpu_metrics_output["xcp_stats.gfx_below_host_limit_thm_acc"][xcp_index] = xcp_detail
|
|
if "xcp_stats.gfx_low_utilization_acc" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(
|
|
gpu_metrics_output["xcp_stats.gfx_low_utilization_acc"]
|
|
):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.gfx_low_utilization_acc:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T))
|
|
gpu_metrics_output["xcp_stats.gfx_low_utilization_acc"][xcp_index] = xcp_detail
|
|
if "xcp_stats.gfx_below_host_limit_total_acc" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(
|
|
gpu_metrics_output["xcp_stats.gfx_below_host_limit_total_acc"]
|
|
):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.gfx_below_host_limit_total_acc:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT64_T))
|
|
gpu_metrics_output["xcp_stats.gfx_below_host_limit_total_acc"][xcp_index] = xcp_detail
|
|
|
|
if "xcp_stats.temperature_xcd" in gpu_metrics_output:
|
|
for xcp_index, xcp_metrics in enumerate(gpu_metrics_output["xcp_stats.temperature_xcd"]):
|
|
xcp_detail = []
|
|
for val in xcp_metrics.temperature_xcd:
|
|
xcp_detail.append(_validate_if_max_uint(val, MaxUIntegerTypes.UINT16_T))
|
|
gpu_metrics_output["xcp_stats.temperature_xcd"][xcp_index] = xcp_detail
|
|
|
|
# APU metrics integration
|
|
gpu_metrics_output["is_apu"] = bool(gpu_metrics.apu_metrics)
|
|
if gpu_metrics.apu_metrics:
|
|
apu = gpu_metrics.apu_metrics.contents
|
|
gpu_metrics_output.update(_populate_apu_metrics(apu))
|
|
else:
|
|
gpu_metrics_output.update(_apu_metrics_na_dict())
|
|
|
|
return gpu_metrics_output
|
|
|
|
|
|
def amdsmi_get_nic_metrics_info(
|
|
processor_handle: amdsmi_wrapper.amdsmi_processor_handle,
|
|
) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
# Create data type
|
|
nic_metrics = amdsmi_wrapper.amdsmi_brcm_nic_hwmon_metrics_t()
|
|
nic_power_metrics = amdsmi_wrapper.amdsmi_brcm_nic_hwmon_power_t()
|
|
nic_temperature_metrics = amdsmi_wrapper.amdsmi_brcm_nic_temperature_metric_t()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_nic_metrics_info(processor_handle, ctypes.byref(nic_metrics))
|
|
)
|
|
|
|
nic_power_metrics = nic_metrics.nic_power
|
|
nic_temperature_metrics = nic_metrics.nic_temperature
|
|
|
|
nic_metrics_output = {
|
|
# Power attributes
|
|
"nic_power_async": nic_power_metrics.nic_power_async.decode("utf-8"),
|
|
"nic_power_control": nic_power_metrics.nic_power_control.decode("utf-8"),
|
|
"nic_power_runtime_active_time": nic_power_metrics.nic_power_runtime_active_time,
|
|
"nic_power_runtime_status": nic_power_metrics.nic_power_runtime_status.decode("utf-8"),
|
|
"nic_power_runtime_usage": nic_power_metrics.nic_power_runtime_usage,
|
|
"nic_power_runtime_active_kids": nic_power_metrics.nic_power_runtime_active_kids,
|
|
"nic_power_runtime_enabled": nic_power_metrics.nic_power_runtime_enabled.decode("utf-8"),
|
|
"nic_power_runtime_suspended_time": nic_power_metrics.nic_power_runtime_suspended_time,
|
|
# Temperature attributes
|
|
"nic_temp_crit_alarm": nic_temperature_metrics.nic_temp_crit_alarm,
|
|
"nic_temp_emergency_alarm": nic_temperature_metrics.nic_temp_emergency_alarm,
|
|
"nic_temp_shutdown_alarm": nic_temperature_metrics.nic_temp_shutdown_alarm,
|
|
"nic_temp_max_alarm": nic_temperature_metrics.nic_temp_max_alarm,
|
|
"nic_temp_crit": math.trunc(nic_temperature_metrics.nic_temp_crit / 1000),
|
|
"nic_temp_emergency": math.trunc(nic_temperature_metrics.nic_temp_emergency / 1000),
|
|
"nic_temp_input": math.trunc(nic_temperature_metrics.nic_temp_input / 1000),
|
|
"nic_temp_max": math.trunc(nic_temperature_metrics.nic_temp_max / 1000),
|
|
"nic_temp_shutdown": math.trunc(nic_temperature_metrics.nic_temp_shutdown / 1000),
|
|
# Error attributes
|
|
"nic_dev_correctable": nic_metrics.nic_device_aer_dev_correctable.decode("utf-8"),
|
|
"nic_dev_fatal": nic_metrics.nic_device_aer_dev_fatal.decode("utf-8"),
|
|
"nic_dev_nonfatal": nic_metrics.nic_device_aer_dev_nonfatal.decode("utf-8"),
|
|
}
|
|
|
|
return nic_metrics_output
|
|
|
|
|
|
def amdsmi_get_switch_metrics_info(
|
|
processor_handle: amdsmi_wrapper.amdsmi_processor_handle,
|
|
) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
# Create data type
|
|
switch_metrics = amdsmi_wrapper.struct_amdsmi_brcm_switch_metric_t()
|
|
switch_power_metrics = amdsmi_wrapper.amdsmi_brcm_switch_power_metric_t()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_switch_metrics_info(
|
|
processor_handle, ctypes.byref(switch_metrics)
|
|
)
|
|
)
|
|
|
|
switch_power_metrics = switch_metrics.brcm_power
|
|
|
|
switch_metrics_output = {
|
|
"brcm_power_async": switch_power_metrics.brcm_power_async.decode("utf-8"),
|
|
"brcm_power_control": switch_power_metrics.brcm_power_control.decode("utf-8"),
|
|
"brcm_power_runtime_active_kids": switch_power_metrics.brcm_power_runtime_active_kids.decode(
|
|
"utf-8"
|
|
),
|
|
"brcm_power_runtime_active_time": switch_power_metrics.brcm_power_runtime_active_time.decode(
|
|
"utf-8"
|
|
),
|
|
"brcm_power_runtime_enabled": switch_power_metrics.brcm_power_runtime_enabled.decode(
|
|
"utf-8"
|
|
),
|
|
"brcm_power_runtime_status": switch_power_metrics.brcm_power_runtime_status.decode("utf-8"),
|
|
"brcm_power_runtime_suspended_time": switch_power_metrics.brcm_power_runtime_suspended_time.decode(
|
|
"utf-8"
|
|
),
|
|
"brcm_power_runtime_usage": switch_power_metrics.brcm_power_runtime_usage.decode("utf-8"),
|
|
"brcm_power_wakeup": switch_power_metrics.brcm_power_wakeup.decode("utf-8"),
|
|
"brcm_power_wakeup_abort_count": switch_power_metrics.brcm_power_wakeup_abort_count.decode(
|
|
"utf-8"
|
|
),
|
|
"brcm_power_wakeup_active": switch_power_metrics.brcm_power_wakeup_active.decode("utf-8"),
|
|
"brcm_power_wakeup_active_count": switch_power_metrics.brcm_power_wakeup_active_count.decode(
|
|
"utf-8"
|
|
),
|
|
"brcm_power_wakeup_count": switch_power_metrics.brcm_power_wakeup_count.decode("utf-8"),
|
|
"brcm_power_wakeup_last_time_ms": switch_power_metrics.brcm_power_wakeup_last_time_ms.decode(
|
|
"utf-8"
|
|
),
|
|
"brcm_power_wakeup_max_time_ms": switch_power_metrics.brcm_power_wakeup_max_time_ms.decode(
|
|
"utf-8"
|
|
),
|
|
"brcm_power_wakeup_total_time_ms": switch_power_metrics.brcm_power_wakeup_total_time_ms.decode(
|
|
"utf-8"
|
|
),
|
|
# Error attributes
|
|
"brcm_device_aer_dev_correctable": switch_metrics.brcm_device_aer_dev_correctable.decode(
|
|
"utf-8"
|
|
),
|
|
"brcm_device_aer_dev_fatal": switch_metrics.brcm_device_aer_dev_fatal.decode("utf-8"),
|
|
"brcm_device_aer_dev_nonfatal": switch_metrics.brcm_device_aer_dev_nonfatal.decode("utf-8"),
|
|
}
|
|
|
|
return switch_metrics_output
|
|
|
|
|
|
def amdsmi_get_gpu_od_volt_curve_regions(
|
|
processor_handle: processor_handle_t, num_regions: int
|
|
) -> List[Dict[str, Any]]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(num_regions, int):
|
|
raise AmdSmiParameterException(num_regions, int)
|
|
|
|
region_count = ctypes.c_uint32(num_regions)
|
|
buffer = (amdsmi_wrapper.amdsmi_freq_volt_region_t * num_regions)()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_od_volt_curve_regions(
|
|
processor_handle, ctypes.byref(region_count), buffer
|
|
)
|
|
)
|
|
|
|
result = []
|
|
|
|
for index in range(region_count.value):
|
|
result.extend(
|
|
[
|
|
{
|
|
"freq_range": {
|
|
"lower_bound": buffer[index].freq_range.lower_bound,
|
|
"upper_bound": buffer[index].freq_range.upper_bound,
|
|
},
|
|
"volt_range": {
|
|
"lower_bound": buffer[index].volt_range.lower_bound,
|
|
"upper_bound": buffer[index].volt_range.upper_bound,
|
|
},
|
|
}
|
|
]
|
|
)
|
|
|
|
return result
|
|
|
|
|
|
def amdsmi_get_gpu_power_profile_presets(
|
|
processor_handle: processor_handle_t, sensor_idx: int
|
|
) -> Dict[str, Any]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(sensor_idx, int):
|
|
raise AmdSmiParameterException(sensor_idx, int)
|
|
|
|
status = amdsmi_wrapper.amdsmi_power_profile_status_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_power_profile_presets(
|
|
processor_handle, sensor_idx, ctypes.byref(status)
|
|
)
|
|
)
|
|
|
|
return {
|
|
"available_profiles": status.available_profiles,
|
|
"current": status.current,
|
|
"num_profiles": status.num_profiles,
|
|
}
|
|
|
|
|
|
def amdsmi_get_gpu_ecc_count(
|
|
processor_handle: processor_handle_t, block: AmdSmiGpuBlock
|
|
) -> Dict[str, int]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(block, AmdSmiGpuBlock):
|
|
raise AmdSmiParameterException(block, AmdSmiGpuBlock)
|
|
|
|
ec = amdsmi_wrapper.amdsmi_error_count_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_ecc_count(processor_handle, block, ctypes.byref(ec)))
|
|
|
|
return {
|
|
"correctable_count": ec.correctable_count,
|
|
"uncorrectable_count": ec.uncorrectable_count,
|
|
"deferred_count": ec.deferred_count,
|
|
}
|
|
|
|
|
|
def amdsmi_get_gpu_ecc_enabled(processor_handle: processor_handle_t) -> int:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
blocks = ctypes.c_uint64(0)
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_ecc_enabled(processor_handle, ctypes.byref(blocks)))
|
|
|
|
return blocks.value
|
|
|
|
|
|
def amdsmi_get_gpu_ecc_status(
|
|
processor_handle: processor_handle_t, block: AmdSmiGpuBlock
|
|
) -> AmdSmiRasErrState:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(block, AmdSmiGpuBlock):
|
|
raise AmdSmiParameterException(block, AmdSmiGpuBlock)
|
|
|
|
state = amdsmi_wrapper.amdsmi_ras_err_state_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_ecc_status(processor_handle, block, ctypes.byref(state))
|
|
)
|
|
|
|
return AmdSmiRasErrState(state.value)
|
|
|
|
|
|
def amdsmi_status_code_to_string(status: amdsmi_wrapper.amdsmi_status_t) -> Union[str, bytes, None]:
|
|
if not isinstance(status, amdsmi_wrapper.amdsmi_status_t):
|
|
raise AmdSmiParameterException(status, amdsmi_wrapper.amdsmi_status_t)
|
|
|
|
status_string_p_p = ctypes.pointer(ctypes.pointer(ctypes.c_char()))
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_status_code_to_string(status, status_string_p_p))
|
|
|
|
return amdsmi_wrapper.string_cast(status_string_p_p.contents)
|
|
|
|
|
|
def amdsmi_get_gpu_compute_process_info() -> List[Dict[str, int]]:
|
|
num_items = ctypes.c_uint32(0)
|
|
nullptr = POINTER(amdsmi_wrapper.amdsmi_process_info_t)()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_compute_process_info(nullptr, ctypes.byref(num_items)))
|
|
|
|
procs = (amdsmi_wrapper.amdsmi_process_info_t * num_items.value)()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_compute_process_info(procs, ctypes.byref(num_items)))
|
|
|
|
return [
|
|
{
|
|
"process_id": proc.process_id,
|
|
"vram_usage": proc.vram_usage,
|
|
"sdma_usage": proc.sdma_usage,
|
|
"cu_occupancy": proc.cu_occupancy,
|
|
"evicted_time": proc.evicted_time,
|
|
}
|
|
for proc in procs
|
|
]
|
|
|
|
|
|
def amdsmi_get_gpu_compute_process_info_by_pid(pid: int) -> Dict[str, int]:
|
|
if not isinstance(pid, int):
|
|
raise AmdSmiParameterException(pid, int)
|
|
|
|
proc = amdsmi_wrapper.amdsmi_process_info_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_compute_process_info_by_pid(
|
|
ctypes.c_uint32(pid), ctypes.byref(proc)
|
|
)
|
|
)
|
|
|
|
return {
|
|
"process_id": proc.process_id,
|
|
"vram_usage": proc.vram_usage,
|
|
"sdma_usage": proc.sdma_usage,
|
|
"cu_occupancy": proc.cu_occupancy,
|
|
"evicted_time": proc.evicted_time,
|
|
}
|
|
|
|
|
|
def amdsmi_get_gpu_compute_process_gpus(pid: int) -> List[int]:
|
|
if not isinstance(pid, int):
|
|
raise AmdSmiParameterException(pid, int)
|
|
|
|
num_devices = ctypes.c_uint32(0)
|
|
nullptr = POINTER(ctypes.c_uint32)()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_compute_process_gpus(pid, nullptr, ctypes.byref(num_devices))
|
|
)
|
|
|
|
dv_indices = (ctypes.c_uint32 * num_devices.value)()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_compute_process_gpus(
|
|
pid, dv_indices, ctypes.byref(num_devices)
|
|
)
|
|
)
|
|
|
|
return [dv_index.value for dv_index in dv_indices]
|
|
|
|
|
|
def amdsmi_gpu_xgmi_error_status(processor_handle: processor_handle_t) -> AmdSmiXgmiStatus:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
status = amdsmi_wrapper.amdsmi_xgmi_status_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_gpu_xgmi_error_status(processor_handle, ctypes.byref(status)))
|
|
|
|
# return AmdSmiXgmiStatus(status.value).value
|
|
return AmdSmiXgmiStatus(status.value)
|
|
|
|
|
|
def amdsmi_reset_gpu_xgmi_error(processor_handle: processor_handle_t) -> None:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_reset_gpu_xgmi_error(processor_handle))
|
|
|
|
|
|
def amdsmi_get_gpu_memory_reserved_pages(processor_handle: processor_handle_t) -> Union[list, str]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
num_pages = ctypes.c_uint32()
|
|
nullptr = POINTER(amdsmi_wrapper.amdsmi_retired_page_record_t)()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_memory_reserved_pages(
|
|
processor_handle, ctypes.byref(num_pages), nullptr
|
|
)
|
|
)
|
|
|
|
if num_pages.value == 0:
|
|
return []
|
|
|
|
mem_reserved_pages = (amdsmi_wrapper.amdsmi_retired_page_record_t * num_pages.value)()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_memory_reserved_pages(
|
|
processor_handle, ctypes.byref(num_pages), mem_reserved_pages
|
|
)
|
|
)
|
|
|
|
return _format_bad_page_info(mem_reserved_pages, num_pages)
|
|
|
|
|
|
def amdsmi_get_gpu_metrics_header_info(processor_handle: processor_handle_t) -> Dict[str, int]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
header_info = amdsmi_wrapper.amd_metrics_table_header_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_metrics_header_info(
|
|
processor_handle, ctypes.byref(header_info)
|
|
)
|
|
)
|
|
|
|
return {
|
|
"structure_size": header_info.structure_size,
|
|
"format_revision": header_info.format_revision,
|
|
"content_revision": header_info.content_revision,
|
|
}
|
|
|
|
|
|
def amdsmi_get_link_topology_nearest(
|
|
processor_handle: processor_handle_t, link_type: AmdSmiLinkType
|
|
) -> Dict[str, Any]:
|
|
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(link_type, AmdSmiLinkType):
|
|
raise AmdSmiParameterException(link_type, AmdSmiLinkType)
|
|
|
|
topology_nearest_list = amdsmi_wrapper.amdsmi_topology_nearest_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_link_topology_nearest(
|
|
processor_handle, link_type, ctypes.byref(topology_nearest_list)
|
|
)
|
|
)
|
|
|
|
device_list = []
|
|
for index in range(topology_nearest_list.count):
|
|
device_list.append(topology_nearest_list.processor_list[index])
|
|
|
|
return {"processor_list": device_list}
|
|
|
|
|
|
def amdsmi_get_gpu_virtualization_mode(
|
|
processor_handle: processor_handle_t,
|
|
) -> Dict[str, AmdSmiVirtualizationMode]:
|
|
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
# make info struct here
|
|
mode = amdsmi_wrapper.amdsmi_virtualization_mode_t()
|
|
|
|
# call lib function here
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_virtualization_mode(processor_handle, ctypes.byref(mode))
|
|
)
|
|
|
|
return {"mode": AmdSmiVirtualizationMode(mode.value)}
|
|
|
|
|
|
def amdsmi_get_gpu_ptl_state(processor_handle: processor_handle_t) -> bool:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
is_ptl_enabled = ctypes.c_bool()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_ptl_state(processor_handle, ctypes.byref(is_ptl_enabled))
|
|
)
|
|
|
|
return is_ptl_enabled.value
|
|
|
|
|
|
def amdsmi_set_gpu_ptl_state(processor_handle: processor_handle_t, state: int) -> None:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
_check_res(amdsmi_wrapper.amdsmi_set_gpu_ptl_state(processor_handle, state))
|
|
|
|
|
|
def amdsmi_get_gpu_ptl_formats(processor_handle: processor_handle_t) -> Tuple[int, int]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
data_format1 = amdsmi_wrapper.amdsmi_ptl_data_format_t()
|
|
data_format2 = amdsmi_wrapper.amdsmi_ptl_data_format_t()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_ptl_formats(
|
|
processor_handle, ctypes.byref(data_format1), ctypes.byref(data_format2)
|
|
)
|
|
)
|
|
|
|
return int(data_format1.value), int(data_format2.value)
|
|
|
|
|
|
def amdsmi_set_gpu_ptl_formats(
|
|
processor_handle: processor_handle_t, fmt1: AmdSmiPtlData, fmt2: AmdSmiPtlData
|
|
) -> None:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
for fmt in (fmt1, fmt2):
|
|
if not isinstance(fmt, AmdSmiPtlData):
|
|
raise AmdSmiParameterException(fmt, AmdSmiPtlData)
|
|
if fmt is AmdSmiPtlData.INVALID:
|
|
raise AmdSmiParameterException(fmt, "A valid PTL data format (not INVALID)")
|
|
|
|
c_fmt1 = amdsmi_wrapper.amdsmi_ptl_data_format_t(int(fmt1))
|
|
c_fmt2 = amdsmi_wrapper.amdsmi_ptl_data_format_t(int(fmt2))
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_set_gpu_ptl_formats(processor_handle, c_fmt1, c_fmt2))
|
|
|
|
|
|
### Non C-Lib APIs ###
|
|
|
|
|
|
def amdsmi_get_rocm_version() -> Tuple[bool, str]:
|
|
"""
|
|
Get the ROCm version for the rocm-core library.
|
|
|
|
This function attempts to retrieve the ROCm version by loading the `librocm-core.so` shared library
|
|
and calling its `getROCmVersion` function. The version is returned as a string in the format "major.minor.patch".
|
|
|
|
Returns:
|
|
Tuple[bool, str]: A tuple containing a boolean and a string.
|
|
- The boolean indicates whether the operation was successful.
|
|
- The string contains the ROCm version if successful, or an error message if not.
|
|
|
|
Raises:
|
|
Exception: If there is an error loading the shared library or calling the function.
|
|
|
|
Example:
|
|
rocm_lib_status, version_message = amdsmi_get_rocm_version()
|
|
if rocm_lib_status:
|
|
print(f"ROCm version: {version_message}")
|
|
else:
|
|
print(f"Error: {version_message}")
|
|
"""
|
|
# librocm-core.so can be located in found using several different methods.
|
|
# Look for it with below priority:
|
|
# 1. ROCM_HOME/ROCM_PATH environment variables
|
|
# - ROCM_HOME/lib
|
|
# - ROCM_PATH/lib (usually set to /opt/rocm/)
|
|
# 2. Decided by the linker
|
|
# - LD_LIBRARY_PATH env var
|
|
# - defined path in /etc/ld.so.conf.d/
|
|
# 3. Relative to amdsmi_wrapper.py in /opt/rocm/share/amd_smi
|
|
# - parent directory
|
|
|
|
try:
|
|
possible_locations = list()
|
|
# 0. Relative to amdsmi_interface.py in TheRock:
|
|
# `amdsmi_interface.py` is located in
|
|
# `_rocm_sdk_core/share/amd_smi/amdsmi`, libraries are in
|
|
# `_rocm_sdk_core/lib`.
|
|
librocm_core_path = (
|
|
Path(__file__).resolve().parent.parent.parent.parent / "lib/librocm-core.so.1"
|
|
)
|
|
possible_locations.append(librocm_core_path)
|
|
# 1.
|
|
rocm_path = os.getenv("ROCM_HOME", os.getenv("ROCM_PATH"))
|
|
if rocm_path:
|
|
possible_locations.append(os.path.join(rocm_path, "lib/librocm-core.so"))
|
|
|
|
# Check if /opt/rocm/lib/librocm-core.so exists and add it to the list
|
|
if os.path.exists("/opt/rocm/lib/librocm-core.so"):
|
|
possible_locations.append("/opt/rocm/lib/librocm-core.so")
|
|
# 2.
|
|
possible_locations.append("librocm-core.so")
|
|
# 3.
|
|
librocm_core_parent_dir = (
|
|
Path(__file__).resolve().parent.parent.parent / "lib" / "librocm-core.so"
|
|
)
|
|
possible_locations.append(librocm_core_parent_dir)
|
|
|
|
for librocm_core_file_path in possible_locations:
|
|
try:
|
|
librocm_core = ctypes.CDLL(librocm_core_file_path)
|
|
VerErrors = ctypes.c_uint32
|
|
get_rocm_core_version = librocm_core.getROCmVersion
|
|
get_rocm_core_version.restype = VerErrors
|
|
get_rocm_core_version.argtypes = [
|
|
POINTER(ctypes.c_uint32),
|
|
POINTER(ctypes.c_uint32),
|
|
POINTER(ctypes.c_uint32),
|
|
]
|
|
|
|
# call the function
|
|
major = ctypes.c_uint32()
|
|
minor = ctypes.c_uint32()
|
|
patch = ctypes.c_uint32()
|
|
|
|
if (
|
|
get_rocm_core_version(
|
|
ctypes.byref(major), ctypes.byref(minor), ctypes.byref(patch)
|
|
)
|
|
== 0
|
|
):
|
|
return True, f"{major.value}.{minor.value}.{patch.value}"
|
|
else:
|
|
return False, "Failed to unpack ROCm version"
|
|
except OSError:
|
|
continue
|
|
|
|
# If we hit here, we were unable to find the librocm-core.so file
|
|
return False, "Could not find librocm-core.so"
|
|
except Exception as e:
|
|
return False, f"Unable to detect ROCm installation, Unknown Error: {e}"
|
|
|
|
|
|
def amdsmi_get_esmi_err_msg(status: AmdSmiStatus) -> str:
|
|
if not isinstance(status, AmdSmiStatus):
|
|
raise AmdSmiParameterException(status, AmdSmiStatus)
|
|
|
|
# Create a pointer to a pointer to char (char**)
|
|
status_string_p_p = ctypes.pointer(ctypes.pointer(ctypes.c_char()))
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_get_esmi_err_msg(status.value, status_string_p_p))
|
|
|
|
# Use string_cast helper function if available in wrapper
|
|
if not status_string_p_p.contents:
|
|
pass
|
|
elif hasattr(amdsmi_wrapper, "string_cast"):
|
|
error_msg = amdsmi_wrapper.string_cast(status_string_p_p.contents)
|
|
if isinstance(error_msg, str):
|
|
return error_msg
|
|
else:
|
|
# Manual string extraction
|
|
error_msg = ctypes.string_at(status_string_p_p.contents).decode("utf-8")
|
|
return error_msg
|
|
return "Unknown error"
|
|
|
|
|
|
def amdsmi_get_gpu_event_notification(timeout_ms: int = 1000) -> Dict[str, Any]:
|
|
if not isinstance(timeout_ms, int):
|
|
raise AmdSmiParameterException(timeout_ms, int)
|
|
|
|
# Convert timeout to C type
|
|
timeout_ms_c = ctypes.c_int32(timeout_ms)
|
|
|
|
# Initialize output parameters
|
|
num_elem = ctypes.c_uint32(MAX_NUM_PROCESSES)
|
|
num_elem_p = ctypes.pointer(num_elem)
|
|
|
|
# Create array for event notification data
|
|
data_array = (amdsmi_wrapper.amdsmi_evt_notification_data_t * MAX_NUM_PROCESSES)()
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_event_notification(timeout_ms_c, num_elem_p, data_array)
|
|
)
|
|
|
|
results = []
|
|
for i in range(num_elem_p.contents.value):
|
|
entry = {
|
|
"processor_handle": data_array[i].processor_handle,
|
|
"event": data_array[i].event,
|
|
"message": data_array[i].message.decode("utf-8") if data_array[i].message else "",
|
|
}
|
|
results.append(entry)
|
|
|
|
result = {"num_elem": num_elem_p.contents.value, "data": results}
|
|
return result
|
|
|
|
|
|
def amdsmi_get_gpu_revision(processor_handle: processor_handle_t) -> str:
|
|
"""
|
|
Get the GPU revision for a given processor handle.
|
|
|
|
Parameters:
|
|
processor_handle (amdsmi_processor_handle): The processor handle for the GPU.
|
|
|
|
Returns:
|
|
str: The GPU revision as a string.
|
|
|
|
Raises:
|
|
AmdSmiParameterException: If the processor handle is invalid.
|
|
AmdSmiLibraryException: If the underlying library call fails.
|
|
"""
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
revision_16 = ctypes.c_uint16()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_gpu_revision(processor_handle, ctypes.byref(revision_16)))
|
|
|
|
return _pad_hex_value(hex(revision_16.value), 2)
|
|
|
|
|
|
def amdsmi_get_processor_count_from_handles(processor_handles_list) -> Dict[str, int]:
|
|
if not isinstance(processor_handles_list, list):
|
|
raise AmdSmiParameterException(processor_handles_list, list)
|
|
|
|
# Convert Python list to C array
|
|
processor_count = len(processor_handles_list)
|
|
processor_handles_array = (amdsmi_wrapper.amdsmi_processor_handle * processor_count)()
|
|
|
|
for i, handle in enumerate(processor_handles_list):
|
|
processor_handles_array[i] = handle
|
|
|
|
processor_count_p = ctypes.pointer(ctypes.c_uint32(processor_count))
|
|
nr_cpusockets = ctypes.pointer(ctypes.c_uint32(0))
|
|
nr_cpucores = ctypes.pointer(ctypes.c_uint32(0))
|
|
nr_gpus = ctypes.pointer(ctypes.c_uint32(0))
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_processor_count_from_handles(
|
|
processor_handles_array, processor_count_p, nr_cpusockets, nr_cpucores, nr_gpus
|
|
)
|
|
)
|
|
|
|
return {
|
|
"nr_cpusockets": nr_cpusockets.contents.value,
|
|
"nr_cpucores": nr_cpucores.contents.value,
|
|
"nr_gpus": nr_gpus.contents.value,
|
|
}
|
|
|
|
|
|
def amdsmi_get_processor_handles_by_type(
|
|
socket_handle: socket_handle_t, processor_type: AmdSmiProcessorType
|
|
):
|
|
if not isinstance(socket_handle, amdsmi_wrapper.amdsmi_socket_handle):
|
|
raise AmdSmiParameterException(socket_handle, amdsmi_wrapper.amdsmi_socket_handle)
|
|
if not isinstance(processor_type, AmdSmiProcessorType):
|
|
raise AmdSmiParameterException(processor_type, AmdSmiProcessorType)
|
|
|
|
processor_handles = (amdsmi_wrapper.amdsmi_processor_handle * MAX_NUM_PROCESSES)()
|
|
processor_count = ctypes.c_uint32(MAX_NUM_PROCESSES)
|
|
ptr_processor_count = ctypes.pointer(processor_count)
|
|
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_processor_handles_by_type(
|
|
socket_handle, processor_type, processor_handles, ptr_processor_count
|
|
)
|
|
)
|
|
|
|
entry = []
|
|
for i in range(ptr_processor_count.contents.value):
|
|
entry.append(amdsmi_wrapper.amdsmi_processor_handle(processor_handles[i]))
|
|
return {"processor_handles": entry, "processor_count": ptr_processor_count.contents.value}
|
|
|
|
|
|
def amdsmi_gpu_validate_ras_eeprom(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_gpu_validate_ras_eeprom(processor_handle))
|
|
|
|
|
|
def amdsmi_init_gpu_event_notification(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_init_gpu_event_notification(processor_handle))
|
|
|
|
|
|
def amdsmi_set_gpu_event_notification_mask(processor_handle: processor_handle_t, mask: int):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
if not isinstance(mask, int):
|
|
raise AmdSmiParameterException(mask, int)
|
|
|
|
mask_64 = ctypes.c_uint64(mask)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_set_gpu_event_notification_mask(processor_handle, mask_64))
|
|
|
|
|
|
def amdsmi_stop_gpu_event_notification(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
_check_res(amdsmi_wrapper.amdsmi_stop_gpu_event_notification(processor_handle))
|
|
|
|
|
|
_FABRIC_CATEGORY_NAMES = [
|
|
"UALOE",
|
|
"SWITCH",
|
|
"CRYPTO",
|
|
"PFC",
|
|
"NETPORT",
|
|
"DERIVED_UALOE",
|
|
"DERIVED_NETPORT",
|
|
]
|
|
|
|
_FABRIC_TYPE_NAMES = {0: "UALOE", 1: "UALINK", 2: "UNKNOWN"}
|
|
_FABRIC_ADDR_MODE_NAMES = {0: "SOURCE_ALIASING", 1: "SOURCE_IDENTIFICATION", 2: "UNKNOWN"}
|
|
_FABRIC_ACCEL_STATE_NAMES = {
|
|
0: "UNCONFIGURED",
|
|
1: "CONFIGURED",
|
|
2: "READY",
|
|
3: "ACTIVE",
|
|
4: "ERROR",
|
|
5: "UNKNOWN",
|
|
}
|
|
|
|
|
|
def amdsmi_get_fabric_telemetry_data(
|
|
processor_handle: processor_handle_t, category_mask: int
|
|
) -> List[Dict[str, Any]]:
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
if not isinstance(category_mask, int):
|
|
raise AmdSmiParameterException(category_mask, int)
|
|
|
|
tel_ptr = ctypes.POINTER(amdsmi_wrapper.amdsmi_fabric_telemetry_t)()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_alloc_fabric_telemetry(
|
|
processor_handle, ctypes.c_uint32(category_mask), ctypes.byref(tel_ptr)
|
|
)
|
|
)
|
|
|
|
try:
|
|
_check_res(amdsmi_wrapper.amdsmi_get_fabric_telemetry_data(processor_handle, tel_ptr))
|
|
|
|
results = []
|
|
tel = tel_ptr.contents
|
|
for cat_idx in range(amdsmi_wrapper.AMDSMI_FABRIC_TELEMETRY_CATEGORY_MAX):
|
|
dataset_ptr = tel.datasets[cat_idx]
|
|
if not dataset_ptr:
|
|
continue
|
|
dataset = dataset_ptr.contents
|
|
instances = []
|
|
for inst_idx in range(dataset.instance_count):
|
|
inst = dataset.instances[inst_idx]
|
|
items = []
|
|
for item_idx in range(inst.item_count):
|
|
item = inst.items[item_idx]
|
|
telem_id = item.id
|
|
name_ptr = ctypes.POINTER(ctypes.c_char)()
|
|
status = amdsmi_wrapper.amdsmi_fabric_telem_id_to_string(
|
|
telem_id, ctypes.byref(name_ptr)
|
|
)
|
|
# Unmapped telemetry ids (newer firmware) return NOT_FOUND;
|
|
# tolerate them so one unknown id does not abort the whole
|
|
# telemetry read.
|
|
if status == amdsmi_wrapper.AMDSMI_STATUS_SUCCESS and name_ptr:
|
|
name_str = ctypes.string_at(name_ptr).decode("utf-8")
|
|
elif status == amdsmi_wrapper.AMDSMI_STATUS_NOT_FOUND:
|
|
name_str = "UNKNOWN"
|
|
else:
|
|
_check_res(status)
|
|
items.append({"id": telem_id, "name": name_str, "value": item.value})
|
|
instances.append(
|
|
{
|
|
"name": inst.name.text.decode("utf-8").rstrip("\x00"),
|
|
"logical_idx": inst.logical_idx,
|
|
"items": items,
|
|
}
|
|
)
|
|
results.append(
|
|
{
|
|
"category": _FABRIC_CATEGORY_NAMES[cat_idx],
|
|
"generation_count": dataset.generation_count,
|
|
"timestamp": {
|
|
"tv_sec": dataset.timestamp.tv_sec,
|
|
"tv_nsec": dataset.timestamp.tv_nsec,
|
|
},
|
|
"instances": instances,
|
|
}
|
|
)
|
|
finally:
|
|
amdsmi_wrapper.amdsmi_free_fabric_telemetry(processor_handle, tel_ptr)
|
|
|
|
return results
|
|
|
|
|
|
def amdsmi_get_gpu_fabric_info(processor_handle: processor_handle_t) -> Dict[str, Any]:
|
|
"""
|
|
Return fabric info from UALoE sysfs (partial reads).
|
|
|
|
The C API may return AMDSMI_STATUS_NO_DATA when no sysfs files produced usable
|
|
lines; the struct is still populated with BDF and sentinel/default fabric fields.
|
|
"""
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
fabric_info = amdsmi_wrapper.amdsmi_fabric_info_t()
|
|
ret = amdsmi_wrapper.amdsmi_get_gpu_fabric_info(processor_handle, ctypes.byref(fabric_info))
|
|
if ret == amdsmi_wrapper.AMDSMI_STATUS_RETRY:
|
|
raise AmdSmiRetryException()
|
|
if ret == amdsmi_wrapper.AMDSMI_STATUS_TIMEOUT:
|
|
raise AmdSmiTimeoutException()
|
|
if ret not in (amdsmi_wrapper.AMDSMI_STATUS_SUCCESS, amdsmi_wrapper.AMDSMI_STATUS_NO_DATA):
|
|
raise AmdSmiLibraryException(ret)
|
|
|
|
v1 = fabric_info.fabric_info.v1
|
|
return {
|
|
"bdf": _format_bdf(fabric_info.bdf),
|
|
"version": fabric_info.fabric_version,
|
|
"accelerator_id": v1.accelerator_id,
|
|
"fabric_type": _FABRIC_TYPE_NAMES.get(v1.fabric_type, "UNKNOWN"),
|
|
"bandwidth": v1.bandwidth,
|
|
"latency": v1.latency,
|
|
"ppod_id": list(v1.ppod_id),
|
|
"ppod_size": v1.ppod_size,
|
|
"vpod_id": v1.vpod_id,
|
|
"vpod_size": v1.vpod_size,
|
|
"local_accelerators": list(v1.local_accelerators),
|
|
"vpod_active_accelerators": list(v1.vpod_active_accelerators),
|
|
"addr_mode": _FABRIC_ADDR_MODE_NAMES.get(v1.addr_mode, "UNKNOWN"),
|
|
"accel_state": _FABRIC_ACCEL_STATE_NAMES.get(v1.accel_state, "UNKNOWN"),
|
|
}
|
|
|
|
|
|
def amdsmi_get_gpu_busy_percent(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
gpu_busy_percent = ctypes.c_uint32(0)
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_busy_percent(processor_handle, ctypes.byref(gpu_busy_percent))
|
|
)
|
|
return _validate_if_max_uint(gpu_busy_percent.value, MaxUIntegerTypes.UINT32_T)
|
|
|
|
|
|
def amdsmi_get_vcn_busy_percent(processor_handle: processor_handle_t):
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
vcn_busy_percent = ctypes.c_uint32(0)
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_vcn_busy_percent(processor_handle, ctypes.byref(vcn_busy_percent))
|
|
)
|
|
return vcn_busy_percent.value
|
|
|
|
|
|
# Memory Size Management Functions
|
|
# Note: UMA carveout and TTM are kernel UAPI features (sysfs/modprobe.d), not libdrm.
|
|
|
|
|
|
def amdsmi_get_gpu_uma_carveout_info(processor_handle: processor_handle_t):
|
|
"""
|
|
Get UMA carveout information for a GPU.
|
|
|
|
Note: This is a kernel UAPI feature (sysfs), not libdrm.
|
|
|
|
Args:
|
|
processor_handle: GPU processor handle
|
|
|
|
Returns:
|
|
dict: Dictionary with 'current_index', 'num_options', and 'options' list
|
|
|
|
Raises:
|
|
AmdSmiParameterException: If processor_handle is invalid
|
|
AmdSmiException: If the function fails
|
|
"""
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
info = amdsmi_wrapper.amdsmi_uma_carveout_info_t()
|
|
_check_res(
|
|
amdsmi_wrapper.amdsmi_get_gpu_uma_carveout_info(processor_handle, ctypes.byref(info))
|
|
)
|
|
|
|
# Convert to Python dict
|
|
result = {"current_index": info.current_index, "num_options": info.num_options, "options": []}
|
|
|
|
for i in range(info.num_options):
|
|
description = (
|
|
info.options[i].description.decode("utf-8")
|
|
if isinstance(info.options[i].description, bytes)
|
|
else info.options[i].description
|
|
)
|
|
if description:
|
|
opt = {"index": info.options[i].index, "description": description}
|
|
result["options"].append(opt)
|
|
|
|
return result
|
|
|
|
|
|
def amdsmi_set_gpu_uma_carveout(processor_handle: processor_handle_t, option_index: int):
|
|
"""
|
|
Set UMA carveout size by option index. Requires reboot.
|
|
|
|
Note: This is a kernel UAPI feature (sysfs), not libdrm.
|
|
|
|
Args:
|
|
processor_handle: GPU processor handle
|
|
option_index: Index of the carveout option to set
|
|
|
|
Raises:
|
|
AmdSmiParameterException: If processor_handle is invalid
|
|
AmdSmiException: If the function fails
|
|
"""
|
|
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
|
raise AmdSmiParameterException(processor_handle, amdsmi_wrapper.amdsmi_processor_handle)
|
|
|
|
_check_res(amdsmi_wrapper.amdsmi_set_gpu_uma_carveout(processor_handle, option_index))
|
|
|
|
|
|
def amdsmi_get_ttm_info():
|
|
"""
|
|
Get Translation Table Manager (TTM) memory information.
|
|
|
|
Note: This is a kernel UAPI feature (modprobe.d), not libdrm.
|
|
TTM is a system-wide setting, not per-GPU.
|
|
|
|
Returns:
|
|
dict: Dictionary with 'current_pages'
|
|
|
|
Raises:
|
|
AmdSmiException: If the function fails
|
|
"""
|
|
info = amdsmi_wrapper.amdsmi_ttm_info_t()
|
|
_check_res(amdsmi_wrapper.amdsmi_get_ttm_info(ctypes.byref(info)))
|
|
|
|
return {"current_pages": info.current_pages}
|
|
|
|
|
|
def amdsmi_set_ttm_pages_limit(pages: int):
|
|
"""
|
|
Set TTM memory limit in pages. Requires reboot.
|
|
|
|
Note: This is a kernel UAPI feature (modprobe.d), not libdrm.
|
|
TTM is a system-wide setting, not per-GPU.
|
|
|
|
Args:
|
|
pages: Number of pages to set as TTM limit
|
|
|
|
Raises:
|
|
AmdSmiException: If the function fails
|
|
"""
|
|
_check_res(amdsmi_wrapper.amdsmi_set_ttm_pages_limit(pages))
|
|
|
|
|
|
def amdsmi_reset_ttm_pages_limit():
|
|
"""
|
|
Reset TTM memory limit to system default. Requires reboot.
|
|
|
|
Note: This is a kernel UAPI feature (modprobe.d), not libdrm.
|
|
TTM is a system-wide setting, not per-GPU.
|
|
|
|
Raises:
|
|
AmdSmiException: If the function fails
|
|
"""
|
|
_check_res(amdsmi_wrapper.amdsmi_reset_ttm_pages_limit())
|