Commit ccb1cd16 authored by Swann Perarnau's avatar Swann Perarnau

Import SC15/Chameleon version of NRM

The SC15/Chameleon experiments were based on a simple power management
scheme built with the help of beacon for transport, RAPL for monitoring,
and socket-based communications between the NRM and the argobots
runtime.

This is an import of the working code we had, in the state it was at the
time. It is quite obvious that this kind of one time hack, and it
probably doesn't work without the exact Chameleon setup.
parents
# the compiler: gcc for C program, define as g++ for C++
CC = gcc
# compiler flags:
CFLAGS = -g -I/nfs/beacon_inst/include -I.
LDFLAGS = -lm -lbeacon -lpthread
# the build target executable:
TARGET = powPerfController
powMon = RaplPowerMon
beacon = beacon_nrm
RM = rm
all: $(powMon) $(TARGET)
$(powMon): $(powMon).c
$(CC) -o $(powMon) $(powMon).c $(LDFLAGS)
$(TARGET): $(TARGET).c $(beacon).c
$(CC) $(CFLAGS) $(TARGET).c $(beacon).c -o $(TARGET) $(LDFLAGS)
clean:
$(RM) -f $(TARGET) $(powMon)
How to run:
1) $ make clean; make
2) $ source /nfs/beacon_inst/env.sh; ./powPerfController 1234
3)in another shell:
$ /nfs/argobots-tascel/argobots-review/examples/dynamic-es/dyn_app 48 1000 localhost 1234
4)in another shell:
$ source /nfs/beacon_inst/env.sh
$ arbitrary_pub BEACON_BROADCAST "message type=2 ; node=frontend ; target watts=190”
sdasd
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <inttypes.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
#include <string.h>
//#include <asm/msr.h>
#define MSR_RAPL_POWER_UNIT 0x606
/*
* Platform specific RAPL Domains.
* Note that PP1 RAPL Domain is supported on 062A only
* And DRAM RAPL Domain is supported on 062D only
*/
/* Package RAPL Domain */
#define MSR_PKG_RAPL_POWER_LIMIT 0x610
#define MSR_PKG_ENERGY_STATUS 0x611
#define MSR_PKG_PERF_STATUS 0x613
#define MSR_PKG_POWER_INFO 0x614
/* PP0 RAPL Domain */
#define MSR_PP0_POWER_LIMIT 0x638
#define MSR_PP0_ENERGY_STATUS 0x639
#define MSR_PP0_POLICY 0x63A
#define MSR_PP0_PERF_STATUS 0x63B
/* PP1 RAPL Domain, may reflect to uncore devices */
#define MSR_PP1_POWER_LIMIT 0x640
#define MSR_PP1_ENERGY_STATUS 0x641
#define MSR_PP1_POLICY 0x642
/* DRAM RAPL Domain */
#define MSR_DRAM_POWER_LIMIT 0x618
#define MSR_DRAM_ENERGY_STATUS 0x619
#define MSR_DRAM_PERF_STATUS 0x61B
#define MSR_DRAM_POWER_INFO 0x61C
/* RAPL UNIT BITMASK */
#define POWER_UNIT_OFFSET 0
#define POWER_UNIT_MASK 0x0F
#define ENERGY_UNIT_OFFSET 0x08
#define ENERGY_UNIT_MASK 0x1F00
#define TIME_UNIT_OFFSET 0x10
#define TIME_UNIT_MASK 0xF000
#define PKG_POWER_LIMIT_LOCK_OFFSET 0x3F
#define PKG_POWER_LIMIT_LOCK_MASK 0x1
#define ENABLE_LIMIT_2_OFFSET 0x2F
#define PKG_POWER_LIMIT_2_MASK 0x7FFF
#define ENABLE_LIMIT_1_OFFSET 0xF
#define ENABLE_LIMIT_1_MASK 0x1
#define PKG_CLAMPING_LIMIT_1_OFFSET 0x10
#define PKG_CLAMPING_LIMIT_1_MASK 0x1
#define PKG_POWER_LIMIT_1_OFFSET 0x0
#define PKG_POWER_LIMIT_1_MASK 0x7FFF
#define TIME_WINDOW_POWER_LIMIT_1_OFFSET 0x11
#define TIME_WINDOW_POWER_LIMIT_1_MASK 0x7F
#define TIME_WINDOW_POWER_LIMIT_2_OFFSET 0x31
#define TIME_WINDOW_POWER_LIMIT_2_MASK 0x7F
int open_msr(int core) {
char msr_filename[BUFSIZ];
int fd;
sprintf(msr_filename, "/dev/cpu/%d/msr", core);
fd = open(msr_filename, O_RDWR);
if ( fd < 0 ) {
if ( errno == ENXIO ) {
fprintf(stderr, "rdmsr: No CPU %d\n", core);
exit(2);
} else if ( errno == EIO ) {
fprintf(stderr, "rdmsr: CPU %d doesn't support MSRs\n", core);
exit(3);
} else {
perror("rdmsr:open");
fprintf(stderr,"Trying to open %s\n",msr_filename);
exit(127);
}
}
return fd;
}
long long read_msr(int fd, int which) {
uint64_t data;
if ( pread(fd, &data, sizeof data, which) != sizeof data ) {
perror("rdmsr:pread");
exit(127);
}
return (long long)data;
}
void write_msr(int fd, int which, uint64_t data) {
if ( pwrite(fd, &data, sizeof data, which) != sizeof data ) {
perror("wrmsr:pwrite");
exit(127);
}
}
int32_t wrmsr(int fd, uint64_t msr_number, uint64_t value)
{
return pwrite(fd, (const void *)&value, sizeof(uint64_t), msr_number);
}
int32_t rdmsr(int fd, uint64_t msr_number, uint64_t * value)
{
return pread(fd, (void *)value, sizeof(uint64_t), msr_number);
}
void set_power_limit(int fd, int watts, double pu)
{
/*
uint32_t setpoint = (uint32_t) ((1 << pu) * watts);
uint64_t reg = 0;
rdmsr(fd, MSR_PKG_RAPL_POWER_LIMIT, &reg);
reg = (reg & 0xFFFFFFFFFFFF0000) | setpoint | 0x8000;
reg = (reg & 0xFFFFFFFF0000FFFF) | 0xD0000;
wrmsr(fd, MSR_PKG_RAPL_POWER_LIMIT, reg);
*/
uint32_t setpoint = (uint32_t) (watts/pu);
uint64_t reg = 0;
rdmsr(fd, MSR_PKG_RAPL_POWER_LIMIT, &reg);
reg = (reg & 0xFFFFFFFFFFFF0000) | setpoint | 0x8000;
reg = (reg & 0xFFFFFFFF0000FFFF) | 0xD0000;
wrmsr(fd, MSR_PKG_RAPL_POWER_LIMIT, reg);
}
#define CPU_SANDYBRIDGE 42
#define CPU_SANDYBRIDGE_EP 45
#define CPU_IVYBRIDGE 58
#define CPU_IVYBRIDGE_EP 62
int main( int argc, char **argv ) {
int fd1,fd2;
long long result1, result2;
double power_units,energy_units,time_units;
double package1_before,package1_after,package2_before,package2_after;
double pp0_before,pp0_after;
double pp1_before=0.0,pp1_after;
double dram_before=0.0,dram_after;
double thermal_spec_power,minimum_power,maximum_power,time_window;
int cpu_model;
struct timeval currentime1,currentime2,beginningtime;
struct timespec interval_1s,interval_1ms,interval_10ms, interval_100ms, interval_500ms;
long double nowtime, power1, power2;
float total_power;
// char *filename;
//char *W = "W";
//FILE *file;
gettimeofday(&beginningtime,NULL);
interval_500ms.tv_sec = 0;
interval_500ms.tv_nsec = 500000000;
interval_100ms.tv_sec = 0;
interval_100ms.tv_nsec = 100000000;
interval_1s.tv_sec = 1;
interval_1s.tv_nsec = 0;
interval_1ms.tv_sec = 0;
interval_1ms.tv_nsec = 1000000;
interval_10ms.tv_sec = 0;
interval_10ms.tv_nsec = 10000000;
const char *powercap = argv[1];
//char filename[20] = "PowerResultsOn";
// strcat(filename, powercap);
// strcat(filename, "W");
// printf("filename = %s",filename);
// file = fopen(filename,"a");
fd1=open_msr(0);
fd2=open_msr(10);
/* Calculate the units used */
result1=read_msr(fd1,MSR_RAPL_POWER_UNIT);
power_units=pow(0.5,(double)(result1&0xf));
energy_units=pow(0.5,(double)((result1>>8)&0x1f));
time_units=pow(0.5,(double)((result1>>16)&0xf));
uint64_t currentval, newval, mask = 0, offset = 0;
currentval=read_msr(fd1,MSR_PKG_RAPL_POWER_LIMIT);
currentval=read_msr(fd2,MSR_PKG_RAPL_POWER_LIMIT);
int i;
for (i= 0; i<1; i++){
result1=read_msr(fd1,MSR_PKG_ENERGY_STATUS);
result2=read_msr(fd2,MSR_PKG_ENERGY_STATUS);
package1_before=(double)result1*energy_units;
package2_before=(double)result2*energy_units;
gettimeofday(&currentime1, NULL);
//printf("\nSleeping 1 second\n\n");
nanosleep(&interval_100ms, NULL);
result1=read_msr(fd1,MSR_PKG_ENERGY_STATUS);
result2=read_msr(fd2,MSR_PKG_ENERGY_STATUS);
gettimeofday(&currentime2, NULL);
package1_after=(double)result1*energy_units;
package2_after=(double)result2*energy_units;
nowtime =((long) ((currentime2.tv_usec - beginningtime.tv_usec) + (currentime2.tv_sec - beginningtime.tv_sec)* 1000000))/1000000.000000;
power1 =((package1_after - package1_before) /((currentime2.tv_usec - currentime1.tv_usec) + (currentime2.tv_sec - currentime1.tv_sec)*1000000))*1000000;
power2 =((package2_after - package2_before) /((currentime2.tv_usec - currentime1.tv_usec) + (currentime2.tv_sec - currentime1.tv_sec)*1000000))*1000000;
//fprintf(file,"%LF %LF %LF\n", nowtime, power1, power2);
total_power = (float)power1 +(float)power2;
}
printf("%f\n", total_power);
return 1;
}
#include <stdio.h>
#include <stdlib.h>
#include <beacon.h>
#include <string.h>
#include <powPerfController.h>
/* Baseline example to receive ERM power settings in the NRM */
// We need the hostname for the message filter in my_beacon_handler
// but would like to set it only once when the callback is set
// via set_nrm_power_target
static char hostname[100];
// We need a function pointer for the function to apply each time a
// new setting is received. set_nrm_power_target will set the value
// and my_beacon_handler() will use it
void (*target_handler)(double watts);
void set_nrm_power_target(void (*handler)(double watts));
/* BEACON boilerplate */
static int SET_NODE_E=2;
BEACON_beep_t binfo;
BEACON_beep_handle_t handle;
BEACON_subscribe_handle_t shandle1;
BEACON_topic_info_t *topic_info;
BEACON_topic_properties_t *eprop;
char data_buf[100];
char beep_name[100];
char filter_string[100];
char topic_string[32];
int BEACON_bcast_init() {
eprop = (BEACON_topic_properties_t *) malloc(sizeof(BEACON_topic_properties_t));
topic_info = (BEACON_topic_info_t *)malloc(sizeof(BEACON_topic_info_t));
if(topic_info == NULL) {
fprintf(stderr, "Malloc error!\n");
exit(0);
}
strcpy(topic_info[0].topic_name, "BEACON_BROADCAST");
sprintf(topic_info[0].severity, "INFO");
printf("The %d topic is %s\n", 0, topic_info[0].topic_name);
memset(&binfo, 0, sizeof(binfo));
strcpy(binfo.beep_version, "1.0");
strcpy(binfo.beep_name, "beacon_test");
int ret = BEACON_Connect(&binfo, &handle);
if (ret != BEACON_SUCCESS) {
printf("BEACON_Connect is not successful ret=%d\n", ret);
exit(-1);
}
strcpy(eprop->topic_scope, "global");
return 1;
}
int is_SET_NODE(char* message, char* node, double* watts) {
int mtype;
int rc = sscanf(message, "message type=%d;", &mtype);
if(rc!=1) {
return 0;
}
if(mtype!=SET_NODE_E) {
return 0;
}
rc = sscanf(message, "message type=%d ; node=%s ; target watts=%lf",&mtype, node, watts);
if(rc!=3) {
printf("wrong arg count %d\n",rc);
return 0;
}
return 1;
}
pthread_t poll_thread;
void* poll_logic(void* args) {
void (*handler)(BEACON_receive_topic_t* caught_topic) = (void (*)(BEACON_receive_topic_t*))args;
while(1) {
BEACON_receive_topic_t caught_topic;
int ret = BEACON_Wait_topic(shandle1, &caught_topic, 5);
if (ret != BEACON_SUCCESS) {
continue;
}
handler(&caught_topic);
}
}
int BEACON_bcast_subscribe(void (*handler)()) {
char* caddr = getenv("BEACON_TOPOLOGY_SERVER_ADDR");
sprintf(filter_string, "cluster_addr=%s,cluster_port=10809,topic_scope=global,topic_name=%s", caddr, topic_info[0].topic_name);
int ret = BEACON_Subscribe(&shandle1, handle, 0, filter_string, NULL);
pthread_create(&poll_thread, NULL, poll_logic, handler);
}
// The callback to send with the subscription
void my_beacon_handler(BEACON_receive_topic_t* topic) {
char node[100];
double watts;
// parse string store parts in enclave and delta
if(is_SET_NODE(topic->topic_payload, node, &watts)) {
if(strcmp(node,hostname)==0) {
target_handler(watts);
}
}
}
/* End boilerplate */
// Test handler to show that we can receive readings
//void test_handler(double watts) {
// printf("got %lf watts\n",watts);
//}
// The function that connects to BEACON and sets up the message handling
void set_nrm_power_target(void (*handler)(double watts)) {
gethostname(hostname,100);
BEACON_bcast_init();
target_handler=handler;
BEACON_bcast_subscribe(my_beacon_handler);
}
// A simple main function that runs the process for about a minute
//int main(int argc, char** argv) {
// set_nrm_power_target(test_handler);
// sleep(30);
//}
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
* See COPYRIGHT in top-level directory.
*/
#ifndef COMMON_H
#define COMMON_H
#define DEFAULT_PORT 60439
#define SEND_BUF_LEN 20
#define RECV_BUF_LEN 20
#endif /* COMMON_H */
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
* See COPYRIGHT in top-level directory.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <poll.h>
#include <assert.h>
#include "common.h"
#include <powPerfController.h>
double power_cap;
static void handle_error(const char *msg);
static float get_power();
void test_handler(double watts) {
power_cap=(float) watts;
printf("new power_cap: %f watts\n",power_cap);
}
enum {
CMD_INIT,
CMD_INC_MODE,
CMD_DEC_MODE,
};
int main(int argc, char *argv[])
{
set_nrm_power_target(test_handler);
int sockfd, port;
struct sockaddr_in my_addr;
struct sockaddr_in abt_addr;
socklen_t addrlen;
struct pollfd abt_pfd;
//saeid
float current_power=0;
power_cap=300;
char send_buf[SEND_BUF_LEN];
char recv_buf[RECV_BUF_LEN];
int quit = 0;
int abt_alive = 0;
int n, ret;
int cur_cmd_mode = CMD_INIT;
int prv_cmd_mode;
int cmd_failed = 0;
int skip_cmd = 0;
if (argc < 2) {
fprintf(stderr, "Usage: %s <port> \n", argv[0]);
exit(1);
}
port = atoi(argv[1]);
// power_cap = atof(argv[2]);
float threshold=0.10;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) handle_error("ERROR: socket");
bzero((char *)&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = INADDR_ANY;
my_addr.sin_port = htons(port);
ret = bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr));
if (ret < 0) handle_error("ERROR: bind");
while (!quit) {
printf("Waiting for connection...\n");
listen(sockfd, 5);
addrlen = sizeof(abt_addr);
abt_pfd.fd = accept(sockfd, (struct sockaddr *)&abt_addr, &addrlen);
if (abt_pfd.fd < 0) handle_error("ERROR: accept");
abt_pfd.events = POLLIN | POLLRDHUP;
abt_alive = 1;
printf("Client connected...\n\n");
while (abt_alive) {
current_power = get_power();
printf("currnet power = %f, power_cap = %f\n",current_power,power_cap);
prv_cmd_mode = cur_cmd_mode;
if (current_power < ((1-threshold)* power_cap)){
bzero(send_buf, SEND_BUF_LEN);
send_buf[0] = 'i';
cur_cmd_mode = CMD_INC_MODE;
}else if (current_power > ((1+threshold)* power_cap)){
bzero(send_buf, SEND_BUF_LEN);
send_buf[0] = 'd';
cur_cmd_mode = CMD_DEC_MODE;
}else{
// Sangmin - fix: we don't need to send a message to Argobots
//bzero(send_buf, SEND_BUF_LEN);
// send_buf[0] = 'n';
skip_cmd = 1;
cur_cmd_mode = CMD_INIT;
}
if (send_buf[0] != 'd' && send_buf[0] != 'i' &&
send_buf[0] != 'n' && send_buf[0] != 'q') {
printf("Unknown command: %s\n", send_buf);
continue;
}
if (cur_cmd_mode == prv_cmd_mode && cmd_failed) {
skip_cmd = 1;
}
if (skip_cmd) {
skip_cmd = 0;
sleep(1);
continue;
}
n = write(abt_pfd.fd, send_buf, strlen(send_buf));
assert(n == strlen(send_buf));
bzero(recv_buf, RECV_BUF_LEN);
/* Wait for the ack */
printf("Waiting for the response...\n");
while (1) {
ret = poll(&abt_pfd, 1, 10);
if (ret == -1) {
handle_error("ERROR: poll");
} else if (ret != 0) {
if (abt_pfd.revents & POLLIN) {
n = read(abt_pfd.fd, recv_buf, RECV_BUF_LEN);
if (n < 0) handle_error("ERROR: read");
printf("Response: %s\n\n", recv_buf);
cmd_failed = strcmp(recv_buf, "failed") == 0;
}
if (abt_pfd.revents & POLLRDHUP) {
abt_alive = 0;
printf("Client disconnected...\n");
break;
}
abt_pfd.revents = 0;
break;
}
}
if (send_buf[0] == 'q') {
quit = 1;
close(abt_pfd.fd);
break;
}
//saeid, for checking sending/recieving is working correctly
sleep(1);
}
}
close(sockfd);
return EXIT_SUCCESS;
}
/*get package power through msr */
static float get_power()
{
FILE *fp;
float current_power;
system("sudo /nfs/powPerfController/RaplPowerMon > power.txt");
fp= fopen("power.txt","r");
if (fp==NULL) handle_error("ERROR:opening file failed");
fscanf(fp,"%f",&current_power);
fclose(fp);
return current_power;
}
static void handle_error(const char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
//Functions
//void set_nrm_power_target(double watts);
void set_nrm_power_target(void (*handler)(double watts));
void test_handler(double watts) ;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment