Files
TheRock/rocm-systems/projects/rdc/python_binding/RdcReader.py
T
derek.holloway 7502bf64a4
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
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

243 lines
9.2 KiB
Python

# Copyright © Advanced Micro Devices, Inc., or its affiliates.
# SPDX-License-Identifier: MIT
import os, time
from rdc_bootstrap import *
from RdcUtil import RdcUtil
from typing import Dict
default_field_ids = [
rdc_field_t.RDC_FI_GPU_MEMORY_USAGE,
rdc_field_t.RDC_FI_GPU_MEMORY_TOTAL,
rdc_field_t.RDC_FI_GPU_MM_ENC_UTIL,
rdc_field_t.RDC_FI_GPU_MM_DEC_UTIL,
rdc_field_t.RDC_FI_GPU_MEMORY_ACTIVITY,
rdc_field_t.RDC_FI_GPU_MEMORY_MAX_BANDWIDTH,
rdc_field_t.RDC_FI_GPU_MEMORY_CUR_BANDWIDTH,
rdc_field_t.RDC_FI_OAM_ID,
rdc_field_t.RDC_FI_POWER_USAGE,
rdc_field_t.RDC_FI_GPU_CLOCK,
rdc_field_t.RDC_FI_GPU_UTIL,
rdc_field_t.RDC_FI_GPU_TEMP,
rdc_field_t.RDC_FI_GPU_MEMORY_USAGE,
]
default_unit_coverter = {
rdc_field_t.RDC_FI_GPU_MEMORY_USAGE: 0.000001, # MegaBytes
rdc_field_t.RDC_FI_GPU_MEMORY_TOTAL: 0.000001, # MegaBytes
rdc_field_t.RDC_FI_POWER_USAGE: 0.000001, # Watts
rdc_field_t.RDC_FI_GPU_CLOCK: 0.000001, # MHz
rdc_field_t.RDC_FI_GPU_TEMP: 0.001, # degree
}
class RdcReader:
# To run the RDC in embedded mode, set the ip_port = None
def __init__(
self,
ip_port="localhost:50051",
field_ids=default_field_ids,
unit_converter: Dict[int, float] = default_unit_coverter,
update_freq=10000000,
max_keep_age=3600.0,
max_keep_samples=1000,
field_group_name="rdc_reader_field_group",
gpu_group_name="rdc_reader_gpu_group",
gpu_indexes=None,
root_ca="/etc/rdc/client/certs/rdc_cacert.pem",
client_cert="/etc/rdc/client/certs/rdc_client_cert.pem",
client_key="/etc/rdc/client/private/rdc_client_cert.key",
):
result = rdc.rdc_init(0)
if rdc_status_t(result) != rdc_status_t.RDC_ST_OK:
raise Exception("RdcReader init fail: " + str(result))
self.rdc_util = RdcUtil()
self.unit_converter = unit_converter
self.rdc_handle = c_void_p()
self.is_standalone = True
if not ip_port: # embedded
self.is_standalone = False
result = rdc.rdc_start_embedded(
rdc_operation_mode_t.RDC_OPERATION_MODE_AUTO, self.rdc_handle
)
if rdc_status_t(result) != rdc_status_t.RDC_ST_OK:
raise Exception("RdcReader start as embedded fail: " + str(result))
else: # standalone
if root_ca == None or client_cert == None or client_key == None:
with_auth = False
root_ca_str = client_cert_str = client_key_str = None
else:
with_auth = True
root_ca_str = self.rdc_util.read_file(root_ca)
client_cert_str = self.rdc_util.read_file(client_cert)
client_key_str = self.rdc_util.read_file(client_key)
result = rdc.rdc_connect(
ip_port.encode("utf-8"),
self.rdc_handle,
root_ca_str,
client_cert_str,
client_key_str,
)
if rdc_status_t(result) != rdc_status_t.RDC_ST_OK:
raise Exception(
"RdcReader standalone auth("
+ str(with_auth)
+ ") connect to "
+ ip_port
+ " fail: "
+ str(result)
)
# Create the GPU group
self.gpu_group_name = gpu_group_name.encode()
if gpu_indexes == None:
self.gpu_indexes = self.rdc_util.get_all_gpu_indexes(self.rdc_handle)
else:
self.gpu_indexes = []
for idx in gpu_indexes:
idx_str = str(idx)
encoded = idx_str.encode("utf-8")
phys_gpu = ctypes.c_uint32()
part_idx = ctypes.c_uint32()
if rdc.rdc_is_partition_string(encoded):
rc = rdc.rdc_parse_partition_string(
encoded, ctypes.byref(phys_gpu), ctypes.byref(part_idx)
)
if not rc:
raise Exception("Rdc failed to parse partition string")
info = rdc_entity_info_t()
info.device_type = 0 # RDC_DEVICE_TYPE_GPU
info.entity_role = 1 # RDC_DEVICE_ROLE_PARTITION
info.instance_index = part_idx
info.device_index = phys_gpu
entity = rdc.rdc_get_entity_index_from_info(info)
self.gpu_indexes.append(entity)
else:
self.gpu_indexes.append(int(idx_str))
self.gpu_group_id, gpu_group_created = self.rdc_util.create_gpu_group(
self.rdc_handle, self.gpu_group_name, self.gpu_indexes
)
# Create the field group
self.field_ids = field_ids
self.field_group_name = field_group_name.encode()
self.field_group_id, field_group_created = self.rdc_util.create_field_group(
self.rdc_handle, self.field_group_name, self.field_ids
)
# Watch the fields
self.update_freq = update_freq
self.max_keep_age = max_keep_age
self.max_keep_samples = max_keep_samples
# Unwatch first to clean up what left from last run
rdc.rdc_field_unwatch(self.rdc_handle, self.gpu_group_id, self.field_group_id)
result = rdc.rdc_field_watch(
self.rdc_handle,
self.gpu_group_id,
self.field_group_id,
self.update_freq,
self.max_keep_age,
self.max_keep_samples,
)
if rdc_status_t(result) != rdc_status_t.RDC_ST_OK:
raise Exception(
"RdcReader fail to watch group "
+ str(self.gpu_group_id)
+ ", field group "
+ str(self.field_group_id)
+ ":"
+ str(result)
)
# Process the fields periodically
def process(self):
has_succeed = False
for gindex in self.gpu_indexes:
for fid in self.field_ids:
value = rdc_field_value()
result = rdc.rdc_field_get_latest_value(self.rdc_handle, gindex, fid, value)
if rdc_status_t(result) == rdc_status_t.RDC_ST_OK:
# Convert the unit
if self.unit_converter != None and fid in self.unit_converter:
if value.type.value == rdc_field_type_t.INTEGER:
value.value.l_int = int(value.value.l_int * self.unit_converter[fid])
if value.type.value == rdc_field_type_t.DOUBLE:
value.value.dbl = int(value.value.dbl * self.unit_converter[fid])
# convert from double to l_int
if value.type.value == rdc_field_type_t.DOUBLE:
value.value.l_int = int(value.value.dbl)
self.handle_field(gindex, value)
has_succeed = True
self.process_other_fields()
if len(self.gpu_indexes) != 0 and len(self.field_ids) != 0 and has_succeed == False:
self.try_reconnect()
def process_other_fields(self):
pass
def try_reconnect(self):
if self.is_standalone == False:
return
try:
# When rdcd restart, the GPU and field group need to be re-created.
self.gpu_group_id, gpu_group_created = self.rdc_util.create_gpu_group(
self.rdc_handle, self.gpu_group_name, self.gpu_indexes
)
self.field_group_id, field_group_created = self.rdc_util.create_field_group(
self.rdc_handle, self.field_group_name, self.field_ids
)
# rdcd restart requires to watch the group again
if gpu_group_created or field_group_created:
result = rdc.rdc_field_watch(
self.rdc_handle,
self.gpu_group_id,
self.field_group_id,
self.update_freq,
self.max_keep_age,
self.max_keep_samples,
)
if rdc_status_t(result) != rdc_status_t.RDC_ST_OK:
raise Exception(
"RdcReader fail to watch group "
+ str(self.gpu_group_id)
+ ", field group "
+ str(self.field_group_id)
+ ":"
+ str(result)
)
except Exception as e:
print(e)
def handle_field(self, gpu_index, value):
info = rdc.rdc_get_info_from_entity_index(gpu_index)
if info.entity_role == 1: # RDC_DEVICE_ROLE_PARTITION_INSTANCE
gpu_str = f"g{info.device_index}.{info.instance_index}"
else:
gpu_str = str(info.device_index)
field_name = self.rdc_util.field_id_string(value.field_id)
print(
"%d %s:%d %s:%d"
% (value.ts, gpu_str, value.field_id.value, field_name, value.value.l_int)
)
if __name__ == "__main__":
# Run the reader in embedded mode
reader = RdcReader(ip_port=None, update_freq=1000000)
while True:
time.sleep(1)
reader.process()