Adding support for uuid and name targeting (this deprecates -t and --target option)

This commit is contained in:
HackTestes
2024-05-17 16:17:52 -03:00
parent e69507dc2c
commit 802580c26e
3 changed files with 66 additions and 11 deletions

View File

@@ -352,7 +352,7 @@ WantedBy=multi-user.target
- [x] Control fan policy
- [ ] Select GPU by UUID (allows users to control more than 1 GPU individually that shares the same model - e.g. 2 RTXs 4080)
- [x] Select GPU by UUID (allows users to control more than 1 GPU individually that shares the same model - e.g. 2 RTXs 4080)
- [ ] Run at startup with necessary permissions (Windows and Linux) - Windows already works

View File

@@ -49,12 +49,22 @@ def print_GPU_info(gpu_handle):
log_helper(f"Fan controller count {pynvml.nvmlDeviceGetNumFans(gpu_handle)}")
def fan_control(configuration):
gpu_handle = get_GPU_handle_by_name(configuration.target_gpu)
gpu_handle = get_GPU_handle(configuration.gpu_name, configuration.gpu_uuid)
print_GPU_info(gpu_handle)
control_and_monitor(gpu_handle, configuration)
# Search for a GPU and return a handle
# This will not work if the user has more than 2 GPUs with the same name/model, use UUID for this case
def get_GPU_handle(gpu_name, gpu_uuid):
if gpu_uuid != '':
return pynvml.nvmlDeviceGetHandleByUUID(gpu_uuid)
else:
return get_GPU_handle_by_name(gpu_name)
# This will NOT work if the user has more than 2 GPUs with the same name/model, use UUID for this case
def get_GPU_handle_by_name(gpu_name):
deviceCount = pynvml.nvmlDeviceGetCount()
@@ -172,7 +182,7 @@ def fan_policy(configuration):
current_policy = ctypes.c_uint(0)
target_fan_policy = configuration.fan_policy
gpu_handle = get_GPU_handle_by_name(configuration.target_gpu)
gpu_handle = get_GPU_handle(configuration.gpu_name, configuration.gpu_uuid)
# The library unfortunately still needs pointers
pynvml.nvmlDeviceGetFanControlPolicy_v2(gpu_handle, 0, ctypes.byref(current_policy))
@@ -219,7 +229,7 @@ def get_power_limit_constraints_watts(gpu_handle):
def print_power_limit_info(configuration):
gpu_handle = get_GPU_handle_by_name(configuration.target_gpu)
gpu_handle = get_GPU_handle(configuration.gpu_name, configuration.gpu_uuid)
constraints = get_power_limit_constraints_watts(gpu_handle)
current_pl = get_current_power_limit_watts(gpu_handle)
@@ -281,7 +291,7 @@ def set_temperature_thresholds(gpu_handle, threshold_type, temperature_C, dry_ru
def print_thresholds_info(configuration):
gpu_handle = get_GPU_handle_by_name(configuration.target_gpu)
gpu_handle = get_GPU_handle(configuration.gpu_name, configuration.gpu_uuid)
temperarure_thresholds = get_temperarure_thresholds(gpu_handle)

View File

@@ -22,8 +22,8 @@ class Configuration:
def __init__(self):
# This only supports one target gpu, use a process for each GPU (erros become isolated to each other)
self.target_gpu = ""
self.name = ""
self.uuid = ""
self.gpu_name = ""
self.gpu_uuid = ""
self.action = ""
self.temp_speed_pair = []
self.curve_type = "fixed" # Currently for internal usage only (I want to later add calculation for lines and curves fuctions)
@@ -31,6 +31,9 @@ class Configuration:
self.time_interval = 1.0 # In seconds
self.dry_run = False
self.fan_policy = ''
self.single_use = False
self.acoustic_temp_limit = 0 # The user must set the value
self.power_limit = 0 # The user must set the value
class TempSpeedPair:
@@ -58,7 +61,12 @@ class TempSpeedPair:
# Some sane checks (in case the user makes a bad config by accident)
def validate_config(config):
if config.target_gpu == '':
# if config.target_gpu == '':
# print("You did not select a target GPU")
# raise InvalidConfig("No GPU was selected")
# At least one of the target setting must be configured
if config.gpu_name == '' and config.gpu_uuid == '':
print("You did not select a target GPU")
raise InvalidConfig("No GPU was selected")
@@ -73,6 +81,18 @@ def validate_config(config):
print("You did not select a fan policy: autmatic or manual")
raise InvalidConfig("No fan policy was selected")
# power-control needs a power limit configuration
if config.action == 'power-control':
if config.power_limit == 0:
print("You did not select a power limit")
raise InvalidConfig("No power limit was selected")
# temp-control needs a power limit configuration
if config.action == 'temp-control':
if config.acoustic_temp_limit == 0:
print("You did not select a temperature limit")
raise InvalidConfig("No temperature limit was selected")
def parse_cmd_args(args):
@@ -107,6 +127,12 @@ def parse_cmd_args(args):
elif (action == 'get-thresholds-info'):
configuration.action = 'get-thresholds-info'
elif (action == 'power-control'):
configuration.action = 'power-control'
elif (action == 'temp-control'):
configuration.action = 'temp-control'
else:
print(f'Invalid action: {action}')
raise InvalidAction("The action passed as argument is incorrect")
@@ -118,8 +144,16 @@ def parse_cmd_args(args):
arg = args[i]
if (arg == '--target' or arg == '-t'):
configuration.target_gpu = args[i+1]
# if (arg == '--target' or arg == '-t'):
# configuration.target_gpu = args[i+1]
# i += 1 # Skip the next iteration
if (arg == '--name' or arg == '-n'):
configuration.gpu_name = args[i+1]
i += 1 # Skip the next iteration
elif (arg == '--uuid' or arg == '-id'):
configuration.gpu_uuid = args[i+1]
i += 1 # Skip the next iteration
elif (arg == '--speed-pair' or arg == '-sp'):
@@ -168,6 +202,17 @@ def parse_cmd_args(args):
elif (arg == '--manual'):
configuration.fan_policy = 'manual'
elif (arg == '--single-use' or arg == '-su'):
configuration.single_use = True
elif (arg == '--acoustic-temp-limit' or arg == '-tl'):
configuration.acoustic_temp_limit = int(args[i+1])
i += 1 # Skip the next iteration
elif (arg == '--power-limit' or arg == '-pl'):
configuration.power_limit = int(args[i+1])
i += 1 # Skip the next iteration
else:
print(f'Invalid option: {arg}')
raise InvalidOption('The option given was invalid')