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
126 changes: 27 additions & 99 deletions src/amdgpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
#include "amdgpu.h"
#include "gpu.h"
#include "cpu.h"
#include "file_utils.h"
#include "overlay.h"
#include "hud_elements.h"
#include "logging.h"
#include "mesa/util/macros.h"


#define IS_VALID_METRIC(FIELD) (FIELD != 0xffff)
void AMDGPU::get_instant_metrics(struct amdgpu_common_metrics *metrics) {
FILE *f;
Expand Down Expand Up @@ -317,24 +317,11 @@ void AMDGPU::metrics_polling_thread() {
}

void AMDGPU::get_sysfs_metrics() {
int64_t value = 0;
if (sysfs_nodes.busy) {
rewind(sysfs_nodes.busy);
fflush(sysfs_nodes.busy);
int value = 0;
if (fscanf(sysfs_nodes.busy, "%d", &value) != 1)
value = 0;
metrics.load = value;
}
if (sysfs_nodes.busy)
metrics.load = read_as<int>(sysfs_nodes.busy).value_or(0);

if (sysfs_nodes.memory_clock) {
rewind(sysfs_nodes.memory_clock);
fflush(sysfs_nodes.memory_clock);
if (fscanf(sysfs_nodes.memory_clock, "%" PRId64, &value) != 1)
value = 0;

metrics.MemClock = value / 1000000;
}
if (sysfs_nodes.memory_clock)
metrics.MemClock = read_as<int64_t>(sysfs_nodes.memory_clock).value_or(0) / 1000000;

// TODO: on some gpus this will use the power1_input instead
// this value is instantaneous and should be averaged over time
Expand All @@ -346,14 +333,8 @@ void AMDGPU::get_sysfs_metrics() {
metrics.powerUsage = 0;
} else
#endif
if (sysfs_nodes.power_usage) {
rewind(sysfs_nodes.power_usage);
fflush(sysfs_nodes.power_usage);
if (fscanf(sysfs_nodes.power_usage, "%" PRId64, &value) != 1)
value = 0;

metrics.powerUsage = value / 1000000;
}
if (sysfs_nodes.power_usage)
metrics.powerUsage = read_as<int64_t>(sysfs_nodes.power_usage).value_or(0) / 1000000;

#ifndef TEST_ONLY
if (!get_params()->enabled[OVERLAY_PARAM_ENABLED_gpu_power_limit]) {
Expand All @@ -362,92 +343,39 @@ void AMDGPU::get_sysfs_metrics() {
metrics.powerLimit = 0;
} else
#endif
if (sysfs_nodes.power_limit) {
rewind(sysfs_nodes.power_limit);
fflush(sysfs_nodes.power_limit);
if (fscanf(sysfs_nodes.power_limit, "%" PRId64, &value) != 1)
value = 0;

metrics.powerLimit = value / 1000000;
}
if (sysfs_nodes.power_limit)
metrics.powerLimit = read_as<int64_t>(sysfs_nodes.power_limit).value_or(0) / 1000000;

if (sysfs_nodes.fan) {
rewind(sysfs_nodes.fan);
fflush(sysfs_nodes.fan);
if (fscanf(sysfs_nodes.fan, "%" PRId64, &value) != 1)
value = 0;
metrics.fan_speed = value;
metrics.fan_speed = read_as<int64_t>(sysfs_nodes.fan).value_or(0);
metrics.fan_rpm = true;
}

if (sysfs_nodes.vram_total) {
rewind(sysfs_nodes.vram_total);
fflush(sysfs_nodes.vram_total);
if (fscanf(sysfs_nodes.vram_total, "%" PRId64, &value) != 1)
value = 0;
metrics.memoryTotal = float(value) / (1024 * 1024 * 1024);
}
if (sysfs_nodes.vram_total)
metrics.memoryTotal = float(read_as<int64_t>(sysfs_nodes.vram_total).value_or(0)) / (1024 * 1024 * 1024);

if (sysfs_nodes.vram_used)
metrics.sys_vram_used = float(read_as<int64_t>(sysfs_nodes.vram_used).value_or(0)) / (1024 * 1024 * 1024);

if (sysfs_nodes.vram_used) {
rewind(sysfs_nodes.vram_used);
fflush(sysfs_nodes.vram_used);
if (fscanf(sysfs_nodes.vram_used, "%" PRId64, &value) != 1)
value = 0;
metrics.sys_vram_used = float(value) / (1024 * 1024 * 1024);
}
// On some GPUs SMU can sometimes return the wrong temperature.
// As HWMON is way more visible than the SMU metrics, let's always trust it as it is the most likely to work
if (sysfs_nodes.core_clock) {
rewind(sysfs_nodes.core_clock);
fflush(sysfs_nodes.core_clock);
if (fscanf(sysfs_nodes.core_clock, "%" PRId64, &value) != 1)
value = 0;
if (sysfs_nodes.core_clock)
metrics.CoreClock = read_as<int64_t>(sysfs_nodes.core_clock).value_or(0) / 1000000;

metrics.CoreClock = value / 1000000;
}
if (sysfs_nodes.temp)
metrics.temp = read_as<int>(sysfs_nodes.temp).value_or(0) / 1000;

if (sysfs_nodes.temp){
rewind(sysfs_nodes.temp);
fflush(sysfs_nodes.temp);
int value = 0;
if (fscanf(sysfs_nodes.temp, "%d", &value) != 1)
value = 0;
metrics.temp = value / 1000;
}
if (sysfs_nodes.junction_temp)
metrics.junction_temp = read_as<int>(sysfs_nodes.junction_temp).value_or(0) / 1000;

if (sysfs_nodes.junction_temp){
rewind(sysfs_nodes.junction_temp);
fflush(sysfs_nodes.junction_temp);
int value = 0;
if (fscanf(sysfs_nodes.junction_temp, "%d", &value) != 1)
value = 0;
metrics.junction_temp = value / 1000;
}
if (sysfs_nodes.memory_temp)
metrics.memory_temp = read_as<int>(sysfs_nodes.memory_temp).value_or(0) / 1000;

if (sysfs_nodes.memory_temp){
rewind(sysfs_nodes.memory_temp);
fflush(sysfs_nodes.memory_temp);
int value = 0;
if (fscanf(sysfs_nodes.memory_temp, "%d", &value) != 1)
value = 0;
metrics.memory_temp = value / 1000;
}

if (sysfs_nodes.gtt_used) {
rewind(sysfs_nodes.gtt_used);
fflush(sysfs_nodes.gtt_used);
if (fscanf(sysfs_nodes.gtt_used, "%" PRId64, &value) != 1)
value = 0;
metrics.gtt_used = float(value) / (1024 * 1024 * 1024);
}
if (sysfs_nodes.gtt_used)
metrics.gtt_used = float(read_as<int64_t>(sysfs_nodes.gtt_used).value_or(0)) / (1024 * 1024 * 1024);

if (sysfs_nodes.gpu_voltage_soc) {
rewind(sysfs_nodes.gpu_voltage_soc);
fflush(sysfs_nodes.gpu_voltage_soc);
if (fscanf(sysfs_nodes.gpu_voltage_soc, "%" PRId64, &value) != 1)
value = 0;
metrics.voltage = value;
}
if (sysfs_nodes.gpu_voltage_soc)
metrics.voltage = read_as<int64_t>(sysfs_nodes.gpu_voltage_soc).value_or(0);
}

AMDGPU::AMDGPU(std::string pci_dev, uint32_t device_id, uint32_t vendor_id) {
Expand Down
101 changes: 35 additions & 66 deletions src/cpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,12 +282,8 @@ bool CPUStats::ReadcpuTempFile(int& temp) {
if (!m_cpuTempFile)
return false;

rewind(m_cpuTempFile);
fflush(m_cpuTempFile);
bool ret = (fscanf(m_cpuTempFile, "%d", &temp) == 1);
temp = temp / 1000;

return ret;
temp = read_as<int>(m_cpuTempFile).value_or(0) / 1000;
return temp == 0;
}

bool CPUStats::UpdateCpuTemp() {
Expand All @@ -312,44 +308,32 @@ static bool get_cpu_power_k10temp(CPUPowerData* cpuPowerData, float& power) {

if(powerData_k10temp->corePowerFile || powerData_k10temp->socPowerFile)
{
rewind(powerData_k10temp->corePowerFile);
rewind(powerData_k10temp->socPowerFile);
fflush(powerData_k10temp->corePowerFile);
fflush(powerData_k10temp->socPowerFile);
int corePower, socPower;
if (fscanf(powerData_k10temp->corePowerFile, "%d", &corePower) != 1)
goto voltagebased;
if (fscanf(powerData_k10temp->socPowerFile, "%d", &socPower) != 1)
goto voltagebased;
power = (corePower + socPower) / 1000000;
return true;
auto const corePower = read_as<int>(powerData_k10temp->corePowerFile);
auto const socPower = read_as<int>(powerData_k10temp->socPowerFile);
if (corePower and socPower) {
power = (corePower.value() + socPower.value()) / 1000000;
return true;
}
}
voltagebased:

if (!powerData_k10temp->coreVoltageFile || !powerData_k10temp->coreCurrentFile || !powerData_k10temp->socVoltageFile || !powerData_k10temp->socCurrentFile)
return false;
rewind(powerData_k10temp->coreVoltageFile);
rewind(powerData_k10temp->coreCurrentFile);
rewind(powerData_k10temp->socVoltageFile);
rewind(powerData_k10temp->socCurrentFile);

fflush(powerData_k10temp->coreVoltageFile);
fflush(powerData_k10temp->coreCurrentFile);
fflush(powerData_k10temp->socVoltageFile);
fflush(powerData_k10temp->socCurrentFile);

int coreVoltage, coreCurrent;
int socVoltage, socCurrent;

if (fscanf(powerData_k10temp->coreVoltageFile, "%d", &coreVoltage) != 1)
auto const coreVoltage = read_as<int>(powerData_k10temp->coreVoltageFile);
if (not coreVoltage)
return false;
if (fscanf(powerData_k10temp->coreCurrentFile, "%d", &coreCurrent) != 1)
auto const coreCurrent = read_as<int>(powerData_k10temp->coreCurrentFile);
if (not coreCurrent)
return false;
if (fscanf(powerData_k10temp->socVoltageFile, "%d", &socVoltage) != 1)
auto const socVoltage = read_as<int>(powerData_k10temp->socVoltageFile);
if (not socVoltage)
return false;
if (fscanf(powerData_k10temp->socCurrentFile, "%d", &socCurrent) != 1)
auto const socCurrent = read_as<int>(powerData_k10temp->socCurrentFile);
if (not socCurrent)
return false;

power = (coreVoltage * coreCurrent + socVoltage * socCurrent) / 1000000;
power = (coreVoltage.value() * coreCurrent.value() +
socVoltage.value() * socCurrent.value()) / 1000000;

return true;
}
Expand All @@ -360,20 +344,14 @@ static bool get_cpu_power_zenpower(CPUPowerData* cpuPowerData, float& power) {
if (!powerData_zenpower->corePowerFile || !powerData_zenpower->socPowerFile)
return false;

rewind(powerData_zenpower->corePowerFile);
rewind(powerData_zenpower->socPowerFile);

fflush(powerData_zenpower->corePowerFile);
fflush(powerData_zenpower->socPowerFile);

int corePower, socPower;

if (fscanf(powerData_zenpower->corePowerFile, "%d", &corePower) != 1)
auto const corePower = read_as<int>(powerData_zenpower->corePowerFile);
if (not corePower)
return false;
if (fscanf(powerData_zenpower->socPowerFile, "%d", &socPower) != 1)
auto const socPower = read_as<int>(powerData_zenpower->socPowerFile);
if (not socPower)
return false;

power = (corePower + socPower) / 1000000;
power = (corePower.value() + socPower.value()) / 1000000;

return true;
}
Expand All @@ -383,23 +361,20 @@ static bool get_cpu_power_zenergy(CPUPowerData* cpuPowerData, float& power) {
if (!powerData_zenergy->energyCounterFile)
return false;

rewind(powerData_zenergy->energyCounterFile);
fflush(powerData_zenergy->energyCounterFile);

uint64_t energyCounterValue = 0;
if (fscanf(powerData_zenergy->energyCounterFile, "%" SCNu64, &energyCounterValue) != 1)
auto const energyCounterValue = read_as<uint64_t>(powerData_zenergy->energyCounterFile);
if (not energyCounterValue)
return false;

Clock::time_point now = Clock::now();
Clock::duration timeDiff = now - powerData_zenergy->lastCounterValueTime;
int64_t timeDiffMicro = std::chrono::duration_cast<std::chrono::microseconds>(timeDiff).count();
uint64_t energyCounterDiff = energyCounterValue - powerData_zenergy->lastCounterValue;
uint64_t energyCounterDiff = energyCounterValue.value() - powerData_zenergy->lastCounterValue;


if (powerData_zenergy->lastCounterValue > 0 && energyCounterValue > powerData_zenergy->lastCounterValue)
power = (float) energyCounterDiff / (float) timeDiffMicro;

powerData_zenergy->lastCounterValue = energyCounterValue;
powerData_zenergy->lastCounterValue = energyCounterValue.value();
powerData_zenergy->lastCounterValueTime = now;

return true;
Expand All @@ -411,22 +386,19 @@ static bool get_cpu_power_rapl(CPUPowerData* cpuPowerData, float& power) {
if (!powerData_rapl->energyCounterFile)
return false;

rewind(powerData_rapl->energyCounterFile);
fflush(powerData_rapl->energyCounterFile);

uint64_t energyCounterValue = 0;
if (fscanf(powerData_rapl->energyCounterFile, "%" SCNu64, &energyCounterValue) != 1)
auto const energyCounterValue = read_as<uint64_t>(powerData_rapl->energyCounterFile);
if (not energyCounterValue)
return false;

Clock::time_point now = Clock::now();
Clock::duration timeDiff = now - powerData_rapl->lastCounterValueTime;
int64_t timeDiffMicro = std::chrono::duration_cast<std::chrono::microseconds>(timeDiff).count();
uint64_t energyCounterDiff = energyCounterValue - powerData_rapl->lastCounterValue;
uint64_t energyCounterDiff = energyCounterValue.value() - powerData_rapl->lastCounterValue;

if (powerData_rapl->lastCounterValue > 0 && energyCounterValue > powerData_rapl->lastCounterValue)
power = energyCounterDiff / timeDiffMicro;

powerData_rapl->lastCounterValue = energyCounterValue;
powerData_rapl->lastCounterValue = energyCounterValue.value();
powerData_rapl->lastCounterValueTime = now;

return true;
Expand All @@ -448,14 +420,11 @@ static bool get_cpu_power_xgene(CPUPowerData* cpuPowerData, float& power) {
if (!powerData_xgene->powerFile)
return false;

rewind(powerData_xgene->powerFile);
fflush(powerData_xgene->powerFile);

uint64_t powerValue = 0;
if (fscanf(powerData_xgene->powerFile, "%" SCNu64, &powerValue) != 1)
auto const powerValue = read_as<uint64_t>(powerData_xgene->powerFile);
if (not powerValue)
return false;

power = (float) powerValue / 1000000.0f;
power = (float) powerValue.value() / 1000000.0f;

return true;
}
Expand Down
18 changes: 12 additions & 6 deletions src/file_utils.cpp
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
#include "file_utils.h"
#include "string_utils.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <limits.h>
#include <fstream>

#include <cstring>
#include <fstream>
#include <regex>
#include <string>

#include <dirent.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <spdlog/spdlog.h>

#ifndef PROCDIR
#define PROCDIR "/proc"
#endif

namespace fs = ghc::filesystem;

std::string read_line(const std::string& filename)
{
std::string line;
Expand Down
Loading