Files
linuxSmartie/src/gpu.cpp

189 lines
7.3 KiB
C++

#include <gpu.hpp>
struct GpuMetrics_v1_1_t {
uint16_t temperature_edge;
uint16_t temperature_hotspot;
uint16_t temperature_mem;
uint16_t temperature_vrgfx;
uint16_t temperature_vrsoc;
uint16_t temperature_vrmem;
uint16_t average_gfx_activity;
uint16_t average_umc_activity;
uint16_t average_mm_activity;
uint16_t average_socket_power;
uint64_t energy_accumulator;
uint64_t system_clock_counter;
uint16_t average_gfxclk_frequency;
uint16_t average_socclk_frequency;
uint16_t average_uclk_frequency;
uint16_t average_vclk0_frequency;
uint16_t average_dclk0_frequency;
uint16_t average_vclk1_frequency;
uint16_t average_dclk1_frequency;
uint16_t current_gfxclk;
uint16_t current_socclk;
uint16_t current_uclk;
uint16_t current_vclk0;
uint16_t current_dclk0;
uint16_t current_vclk1;
uint16_t current_dclk1;
uint32_t throttle_status;
uint16_t current_fan_speed;
uint16_t pcie_link_width;
uint16_t pcie_link_speed;
uint16_t padding;
uint32_t gfx_activity_acc;
uint32_t mem_activity_acc;
uint16_t temperature_hbm;
};
struct GpuMetrics_v1_3_t {
uint16_t temperature_edge;
uint16_t temperature_hotspot;
uint16_t temperature_mem;
uint16_t temperature_vrgfx;
uint16_t temperature_vrsoc;
uint16_t temperature_vrmem;
uint16_t average_gfx_activity;
uint16_t average_umc_activity;
uint16_t average_mm_activity;
uint16_t average_socket_power;
uint64_t energy_accumulator;
uint64_t system_clock_counter;
uint16_t average_gfxclk_frequency;
uint16_t average_socclk_frequency;
uint16_t average_uclk_frequency;
uint16_t average_vclk0_frequency;
uint16_t average_dclk0_frequency;
uint16_t average_vclk1_frequency;
uint16_t average_dclk1_frequency;
uint16_t current_gfxclk;
uint16_t current_socclk;
uint16_t current_uclk;
uint16_t current_vclk0;
uint16_t current_dclk0;
uint16_t current_vclk1;
uint16_t current_dclk1;
uint32_t throttle_status;
uint16_t current_fan_speed;
uint16_t pcie_link_width;
uint16_t pcie_link_speed;
uint16_t padding;
uint32_t gfx_activity_acc;
uint32_t mem_activity_acc;
uint16_t temperature_hbm;
uint64_t firmware_timestamp;
uint16_t voltage_soc;
uint16_t voltage_gfx;
uint16_t voltage_mem;
uint8_t padding1;
};
std::string detectGpuHwmon(std::string pci) {
std::string path = getFirstDir("/sys/bus/pci/devices/" + pci + "/hwmon");
std::println("[GpuHwmon] Detected path \"{}\"", path);
return path;
}
GpuMetricsHeader_t getGpuMetricsHeader(std::string path) {
GpuMetricsHeader_t header;
std::ifstream f(path, std::ios::binary);
if (f.good()) {
f.read(reinterpret_cast<char *>(&header), sizeof(header));
std::println("[GpuMetrics] header at path {} read, GpuMetrics_v{}_{}, size {}", path, header.format_revision, header.content_revision, header.structure_size);
f.close();
} else {
std::println("[GpuMetrics] error reading header at path {} (wrong card # ?)", path); // should be err
}
return header;
}
/* will return empty metric if fails */
auto getGpuMetrics(GpuMetricsHeader_t h, std::string path) {
GpuMetrics_v1_3_t metrics;
uint8_t rev = h.format_revision * 10 + h.content_revision;
switch (rev) {
case 13: {
std::ifstream f(path, std::ios::binary);
if (f.good()) {
f.ignore(sizeof(h)); // skip header
f.read(reinterpret_cast<char *>(&metrics), sizeof(metrics));
f.close();
}
} break;
}
return metrics;
}
// clean abstraction of gpu_metrics + extra metrics from fs, works with rx7800xt
gpu_t getGpu(GpuMetricsHeader_t header, std::string hw) {
gpu_t gpu;
uint8_t hwmon = 3;
// these are always read from fs
gpu.fan_speed = std::stol(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/fan1_input"));
gpu.vcore = std::stol(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/in0_input")) / 1000.0;
gpu.power_cap = std::stol(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/power1_cap", 3));
gpu.power_max = std::stol(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/power1_cap_max", 3));
// gpu.fan_pwm = std::stoi(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon)+ "/pwm1")); // not super useful
gpu.vram_used = std::stoul(readFile(hw + "/mem_info_vram_used"));
gpu.vram_total = std::stoul(readFile(hw + "/mem_info_vram_total"));
auto metrics = getGpuMetrics(header, hw + "/gpu_metrics");
// check if metrics valid, if not use fs
if (header.structure_size != 0) {
gpu.core_clock = metrics.average_vclk1_frequency; // why not gfxclock?
gpu.mem_clock = metrics.average_gfxclk_frequency; // why gfxclock? min mem clock seems to be 96mhz, this is probably including time sleeping
gpu.core_usage = metrics.average_gfx_activity;
gpu.media_usage = metrics.average_mm_activity;
gpu.umc_usage = metrics.average_umc_activity;
gpu.edge_temp = metrics.temperature_edge;
gpu.hotspot_temp = metrics.temperature_hotspot;
gpu.mem_temp = metrics.temperature_mem;
gpu.gfx_vrm_temp = metrics.temperature_vrgfx;
gpu.soc_vrm_temp = metrics.temperature_vrsoc;
gpu.mem_vrm_temp = metrics.temperature_vrmem;
gpu.power_avg = metrics.average_socket_power;
} else {
gpu.core_clock = std::stoll(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/freq1_input", 16)) / 1000000;
gpu.mem_clock = std::stoll(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/freq2_input", 16)) / 1000000;
gpu.vcore = std::stod(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/in0_input", 8)) / 1000.0;
gpu.power_avg = std::stol(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/power1_input", 3));
gpu.edge_temp = std::stol(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/temp1_input", 2));
gpu.core_usage = std::stoi(readFile(hw + "/gpu_busy_percent"));
}
if (gpu.fan_speed > 9999)
gpu.fan_speed = 9999;
return gpu;
}
gpu_t getGpu(std::string hwmon) {
gpu_t gpu;
// these are always read from fs
gpu.fan_speed = std::stol(readFile(hwmon + "/fan1_input", 4));
gpu.vcore = std::stol(readFile(hwmon + "/in0_input", 4)) / 1000.0;
gpu.power_cap = std::stol(readFile(hwmon + "/power1_cap", 16)) / 1000000;
// gpu.power_max = std::stol(readFile(hwmon + "/power1_cap_max", 16)) / 1000000;
// gpu.fan_pwm = std::stoi(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon)+ "/pwm1")); // not super useful
gpu.vram_used = std::stoul(readFile(hwmon + "/../../mem_info_vram_used", 16));
// gpu.vram_total = std::stoul(readFile(hwmon + "/../../mem_info_vram_total", 16));
// these also exist in gpu_metrics?
gpu.core_clock = std::stoll(readFile(hwmon + "/freq1_input", 16)) / 1000000;
gpu.mem_clock = std::stoll(readFile(hwmon + "/freq2_input", 16)) / 1000000;
gpu.power_avg = std::stol(readFile(hwmon + "/power1_input", 16)) / 1000000;
gpu.edge_temp = std::stol(readFile(hwmon + "/temp1_input", 2));
gpu.core_usage = std::stoi(readFile(hwmon + "/../../gpu_busy_percent"));
if (gpu.fan_speed > 9999)
gpu.fan_speed = 9999;
return gpu;
}