Skip to content

Commit

Permalink
Added component support for power measurements
Browse files Browse the repository at this point in the history
  • Loading branch information
xaguilar committed Nov 2, 2018
1 parent c0e8145 commit 152a17a
Show file tree
Hide file tree
Showing 5 changed files with 264 additions and 85 deletions.
12 changes: 12 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ if (ALLSCALE_WITH_PAPI)
add_definitions(-DHAVE_PAPI)
endif()

if (ALLSCALE_WITH_CRAY_PM)
add_definitions(-DCRAY_COUNTERS)
endif()

if (ALLSCALE_WITH_POWER_ESTIMATE)
add_definitions(-DPOWER_ESTIMATE)
endif()

if (ALLSCALE_READ_VOLTAGE)
add_definitions(-DREAD_VOLTAGE_FILE)
endif()

if (ALLSCALE_WITH_EXTRAE)
if(NOT EXTRAE_DIR)
message(FATAL_ERROR "EXTRAE_DIR Cmake variable not set. Please set it to point to the directory where EXTRAE is installed")
Expand Down
28 changes: 13 additions & 15 deletions allscale/components/monitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
#include <allscale/work_item_stats.hpp>
#include <allscale/util/graph_colouring.hpp>
#include <allscale/historical_data.hpp>
#include <allscale/task_times.hpp>


#include <hpx/include/components.hpp>

