Get amdgpu name from amdgpu.ids

This commit is contained in:
Ognyan Kulev
2025-12-13 21:33:22 +02:00
parent ff5e33d856
commit ec11dff2cd

View File

@@ -11,6 +11,7 @@
The class grabs the stats from the /sys/class/drm/ directory.
See: https://wiki.archlinux.org/title/AMDGPU#Manually
amdgpu.ids source: https://cgit.freedesktop.org/drm/libdrm/tree/data/amdgpu.ids
"""
# Example
@@ -20,6 +21,7 @@ See: https://wiki.archlinux.org/title/AMDGPU#Manually
# │   └── drm
# │   └── card0
# │   └── device
# │   ├── device
# │   ├── gpu_busy_percent
# │   ├── hwmon
# │   │   └── hwmon0
@@ -27,7 +29,8 @@ See: https://wiki.archlinux.org/title/AMDGPU#Manually
# │   ├── mem_info_vram_total
# │   ├── mem_info_vram_used
# │   ├── pp_dpm_mclk
# │   ── pp_dpm_sclk
# │   ── pp_dpm_sclk
# │   └── revision
# └── kernel
# └── debug
# └── dri
@@ -37,10 +40,14 @@ See: https://wiki.archlinux.org/title/AMDGPU#Manually
import os
import re
from typing import Optional
import functools
DRM_ROOT_FOLDER: str = '/sys/class/drm'
CARD_REGEX: str = r"^card\d$"
DEVICE_FOLDER: str = 'device'
AMDGPU_IDS: str = '/usr/share/libdrm/amdgpu.ids'
PCI_DEVICE_ID: str = 'device'
PCI_REVISION_ID: str = 'revision'
GPU_PROC_PERCENT: str = 'gpu_busy_percent'
GPU_MEM_TOTAL: str = 'mem_info_vram_total'
GPU_MEM_USED: str = 'mem_info_vram_used'
@@ -99,28 +106,46 @@ def get_device_list(drm_root_folder: str) -> list:
return ret
def read_file(*path_segments: str) -> Optional[str]:
"""Return content of file."""
path = os.path.join(*path_segments)
if os.path.isfile(path):
with open(path) as f:
try:
return f.read().strip()
except PermissionError:
# Catch exception (see issue #3125)
return None
return None
@functools.cache
def get_device_name(device_folder: str) -> str:
"""Return the GPU name."""
device_id = read_file(device_folder, PCI_DEVICE_ID)
revision_id = read_file(device_folder, PCI_REVISION_ID)
amdgpu_ids = read_file(AMDGPU_IDS)
if device_id and revision_id and amdgpu_ids:
# Strip leading "0x" and convert to uppercase hexadecimal
device_id = device_id[2:].upper()
revision_id = revision_id[2:].upper()
# Syntax:
# device_id, revision_id, product_name <-- single tab after comma
pattern = re.compile(f'^{device_id},\\s{revision_id},\\s(.+)$', re.MULTILINE)
if match := pattern.search(amdgpu_ids):
return match.group(1)
return 'AMD GPU'
def get_mem(device_folder: str) -> Optional[int]:
"""Return the memory consumption in %."""
mem_info_vram_total = os.path.join(device_folder, GPU_MEM_TOTAL)
mem_info_vram_used = os.path.join(device_folder, GPU_MEM_USED)
if os.path.isfile(mem_info_vram_total) and os.path.isfile(mem_info_vram_used):
with open(mem_info_vram_total) as f:
try:
mem_info_vram_total = int(f.read())
except PermissionError:
# Catch exception (see issue #3125)
return None
with open(mem_info_vram_used) as f:
try:
mem_info_vram_used = int(f.read())
except PermissionError:
# Catch exception (see issue #3125)
return None
mem_info_vram_total = read_file(device_folder, GPU_MEM_TOTAL)
mem_info_vram_used = read_file(device_folder, GPU_MEM_USED)
if mem_info_vram_total and mem_info_vram_used:
mem_info_vram_total = int(mem_info_vram_total)
mem_info_vram_used = int(mem_info_vram_used)
if mem_info_vram_total > 0:
return round(mem_info_vram_used / mem_info_vram_total * 100)
return None
@@ -128,14 +153,8 @@ def get_mem(device_folder: str) -> Optional[int]:
def get_proc(device_folder: str) -> Optional[int]:
"""Return the processor consumption in %."""
gpu_busy_percent = os.path.join(device_folder, GPU_PROC_PERCENT)
if os.path.isfile(gpu_busy_percent):
with open(gpu_busy_percent) as f:
try:
return int(f.read())
except PermissionError:
# Catch exception (see issue #3125)
return None
if gpu_busy_percent := read_file(device_folder, GPU_PROC_PERCENT):
return int(gpu_busy_percent)
return None
@@ -148,12 +167,10 @@ def get_temperature(device_folder: str) -> Optional[int]:
for _, _, files in os.walk(os.path.join(root, d)):
for f in files:
if re.match(GPU_TEMPERATURE_REGEXP, f):
with open(os.path.join(root, d, f)) as f:
try:
temp_input.append(int(f.read()))
except PermissionError:
# Catch exception (see issue #3125)
return None
if a_temp_input := read_file(root, d, f):
temp_input.append(int(a_temp_input))
else:
return None
if temp_input:
return round(sum(temp_input) / len(temp_input) / 1000)
return None