Commit 8df9827f authored by Hendryk Bockelmann's avatar Hendryk Bockelmann
Browse files

(key, value) attribute interface for hdf5 report added

parent 7c31acbd
......@@ -45,6 +45,9 @@ static const int root = 0;
// meta data:
static sct_meta_type *meta_pool;
// attribute table:
static sct_attribute_table *attribute_table = NULL;
// context free thread private marks:
/// \todo Threadprivate pragma can be replaced by double allocation, access might be faster for some compilers
static sct_mark_type *mark_pool = NULL; // mark_pool[itimer]
......@@ -308,6 +311,111 @@ char *sct_get_event_cname(const int ie) {
#endif
}
// attributes:
sct_attribute_table *sct_internal_create_attribute_table(void) {
sct_attribute_table *t;
if ( !(t = (sct_attribute_table*) malloc(sizeof(sct_attribute_table))) )
sct_abort("memory allocation failed", __FILE__, __LINE__);
t->first = NULL;
return t;
}
const sct_attribute_table *sct_internal_get_attribute_table(void) {
return attribute_table;
}
void sct_add_report_attribute_int(const char *key, int val) {
if (attribute_table == NULL) attribute_table = sct_internal_create_attribute_table();
sct_attribute_type *a;
if ( !(a = (sct_attribute_type*) malloc(sizeof(sct_attribute_type))) )
sct_abort("memory allocation failed", __FILE__, __LINE__);
a->key = key;
a->type = SCT_INT;
int *i = (int*) malloc(sizeof(int));
*i = val;
a->value = i;
a->next = attribute_table->first;
attribute_table->first = a;
}
void sct_add_report_attribute_long(const char *key, long val) {
if (attribute_table == NULL) attribute_table = sct_internal_create_attribute_table();
sct_attribute_type *a;
if ( !(a = (sct_attribute_type*) malloc(sizeof(sct_attribute_type))) )
sct_abort("memory allocation failed", __FILE__, __LINE__);
a->key = key;
a->type = SCT_LONG;
long *i = (long*) malloc(sizeof(long));
*i = val;
a->value = i;
a->next = attribute_table->first;
attribute_table->first = a;
}
void sct_add_report_attribute_float(const char *key, float val) {
if (attribute_table == NULL) attribute_table = sct_internal_create_attribute_table();
sct_attribute_type *a;
if ( !(a = (sct_attribute_type*) malloc(sizeof(sct_attribute_type))) )
sct_abort("memory allocation failed", __FILE__, __LINE__);
a->key = key;
a->type = SCT_FLOAT;
float *i = (float*) malloc(sizeof(float));
*i = val;
a->value = i;
a->next = attribute_table->first;
attribute_table->first = a;
}
void sct_add_report_attribute_double(const char *key, double val) {
if (attribute_table == NULL) attribute_table = sct_internal_create_attribute_table();
sct_attribute_type *a;
if ( !(a = (sct_attribute_type*) malloc(sizeof(sct_attribute_type))) )
sct_abort("memory allocation failed", __FILE__, __LINE__);
a->key = key;
a->type = SCT_DOUBLE;
double *i = (double*) malloc(sizeof(double));
*i = val;
a->value = i;
a->next = attribute_table->first;
attribute_table->first = a;
}
void sct_add_report_attribute_string(const char *key, char *val) {
if (attribute_table == NULL) attribute_table = sct_internal_create_attribute_table();
sct_attribute_type *a;
if ( !(a = (sct_attribute_type*) malloc(sizeof(sct_attribute_type))) )
sct_abort("memory allocation failed", __FILE__, __LINE__);
a->key = key;
a->type = SCT_STRING;
a->value = val;
a->next = attribute_table->first;
attribute_table->first = a;
}
void sct_internal_free_attribute_table(void) {
if (attribute_table != NULL) {
sct_attribute_type *a, *nexta;
for (a = attribute_table->first; nexta != NULL; a = nexta) {
nexta = a->next;
if (a->type == SCT_INT ||
a->type == SCT_LONG ||
a->type == SCT_FLOAT ||
a->type == SCT_DOUBLE) free(a->value);
free(a);
}
free(attribute_table);
}
}
// contexts:
int sct_get_context_num() {
......@@ -1022,6 +1130,9 @@ void sct_finalize() {
PAPI_shutdown();
}
#endif
// cleanup any attributes
sct_internal_free_attribute_table();
}
......
......@@ -121,6 +121,29 @@ typedef struct {
} sct_mark_type;
typedef enum {
SCT_INT = 0,
SCT_LONG,
SCT_FLOAT,
SCT_DOUBLE,
SCT_STRING,
SCT_VALUE_UNDEFINED
} sct_attribute_value_type;
/*! \brief attribute type to hold a generic key-value pair to be used for reporting */
typedef struct sct_attribute {
const char* key;
void* value;
sct_attribute_value_type type;
struct sct_attribute *next;
} sct_attribute_type;
/*! \brief attribute table implemented as linked list of attributes*/
typedef struct {
sct_attribute_type *first;
} sct_attribute_table;
// declarations:
//public+
......@@ -245,6 +268,23 @@ void sct_set_eventcounters(const int val);
*/
void sct_set_nestedtimers(const int val);
/*! \brief add attribute for timer report in key-value pair style
\param[in] key
\param[in] val
*/
void sct_add_report_attribute_int(const char *key, int val);
void sct_add_report_attribute_long(const char *key, long val);
void sct_add_report_attribute_float(const char *key, float val);
void sct_add_report_attribute_double(const char *key, double val);
void sct_add_report_attribute_string(const char *key, char *val);
#define sct_add_report_attribute(_1, _2) _Generic((_2), \
int: sct_add_report_attribute_int, \
long: sct_add_report_attribute_long, \
float: sct_add_report_attribute_float, \
double: sct_add_report_attribute_double, \
char*: sct_add_report_attribute_string \
)(_1,_2)
//public-
/*! \brief stop timer if active - do nothing else
......@@ -278,4 +318,8 @@ void sct_internal_free_event_arrays(sct_stats_type *s);
int sct_internal_get_max_name_length();
int sct_internal_get_name_length(const int it);
sct_attribute_table *sct_internal_create_attribute_table(void);
const sct_attribute_table *sct_internal_get_attribute_table(void);
void sct_internal_free_attribute_table(void);
#endif
......@@ -581,18 +581,70 @@ static void report_hdf5(int timer_choice){
#endif
hid_t attr_id = H5Screate(H5S_SCALAR);
/* separate sct internal attributes into group */
hid_t group_id = H5Gcreate(file_id, "sct_internal_attributes", H5P_DEFAULT,
H5P_DEFAULT, H5P_DEFAULT);
status = H5Tset_size(attr_type, strlen(prog_mode)+1);
status = H5Tset_strpad(attr_type, H5T_STR_NULLTERM);
hid_t attr = H5Acreate(file_id, "sct program mode", attr_type, attr_id,
hid_t attr = H5Acreate(group_id, "sct program mode", attr_type, attr_id,
H5P_DEFAULT, H5P_DEFAULT);
status = H5Awrite(attr, attr_type, prog_mode);
status = H5Aclose(attr);
status = H5Tset_size(attr_type, strlen(print_prg_start_time())+1);
status = H5Tset_strpad(attr_type, H5T_STR_NULLTERM);
attr = H5Acreate(file_id, "sct start time", attr_type, attr_id,
attr = H5Acreate(group_id, "sct start time", attr_type, attr_id,
H5P_DEFAULT, H5P_DEFAULT);
status = H5Awrite(attr, attr_type, print_prg_start_time());
status = H5Aclose(attr);
status = H5Gclose(group_id);
/* add various attributes if attribute_table is not NULL */
const sct_attribute_table *attr_table = sct_internal_get_attribute_table();
if ( attr_table != NULL ) {
group_id = H5Gcreate(file_id, "report_attributes", H5P_DEFAULT,
H5P_DEFAULT, H5P_DEFAULT);
sct_attribute_type *a;
for (a = attr_table->first; a != NULL; a = a->next) {
switch (a->type) {
case SCT_INT:
attr = H5Acreate(group_id, a->key, H5T_NATIVE_INT, attr_id,
H5P_DEFAULT, H5P_DEFAULT);
status = H5Awrite(attr, H5T_NATIVE_INT, a->value);
break;
case SCT_LONG:
attr = H5Acreate(group_id, a->key, H5T_NATIVE_LONG, attr_id,
H5P_DEFAULT, H5P_DEFAULT);
status = H5Awrite(attr, H5T_NATIVE_LONG, a->value);
break;
case SCT_FLOAT:
attr = H5Acreate(group_id, a->key, H5T_NATIVE_FLOAT, attr_id,
H5P_DEFAULT, H5P_DEFAULT);
status = H5Awrite(attr, H5T_NATIVE_FLOAT, a->value);
break;
case SCT_DOUBLE:
attr = H5Acreate(group_id, a->key, H5T_NATIVE_DOUBLE, attr_id,
H5P_DEFAULT, H5P_DEFAULT);
status = H5Awrite(attr, H5T_NATIVE_DOUBLE, a->value);
break;
case SCT_STRING:
status = H5Tset_size(attr_type, strlen(a->value)+1);
status = H5Tset_strpad(attr_type, H5T_STR_NULLTERM);
attr = H5Acreate(group_id, a->key, attr_type, attr_id,
H5P_DEFAULT, H5P_DEFAULT);
status = H5Awrite(attr, attr_type, a->value);
break;
default:
sct_abort("internal error", __FILE__, __LINE__);
}
status = H5Aclose(attr);
}
status = H5Gclose(group_id);
}
#ifdef HAVE_MPI
attr = H5Acreate(file_id, "number of MPI tasks", H5T_NATIVE_INT, attr_id,
......@@ -717,7 +769,7 @@ static void report_hdf5(int timer_choice){
/* group for the context which is accessible via "red->context_name.cs" */
hid_t group_id = H5Gcreate(file_id, red->context_name.cs, H5P_DEFAULT,
H5P_DEFAULT, H5P_DEFAULT);
H5P_DEFAULT, H5P_DEFAULT);
/* timer names are valid for all following groups */
hid_t dataspace_id = H5Screate_simple(2, timername_dims, NULL);
......
......@@ -181,6 +181,13 @@ int main( int argc, char **argv ) {
free(mresult);
}
/* specify some dummy attributes (key-value pairs) for timer report */
sct_add_report_attribute("fooINT", 42);
sct_add_report_attribute("fooLONG", (long)42);
sct_add_report_attribute("fooFLOAT", (float)15.7);
sct_add_report_attribute("fooDOUBLE", 15.7);
sct_add_report_attribute("bar", "test");
sct_report(SCT_GETENV, SCT_GETENV, SCT_GETENV);
#ifdef HAVE_MPI
MPI_Barrier(MPI_COMM_WORLD);
......
Supports Markdown
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