Expand All @@ -46,7 +44,6 @@ namespace allscale { namespace components {
struct HPX_COMPONENT_EXPORT monitor
: hpx::components::component_base<monitor>
{
typedef hpx::lcos::local::spinlock mutex_type;

monitor()
{
Expand All @@ -65,14 +62,6 @@ namespace allscale { namespace components {
// hpx::id_type get_left_neighbour() { return left_; }
// hpx::id_type get_right_neighbour() { return right_; }

mutex_type task_times_mtx_;
task_times task_times_;
task_times last_task_times_;
std::chrono::high_resolution_clock::time_point last_task_times_sample_;

void add_task_time(task_id::task_path const& path, task_times::time_t const& time);

task_times get_task_times();

/////////////////////////////////////////////////////////////////////////////////////
/// Performance Data Introspection
Expand Down Expand Up @@ -346,9 +335,19 @@ namespace allscale { namespace components {
// // /// \returns Cpu load
float get_cpu_load();

double get_avg_task_duration();

/// \brief This function returns the current power
// // /// \returns Power
float get_current_power();


/// \brief This function returns the max power that can be consumed
// // /// \returns Max power
float get_max_power();


private:
typedef hpx::lcos::local::spinlock mutex_type;

// MONITOR MANAGEMENT
// Measuring total execution time
Expand All @@ -360,9 +359,7 @@ namespace allscale { namespace components {
std::uint64_t num_localities_;
mutex_type init_mutex;
bool initialized = false;
public:
bool enable_monitor;
private:

// System parameters
unsigned long long total_memory_;
Expand Down Expand Up @@ -465,12 +462,12 @@ namespace allscale { namespace components {
// hpx::id_type idle_rate_avg_counter_;
// double idle_rate_avg_;

#ifdef REALTIME_VIZ
// REALTIME VIZ
std::mutex counter_mutex_;
std::uint64_t num_active_tasks_;
std::uint64_t total_tasks_;
double total_task_duration_;
#ifdef REALTIME_VIZ

hpx::id_type idle_rate_counter_;
double idle_rate_;
Expand All @@ -482,6 +479,7 @@ namespace allscale { namespace components {
unsigned long long int sample_id_;

bool sample_task_stats();
double get_avg_task_duration();
#endif

// HISTORICAL DATA
Expand Down
180 changes: 180 additions & 0 deletions allscale/power.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
#ifndef ALLSCALE_POWER_HPP
#define ALLSCALE_POWER_HPP

#include <cstdlib>
#include <vector>
#include <iostream>
#include <fstream>
#include <string>


#ifdef CRAY_COUNTERS
#define NUM_PM_COUNTERS 3
#define FRESHNESS_COUNTER 0
#define ENERGY_COUNTER 1
#define POWER_COUNTER 2

#define PM_MAX_ATTEMPTS 10
#endif

namespace allscale { namespace power
{

#ifdef CRAY_COUNTERS
std::ifstream pm_files[NUM_PM_COUNTERS];
#endif

// std::vector<unsigned long long> power_history;
// std::vector<unsigned long long> energy_history;
double last_instant_power;
double last_instant_energy;
double instant_power;
double instant_energy;


void init_power_measurements()
{

#ifdef CRAY_COUNTERS
pm_files[FRESHNESS_COUNTER].open("/sys/cray/pm_counters/freshness");
if(!pm_files[FRESHNESS_COUNTER]) {
std::cerr << "ERROR: Cannot open /sys/cray/pm_counters/freshness\n";
exit(1);
}

pm_files[ENERGY_COUNTER].open("/sys/cray/pm_counters/energy");
if(!pm_files[ENERGY_COUNTER]) {
std::cerr << "ERROR: Cannot open /sys/cray/pm_counters/energy\n";
exit(1);
}

pm_files[POWER_COUNTER].open("/sys/cray/pm_counters/power");
if(!pm_files[POWER_COUNTER]) {
std::cerr << "ERROR: Cannot open /sys/cray/pm_counters/power\n";
exit(1);
}
#endif
last_instant_power = instant_power = last_instant_energy = instant_energy = 0.0;
}



void finish_power_measurements()
{
#ifdef CRAY_COUNTERS
if(pm_files[FRESHNESS_COUNTER].is_open()) pm_files[FRESHNESS_COUNTER].close();

if(pm_files[ENERGY_COUNTER].is_open()) pm_files[ENERGY_COUNTER].close();

if(pm_files[POWER_COUNTER].is_open()) pm_files[POWER_COUNTER].close();
#endif
}


// Returns last instant power in Watts
double get_instant_power() { return instant_power; }

// Returns last instant energy in J
double get_instant_energy() { return instant_energy; }

// Returns all power samples
// std::vector<unsigned long long> get_power_history() { return power_history; }

// Returns all energy samples
// std::vector<unsigned long long> get_energy_history() { return energy_history; }


#ifdef CRAY_COUNTERS
// Returns 0 is the results are valid
int read_pm_counters() {

int freshness1, freshness2, n_attempts = 0;
std::string line;
unsigned long long tmp_energy, tmp_power;

// We need to check that the counters have not been updated while we were accessing them
do {

n_attempts++;
pm_files[FRESHNESS_COUNTER].seekg(0);
std::getline(pm_files[FRESHNESS_COUNTER], line);

freshness1 = std::atoi(line.c_str());

// Read energy
pm_files[ENERGY_COUNTER].seekg(0);
std::getline(pm_files[ENERGY_COUNTER], line);

tmp_energy = std::strtoull(line.c_str(), NULL, 10);

// Read power
pm_files[POWER_COUNTER].seekg(0);
std::getline(pm_files[POWER_COUNTER], line);

tmp_power = std::strtoull(line.c_str(), NULL, 10);

pm_files[FRESHNESS_COUNTER].seekg(0);
std::getline(pm_files[FRESHNESS_COUNTER], line);

freshness2 = std::atoi(line.c_str());

} while(n_attempts < PM_MAX_ATTEMPTS && freshness1 != freshness2);

if(freshness1 != freshness2) return 1;
else {
// power_history.push_back(tmp_power);
// energy_history.push_back(tmp_energy);

instant_power = (double)tmp_power - last_instant_power;
last_instant_power = (double)tmp_power;

instant_energy = (double)tmp_energy - last_instant_energy;
last_instant_energy = (double)tmp_energy;

return 0;
}
}


#endif

#ifdef POWER_ESTIMATE

// Estimate basic power
double estimate_power(std::uint64_t frequency)
{
static const char * file_name = "/sys/class/i2c-dev/i2c-3/device/3-002d/regulator/regulator.1/microvolts";
std::ifstream file;
std::uint64_t microvolts = 0;
float U = 0.9;

// Estimate using C * U^2 * f

// for now C is 30pF, not able to find it for Cortex A53
auto C = 30 * 1.0e-12; //


// voltage U
#ifdef READ_VOLTAGE_FILE
file.open(file_name);
if(!file)
std::cerr << "Warning: Cannot read voltage from /sys/class, using 0.9 instead" << std::endl;
else {
file >> microvolts;
U = (double)microvolts * 1.0e-6;

file.close();
}
#endif
instant_power = (double)C * (U * U) * (double)(frequency * 1000); // freq is in kHz

return instant_power;
}
#endif



}}

#endif

Loading

0 comments on commit 152a17a

Please sign in to comment.