Implement: get_nvidia_gpu_devices, parse_nvidia_gpu_line

This commit is contained in:
Meliox 2026-01-05 21:00:39 +01:00
parent e66125954a
commit 5893aaec65

View File

@ -52,7 +52,7 @@ my $COLLECTOR_TIMEOUT = 10; # Stop collectors x seconds after last get_graphic
my $intel_gpu_enabled = 1; # Set to 0 to disable Intel GPU support my $intel_gpu_enabled = 1; # Set to 0 to disable Intel GPU support
my $amd_gpu_enabled = 0; # Set to 1 to enable AMD GPU support (not yet implemented) my $amd_gpu_enabled = 0; # Set to 1 to enable AMD GPU support (not yet implemented)
my $nvidia_gpu_enabled = 0; # Set to 1 to enable NVIDIA GPU support (not yet implemented) my $nvidia_gpu_enabled = 1; # Set to 1 to enable NVIDIA GPU support (not yet implemented)
my $pve_mod_worker_pid; my $pve_mod_worker_pid;
my $pve_mod_worker_running = 0; my $pve_mod_worker_running = 0;
@ -137,6 +137,7 @@ sub _get_intel_gpu_devices {
return @devices unless -x '/usr/bin/intel_gpu_top'; return @devices unless -x '/usr/bin/intel_gpu_top';
_debug(__LINE__, "Getting Intel GPU devices");
if (open my $fh, '-|', 'intel_gpu_top -L') { if (open my $fh, '-|', 'intel_gpu_top -L') {
while (<$fh>) { while (<$fh>) {
chomp; chomp;
@ -152,7 +153,7 @@ sub _get_intel_gpu_devices {
path => $path, path => $path,
drm_path => "/dev/dri/$card" drm_path => "/dev/dri/$card"
}; };
_debug(__LINE__, "Found GPU device: $card -> $name ($path)"); _debug(__LINE__, "Found Intel device: $card -> $name ($path)");
} }
} }
close $fh; close $fh;
@ -276,25 +277,123 @@ sub _collector_for_amd_device {
# ============================================================================ # ============================================================================
sub get_nvidia_gpu_devices { sub get_nvidia_gpu_devices {
# TODO: Implement NVIDIA GPU detection my @devices = ();
# Use nvidia-smi to detect NVIDIA GPUs
_debug(__LINE__, "NVIDIA GPU support not yet implemented"); # Expected format (CSV with header):
return (); # index, name
# 0, NVIDIA GeForce RTX 3080
# 1, NVIDIA RTX A4000
# add debug mode where Expected format is loaded from a file instead or calling nvidia-smi
my $debug_file = '/tmp/nvidia-smi-debug.csv';
my $use_debug_file = 1; # Set to 1 to enable debug mode
# todo - delete this block later
if ($use_debug_file && -f $debug_file) {
_debug(__LINE__, "Debug mode: reading NVIDIA GPU data from $debug_file");
if (open my $fh, '<', $debug_file) {
while (<$fh>) {
chomp;
# Skip empty lines
next if /^\s*$/;
# Parse CSV: "0, NVIDIA GeForce RTX 3080"
if (/^\s*(\d+)\s*,\s*(.+?)\s*$/) {
my $index = $1;
my $name = $2;
push @devices, {
name => $name,
index => $index,
};
_debug(__LINE__, "Found NVIDIA GPU device (debug): $name -> (index: $index)");
}
}
close $fh;
} else {
_debug(__LINE__, "Failed to open debug file $debug_file: $!");
}
}
return @devices;
# if (open my $fh, '-|', 'nvidia-smi --query-gpu=index,name --format=csv') {
# while (<$fh>) {
# chomp;
# # Skip empty lines
# next if /^\s*$/;
# # Parse CSV: "0, NVIDIA GeForce RTX 3080"
# if (/^\s*(\d+)\s*,\s*(.+?)\s*$/) {
# my $index = $1;
# my $name = $2;
# push @devices, {
# name => $name,
# index => $index,
# };
# _debug(__LINE__, "Found NVIDIA GPU device: $name -> (index: $index)");
# }
# }
# close $fh;
# } else {
# _debug(__LINE__, "Failed to run nvidia-smi: $!");
# }
# return @devices;
} }
sub parse_nvidia_gpu_line { sub parse_nvidia_gpu_line {
my ($line) = @_; my ($line) = @_;
# TODO: Implement NVIDIA GPU line parsing
# Parse nvidia-smi output # Expected format (CSV) for multiple GPUs:
_debug(__LINE__, "NVIDIA GPU line parsing not yet implemented"); # index, name, temperature.gpu, utilization.gpu, utilization.memory, memory.used, memory.total, power.draw, power.limit, fan.speed
return undef; #0, NVIDIA GeForce RTX 3080, 62, 79, 44, 8260, 10240, 268.12, 320.00, 67
# Remove leading/trailing whitespace
$line =~ s/^\s+|\s+$//g;
# Skip empty lines
return unless $line;
# Split by comma and trim whitespace from each field
my @values = map { s/^\s+|\s+$//gr } split(/,/, $line);
# Expected: index(0), name(1), temp(2), util_gpu(3), util_mem(4), mem_used(5), mem_total(6), power_draw(7), power_limit(8), fan_speed(9)
return unless @values >= 10;
my $stats = {
index => $values[0] + 0,
name => $values[1],
temperature => {
gpu => $values[2] + 0.0,
unit => "°C"
},
utilization => {
gpu => $values[3] + 0.0,
memory => $values[4] + 0.0,
unit => "%"
},
memory => {
used => $values[5] + 0.0,
total => $values[6] + 0.0,
unit => "MiB"
},
power => {
draw => $values[7] + 0.0,
limit => $values[8] + 0.0,
unit => "W"
},
fan => {
speed => $values[9] + 0.0,
unit => "%"
}
};
return $stats;
} }
sub collector_for_nvidia_device { sub collector_for_nvidia_device {
my ($device) = @_; my ($device) = @_;
# TODO: Implement NVIDIA GPU collector # nvidia-smi --query-gpu=index,name,temperature.gpu,utilization.gpu,utilization.memory,memory.used,memory.total,power.draw,power.limit,fan.speed --format=csv,nounits,noheader --loop=1
_debug(__LINE__, "NVIDIA GPU collector not yet implemented");
exit 0;
} }
# ============================================================================ # ============================================================================
@ -543,15 +642,13 @@ sub _start_graphics_collectors {
_debug(__LINE__, "Checking for intel_gpu_top"); _debug(__LINE__, "Checking for intel_gpu_top");
unless (-x '/usr/bin/intel_gpu_top') { unless (-x '/usr/bin/intel_gpu_top') {
_debug(__LINE__, "intel_gpu_top not executable"); _debug(__LINE__, "intel_gpu_top not executable");
unlink($startup_lock);
return; return;
} }
_debug(__LINE__, "intel_gpu_top is executable"); _debug(__LINE__, "intel_gpu_top is executable");
_debug(__LINE__, "Getting Intel GPU devices");
my @intel_devices = _get_intel_gpu_devices(); my @intel_devices = _get_intel_gpu_devices();
unless (@intel_devices) { unless (@intel_devices) {
_debug(__LINE__, "No Intel GPU devices found"); _debug(__LINE__, "No Intel GPU devices found");
unlink($startup_lock);
return; return;
} }
_debug(__LINE__, "Found " . scalar(@intel_devices) . " Intel GPU device(s)"); _debug(__LINE__, "Found " . scalar(@intel_devices) . " Intel GPU device(s)");
@ -571,6 +668,15 @@ sub _start_graphics_collectors {
} }
# NVIDIA (future) # NVIDIA (future)
if ($nvidia_gpu_enabled) { if ($nvidia_gpu_enabled) {
_debug(__LINE__, "NVIDIA GPU support enabled");
# _debug(__LINE__, "Checking for nvidia-smi");
# unless (-x '/usr/bin/nvidia-smi') {
# _debug(__LINE__, "nvidia-smi not executable");
# return;
# }
_debug(__LINE__, "nvidia-smi is executable");
my @nvidia_devices = get_nvidia_gpu_devices(); my @nvidia_devices = get_nvidia_gpu_devices();
_debug(__LINE__, "Got " . scalar(@nvidia_devices) . " NVIDIA devices"); _debug(__LINE__, "Got " . scalar(@nvidia_devices) . " NVIDIA devices");
foreach my $device (@nvidia_devices) { foreach my $device (@nvidia_devices) {