|
1 | 1 | #include "gpu_fdinfo.h" |
| 2 | +#include "file_utils.h" |
2 | 3 |
|
3 | 4 | #ifndef TEST_ONLY |
4 | 5 | #include "hud_elements.h" |
@@ -303,8 +304,96 @@ void GPU_fdinfo::get_current_hwmon_readings() |
303 | 304 | } |
304 | 305 | } |
305 | 306 |
|
| 307 | +void GPU_fdinfo::find_intel_gpu_rapl_power() |
| 308 | +{ |
| 309 | + std::string powercap = "/sys/class/powercap/"; |
| 310 | + auto powercap_dirs = ls(powercap.c_str()); |
| 311 | + |
| 312 | + for (auto& dir : powercap_dirs) { |
| 313 | + auto path = powercap + dir; |
| 314 | + auto name = read_line(path + "/name"); |
| 315 | + |
| 316 | + if (name != "uncore") |
| 317 | + continue; |
| 318 | + |
| 319 | + auto energy_path = path + "/energy_uj"; |
| 320 | + auto energy_stream = std::ifstream(energy_path); |
| 321 | + |
| 322 | + if (!energy_stream.good()) { |
| 323 | + SPDLOG_DEBUG( |
| 324 | + "powercap: Intel GPU RAPL energy is not accessible at {}", |
| 325 | + energy_path |
| 326 | + ); |
| 327 | + continue; |
| 328 | + } |
| 329 | + |
| 330 | + intel_gpu_rapl_energy_stream = std::move(energy_stream); |
| 331 | + |
| 332 | + try { |
| 333 | + auto max_energy_range = read_line(path + "/max_energy_range_uj"); |
| 334 | + if (!max_energy_range.empty()) |
| 335 | + intel_gpu_rapl_max_energy_range_uj = std::stoull(max_energy_range); |
| 336 | + } catch (...) { |
| 337 | + intel_gpu_rapl_max_energy_range_uj = 0; |
| 338 | + } |
| 339 | + |
| 340 | + SPDLOG_DEBUG("powercap: using Intel GPU RAPL energy at {}", energy_path); |
| 341 | + return; |
| 342 | + } |
| 343 | +} |
| 344 | + |
| 345 | +bool GPU_fdinfo::read_intel_gpu_rapl_energy(uint64_t& energy_uj) |
| 346 | +{ |
| 347 | + if (!intel_gpu_rapl_energy_stream.is_open()) |
| 348 | + return false; |
| 349 | + |
| 350 | + intel_gpu_rapl_energy_stream.clear(); |
| 351 | + intel_gpu_rapl_energy_stream.seekg(0); |
| 352 | + |
| 353 | + std::string energy; |
| 354 | + std::getline(intel_gpu_rapl_energy_stream, energy); |
| 355 | + |
| 356 | + if (energy.empty()) |
| 357 | + return false; |
| 358 | + |
| 359 | + try { |
| 360 | + energy_uj = std::stoull(energy); |
| 361 | + } catch (...) { |
| 362 | + return false; |
| 363 | + } |
| 364 | + |
| 365 | + return true; |
| 366 | +} |
| 367 | + |
| 368 | +float GPU_fdinfo::get_intel_gpu_rapl_power_usage() |
| 369 | +{ |
| 370 | + uint64_t now = 0; |
| 371 | + if (!read_intel_gpu_rapl_energy(now)) |
| 372 | + return 0.f; |
| 373 | + |
| 374 | + if (!intel_gpu_rapl_energy_initialized) { |
| 375 | + intel_gpu_rapl_last_energy_uj = now; |
| 376 | + intel_gpu_rapl_energy_initialized = true; |
| 377 | + return 0.f; |
| 378 | + } |
| 379 | + |
| 380 | + uint64_t delta = 0; |
| 381 | + if (now >= intel_gpu_rapl_last_energy_uj) { |
| 382 | + delta = now - intel_gpu_rapl_last_energy_uj; |
| 383 | + } else if (intel_gpu_rapl_max_energy_range_uj > intel_gpu_rapl_last_energy_uj) { |
| 384 | + delta = intel_gpu_rapl_max_energy_range_uj - intel_gpu_rapl_last_energy_uj + now; |
| 385 | + } |
| 386 | + |
| 387 | + intel_gpu_rapl_last_energy_uj = now; |
| 388 | + |
| 389 | + return (static_cast<float>(delta) / (METRICS_UPDATE_PERIOD_MS / 1000.f)) / 1'000'000; |
| 390 | +} |
| 391 | + |
306 | 392 | float GPU_fdinfo::get_power_usage() |
307 | 393 | { |
| 394 | + if ((module == "i915" || module == "xe") && intel_gpu_rapl_energy_stream.is_open()) |
| 395 | + return get_intel_gpu_rapl_power_usage(); |
| 396 | + |
308 | 397 | if (!hwmon_sensors["power"].filename.empty()) |
309 | 398 | return static_cast<float>(hwmon_sensors["power"].val) / 1'000'000; |
310 | 399 |
|
|
0 commit comments