Commit 1cf89cc7 authored by Philip Carns's avatar Philip Carns

copy over misc. utility code from CODES repo

parent 507b01d9
/*
* Copyright (C) 2013, University of Chicago
*
* See COPYRIGHT notice in top-level directory.
*/
#ifndef CODES_H
#define CODES_H
#include <ross.h>
#include <assert.h>
#if 0
#define codes_event_new tw_event_new
#else
static inline tw_event * codes_event_new(
tw_lpid dest_gid,
tw_stime offset_ts,
tw_lp * sender)
{
tw_stime abs_ts = offset_ts + tw_now(sender);
assert(abs_ts < g_tw_ts_end);
//printf("codes_event_new() abs_ts: %.9f\n", abs_ts);
return(tw_event_new(dest_gid, offset_ts, sender));
}
#endif
/* TODO: validate what value we should use here */
/* Modeled latency for communication between local software components and
* communication between daemons and hardware devices. Measured in
* nanoseconds.
*/
#define CODES_MEAN_LOCAL_LATENCY 0.01
static inline tw_stime codes_local_latency(tw_lp *lp)
{
tw_stime tmp;
tmp = tw_rand_exponential(lp->rng, CODES_MEAN_LOCAL_LATENCY);
return(tmp);
}
static inline void codes_local_latency_reverse(tw_lp *lp)
{
tw_rand_reverse_unif(lp->rng);
return;
}
#endif /* CODES_H */
/*
* Local variables:
* c-indent-level: 4
* c-basic-offset: 4
* End:
*
* vim: ft=c ts=8 sts=4 sw=4 expandtab
*/
/*
* Copyright (C) 2011, University of Chicago
*
* See COPYRIGHT notice in top-level directory.
*/
/* SUMMARY:
* CODES custom mapping file for ROSS
*/
#include "configuration.h"
#include "codes.h"
#include "lp-type-lookup.h"
#define MAX_NAME_LENGTH 256
/* number of LPs assigned to the current PE (abstraction of MPI rank) */
static int lps_for_this_pe = 0;
/* data structure to hold configuration */
configuration_t config;
/* char arrays for holding lp type name and group name*/
char local_grp_name[MAX_NAME_LENGTH], local_lp_name[MAX_NAME_LENGTH];
/* Returns number of LPs on the current PE */
int codes_mapping_get_lps_for_pe(void);
/* Takes the global LP ID and returns the rank (PE id) on which the LP is mapped.*/
tw_peid codes_mapping( tw_lpid gid);
/* loads the configuration file and sets up the number of LPs on each PE. */
void codes_mapping_setup(char* filepath);
/* Takes the group name , type name, rep ID and offset (for that lp type + repetition) and then returns the global LP ID. */
void codes_mapping_get_lp_id(char* grp_name, char* lp_type_name, int rep_id, int offset, tw_lpid* gid);
/* takes the LP ID and returns its grp name and index, lp type name and ID, repetition ID and the offset of the LP
* (for multiple LPs in a repetition). */
void codes_mapping_get_lp_info(tw_lpid gid, char* grp_name, int* grp_id, int* lp_type_id, char* lp_type_name, int* grp_rep_id, int* offset);
/* assigns local and global lp ids for ROSS. */
void codes_mapping_init(void);
/* Takes the global LP ID, maps it to the local LP ID and returns the LP.
* lps have global and local LP IDs.
* global LP IDs are unique across all PEs, local LP IDs are unique within a PE. */
tw_lp * codes_mapping_to_lp( tw_lpid lpid);
#ifndef __CONFIGURATION_H__
#define __CONFIGURATION_H__
#include <stdint.h>
#include <stdlib.h>
#define CONFIGURATION_MAX_NAME 256
#define CONFIGURATION_MAX_GROUPS 10
#define CONFIGURATION_MAX_TYPES 10
typedef struct config_lptype_s
{
char name[CONFIGURATION_MAX_NAME];
uint64_t count;
} config_lptype_t;
typedef struct config_lpgroup_s
{
char name[CONFIGURATION_MAX_NAME];
uint64_t repetitions;
config_lptype_t lptypes[CONFIGURATION_MAX_TYPES];
uint64_t lptypes_count;
} config_lpgroup_t;
typedef struct configuration_s
{
config_lpgroup_t lpgroups[CONFIGURATION_MAX_GROUPS];
uint64_t lpgroups_count;
} configuration_t;
int configuration_load (const char * filepath, configuration_t *config);
int configuration_dump (configuration_t *config);
#endif
This diff is collapsed.
/*
* Copyright (C) 2011, University of Chicago
*
* See COPYRIGHT notice in top-level directory.
*/
#ifndef LP_IO_H
#define LP_IO_H
#include <ross.h>
typedef char* lp_io_handle;
#define LP_IO_UNIQ_SUFFIX 1
/* to be called (collectively) before running simulation to prepare the
* output directory.
*/
int lp_io_prepare(char *directory, int flags, lp_io_handle* handle, MPI_Comm comm);
/* to be called within LPs to store a block of data */
int lp_io_write(tw_lpid gid, char* identifier, int size, void* buffer);
/* to be called (collectively) after tw_run() to flush data to disk */
int lp_io_flush(lp_io_handle handle, MPI_Comm comm);
/* retrieves the directory name for a handle */
static inline char* lp_io_handle_to_dir(lp_io_handle handle)
{
return(strdup(handle));
}
#endif /* LP_IO_H */
/*
* Local variables:
* c-indent-level: 4
* c-basic-offset: 4
* End:
*
* vim: ft=c ts=8 sts=4 sw=4 expandtab
*/
/*
* Copyright (C) 2013, University of Chicago
*
* See COPYRIGHT notice in top-level directory.
*/
#ifndef LP_TYPE_LOOKUP_H
#define LP_TYPE_LOOKUP_H
#include "ross.h"
const tw_lptype* lp_type_lookup(const char* name);
void lp_type_register(const char* name, const tw_lptype* type);
#endif /* LP_TYPE_LOOKUP_H */
/*
* Local variables:
* c-indent-level: 4
* c-basic-offset: 4
* End:
*
* vim: ft=c ts=8 sts=4 sw=4 expandtab
*/
...@@ -55,7 +55,13 @@ nobase_include_HEADERS = \ ...@@ -55,7 +55,13 @@ nobase_include_HEADERS = \
codes/codesparser.h \ codes/codesparser.h \
codes/quickhash.h \ codes/quickhash.h \
codes/configfile.h \ codes/configfile.h \
codes/quicklist.h codes/quicklist.h \
codes/codes_mapping.h \
codes/lp-type-lookup.h \
codes/codes.h \
codes/configuration.h \
codes/dotconf.h \
codes/lp-io.h
src_libcodes_base_a_SOURCES = \ src_libcodes_base_a_SOURCES = \
codes/codesparser.h \ codes/codesparser.h \
...@@ -90,6 +96,11 @@ src_libcodes_base_a_SOURCES = \ ...@@ -90,6 +96,11 @@ src_libcodes_base_a_SOURCES = \
src/util/red-black-tree.c \ src/util/red-black-tree.c \
src/util/codes-callbacks.h \ src/util/codes-callbacks.h \
src/util/codes-callbacks.c \ src/util/codes-callbacks.c \
src/util/codes_mapping.c \
src/util/lp-type-lookup.c \
src/util/configuration.c \
src/util/dotconf.c \
src/util/lp-io.c \
codes/codeslogging.h \ codes/codeslogging.h \
src/logging/codeslogging.c \ src/logging/codeslogging.c \
codes/timeline.h \ codes/timeline.h \
......
/*
* Copyright (C) 2011, University of Chicago
*
* See COPYRIGHT notice in top-level directory.
*/
/* SUMMARY:
* CODES custom mapping file for ROSS
*/
#include "codes/codes_mapping.h"
int codes_mapping_get_lps_for_pe()
{
return lps_for_this_pe;
}
/* Takes the global LP ID and returns the rank (PE id) on which the LP is mapped */
tw_peid codes_mapping( tw_lpid gid)
{
return gid / lps_for_this_pe;
}
/* This function loads the configuration file and sets up the number of LPs on each PE */
void codes_mapping_setup(char* filepath)
{
/* TODO: Add full file path? This one only runs from current directory */
configuration_load(filepath, &config);
configuration_dump(&config);
int grp, lpt;
int pes = tw_nnodes();
for (grp = 0; grp < config.lpgroups_count; grp++)
{
for (lpt = 0; lpt < config.lpgroups[grp].lptypes_count; lpt++)
lps_for_this_pe += (config.lpgroups[grp].lptypes[lpt].count * config.lpgroups[grp].repetitions);
}
lps_for_this_pe /= pes;
//printf("\n LPs for this PE are %d reps %d ", lps_for_this_pe, config.lpgroups[grp].repetitions);
}
/* This function takes the group ID , type ID and rep ID then returns the global LP ID */
/* TODO: Add string based search for LP group and type names */
void codes_mapping_get_lp_id(char* grp_name, char* lp_type_name, int rep_id, int offset, tw_lpid* gid)
{
int grp, lpt, lpcount = 0, lp_types_count, rep, count_for_this_lpt;
short found = 0;
// Account for all lps in the previous groups
for(grp = 0; grp < config.lpgroups_count; grp++)
{
lp_types_count = config.lpgroups[grp].lptypes_count;
rep = config.lpgroups[grp].repetitions;
if(strcmp(config.lpgroups[grp].name, grp_name) == 0)
{
found = 1;
break;
}
for(lpt = 0; lpt < lp_types_count; lpt++)
lpcount += (rep * config.lpgroups[grp].lptypes[lpt].count);
}
assert(found);
found = 0;
lp_types_count = config.lpgroups[grp].lptypes_count;
// Account for the previous lp types in the current repetition
for(lpt = 0; lpt < lp_types_count; lpt++)
{
count_for_this_lpt = config.lpgroups[grp].lptypes[lpt].count;
if(strcmp(config.lpgroups[grp].lptypes[lpt].name, lp_type_name) == 0)
{
found = 1;
break;
}
lpcount += count_for_this_lpt;
}
assert(found);
// Account for all previous repetitions
for(rep = 0; rep < rep_id; rep++)
{
for(lpt = 0; lpt < lp_types_count; lpt++)
lpcount += config.lpgroups[grp].lptypes[lpt].count;
}
*gid = lpcount + offset;
}
/* This function takes the LP ID and returns its grp index, lp type ID and repetition ID */
void codes_mapping_get_lp_info(tw_lpid gid, char* grp_name, int* grp_id, int* lp_type_id, char* lp_type_name, int* grp_rep_id, int* offset)
{
int grp, lpt, rep, grp_offset, lp_offset, rep_offset;
int lp_tmp_id, lp_types_count, lp_count;
unsigned long grp_lp_count=0;
short found = 0;
/* Find the group id first */
for(grp = 0; grp < config.lpgroups_count; grp++)
{
grp_offset = 0;
rep_offset = 0;
rep = config.lpgroups[grp].repetitions;
lp_types_count = config.lpgroups[grp].lptypes_count;
for(lpt = 0; lpt < lp_types_count; lpt++)
{
lp_count = config.lpgroups[grp].lptypes[lpt].count;
grp_offset += (rep * lp_count);
rep_offset += lp_count;
}
/* Each gid is assigned an increasing number starting from 0th group and 0th lp type
* so we check here if the gid lies within the numeric range of a group */
if(gid >= grp_lp_count && gid < grp_lp_count + grp_offset)
{
*grp_id = grp;
strcpy(local_grp_name, config.lpgroups[grp].name);
lp_offset = gid - grp_lp_count; /* gets the lp offset starting from the point where the group begins */
*grp_rep_id = lp_offset / rep_offset;
lp_tmp_id = lp_offset - (*grp_rep_id * rep_offset);
found = 1;
break;
}
grp_lp_count += grp_offset; /* keep on increasing the group lp count to next group range*/
}
assert(found);
lp_offset = 0;
found = 0; /* reset found for finding LP type */
/* Now we compute the LP type ID here based on the lp offset that we just got */
for(lpt = 0; lpt < lp_types_count; lpt++)
{
lp_count = config.lpgroups[grp].lptypes[lpt].count;
if(lp_tmp_id >= lp_offset && lp_tmp_id < lp_offset + lp_count)
{
*lp_type_id = lpt;
strcpy(local_lp_name, config.lpgroups[grp].lptypes[lpt].name);
*offset = lp_tmp_id - lp_offset;
found = 1;
break;
}
lp_offset += lp_count;
}
assert(found);
strncpy(grp_name, local_grp_name, MAX_NAME_LENGTH);
strncpy(lp_type_name, local_lp_name, MAX_NAME_LENGTH);
//printf("\n gid %d lp type name %s rep_id %d ", gid, lp_type_name, *grp_rep_id);
}
/* This function assigns local and global LP Ids to LPs */
void codes_mapping_init(void)
{
int grp_id, lpt_id, rep_id, offset;
tw_lpid ross_gid, ross_lid; /* ross global and local IDs */
tw_pe * pe;
char lp_type_name[MAX_NAME_LENGTH];
char grp_name[MAX_NAME_LENGTH];
int nkp_per_pe = 16;
tw_lpid lpid, kpid;
/* have 16 kps per pe, this is the optimized configuration for ROSS custom mapping */
for(kpid = 0; kpid < nkp_per_pe; kpid++)
tw_kp_onpe(kpid, g_tw_pe[0]);
int lp_init_range = g_tw_mynode * lps_for_this_pe;
codes_mapping_get_lp_info(lp_init_range, grp_name, &grp_id, &lpt_id, lp_type_name, &rep_id, &offset);
for (lpid = lp_init_range; lpid < lp_init_range + lps_for_this_pe; lpid++)
{
ross_gid = lpid;
ross_lid = lpid - lp_init_range;
kpid = ross_lid % g_tw_nkp;
pe = tw_getpe(kpid % g_tw_npe);
codes_mapping_get_lp_info(ross_gid, grp_name, &grp_id, &lpt_id, lp_type_name, &rep_id, &offset);
tw_lp_onpe(ross_lid , pe, ross_gid);
tw_lp_onkp(g_tw_lp[ross_lid], g_tw_kp[kpid]);
tw_lp_settype(ross_lid, lp_type_lookup(lp_type_name));
}
return;
}
/* This function takes the global LP ID, maps it to the local LP ID and returns the LP
* lps have global and local LP IDs
* global LP IDs are unique across all PEs, local LP IDs are unique within a PE */
tw_lp * codes_mapping_to_lp( tw_lpid lpid)
{
int index = lpid - (g_tw_mynode * lps_for_this_pe);
// printf("\n global id %d index %d lps_before %d lps_offset %d local index %d ", lpid, index, lps_before, g_tw_mynode, local_index);
return g_tw_lp[index];
}
#include <string.h>
#include "codes/configuration.h"
#include "codes/txt_configfile.h"
int configuration_load (const char *filepath, configuration_t *config)
{
char *errstr;
ConfigHandle ch;
SectionHandle sh;
SectionHandle subsh;
SectionEntry se[10];
SectionEntry subse[10];
size_t se_count = 10;
size_t subse_count = 10;
int i, j, lpt;
char data[256];
memset (config, 0, sizeof(*config));
errstr = NULL;
ch = txtfile_openConfig(filepath, &errstr);
cf_openSection(ch, ROOT_SECTION, "LPGROUPS", &sh);
cf_listSection(ch, sh, se, &se_count);
for (i = 0; i < se_count; i++)
{
printf("section: %s type: %d\n", se[i].name, se[i].type);
if (se[i].type == SE_SECTION)
{
subse_count = 10;
cf_openSection(ch, sh, se[i].name, &subsh);
cf_listSection(ch, subsh, subse, &subse_count);
strncpy(config->lpgroups[i].name, se[i].name,
CONFIGURATION_MAX_NAME);
config->lpgroups[i].repetitions = 1;
config->lpgroups_count++;
for (j = 0, lpt = 0; j < subse_count; j++)
{
if (subse[j].type == SE_KEY)
{
cf_getKey(ch, subsh, subse[j].name, data, sizeof(data));
printf("key: %s value: %s\n", subse[j].name, data);
if (strcmp("repetitions", subse[j].name) == 0)
{
config->lpgroups[i].repetitions = atoi(data);
// printf("\n Repetitions: %d ", config->lpgroups[i].repetitions);
}
else
{
// assume these are lptypes and counts
strncpy(config->lpgroups[i].lptypes[lpt].name,
subse[j].name,
sizeof(config->lpgroups[i].lptypes[lpt].name));
config->lpgroups[i].lptypes[lpt].count = atoi(data);
config->lpgroups[i].lptypes_count++;
lpt++;
}
}
}
cf_closeSection(ch, subsh);
}
}
cf_closeSection(ch, sh);
if (errstr) free(errstr);
return 0;
}
int configuration_dump (configuration_t *config)
{
int grp;
int lpt;
for (grp = 0; grp < config->lpgroups_count; grp++)
{
printf("group: %s\n", config->lpgroups[grp].name);
printf("\trepetitions: %d\n", config->lpgroups[grp].repetitions);
for (lpt = 0; lpt < config->lpgroups[grp].lptypes_count; lpt++)
{
printf("\t%s: %ld\n",
config->lpgroups[grp].lptypes[lpt].name,
config->lpgroups[grp].lptypes[lpt].count);
}
}
return 0;
}
This diff is collapsed.
/*
* Copyright (C) 2011, University of Chicago
*
* See COPYRIGHT notice in top-level directory.
*/
#include <assert.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "codes/lp-io.h"
struct io_buffer
{
tw_lpid gid;
int size;
void* buffer;
struct io_buffer *next;
};
struct identifier
{
char identifier[32];
struct io_buffer *buffers;
int buffers_count;
int buffers_total_size;
struct identifier *next;
};
/* local list of identifiers */
static struct identifier* identifiers = NULL;
int identifiers_count = 0;
/* array of all identifiers used across all procs */
struct identifier global_identifiers[64];
int global_identifiers_count = 0;
static int write_id(char* directory, char* identifier, MPI_Comm comm);
int lp_io_write(tw_lpid gid, char* identifier, int size, void* buffer)
{
struct identifier* id;
struct io_buffer *buf;
if(strlen(identifier) >= 32)
{
fprintf(stderr, "Error: identifier %s too big.\n", identifier);
return(-1);
}
buf = malloc(sizeof(*buf));
if(!buf)
return(-1);
buf->gid = gid;
buf->size = size;
/* allocate copy of data being written */
buf->buffer = malloc(size);
if(!buf->buffer)
{
free(buf);
return(-1);
}
memcpy(buf->buffer, buffer, size);
buf->next = NULL;
/* see if we have this identifier already */
id = identifiers;
while(id && (strcmp(identifier, id->identifier) != 0))
id = id->next;
if(id)
{
/* add buffer to front of list */
buf->next = id->buffers;
id->buffers = buf;
id->buffers_count++;
id->buffers_total_size += size;
}
else
{
/* new identifier */
id = malloc(sizeof(*id));
if(!id)
{
free(buf->buffer);
free(buf);
return(-1);
}
strcpy(id->identifier, identifier);
id->next = identifiers;
identifiers = id;
id->buffers = buf;
id->buffers_count = 1;
id->buffers_total_size = size;
buf->next = NULL;
identifiers_count++;
}
return(0);
}
int lp_io_prepare(char *directory, int flags, lp_io_handle* handle, MPI_Comm comm)
{
int ret;
int rank;
int save_err;
MPI_Comm_rank(comm, &rank);
if(flags & LP_IO_UNIQ_SUFFIX)
{
*handle = malloc(256);
if(!(*handle))
{
return(-1);
}
if(rank == 0)
sprintf(*handle, "%s-%ld-%ld", directory, (long)getpid(), (long)time(NULL));
MPI_Bcast(*handle, 256, MPI_CHAR, 0, comm);
}
else
{
*handle = strdup(directory);
if(!(*handle))
{
return(-1);
}
}
if(rank == 0)
{
/* create output directory */
ret = mkdir(*handle, 0775);
if(ret != 0)
{
save_err = errno;
fprintf(stderr, "mkdir(\"%s\") failed: %s\n", *handle, strerror(save_err));
return(-1);
}
}
MPI_Barrier(comm);
return(0);
}
int lp_io_flush(lp_io_handle handle, MPI_Comm comm)
{
int comm_size;
int rank;
MPI_Status status;
int ret;
int i;
struct identifier *id;
int match = 0;
char* directory = handle;
memset(global_identifiers, 0, 64*sizeof(global_identifiers[0]));
MPI_Comm_size(comm, &comm_size);
MPI_Comm_rank(comm, &rank);
/* The first thing we need to do is come up with a global list of
* identifiers. We can't really guarantee that every MPI proc had data
* written to every identifier, but we want to collectively write each
* ID.
*/
/* To do this, each rank will receive an initial set of ideas from
* rank+1 and add its own identifiers to the set before transmitting to
* rank-1. Rank 0 will then broadcast the results to everyone.
*/
/* get array so far from rank +1 */
if(rank != comm_size-1)
{
ret = MPI_Recv(&global_identifiers_count, 1, MPI_INT, rank+1, 0, comm, &status);
assert(ret == 0);
ret = MPI_Recv(global_identifiers, 64*sizeof(global_identifiers[0]), MPI_BYTE,
rank+1, 0, comm, &status);
assert(ret == 0);
}
/* add our own entries to the array */
id = identifiers;
while(id)
{
match = 0;
for(i = 0; i<global_identifiers_count; i++)
{
if(strcmp(id->identifier, global_identifiers[i].identifier) == 0)
{
match = 1;
break;
}
}
if(!match)
{
assert(global_identifiers_count < 64);
global_identifiers[global_identifiers_count] = *id;
global_identifiers_count++;
}
id = id->next;
}
/* send results to rank-1 */
if(rank != 0)
{
ret = MPI_Send(&global_identifiers_count, 1, MPI_INT, rank-1, 0, comm);
assert(ret == 0);
ret = MPI_Send(global_identifiers, 64*sizeof(global_identifiers[0]), MPI_BYTE,
rank-1, 0, comm);
assert(ret == 0);
}
/* broadcast results to everyone */