intel / pcm

Intel® Performance Counter Monitor (Intel® PCM)
BSD 3-Clause "New" or "Revised" License
2.75k stars 469 forks source link

How to get CPU power? #800

Closed artiomn closed 1 month ago

artiomn commented 1 month ago

I need to get CPU power and using PCM for this task in a similar way:

CpuPower::CpuPower(uint32_t cpu_sock_no) : cpu_sock_no_(cpu_sock_no), pcm_instance_(pcm::PCM::getInstance())
{
    assert(pcm_instance_);
    // This is the instance, memory releasing doesn't need.
    const pcm::PCM::ErrorCode status = pcm_instance_->program(pcm::PCM::DEFAULT_EVENTS, nullptr, true, ::getpid());

    try
    {
        check_pcm_status(status);
        get_power();
    }
    catch (const std::logic_error& e)
    {
        SPDLOG_WARN("Error during power consumption counter init: {}", e.what());
    }
}

float CpuPower::get_power()
{
    if (!pcm_instance_->packageEnergyMetricsAvailable())
    {
        throw std::logic_error("Energy metrics unavailable!");
    }

    std::swap(sktstate1_, sktstate2_);

    sktstate1_ = pcm_instance_->PCM::getSocketCounterState(cpu_sock_no_);
    // pcm_instance_->getAllCounterStates(sstate2_, sktstate2_, cstates2_);
    const auto time_now = std::chrono::steady_clock::now();
    const auto consumed_joules = pcm::getConsumedJoules(sktstate2_, sktstate1_);
    const auto consumed_watts =
        consumed_joules / std::chrono::duration_cast<std::chrono::seconds>(time_now - time_start_).count();

    SPDLOG_DEBUG("CPU, Joules = {}, Watts = {}", consumed_joules, consumed_watts);

    time_start_ = time_now;

    return consumed_watts;
}

All is ok (under Linux, at least), but there is two problems:

Is it possible to get power not under the root and get power per CPU core?

rdementi commented 1 month ago

It is possible to get some PCM metrics as non-root user (pcm uses standard Linux APIs then). But not all metrics are exposed by Linux APIs.. Please check out this: https://github.com/intel/pcm/?tab=readme-ov-file#executing-pcm-tools-under-non-root-user-on-linux

Is it possible to get power not under the root

not aware of such method. Even the Linux sysfs API for that (/sys/class/powercap/*/energy_uj) is only for root ("-r--------")

Is it possible to get power per CPU core?

Client (Desktop/Laptop) CPUs have MSRs for PKG (package power), PP0 (all cores), PP1 (uncore). But there is no per-core power MSR on client and server processors.

artiomn commented 1 month ago

Ok, I understood. Thank you. Maybe a daemon will solve this problem (but it's not very suitable for my project right now).