Skip to content
Snippets Groups Projects
Select Git revision
  • 3dcea9061574c4959f031e8500d93e70f70ed1cb
  • master default protected
  • optimize_workflow
  • poppy_integration_v50
  • poppy_integration
  • releases/v5.0 protected
  • use-versioned-releases
  • releases/v5.0rc2 protected
  • releases/v5.0rc1 protected
  • releases/ldv_v407_atdb protected
  • ldv_v407_debug
  • releases/ldv_v406_debug protected
  • releases/ldv_v405 protected
  • releases/ldv_v404 protected
  • v5.0
  • v5.0rc2
  • v5.0rc1
  • ldv_v406_debug
  • ldv_v405_debug
  • ldv_v404
  • ldv_v403
  • ldv_v402
  • v4.0
  • ldv_v401
  • ldv_v40
  • ldv_v031
  • ldv_v03
  • ldv_v01
28 results

linc_calibrator.cwl

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    RaplImpl.cpp 6.71 KiB
    #include <algorithm>
    #include <iostream>
    #include <fstream>
    #include <stdexcept>
    
    #include <unistd.h>
    
    #include "RaplImpl.h"
    
    namespace {
    std::vector<int> GetActiveCPUs() {
      cpu_set_t cpu_set;
      CPU_ZERO(&cpu_set);
    
      const int result = sched_getaffinity(0, sizeof(cpu_set), &cpu_set);
      if (result == -1) {
        throw std::system_error(errno, std::generic_category(),
                                "sched_getaffinity");
      }
    
      const int n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
    
      std::vector<int> active_cpus;
      for (int cpu = 0; cpu < n_cpus; ++cpu) {
        if (CPU_ISSET(cpu, &cpu_set)) {
          active_cpus.push_back(cpu);
        }
      }
    
      return active_cpus;
    }
    
    template <typename T>
    void RemoveDuplicates(std::vector<T>& v) {
      std::sort(v.begin(), v.end());
      v.erase(std::unique(v.begin(), v.end()), v.end());
    }
    }  // namespace
    
    namespace pmt::rapl {
    
    RaplState::operator pmt::State() {
      State state;
      state.timeAtRead = timeAtRead;
      state.joulesAtRead = consumedEnergyTotal;
      state.misc.reserve(measurements.size());
      for (size_t i = 0; i < measurements.size(); i++) {
        const rapl::RaplMeasurement& m = measurements[i];
        const std::string name = m.name;
        const double value = measurements[i].value;
        state.misc.push_back({name, value});
      }
      return state;
    }
    
    RaplImpl::RaplImpl() {
      Init();
      StartThread();
    }
    
    RaplImpl::~RaplImpl() {
      stopDumpThread();
      StopThread();
    }
    
    std::vector<int> RaplImpl::DetectPackages() {
      std::string filename;
      std::ifstream file;
    
      const int n_cpus = sysconf(_SC_NPROCESSORS_ONLN);
    
      std::vector<int> active_cpus = GetActiveCPUs();
      std::vector<int> active_packages;
    
      for (int cpu = 0; cpu < n_cpus; cpu++) {
        filename = "/sys/devices/system/cpu/cpu" + std::to_string(cpu) +
                   "/topology/physical_package_id";
        file.open(filename);
        if (!file.is_open()) {
          break;
        }
        int package;
        file >> package;
        file.close();
    
        const bool cpu_is_active = std::find(active_cpus.begin(), active_cpus.end(),
                                             cpu) != active_cpus.end();
        if (cpu_is_active) {
          active_packages.push_back(package);
        }
      }
    
      RemoveDuplicates(active_packages);
    
    #if defined(DEBUG)
      std::cout << "Detected " << active_cpus.size() << " cores in "
                << active_packages.size() << " package";
      if (active_packages.size() > 1) {
        std::cout << "s";
      }
      std::cout << std::endl;
    #endif
    
      return active_packages;
    }
    
    std::string GetBasename(int package_id) {
      return std::string("/sys/class/powercap/intel-rapl/intel-rapl:" +
                         std::to_string(package_id));
    }
    
    template <typename T>
    bool ReadFile(const std::string& filename, T& destination) {
      T temp1;
      T temp2;
      while (true) {
        std::ifstream file(filename);
        if (!file.is_open()) {
    #if defined(DEBUG)
          std::cerr << "Could not open " << filename << std::endl;
    #endif
          return false;
        } else {
          file >> temp1;
          file.seekg(0);
          file >> temp2;
          if (temp1 == temp2) {
            destination = temp1;
            return true;
          }
        }
      }
    }
    
    void RaplImpl::Init() {
      // Get active packages
      const std::vector<int> package_ids = DetectPackages();
    
      for (int package_id : package_ids) {
        for (int domain = 0; domain < kNumRaplDomains; domain++) {
          std::string basename = GetBasename(package_id);
          if (domain > 0) {
            basename += "/intel-rapl:" + std::to_string(package_id) + ":" +
                        std::to_string(domain - 1);
          }
    
          // Read domain name
          const std::string filename_domain = basename + "/name";
          std::string domain_name;
          bool valid = ReadFile(filename_domain, domain_name);
          if (domain > 0) {
            domain_name = domain_name + "-" + std::to_string(package_id);
          }
    
          // Read max energy
          const std::string filename_max_energy = basename + "/max_energy_range_uj";
          size_t max_energy_range_uj = 0;
          if (valid) {
            valid &= ReadFile(filename_max_energy, max_energy_range_uj);
          }
    
          // Read energy
          const std::string filename_energy = basename + "/energy_uj";
          if (valid) {
            size_t energy_uj = 0;
            valid &= ReadFile(filename_energy, energy_uj);
          }
    
          if (valid) {
            domain_names_.push_back(domain_name);
            uj_max_.push_back(max_energy_range_uj);
            file_names_.push_back(filename_energy);
          }
        }
      }
    
      // Initialize state variables
      const size_t n = uj_max_.size();
      uj_first_.resize(n);
      uj_previous_.resize(n);
      uj_total_.resize(n);
      std::vector<RaplMeasurement> measurements = GetMeasurements();
      for (size_t i = 0; i < n; i++) {
        uj_first_[i] = measurements[i].value;
        uj_previous_[i] = uj_first_[i];
        uj_total_[i] = 0;
      }
    
      measurement_interval_ = 100;
    }
    
    void RaplImpl::StartThread() {
      thread_ = std::thread([&] {
        while (!stop_) {
          GetMeasurements();
          for (size_t i = 0; i < kKeepAliveInterval && !stop_; i++) {
            std::this_thread::sleep_for(
                std::chrono::milliseconds(getMeasurementInterval()));
          }
        }
      });
    }
    
    void RaplImpl::StopThread() {
      stop_ = true;
      if (thread_.joinable()) {
        thread_.join();
      }
    }
    
    RaplState RaplImpl::GetRaplState() {
      RaplState state;
      state.timeAtRead = get_wtime();
      state.measurements = GetMeasurements();
    
      for (rapl::RaplMeasurement& m : state.measurements) {
        m.value *= 1e-6;  // convert uj to j
      }
    
      const size_t n_measurements = state.measurements.size();
    
      // Fill the current state
      state.consumedEnergyTotal = 0;
      for (size_t i = 0; i < state.measurements.size(); i++) {
        const std::string name = state.measurements[i].name;
        const size_t joulesAtRead = state.measurements[i].value;
        if (name.find("package") != std::string::npos) {
          state.consumedEnergyTotal += joulesAtRead;
        }
      }
    
      return state;
    }
    
    std::vector<RaplMeasurement> RaplImpl::GetMeasurements() {
      std::lock_guard<std::mutex> lock(mutex_);
    
      std::vector<RaplMeasurement> measurements;
    
      const size_t n = domain_names_.size();
      assert(n == file_names_.size());
      assert(n == uj_max_.size());
    
      auto file_name = file_names_.begin();
      auto domain_name = domain_names_.begin();
    
      // Take all measurements
      for (size_t i = 0; i < n; i++) {
        size_t measurement;
        if (!ReadFile(*file_name, measurement)) {
          throw std::runtime_error("Could not open " + *file_name);
        }
        measurements.push_back({*domain_name, measurement});
    
        file_name = std::next(file_name);
        domain_name = std::next(domain_name);
      }
    
      for (size_t i = 0; i < measurements.size(); i++) {
        const size_t uj_now = measurements[i].value;
        if (uj_now < uj_previous_[i]) {
          uj_total_[i] += uj_max_[i];
        }
        uj_previous_[i] = uj_now;
        measurements[i].value = uj_total_[i] + uj_now - uj_first_[i];
      }
    
      return measurements;
    }  // end Rapl::measure
    
    }  // namespace pmt::rapl