Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/gpu_metrics_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct gpu_metrics {
#define METRICS_UPDATE_PERIOD_MS 500
#define METRICS_POLLING_PERIOD_MS 25
#define METRICS_SAMPLE_COUNT (METRICS_UPDATE_PERIOD_MS/METRICS_POLLING_PERIOD_MS)
#define NVML_SLOW_POLL_PERIOD_MS METRICS_UPDATE_PERIOD_MS

#define GPU_UPDATE_METRIC_AVERAGE(FIELD) do { int value_sum = 0; for (size_t s=0; s < METRICS_SAMPLE_COUNT; s++) { value_sum += metrics_buffer[s].FIELD; } metrics.FIELD = value_sum / METRICS_SAMPLE_COUNT; } while(0)
#define GPU_UPDATE_METRIC_AVERAGE_FLOAT(FIELD) do { float value_sum = 0; for (size_t s=0; s < METRICS_SAMPLE_COUNT; s++) { value_sum += metrics_buffer[s].FIELD; } metrics.FIELD = value_sum / METRICS_SAMPLE_COUNT; } while(0)
Expand Down
14 changes: 14 additions & 0 deletions src/loaders/loader_nvml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@ bool libnvml_loader::Load(const std::string& library_name) {
return false;
}

#if defined(LIBRARY_LOADER_NVML_H_DLOPEN)
nvmlDeviceGetMemoryInfo_v2 =
reinterpret_cast<decltype(this->nvmlDeviceGetMemoryInfo_v2)>(
dlsym(library_, "nvmlDeviceGetMemoryInfo_v2"));
#endif

#if defined(LIBRARY_LOADER_NVML_H_DLOPEN)
nvmlDeviceGetClockInfo =
reinterpret_cast<decltype(this->nvmlDeviceGetClockInfo)>(
Expand Down Expand Up @@ -265,6 +271,12 @@ bool libnvml_loader::Load(const std::string& library_name) {
return false;
}

#if defined(LIBRARY_LOADER_NVML_H_DLOPEN)
nvmlDeviceGetFanSpeed_v2 =
reinterpret_cast<decltype(this->nvmlDeviceGetFanSpeed_v2)>(
dlsym(library_, "nvmlDeviceGetFanSpeed_v2"));
#endif

#if defined(LIBRARY_LOADER_NVML_H_DLOPEN)
nvmlDeviceGetGraphicsRunningProcesses =
reinterpret_cast<decltype(this->nvmlDeviceGetGraphicsRunningProcesses)>(
Expand Down Expand Up @@ -303,5 +315,7 @@ void libnvml_loader::CleanUp(bool unload) {
nvmlUnitGetFanSpeedInfo = NULL;
nvmlUnitGetHandleByIndex = NULL;
nvmlDeviceGetFanSpeed = NULL;
nvmlDeviceGetFanSpeed_v2 = NULL;
nvmlDeviceGetMemoryInfo_v2 = NULL;
nvmlDeviceGetGraphicsRunningProcesses = NULL;
}
13 changes: 13 additions & 0 deletions src/loaders/loader_nvml.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ typedef nvmlProcessInfo_t nvmlProcessInfo_v1_t;
#endif
#define LIBRARY_LOADER_NVML_H_DLOPEN

#ifndef nvmlMemory_v2
typedef struct nvmlMemory_v2_st {
unsigned int version;
unsigned long long total;
unsigned long long reserved;
unsigned long long free;
unsigned long long used;
} nvmlMemory_v2_t;
#define nvmlMemory_v2 (unsigned int)(sizeof(nvmlMemory_v2_t) | (2 << 24U))
#endif

#include <string>
#include <dlfcn.h>
#include <memory>
Expand All @@ -36,6 +47,7 @@ class libnvml_loader {
decltype(&::nvmlDeviceGetHandleByIndex_v2) nvmlDeviceGetHandleByIndex_v2;
decltype(&::nvmlDeviceGetHandleByPciBusId_v2) nvmlDeviceGetHandleByPciBusId_v2;
decltype(&::nvmlDeviceGetMemoryInfo) nvmlDeviceGetMemoryInfo;
nvmlReturn_t (*nvmlDeviceGetMemoryInfo_v2)(nvmlDevice_t, nvmlMemory_v2_t*);
decltype(&::nvmlDeviceGetClockInfo) nvmlDeviceGetClockInfo;
decltype(&::nvmlErrorString) nvmlErrorString;
decltype(&::nvmlDeviceGetPowerUsage) nvmlDeviceGetPowerUsage;
Expand All @@ -44,6 +56,7 @@ class libnvml_loader {
decltype(&::nvmlUnitGetFanSpeedInfo) nvmlUnitGetFanSpeedInfo;
decltype(&::nvmlUnitGetHandleByIndex) nvmlUnitGetHandleByIndex;
decltype(&::nvmlDeviceGetFanSpeed) nvmlDeviceGetFanSpeed;
nvmlReturn_t (*nvmlDeviceGetFanSpeed_v2)(nvmlDevice_t, unsigned int, unsigned int*);
decltype(&::nvmlDeviceGetGraphicsRunningProcesses) nvmlDeviceGetGraphicsRunningProcesses;

private:
Expand Down
135 changes: 90 additions & 45 deletions src/nvidia.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,12 @@ void NVIDIA::get_instant_metrics_nvml(struct gpu_metrics *metrics, struct overla
nvmlReturn_t response;

if (nvml && nvml_available) {
nvml_get_process_info();
static const unsigned int slow_poll_divisor =
MAX(1u, (unsigned int)(NVML_SLOW_POLL_PERIOD_MS / METRICS_POLLING_PERIOD_MS));
const bool slow_tick = (slow_sample_counter == 0);
const bool log_active = (logger && logger->is_active());

slow_sample_counter = (slow_sample_counter + 1) % slow_poll_divisor;

struct nvmlUtilization_st nvml_utilization;
response = nvml->nvmlDeviceGetUtilizationRates(device, &nvml_utilization);
Expand All @@ -92,58 +97,98 @@ void NVIDIA::get_instant_metrics_nvml(struct gpu_metrics *metrics, struct overla

metrics->load = nvml_utilization.gpu;

if (params->enabled[OVERLAY_PARAM_ENABLED_gpu_temp] || (logger && logger->is_active())) {
unsigned int temp;
nvml->nvmlDeviceGetTemperature(device, NVML_TEMPERATURE_GPU, &temp);
metrics->temp = temp;
}
if (slow_tick) {
if (params->enabled[OVERLAY_PARAM_ENABLED_proc_vram] || log_active) {
nvml_get_process_info();
cached_slow_metrics.proc_vram_used = get_proc_vram() / (1024.f * 1024.f * 1024.f);
}

if (params->enabled[OVERLAY_PARAM_ENABLED_vram] || (logger && logger->is_active())) {
struct nvmlMemory_st nvml_memory;
nvml->nvmlDeviceGetMemoryInfo(device, &nvml_memory);
metrics->memoryTotal = nvml_memory.total / (1024.f * 1024.f * 1024.f);
metrics->sys_vram_used = nvml_memory.used / (1024.f * 1024.f * 1024.f);
}
if (params->enabled[OVERLAY_PARAM_ENABLED_gpu_temp] || log_active) {
unsigned int temp;
nvml->nvmlDeviceGetTemperature(device, NVML_TEMPERATURE_GPU, &temp);
cached_slow_metrics.temp = temp;
}

if (params->enabled[OVERLAY_PARAM_ENABLED_proc_vram])
metrics->proc_vram_used = get_proc_vram() / (1024.f * 1024.f * 1024.f);
if (params->enabled[OVERLAY_PARAM_ENABLED_vram] || log_active) {
const float to_gib = 1024.f * 1024.f * 1024.f;

if (params->enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock] || (logger && logger->is_active())) {
unsigned int core_clock;
nvml->nvmlDeviceGetClockInfo(device, NVML_CLOCK_GRAPHICS, &core_clock);
metrics->CoreClock = core_clock;
}
if (nvml->nvmlDeviceGetMemoryInfo_v2) {
nvmlMemory_v2_t nvml_memory_v2 {};
nvml_memory_v2.version = nvmlMemory_v2;

if (params->enabled[OVERLAY_PARAM_ENABLED_gpu_mem_clock] || (logger && logger->is_active())) {
unsigned int memory_clock;
nvml->nvmlDeviceGetClockInfo(device, NVML_CLOCK_MEM, &memory_clock);
metrics->MemClock = memory_clock;
}
if (nvml->nvmlDeviceGetMemoryInfo_v2(device, &nvml_memory_v2) == NVML_SUCCESS) {
cached_slow_metrics.memoryTotal = nvml_memory_v2.total / to_gib;
cached_slow_metrics.sys_vram_used = nvml_memory_v2.used / to_gib;
}
} else {
struct nvmlMemory_st nvml_memory;

if (params->enabled[OVERLAY_PARAM_ENABLED_gpu_power] || (logger && logger->is_active())) {
unsigned int power, limit;
nvml->nvmlDeviceGetPowerUsage(device, &power);
nvml->nvmlDeviceGetPowerManagementLimit(device, &limit);
metrics->powerUsage = power / 1000;
metrics->powerLimit = limit / 1000;
}
if (nvml->nvmlDeviceGetMemoryInfo(device, &nvml_memory) == NVML_SUCCESS) {
cached_slow_metrics.memoryTotal = nvml_memory.total / to_gib;
cached_slow_metrics.sys_vram_used = nvml_memory.used / to_gib;
}
}
}

if (params->enabled[OVERLAY_PARAM_ENABLED_throttling_status]) {
unsigned long long nvml_throttle_reasons;
nvml->nvmlDeviceGetCurrentClocksThrottleReasons(device, &nvml_throttle_reasons);
metrics->is_temp_throttled = (nvml_throttle_reasons & 0x0000000000000060LL) != 0;
metrics->is_power_throttled = (nvml_throttle_reasons & 0x000000000000008CLL) != 0;
metrics->is_other_throttled = (nvml_throttle_reasons & 0x0000000000000112LL) != 0;
if (throttling)
throttling->indep_throttle_status = nvml_throttle_reasons;
}
if (params->enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock] || log_active) {
unsigned int core_clock;
nvml->nvmlDeviceGetClockInfo(device, NVML_CLOCK_GRAPHICS, &core_clock);
cached_slow_metrics.CoreClock = core_clock;
}

if (params->enabled[OVERLAY_PARAM_ENABLED_gpu_fan] || (logger && logger->is_active())){
unsigned int fan_speed;
nvml->nvmlDeviceGetFanSpeed(device, &fan_speed);
metrics->fan_speed = fan_speed;
metrics->fan_rpm = false;
if (params->enabled[OVERLAY_PARAM_ENABLED_gpu_mem_clock] || log_active) {
unsigned int memory_clock;
nvml->nvmlDeviceGetClockInfo(device, NVML_CLOCK_MEM, &memory_clock);
cached_slow_metrics.MemClock = memory_clock;
}

if (params->enabled[OVERLAY_PARAM_ENABLED_gpu_power] || log_active) {
unsigned int power, limit;
nvml->nvmlDeviceGetPowerUsage(device, &power);
nvml->nvmlDeviceGetPowerManagementLimit(device, &limit);
cached_slow_metrics.powerUsage = power / 1000;
cached_slow_metrics.powerLimit = limit / 1000;
}

if (params->enabled[OVERLAY_PARAM_ENABLED_throttling_status]) {
unsigned long long nvml_throttle_reasons;
nvml->nvmlDeviceGetCurrentClocksThrottleReasons(device, &nvml_throttle_reasons);
cached_slow_metrics.is_temp_throttled = (nvml_throttle_reasons & 0x0000000000000060LL) != 0;
cached_slow_metrics.is_power_throttled = (nvml_throttle_reasons & 0x000000000000008CLL) != 0;
cached_slow_metrics.is_other_throttled = (nvml_throttle_reasons & 0x0000000000000112LL) != 0;
if (throttling)
throttling->indep_throttle_status = nvml_throttle_reasons;
}

if (params->enabled[OVERLAY_PARAM_ENABLED_gpu_fan] || log_active) {
unsigned int fan_speed;
nvmlReturn_t fan_response;

if (nvml->nvmlDeviceGetFanSpeed_v2)
fan_response = nvml->nvmlDeviceGetFanSpeed_v2(device, 0, &fan_speed);
else
fan_response = nvml->nvmlDeviceGetFanSpeed(device, &fan_speed);

if (fan_response == NVML_SUCCESS)
cached_slow_metrics.fan_speed = fan_speed;

cached_slow_metrics.fan_rpm = false;
}
}

metrics->proc_vram_used = cached_slow_metrics.proc_vram_used;
metrics->temp = cached_slow_metrics.temp;
metrics->memoryTotal = cached_slow_metrics.memoryTotal;
metrics->sys_vram_used = cached_slow_metrics.sys_vram_used;
metrics->CoreClock = cached_slow_metrics.CoreClock;
metrics->MemClock = cached_slow_metrics.MemClock;
metrics->powerUsage = cached_slow_metrics.powerUsage;
metrics->powerLimit = cached_slow_metrics.powerLimit;
metrics->is_temp_throttled = cached_slow_metrics.is_temp_throttled;
metrics->is_power_throttled = cached_slow_metrics.is_power_throttled;
metrics->is_other_throttled = cached_slow_metrics.is_other_throttled;
metrics->fan_speed = cached_slow_metrics.fan_speed;
metrics->fan_rpm = cached_slow_metrics.fan_rpm;
#ifdef HAVE_XNVCTRL
if (nvctrl_available) {
metrics->fan_rpm = true;
Expand Down
3 changes: 3 additions & 0 deletions src/nvidia.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ class NVIDIA {
#ifdef HAVE_NVML
nvmlDevice_t device;

unsigned int slow_sample_counter = 0;
gpu_metrics cached_slow_metrics {};

std::vector<nvmlProcessInfo_v1_t> process_info = {};

void get_instant_metrics_nvml(struct gpu_metrics *metrics, struct overlay_params *params);
Expand Down