diff --git a/README-vis.md b/README-vis.md new file mode 100644 index 0000000000000000000000000000000000000000..4a419d781e1a4bc095b2c686df60ebed0789bf67 --- /dev/null +++ b/README-vis.md @@ -0,0 +1,127 @@ +## README for using ROSS instrumentation in CODES + +For details about the ROSS instrumentation, see the [ROSS Instrumentation blog post](http://carothersc.github.io/ROSS/feature/instrumentation.html) on the ROSS webpage. +The instrumentation will be merged into the master branch of the ROSS repo very soon. + +There are currently 3 types of instrumentation: GVT-based, real time, and event tracing. See the ROSS documentation for more info on +the specific options or use `--help` with your model. The GVT-based and real time sampling do not require any changes to your model code. +The event tracing will run without any changes, but some additions to the model code is needed in order to get specific model event types. +This document describes how to do it. + +### Register LP event tracing function + +The examples here are based on the server LP for the synthetic workload generation for dragonfly (`src/network-workloads/model-net-synthetic.c`). + +As described in the ROSS Vis documentation, we need to first add our function that will save the event type (and any other desired data) to the +buffer location provided by ROSS. +```C +void svr_event_collect(svr_msg *m, tw_lp *lp, char *buffer) +{ + int type = (int) m->svr_event_type; + memcpy(buffer, &type, sizeof(type)); +} +``` + +Then we need to create a `st_trace_type` struct with the pointer and size information. +```C +st_trace_type svr_trace_types[] = { + {(rbev_trace_f) svr_event_collect, + sizeof(int), + (ev_trace_f) svr_event_collect, + sizeof(int)}, + {0} +} +``` + +And a function to return this struct +```C +static const st_trace_type *svr_get_trace_types(void) +{ + return(&svr_trace_types[0]); +} +``` + +As a reminder, there are two types of event tracing the full event trace (`ev_trace_f`) or only events that trigger rollbacks (`rbev_trace_f`). +It's set up so that you can have different functions for both types of event tracing, or you can use the same function for both. +Immediately after each function pointer is a `size_t` type that takes the amount of data that the function will be placing in the buffer, +so ROSS can appropriately handle things. + +If you have multiple LPs, you can do a `st_trace_type` for each LP, or you can reuse. *Note*: You can only reuse `st_trace_type` and the event type collection +function for LPs that use the same type of message struct. For example, the dragonfly terminal and router LPs both use the `terminal_message` struct, so they can +use the same functions for event tracing. However the model net base LP uses the `model_net_wrap_msg` struct, so it gets its own event collection function and +`st_trace_type` struct, in order to read the event type correctly from the model. + +`codes_mapping_init()` was changed to register the function pointers when it is setting up the LP types. So for CODES models, you need to add a register function: +```C +void svr_register_trace() +{ + trace_type_register("server", svr_get_trace_types()); +} +``` + +`trace_type_register(const char* name, const st_trace_type* type)` is part of the API and lets CODES know the pointers for LP initialization. + +Now in the main function, you call the register function *before* calling `codes_mapping_setup()`. +```C +if (g_st_ev_trace) + svr_register_trace(); +``` + +`g_st_ev_trace` is a ROSS flag for determining if event tracing is turned on. + +That's all you need to add for each LP. + +### Model Net LPs +In addition to the dragonfly synthetic server LP, I've already added in the necessary changes for both the model net base LP type and dragonfly (both router and terminal LPs), +so no other changes need to be made to those LPs. (Unless you want to collect some additional data.) +For any other network LPs that are based on the model net base LP type, there are a few additional details to know. +There are two fields added to the `model_net_method` struct for pointers to the trace registration functions for each LP. + +```C +void (*mn_trace_register)(st_trace_type *base_type); +const st_trace_type* (*mn_get_trace_type)(); +``` + +For example, right now, both the dragonfly router and terminal LPs use the same `st_trace_type dragonfly_trace_types` struct and the following function to return its pointer: +```C +static const st_trace_type *dragonfly_get_trace_types(void) +{ + return(&dragonfly_trace_types[0]); +} +``` + +They have different register functions: +```C +static void dragonfly_register_trace(st_trace_type *base_type) +{ + trace_type_register(LP_CONFIG_NM_TERM, base_type); +} + +static void router_register_trace(st_trace_type *base_type) +{ + trace_type_register(LP_CONFIG_NM_ROUT, base_type); +} +``` + +And then the following additions to their `model_net_method` structs: +```C +struct model_net_method dragonfly_method = +{ + // the fields already in the struct + ... + // event tracing additions + .mn_trace_register = dragonfly_register_trace, + .mn_get_trace_type = dragonfly_get_trace_types, +}; + +struct model_net_method dragonfly_router_method = +{ + // the fields already in the struct + ... + // event tracing additions + .mn_trace_register = router_register_trace, + .mn_get_trace_type = dragonfly_get_trace_types, +}; +``` + +Any other LPs built off of the model net LP, can be changed in the same way. diff --git a/codes/lp-type-lookup.h b/codes/lp-type-lookup.h index 2b4dc1501b79b913ad679249ef3a18f9815d6313..d3c0540a23b2cf29978f434082b4e7ccb4697204 100644 --- a/codes/lp-type-lookup.h +++ b/codes/lp-type-lookup.h @@ -21,6 +21,8 @@ const tw_lptype* lp_type_lookup(const char* name); /* register an LP with CODES/ROSS */ void lp_type_register(const char* name, const tw_lptype* type); +void trace_type_register(const char* name, const st_trace_type* type); +const st_trace_type* trace_type_lookup(const char* name); #ifdef __cplusplus } #endif diff --git a/codes/model-net-method.h b/codes/model-net-method.h index 98a722c6de885b32416f35e829a33095c6b087cf..2ed54a898094552c629e4c2113038a435cbe734d 100644 --- a/codes/model-net-method.h +++ b/codes/model-net-method.h @@ -63,6 +63,8 @@ struct model_net_method revent_f mn_sample_rc_fn; init_f mn_sample_init_fn; final_f mn_sample_fini_fn; + void (*mn_trace_register)(st_trace_type *base_type); + const st_trace_type* (*mn_get_trace_type)(); }; extern struct model_net_method * method_array[]; diff --git a/codes/net/dragonfly.h b/codes/net/dragonfly.h index 65ab4c89d6e264a566151bd9687c8edfd5d7ed13..1fe03d52f2189ca443374547ed6652db9da7744d 100644 --- a/codes/net/dragonfly.h +++ b/codes/net/dragonfly.h @@ -13,6 +13,9 @@ extern "C" { #include +extern void dragonfly_register_evcol(); +extern void router_register_evcol(); + typedef struct terminal_message terminal_message; /* this message is used for both dragonfly compute nodes and routers */ diff --git a/src/network-workloads/model-net-synthetic.c b/src/network-workloads/model-net-synthetic.c index fd7f658412af3eaab1ef495ffbe1aa59e0fb321a..8461264a6a508f1f50600c7608d96ccdf4af9c83 100644 --- a/src/network-workloads/model-net-synthetic.c +++ b/src/network-workloads/model-net-synthetic.c @@ -15,6 +15,7 @@ #include "codes/codes_mapping.h" #include "codes/configuration.h" #include "codes/lp-type-lookup.h" +#include "codes/net/dragonfly.h" #define PAYLOAD_SZ 2048 @@ -105,6 +106,34 @@ tw_lptype svr_lp = { sizeof(svr_state), }; +/* setup for the ROSS event tracing + * can have a different function for rbev_trace_f and ev_trace_f + * but right now it is set to the same function for both + */ +void svr_event_collect(svr_msg *m, tw_lp *lp, char *buffer) +{ + int type = (int) m->svr_event_type; + memcpy(buffer, &type, sizeof(type)); +} + +st_trace_type svr_trace_types[] = { + {(rbev_trace_f) svr_event_collect, + sizeof(int), + (ev_trace_f) svr_event_collect, + sizeof(int)}, + {0} +}; + +static const st_trace_type *svr_get_trace_types(void) +{ + return(&svr_trace_types[0]); +} + +void svr_register_trace() +{ + trace_type_register("server", svr_get_trace_types()); +} + const tw_optdef app_opt [] = { TWOPT_GROUP("Model net synthetic traffic " ), @@ -364,6 +393,9 @@ int main( model_net_register(); svr_add_lp_type(); + if (g_st_ev_trace) + svr_register_trace(); + codes_mapping_setup(); net_ids = model_net_configure(&num_nets); diff --git a/src/networks/model-net/dragonfly.c b/src/networks/model-net/dragonfly.c index dcc0f085077db83c872d38069fd72209de88fb9a..ad64c3ff92b9d686a6ed251f563b18775a9fc266 100644 --- a/src/networks/model-net/dragonfly.c +++ b/src/networks/model-net/dragonfly.c @@ -3264,6 +3264,37 @@ tw_lptype dragonfly_lps[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0}, }; +/* For ROSS event tracing */ +void dragonfly_event_collect(terminal_message *m, tw_lp *lp, char *buffer) +{ + int type = (int) m->type; + memcpy(buffer, &type, sizeof(type)); +} + +st_trace_type dragonfly_trace_types[] = { + {(rbev_trace_f) dragonfly_event_collect, + sizeof(int), + (ev_trace_f) dragonfly_event_collect, + sizeof(int)}, + {0} +}; + +static const st_trace_type *dragonfly_get_trace_types(void) +{ + return(&dragonfly_trace_types[0]); +} + +static void dragonfly_register_trace(st_trace_type *base_type) +{ + trace_type_register(LP_CONFIG_NM_TERM, base_type); +} + +static void router_register_trace(st_trace_type *base_type) +{ + trace_type_register(LP_CONFIG_NM_ROUT, base_type); +} +/*** END of ROSS event tracing additions */ + /* returns the dragonfly lp type for lp registration */ static const tw_lptype* dragonfly_get_cn_lp_type(void) { @@ -3299,7 +3330,9 @@ struct model_net_method dragonfly_method = .mn_sample_fn = (void*)dragonfly_sample_fn, .mn_sample_rc_fn = (void*)dragonfly_sample_rc_fn, .mn_sample_init_fn = (void*)dragonfly_sample_init, - .mn_sample_fini_fn = (void*)dragonfly_sample_fin + .mn_sample_fini_fn = (void*)dragonfly_sample_fin, + .mn_trace_register = dragonfly_register_trace, + .mn_get_trace_type = dragonfly_get_trace_types, }; struct model_net_method dragonfly_router_method = @@ -3318,5 +3351,7 @@ struct model_net_method dragonfly_router_method = .mn_sample_fn = (void*)dragonfly_rsample_fn, .mn_sample_rc_fn = (void*)dragonfly_rsample_rc_fn, .mn_sample_init_fn = (void*)dragonfly_rsample_init, - .mn_sample_fini_fn = (void*)dragonfly_rsample_fin + .mn_sample_fini_fn = (void*)dragonfly_rsample_fin, + .mn_trace_register = router_register_trace, + .mn_get_trace_type = dragonfly_get_trace_types, }; diff --git a/src/networks/model-net/model-net-lp.c b/src/networks/model-net/model-net-lp.c index 7ee3537399de417c09417557e09e91660ecedc9e..f4ca25122baca98b50bd138829c3756dd2c92cc1 100644 --- a/src/networks/model-net/model-net-lp.c +++ b/src/networks/model-net/model-net-lp.c @@ -113,6 +113,23 @@ tw_lptype model_net_base_lp = { sizeof(model_net_base_state), }; +/* setup for the ROSS event tracing + * can have a different function for rbev_trace_f and ev_trace_f + * but right now it is set to the same function for both + */ +void mn_event_collect(model_net_wrap_msg *m, tw_lp *lp, char *buffer) +{ + int type = (int) m->h.event_type; + memcpy(buffer, &type, sizeof(type)); +} + +st_trace_type mn_trace_types = { + (rbev_trace_f) mn_event_collect, + sizeof(int), + (ev_trace_f) mn_event_collect, + sizeof(int), +}; + /**** END LP, EVENT PROCESSING FUNCTION DECLS ****/ /**** BEGIN IMPLEMENTATIONS ****/ @@ -151,6 +168,13 @@ void model_net_base_register(int *do_config_nets){ &model_net_base_lp); else method_array[i]->mn_register(&model_net_base_lp); + if (g_st_ev_trace) // for ROSS event tracing + { + if (method_array[i]->mn_trace_register == NULL) + trace_type_register(model_net_lp_config_names[i], &mn_trace_types); + else + method_array[i]->mn_trace_register(&mn_trace_types); + } } } } diff --git a/src/util/codes_mapping.c b/src/util/codes_mapping.c index ed703a526182d72c9366394a670de23b0d7f2bf4..647879df886940948d91aed10a6b3fe2b2459e81 100644 --- a/src/util/codes_mapping.c +++ b/src/util/codes_mapping.c @@ -458,6 +458,7 @@ static void codes_mapping_init(void) tw_lpid nkp_per_pe = g_tw_nkp; tw_lpid lpid, kpid; const tw_lptype *lptype; + const st_trace_type *trace_type; /* have 16 kps per pe, this is the optimized configuration for ROSS custom mapping */ for(kpid = 0; kpid < nkp_per_pe; kpid++) @@ -488,6 +489,11 @@ static void codes_mapping_init(void) else /* sorry, const... */ tw_lp_settype(ross_lid, (tw_lptype*) lptype); + if (g_st_ev_trace) + { + trace_type = trace_type_lookup(lp_type_name); + st_evtrace_settype(ross_lid, (st_trace_type*) trace_type); + } } return; } diff --git a/src/util/lp-type-lookup.c b/src/util/lp-type-lookup.c index fe17ee5b9d92e1a94b66944edfe6d117144a7d31..452bc3ebbc2947524ca6b4b16615d0a8cb690490 100644 --- a/src/util/lp-type-lookup.c +++ b/src/util/lp-type-lookup.c @@ -16,6 +16,7 @@ struct lp_name_mapping { const char* name; const tw_lptype* type; + const st_trace_type* trace_type; }; static struct lp_name_mapping map_array[MAX_LP_TYPES]; @@ -46,6 +47,35 @@ const tw_lptype* lp_type_lookup(const char* name) return(NULL); } +// needs to be called after lp_type_register() +void trace_type_register(const char* name, const st_trace_type* type) +{ + int i; + + for(i=0; i