codes-iolang-wrkld.c 7.81 KB
Newer Older
1 2 3 4 5
/*
 * Copyright (C) 2013 University of Chicago.
 * See COPYRIGHT notice in top-level directory.
 *
 */
6
#include <assert.h>
7
#include <ross.h>
8 9 10 11 12 13
#include "src/iokernellang/CodesIOKernelTypes.h"
#include "src/iokernellang/CodesIOKernelParser.h"
#include "src/iokernellang/CodesIOKernelContext.h"
#include "src/iokernellang/codesparser.h"
#include "src/iokernellang/CodesKernelHelpers.h"
#include "src/iokernellang/codeslexer.h"
14 15

#include "codes/codes-workload.h"
16
#include "src/workload/codes-workload-method.h"
17 18 19
#include "codes/quickhash.h"

#define RANK_HASH_TABLE_SIZE 400 
20 21 22 23

/* This file implements the CODES workload API for the I/O kernel language of
the BG/P storage model */

24 25
static void * iolang_io_workload_read_config(
        ConfigHandle * handle,
26 27 28
        char const * section_name,
        char const * annotation,
        int num_ranks);
29

30
/* load the workload file */
31
static int iolang_io_workload_load(const char* params, int app_id, int rank);
32 33

/* get next operation */
34
static void iolang_io_workload_get_next(int app_id, int rank, struct codes_workload_op *op);
35 36 37

/* mapping from bg/p operation enums to CODES workload operations enum */
static int convertTypes(int inst);
38
static int hash_rank_compare(void *key, struct qhash_head *link);
39

40
typedef struct codes_iolang_wrkld_state_per_rank codes_iolang_wrkld_state_per_rank;
41 42 43
static struct qhash_table *rank_tbl = NULL;
static int rank_tbl_pop = 0;
int num_ranks = -1;
44 45

/* implements the codes workload method */
46
struct codes_workload_method iolang_workload_method =
47
{
48
    .method_name = "iolang_workload",
49
    .codes_workload_read_config = iolang_io_workload_read_config,
50 51
    .codes_workload_load = iolang_io_workload_load,
    .codes_workload_get_next = iolang_io_workload_get_next,
52 53 54
};

/* state of the I/O workload that each simulated compute node/MPI rank will have */
55
struct codes_iolang_wrkld_state_per_rank
56
{
57
    int rank;
58 59 60
    CodesIOKernelContext codes_context;
    CodesIOKernel_pstate * codes_pstate;
    codeslang_inst next_event;
61
    struct qhash_head hash_link;
62
    iolang_workload_info task_info;
63 64
};

65 66 67

static void * iolang_io_workload_read_config(
        ConfigHandle * handle,
68 69 70
        char const * section_name,
        char const * annotation,
        int num_ranks)
71 72 73 74 75 76 77 78 79
{
    iolang_params *p = malloc(sizeof(*p));
    assert(p);
    p->num_cns = -1;
    p->use_relpath = 1;
    p->io_kernel_meta_path[0] = '\0';
    p->io_kernel_path[0] = '\0';

    int rc = configuration_get_value_relpath(handle, section_name,
80
            "io_kernel_meta_path", annotation, p->io_kernel_meta_path,
81 82
            MAX_NAME_LENGTH_WKLD);
    assert(rc > 0);
83 84
    rc = configuration_get_value_int(handle, section_name, "num_ranks",
            annotation, &p->num_cns);
85
    if (rc != 0)
86
        p->num_cns = num_ranks;
87 88 89
    return p;
}

90
/* loads the workload file for each simulated MPI rank/ compute node LP */
91
int iolang_io_workload_load(const char* params, int app_id, int rank)
92 93
{
    int t = -1;
94
    iolang_params* i_param = (struct iolang_params*)params;
95

96 97
    APP_ID_UNSUPPORTED(app_id, "iolang")

98
    /* we have to get the number of compute nodes/ranks from the bg/p model parameters
99
     * because the number of ranks are specified in the iolang config file not the
100 101
     * workload files */
    if(num_ranks == -1)
102
        num_ranks = i_param->num_cns;
103

104
    codes_iolang_wrkld_state_per_rank* wrkld_per_rank = NULL;
105
    if(!rank_tbl)
106
    {
107 108 109 110 111
	  rank_tbl = qhash_init(hash_rank_compare, quickhash_32bit_hash, RANK_HASH_TABLE_SIZE);
	  if(!rank_tbl)
	  {
		  return -1;
	  }
112
    }
113
    wrkld_per_rank = (codes_iolang_wrkld_state_per_rank*)malloc(sizeof(*wrkld_per_rank));
114 115 116 117 118
    if(!wrkld_per_rank)
	    return -1;

    wrkld_per_rank->codes_pstate = CodesIOKernel_pstate_new();
    wrkld_per_rank->rank = rank;
119 120
    t = codes_kernel_helper_bootstrap(i_param->io_kernel_path, 
				      i_param->io_kernel_meta_path,
121
        			      rank, 
122
                          num_ranks,
123
                      i_param->use_relpath,
124 125 126 127 128 129
				      &(wrkld_per_rank->codes_context), 
				      &(wrkld_per_rank->codes_pstate), 
				      &(wrkld_per_rank->task_info), 
				      &(wrkld_per_rank->next_event));
    qhash_add(rank_tbl, &(wrkld_per_rank->rank), &(wrkld_per_rank->hash_link));
    rank_tbl_pop++;
130 131 132 133 134 135 136 137 138
    return t;
}

