Commit 06f3402d authored by Neil McGlohon's avatar Neil McGlohon
Browse files

removing placeholder storage of dfdally w qos work

parent 8274da0d
/*
* Copyright (C) 2013 University of Chicago.
* See COPYRIGHT notice in top-level directory.
*
*/
#include <ross.h>
#include "codes/jenkins-hash.h"
#include "codes/codes_mapping.h"
#include "codes/codes.h"
#include "codes/model-net.h"
#include "codes/model-net-method.h"
#include "codes/model-net-lp.h"
#include "codes/net/dragonfly-custom.h"
#include "sys/file.h"
#include "codes/quickhash.h"
#include "codes/rc-stack.h"
#include <vector>
#include <map>
#include <set>
#ifdef ENABLE_CORTEX
#include <cortex/cortex.h>
#include <cortex/topology.h>
#endif
#define DUMP_CONNECTIONS 0
#define PRINT_CONFIG 1
#define CREDIT_SIZE 8
#define DFLY_HASH_TABLE_SIZE 4999
// debugging parameters
#define BW_MONITOR 1
#define DEBUG_LP 892
#define T_ID -1
#define TRACK -1
#define TRACK_PKT -1
#define TRACK_MSG -1
#define DEBUG 0
#define MAX_STATS 65536
#define SHOW_ADAP_STATS 1
#define LP_CONFIG_NM_TERM (model_net_lp_config_names[DRAGONFLY_CUSTOM])
#define LP_METHOD_NM_TERM (model_net_method_names[DRAGONFLY_CUSTOM])
#define LP_CONFIG_NM_ROUT (model_net_lp_config_names[DRAGONFLY_CUSTOM_ROUTER])
#define LP_METHOD_NM_ROUT (model_net_method_names[DRAGONFLY_CUSTOM_ROUTER])
static int debug_cnt = 0;
static int max_lvc_src_g = 1;
static int max_lvc_intm_g = 3;
static int min_gvc_src_g = 0;
static int min_gvc_intm_g = 1;
static int BIAS_MIN = 1;
static int DF_DALLY = 0;
static int adaptive_threshold = 1024;
static tw_stime max_qos_monitor = 5000000000;
static long num_local_packets_sr = 0;
static long num_local_packets_sg = 0;
static long num_remote_packets = 0;
/* time in nanosecs */
static int bw_reset_window = 5000000;
#define indexer3d(_ptr, _x, _y, _z, _maxx, _maxy, _maxz) \
((_ptr) + _z * (_maxx * _maxz) + _y * (_maxx) + _x)
#define indexer2d(_ptr, _x, _y, _maxx, _maxy) \
((_ptr) + _y * (_maxx) + _x)
using namespace std;
struct Link {
int offset, type;
};
struct bLink {
int offset, dest;
};
/* Each entry in the vector is for a router id
* against each router id, there is a map of links (key of the map is the dest
* router id)
* link has information on type (green or black) and offset (number of links
* between that particular source and dest router ID)*/
vector< map< int, vector<Link> > > intraGroupLinks;
/* contains mapping between source router and destination group via link (link
* has dest ID)*/
vector< map< int, vector<bLink> > > interGroupLinks;
/*MM: Maintains a list of routers connecting the source and destination groups */
vector< vector< vector<int> > > connectionList;
struct IntraGroupLink {
int src, dest, type;
};
struct InterGroupLink {
int src, dest;
};
#ifdef ENABLE_CORTEX
/* This structure is defined at the end of the file */
extern "C" {
extern cortex_topology dragonfly_custom_cortex_topology;
}
#endif
static int debug_slot_count = 0;
static long term_ecount, router_ecount, term_rev_ecount, router_rev_ecount;
static long packet_gen = 0, packet_fin = 0;
static double maxd(double a, double b) { return a < b ? b : a; }
/* minimal and non-minimal packet counts for adaptive routing*/
static int minimal_count=0, nonmin_count=0;
static int num_routers_per_mgrp = 0;
typedef struct dragonfly_param dragonfly_param;
/* annotation-specific parameters (unannotated entry occurs at the
* last index) */
static uint64_t num_params = 0;
static dragonfly_param * all_params = NULL;
static const config_anno_map_t * anno_map = NULL;
/* global variables for codes mapping */
static char lp_group_name[MAX_NAME_LENGTH];
static int mapping_grp_id, mapping_type_id, mapping_rep_id, mapping_offset;
/* router magic number */
static int router_magic_num = 0;
/* terminal magic number */
static int terminal_magic_num = 0;
/* Hops within a group */
static int num_intra_nonmin_hops = 4;
static int num_intra_min_hops = 2;
static FILE * dragonfly_rtr_bw_log = NULL;
//static FILE * dragonfly_term_bw_log = NULL;
static int sample_bytes_written = 0;
static int sample_rtr_bytes_written = 0;
static char cn_sample_file[MAX_NAME_LENGTH];
static char router_sample_file[MAX_NAME_LENGTH];
//don't do overhead here - job of MPI layer
static tw_stime mpi_soft_overhead = 0;
typedef struct terminal_custom_message_list terminal_custom_message_list;
struct terminal_custom_message_list {
terminal_custom_message msg;
char* event_data;
terminal_custom_message_list *next;
terminal_custom_message_list *prev;
};
static void init_terminal_custom_message_list(terminal_custom_message_list *thisO,
terminal_custom_message *inmsg) {
thisO->msg = *inmsg;
thisO->event_data = NULL;
thisO->next = NULL;
thisO->prev = NULL;
}
static void delete_terminal_custom_message_list(void *thisO) {
terminal_custom_message_list* toDel = (terminal_custom_message_list*)thisO;
if(toDel->event_data != NULL) free(toDel->event_data);
free(toDel);
}
struct dragonfly_param
{
// configuration parameters
int num_routers; /*Number of routers in a group*/
double local_bandwidth;/* bandwidth of the router-router channels within a group */
double global_bandwidth;/* bandwidth of the inter-group router connections */
double cn_bandwidth;/* bandwidth of the compute node channels connected to routers */
int num_vcs; /* number of virtual channels */
int local_vc_size; /* buffer size of the router-router channels */
int global_vc_size; /* buffer size of the global channels */
int cn_vc_size; /* buffer size of the compute node channels */
int chunk_size; /* full-sized packets are broken into smaller chunks.*/
// derived parameters
int num_cn;
int intra_grp_radix;
int num_col_chans;
int num_row_chans;
int num_router_rows;
int num_router_cols;
int num_groups;
int radix;
int total_routers;
int total_terminals;
int num_global_channels;
int num_qos_levels;
int * qos_bandwidths;
double cn_delay;
double local_delay;
double global_delay;
double credit_delay;
double router_delay;
int max_hops_notify; //maximum number of hops allowed before notifying via printout
};
static const dragonfly_param* stored_params;
struct dfly_hash_key
{
uint64_t message_id;
tw_lpid sender_id;
};
struct dfly_router_sample
{
tw_lpid router_id;
tw_stime* busy_time;
int64_t* link_traffic_sample;
tw_stime end_time;
long fwd_events;
long rev_events;
};
struct dfly_cn_sample
{
tw_lpid terminal_id;
long fin_chunks_sample;
long data_size_sample;
double fin_hops_sample;
tw_stime fin_chunks_time;
tw_stime busy_time_sample;
tw_stime end_time;
long fwd_events;
long rev_events;
};
struct dfly_qhash_entry
{
struct dfly_hash_key key;
char * remote_event_data;
int num_chunks;
int remote_event_size;
struct qhash_head hash_link;
};
/* handles terminal and router events like packet generate/send/receive/buffer */
typedef struct terminal_state terminal_state;
typedef struct router_state router_state;
/* dragonfly compute node data structure */
struct terminal_state
{
uint64_t packet_counter;
int packet_gen;
int packet_fin;
// Dragonfly specific parameters
unsigned int router_id;
unsigned int terminal_id;
// Each terminal will have an input and output channel with the router
int* vc_occupancy; // NUM_VC
tw_stime terminal_available_time;
terminal_custom_message_list **terminal_msgs;
terminal_custom_message_list **terminal_msgs_tail;
int in_send_loop;
struct mn_stats dragonfly_stats_array[CATEGORY_MAX];
int * qos_status;
int * qos_data;
int rc_index;
int* last_qos_status;
int* last_qos_data;
int last_qos_lvl;
int is_monitoring_bw;
struct rc_stack * st;
int issueIdle;
int* terminal_length;
const char * anno;
const dragonfly_param *params;
struct qhash_table *rank_tbl;
uint64_t rank_tbl_pop;
tw_stime total_time;
uint64_t total_msg_size;
double total_hops;
long finished_msgs;
long finished_chunks;
long finished_packets;
tw_stime last_buf_full;
tw_stime busy_time;
tw_stime max_latency;
tw_stime min_latency;
char output_buf[4096];
char output_buf2[4096];
/* For LP suspend functionality */
int error_ct;
/* For sampling */
long fin_chunks_sample;
long data_size_sample;
double fin_hops_sample;
tw_stime fin_chunks_time;
tw_stime busy_time_sample;
int num_term_rc_windows;
char sample_buf[4096];
struct dfly_cn_sample * sample_stat;
int op_arr_size;
int max_arr_size;
/* for logging forward and reverse events */
long fwd_events;
long rev_events;
/* following used for ROSS model-level stats collection */
long fin_chunks_ross_sample;
long data_size_ross_sample;
long fin_hops_ross_sample;
tw_stime fin_chunks_time_ross_sample;
tw_stime busy_time_ross_sample;
struct dfly_cn_sample ross_sample;
};
typedef enum qos_priority
{
Q_HIGH =0,
Q_MEDIUM,
Q_LOW,
Q_UNKNOWN,
} qos_priority;
typedef enum qos_status
{
Q_ACTIVE = 1,
Q_OVERBW,
} qos_status;
/* terminal event type (1-4) */
typedef enum event_t
{
T_GENERATE=1,
T_ARRIVE,
T_SEND,
T_BUFFER,
R_SEND,
R_ARRIVE,
R_BUFFER,
R_BANDWIDTH,
R_BW_HALT,
T_BANDWIDTH,
} event_t;
/* whether the last hop of a packet was global, local or a terminal */
enum last_hop
{
GLOBAL=1,
LOCAL,
TERMINAL,
ROOT
};
/* three forms of routing algorithms available, adaptive routing is not
* accurate and fully functional in the current version as the formulas
* for detecting load on global channels are not very accurate */
enum ROUTING_ALGO
{
MINIMAL = 1,
NON_MINIMAL,
ADAPTIVE,
PROG_ADAPTIVE
};
enum LINK_TYPE
{
GREEN,
BLACK,
};
struct router_state
{
unsigned int router_id;
int group_id;
int op_arr_size;
int max_arr_size;
int rc_index;
int num_rtr_rc_windows;
int* global_channel;
tw_stime* next_output_available_time;
tw_stime* cur_hist_start_time;
tw_stime* last_buf_full;
tw_stime* busy_time;
tw_stime* busy_time_sample;
terminal_custom_message_list ***pending_msgs;
terminal_custom_message_list ***pending_msgs_tail;
terminal_custom_message_list ***queued_msgs;
terminal_custom_message_list ***queued_msgs_tail;
int *in_send_loop;
int *queued_count;
struct rc_stack * st;
int* last_sent_chan;
int** vc_occupancy;
int64_t* link_traffic;
int64_t * link_traffic_sample;
int is_monitoring_bw;
int* last_qos_lvl;
int** qos_status;
int** qos_data;
/* for reverse handler */
int* last_qos_status;
int* last_qos_data;
const char * anno;
const dragonfly_param *params;
int* prev_hist_num;
int* cur_hist_num;
char output_buf[4096];
struct dfly_router_sample * rsamples;
long fwd_events;
long rev_events;
/* following used for ROSS model-level stats collection */
tw_stime* busy_time_ross_sample;
int64_t * link_traffic_ross_sample;
struct dfly_router_sample ross_rsample;
};
/* had to pull some of the ROSS model stats collection stuff up here */
void custom_dragonfly_event_collect(terminal_custom_message *m, tw_lp *lp, char *buffer, int *collect_flag);
void custom_dragonfly_model_stat_collect(terminal_state *s, tw_lp *lp, char *buffer);
void custom_dfly_router_model_stat_collect(router_state *s, tw_lp *lp, char *buffer);
static void ross_custom_dragonfly_rsample_fn(router_state * s, tw_bf * bf, tw_lp * lp, struct dfly_router_sample *sample);
static void ross_custom_dragonfly_rsample_rc_fn(router_state * s, tw_bf * bf, tw_lp * lp, struct dfly_router_sample *sample);
static void ross_custom_dragonfly_sample_fn(terminal_state * s, tw_bf * bf, tw_lp * lp, struct dfly_cn_sample *sample);
static void ross_custom_dragonfly_sample_rc_fn(terminal_state * s, tw_bf * bf, tw_lp * lp, struct dfly_cn_sample *sample);
st_model_types custom_dragonfly_model_types[] = {
{(ev_trace_f) custom_dragonfly_event_collect,
sizeof(int),
(model_stat_f) custom_dragonfly_model_stat_collect,
sizeof(tw_lpid) + sizeof(long) * 2 + sizeof(double) + sizeof(tw_stime) *2,
(sample_event_f) ross_custom_dragonfly_sample_fn,
(sample_revent_f) ross_custom_dragonfly_sample_rc_fn,
sizeof(struct dfly_cn_sample) } ,
{(ev_trace_f) custom_dragonfly_event_collect,
sizeof(int),
(model_stat_f) custom_dfly_router_model_stat_collect,
0, //updated in router_custom_setup() since it's based on the radix
(sample_event_f) ross_custom_dragonfly_rsample_fn,
(sample_revent_f) ross_custom_dragonfly_rsample_rc_fn,
0 } , //updated in router_custom_setup() since it's based on the radix
{NULL, 0, NULL, 0, NULL, NULL, 0}
};
/* End of ROSS model stats collection */
static short routing = MINIMAL;
static tw_stime dragonfly_total_time = 0;
static tw_stime dragonfly_max_latency = 0;
static long long total_hops = 0;
static long long N_finished_packets = 0;
static long long total_msg_sz = 0;
static long long N_finished_msgs = 0;
static long long N_finished_chunks = 0;
/* convert ns to seconds */
static tw_stime ns_to_s(tw_stime ns)
{
return(ns / (1000.0 * 1000.0 * 1000.0));
}
static double bytes_to_gigabytes(double bytes)
{
return bytes / (double) (1024 * 1024 * 1024);
}
static int dragonfly_rank_hash_compare(
void *key, struct qhash_head *link)
{
struct dfly_hash_key *message_key = (struct dfly_hash_key *)key;
struct dfly_qhash_entry *tmp = NULL;
tmp = qhash_entry(link, struct dfly_qhash_entry, hash_link);
if (tmp->key.message_id == message_key->message_id
&& tmp->key.sender_id == message_key->sender_id)
return 1;
return 0;
}
static int dragonfly_hash_func(void *k, int table_size)
{
struct dfly_hash_key *tmp = (struct dfly_hash_key *)k;
uint32_t pc = 0, pb = 0;
bj_hashlittle2(tmp, sizeof(*tmp), &pc, &pb);
return (int)(pc % (table_size - 1));
/*uint64_t key = (~tmp->message_id) + (tmp->message_id << 18);
key = key * 21;
key = ~key ^ (tmp->sender_id >> 4);
key = key * tmp->sender_id;
return (int)(key & (table_size - 1));*/
}
/* convert GiB/s and bytes to ns */
static tw_stime bytes_to_ns(uint64_t bytes, double GB_p_s)
{
tw_stime time;
/* bytes to GB */
time = ((double)bytes)/(1024.0*1024.0*1024.0);
/* GiB to s */
time = time / GB_p_s;
/* s to ns */
time = time * 1000.0 * 1000.0 * 1000.0;
return(time);
}
/* returns the dragonfly message size */
int dragonfly_custom_get_msg_sz(void)
{
return sizeof(terminal_custom_message);
}
static void free_tmp(void * ptr)
{
struct dfly_qhash_entry * dfly = (dfly_qhash_entry *)ptr;
if(dfly->remote_event_data)
free(dfly->remote_event_data);
if(dfly)
free(dfly);
}
int get_vcg_from_category(terminal_custom_message * msg)
{
if(strcmp(msg->category, "high") == 0)
return Q_HIGH;
else if(strcmp(msg->category, "medium") == 0)
return Q_MEDIUM;
else
tw_error(TW_LOC, "\n priority needs to be specified with qos_levels>1 %d", msg->category);
}
static void append_to_terminal_custom_message_list(
terminal_custom_message_list ** thisq,
terminal_custom_message_list ** thistail,
int index,
terminal_custom_message_list *msg) {
// printf("\n msg id %d ", msg->msg.packet_ID);
if(thisq[index] == NULL) {
thisq[index] = msg;
} else {
assert(thistail[index] != NULL);
thistail[index]->next = msg;
msg->prev = thistail[index];
}
thistail[index] = msg;
// printf("\n done adding %d ", msg->msg.packet_ID);
}
static void prepend_to_terminal_custom_message_list(
terminal_custom_message_list ** thisq,
terminal_custom_message_list ** thistail,
int index,
terminal_custom_message_list *msg) {
if(thisq[index] == NULL) {
thistail[index] = msg;
} else {
thisq[index]->prev = msg;
msg->next = thisq[index];
}
thisq[index] = msg;
}
static terminal_custom_message_list* return_head(
terminal_custom_message_list ** thisq,
terminal_custom_message_list ** thistail,
int index) {
terminal_custom_message_list *head = thisq[index];
if(head != NULL) {
thisq[index] = head->next;
if(head->next != NULL) {
head->next->prev = NULL;
head->next = NULL;
} else {
thistail[index] = NULL;
}
}
return head;
}