make cpu wayyy cleaner
This commit is contained in:
236
src/gpu.cpp
236
src/gpu.cpp
@@ -6,100 +6,7 @@ have a gpu_t getGpu(std::string path, bool hasMetrics) function
|
||||
maybe have a read pp_table function
|
||||
|
||||
MAYBE PASS A POINTER TO SENSORS/SENSORS->GPU TO FUNCS
|
||||
|
||||
general order of operation
|
||||
1. [main] get hwmon path from the detectGpuHwmon func
|
||||
2. [main] check if we have gpu_metrics present and set hasMetrics accordingly
|
||||
3. [main, loop] keep calling getGpu with hasMetrics
|
||||
3. [gpu] getGpu called, parses whatever metrics we read from sysfs, then checks if hasMetrics == true
|
||||
- if true, reads file at (hwmon + REL_METRICS_PATH) into buf
|
||||
- reads first 4 bytes into GpuMetricsHeader_t with reinterpret_cast
|
||||
- parses them for format and content version
|
||||
- skips first 4 bytes of the buf and reinterpret_casts the rest into a correct gpu_metrics type (switch case?)
|
||||
- populates gpu_t with values from gpu_metrics
|
||||
- if false, reads the rest of relevant metrics from sysfs
|
||||
- returns gpu_t
|
||||
|
||||
*/
|
||||
|
||||
struct [[gnu::packed]] 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 [[gnu::packed]] 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");
|
||||
@@ -107,87 +14,60 @@ std::string detectGpuHwmon(std::string pci) {
|
||||
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
|
||||
bool checkForMetrics(std::string hwmon) {
|
||||
if (FILE* file = fopen((hwmon + REL_METRICS_PATH).c_str(), "r")) {
|
||||
fclose(file);
|
||||
std::println("[GpuMetrics] found metrics file");
|
||||
return true;
|
||||
}
|
||||
|
||||
return header;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* will return empty metric if fails */
|
||||
auto getGpuMetrics(GpuMetricsHeader_t h, std::string path) {
|
||||
GpuMetrics_v1_3_t metrics;
|
||||
// void* raw_data;
|
||||
uint8_t rev = h.format_revision * 10 + h.content_revision;
|
||||
// const auto* metrics = reinterpret_cast<const GpuMetrics_v1_3_t*>(raw_data); // raw data is actual metrics read from disk
|
||||
|
||||
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 getGpuFromMetrics(std::string hwmon) {
|
||||
gpu_t gpu;
|
||||
uint8_t hwmon = 4;
|
||||
char raw_metrics[MAX_METRICS_LENGTH];
|
||||
if(!readFile2(hwmon + REL_METRICS_PATH, raw_metrics, sizeof(raw_metrics))) return gpu; // return empty struct if cant read metrics
|
||||
auto header = reinterpret_cast<gpu::metrics_table_header*>(raw_metrics);
|
||||
|
||||
// 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(hwmon + "/pwm1", 4)) * 100 / 256; // 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"));
|
||||
switch (header->format_revision * 10 + header->content_revision) {
|
||||
|
||||
auto metrics = getGpuMetrics(header, hw + "/gpu_metrics");
|
||||
/* rx7800xt */
|
||||
case 13: {
|
||||
auto metrics = reinterpret_cast<gpu::gpu_metrics_v1_3*>(raw_metrics);
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
||||
// 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"));
|
||||
/* ryzen 5 5600g */
|
||||
case 22: {
|
||||
auto metrics = reinterpret_cast<gpu::gpu_metrics_v2_2*>(raw_metrics);
|
||||
gpu.edge_temp = metrics->temperature_gfx / 100;
|
||||
gpu.power_avg = metrics->average_gfx_power;
|
||||
gpu.core_usage = metrics->average_gfx_activity;
|
||||
break;
|
||||
}
|
||||
|
||||
/* werid hardware i probably dont like */
|
||||
default: {
|
||||
std::println("[GpuMetrics] Unsupported gpu_metrics_v{}_{}", header->format_revision, header->content_revision);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (gpu.fan_speed > 9999)
|
||||
gpu.fan_speed = 9999;
|
||||
|
||||
return gpu;
|
||||
}
|
||||
|
||||
gpu_t getGpu(std::string hwmon, bool hasMetrics) {
|
||||
gpu_t getGpuFromFs(std::string hwmon) {
|
||||
gpu_t gpu;
|
||||
|
||||
// these are always read from fs
|
||||
@@ -195,21 +75,23 @@ gpu_t getGpu(std::string hwmon, bool hasMetrics) {
|
||||
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(hwmon + "/pwm1", 4)) * 100 / 256;
|
||||
gpu.fan_pwm = std::stoi(readFile(hwmon + "/pwm1", 4)) * 100 / 256;
|
||||
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?
|
||||
if (!hasMetrics) {
|
||||
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;
|
||||
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"));
|
||||
|
||||
return gpu;
|
||||
}
|
||||
}
|
||||
|
||||
gpu_t getGpu(std::string hwmon, bool hasMetrics) {
|
||||
if (hasMetrics) {
|
||||
return getGpuFromMetrics(hwmon);
|
||||
} else {
|
||||
return getGpuFromFs(hwmon);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user