/* Maps the enum types from I/O language to the CODES workload API */
static int convertTypes(int inst)
{
    switch(inst)
    {
        case CL_WRITEAT: /* write to file */
139 140 141
	    return CODES_WK_WRITE;
	case CL_READAT:
	    return CODES_WK_READ;
142
	case CL_CLOSE:
143
	    return CODES_WK_CLOSE; /* close the file */
144
	case CL_OPEN:
145
	    return CODES_WK_OPEN; /* open file */
146
	case CL_SYNC:
147
	    return CODES_WK_BARRIER; /* barrier in CODES workload is similar to sync in I/O lang? */
148
	case CL_SLEEP:
149
	    return CODES_WK_DELAY; /* sleep or delay */
150
	case CL_EXIT:
151
	    return CODES_WK_END; /* end of the operations/ no more operations in file */
152
	case CL_DELETE:
Jonathan Jenkins's avatar
Jonathan Jenkins committed
153
	    return CODES_WK_IGNORE;
154
	case CL_GETRANK: 
Jonathan Jenkins's avatar
Jonathan Jenkins committed
155
	    return CODES_WK_IGNORE; /* defined in I/O lang but not in workloads API*/
156
	case CL_GETSIZE: 
Jonathan Jenkins's avatar
Jonathan Jenkins committed
157
	    return CODES_WK_IGNORE; /* defined in I/O lang but not in workload API */
158
	default:
Jonathan Jenkins's avatar
Jonathan Jenkins committed
159
	   return CODES_WK_IGNORE;
160
    } 
161 162
}

163
/* Gets the next operation specified in the workload file for the simulated MPI rank */
164
void iolang_io_workload_get_next(int app_id, int rank, struct codes_workload_op *op)
165 166 167
{
    /* If the number of simulated compute nodes per LP is initialized only then we get the next operation
	else we return an error code may be?  */
168
        codes_iolang_wrkld_state_per_rank* next_wrkld;
169 170 171 172 173 174 175
	struct qhash_head *hash_link = NULL; 
	hash_link = qhash_search(rank_tbl, &rank);
	if(!hash_link)
	{
		op->op_type = CODES_WK_END;
		return;
	}
176
	next_wrkld = qhash_entry(hash_link, struct codes_iolang_wrkld_state_per_rank, hash_link);
177 178

	int type = codes_kernel_helper_parse_input(next_wrkld->codes_pstate, &(next_wrkld->codes_context),&(next_wrkld->next_event));
179
        op->op_type = (enum codes_workload_op_type) convertTypes(type);
Elsa Gonsiorowski (Uranus)'s avatar
merge  
Elsa Gonsiorowski (Uranus) committed
180 181
        if (op->op_type == CODES_WK_IGNORE)
            return;
182 183 184 185
	switch(op->op_type)
	{
	    case CODES_WK_WRITE:
	    {
186
                op->u.write.file_id = (next_wrkld->next_event).var[0];
187
		op->u.write.offset = (next_wrkld->next_event).var[2];
188
		op->u.write.size = (next_wrkld->next_event).var[1];
189 190 191 192
	    }
	    break;
	    case CODES_WK_DELAY:
	    {
193 194
            /* io language represents delays in nanoseconds */
            op->u.delay.seconds = (double)(next_wrkld->next_event).var[0] / (1000 * 1000 * 1000);
195 196 197 198
	    }
	    break;
	    case CODES_WK_END:
	    {
199 200 201 202 203 204
		/* delete the hash entry*/
		  qhash_del(hash_link); 
		  rank_tbl_pop--;

		  /* if no more entries are there, delete the hash table */
		  if(!rank_tbl_pop)
205 206 207 208
          {
            qhash_finalize(rank_tbl);
            rank_tbl = NULL;
          }
209 210 211 212
	    }
	    break;
	    case CODES_WK_CLOSE:
	    {
213
	        op->u.close.file_id = (next_wrkld->next_event).var[0];
214 215 216 217
	    }
	    break;
	    case CODES_WK_BARRIER:
	    {
218
	       op->u.barrier.count = num_ranks;
219 220 221 222 223
	       op->u.barrier.root = 0;
	    }
	    break;
	    case CODES_WK_OPEN:
	    {
224
	        op->u.open.file_id =  (next_wrkld->next_event).var[0];
225
            op->u.open.create_flag = 1;
226 227 228 229
	    }
	    break;
	    case CODES_WK_READ:
	    {
230
                op->u.read.file_id = (next_wrkld->next_event).var[0];
231
		op->u.read.offset = (next_wrkld->next_event).var[2];
232
		op->u.read.size = (next_wrkld->next_event).var[1];
233 234 235 236
	    }
	    break;
	    default:
	     {
Jonathan Jenkins's avatar
Jonathan Jenkins committed
237

238 239 240 241 242 243
		// Return error code
		//printf("\n Invalid operation specified %d ", op->op_type);
	     }
	}
    return;
}
244 245 246 247

static int hash_rank_compare(void *key, struct qhash_head *link)
{
    int *in_rank = (int *)key;
248
    codes_iolang_wrkld_state_per_rank *tmp;
249

250
    tmp = qhash_entry(link, codes_iolang_wrkld_state_per_rank, hash_link);
251 252 253 254 255 256
    if (tmp->rank == *in_rank)
	return 1;

    return 0;
}

Jonathan Jenkins's avatar
Jonathan Jenkins committed
257 258 259 260 261 262 263 264
/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 * End:
 *
 * vim: ft=c ts=8 sts=4 sw=4 expandtab
 */