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

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

#define RANK_HASH_TABLE_SIZE 400 
20
21
22
23
24
25
26
27
28
29
30
31

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

/* load the workload file */
int bgp_io_workload_load(const char* params, int rank);

/* get next operation */
void bgp_io_workload_get_next(int rank, struct codes_workload_op *op);

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

34
35
36
37
typedef struct codes_bgp_wrkld_state_per_rank codes_bgp_wrkld_state_per_rank;
static struct qhash_table *rank_tbl = NULL;
static int rank_tbl_pop = 0;
int num_ranks = -1;
38
39
40
41
42
43
44
45
46
47

/* implements the codes workload method */
struct codes_workload_method bgp_io_workload_method =
{
    .method_name = "bgp_io_workload",
    .codes_workload_load = bgp_io_workload_load,
    .codes_workload_get_next = bgp_io_workload_get_next,
};

/* state of the I/O workload that each simulated compute node/MPI rank will have */
48
struct codes_bgp_wrkld_state_per_rank
49
{
50
    int rank;
51
52
53
    CodesIOKernelContext codes_context;
    CodesIOKernel_pstate * codes_pstate;
    codeslang_inst next_event;
54
    struct qhash_head hash_link;
55
    codes_workload_info task_info;
56
57
58
59
60
61
62
};

/* loads the workload file for each simulated MPI rank/ compute node LP */
int bgp_io_workload_load(const char* params, int rank)
{
    int t = -1;
    bgp_params* b_param = (bgp_params*)params;
63
64
65
66
67
68
69
70
71

    /* we have to get the number of compute nodes/ranks from the bg/p model parameters
     * because the number of ranks are specified in the bgp config file not the
     * workload files */
    if(num_ranks == -1)
        num_ranks = b_param->num_cns;

    codes_bgp_wrkld_state_per_rank* wrkld_per_rank = NULL;
    if(!rank_tbl)
72
    {
73
74
75
76
77
	  rank_tbl = qhash_init(hash_rank_compare, quickhash_32bit_hash, RANK_HASH_TABLE_SIZE);
	  if(!rank_tbl)
	  {
		  return -1;
	  }
78
    }
79
80
81
82
83
84
    wrkld_per_rank = malloc(sizeof(*wrkld_per_rank));
    if(!wrkld_per_rank)
	    return -1;

    wrkld_per_rank->codes_pstate = CodesIOKernel_pstate_new();
    wrkld_per_rank->rank = rank;
85
86
87
88
    t = codes_kernel_helper_bootstrap(b_param->io_kernel_path, 
				      b_param->io_kernel_def_path, 
				      b_param->io_kernel_meta_path,
        			      rank, 
89
90
91
92
93
94
				      &(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++;
95
96
97
98
99
100
101
102
103
    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 */
104
105
106
	    return CODES_WK_WRITE;
	case CL_READAT:
	    return CODES_WK_READ;
107
	case CL_CLOSE:
108
	    return CODES_WK_CLOSE; /* close the file */
109
	case CL_OPEN:
110
	    return CODES_WK_OPEN; /* open file */
111
	case CL_SYNC:
112
	    return CODES_WK_BARRIER; /* barrier in CODES workload is similar to sync in I/O lang? */
113
	case CL_SLEEP:
114
	    return CODES_WK_DELAY; /* sleep or delay */
115
	case CL_EXIT:
116
	    return CODES_WK_END; /* end of the operations/ no more operations in file */
117
	case CL_DELETE:
118
	    return -2;
119
	case CL_GETRANK: 
120
	    return -3; /* defined in I/O lang but not in workloads API*/
121
	case CL_GETSIZE: 
122
	    return -4; /* defined in I/O lang but not in workload API */
123
	default:
124
125
	   return -1;
    } 
126
127
}

128
/* Gets the next operation specified in the workload file for the simulated MPI rank */
129
130
131
132
void bgp_io_workload_get_next(int rank, struct codes_workload_op *op)
{
    /* 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?  */
133
134
135
136
137
138
139
140
141
142
143
        codes_bgp_wrkld_state_per_rank* next_wrkld;
	struct qhash_head *hash_link = NULL; 
	hash_link = qhash_search(rank_tbl, &rank);
	if(!hash_link)
	{
		op->op_type = CODES_WK_END;
		return;
	}
	next_wrkld = qhash_entry(hash_link, struct codes_bgp_wrkld_state_per_rank, hash_link);

	int type = codes_kernel_helper_parse_input(next_wrkld->codes_pstate, &(next_wrkld->codes_context),&(next_wrkld->next_event));
144
145
146
147
148
        op->op_type = convertTypes(type);
	switch(op->op_type)
	{
	    case CODES_WK_WRITE:
	    {
149
                op->u.write.file_id = (next_wrkld->next_event).var[0];
150
		op->u.write.offset = (next_wrkld->next_event).var[2];
151
		op->u.write.size = (next_wrkld->next_event).var[1];
152
153
154
155
	    }
	    break;
	    case CODES_WK_DELAY:
	    {
156
		op->u.delay.seconds = (next_wrkld->next_event).var[0];
157
158
159
160
	    }
	    break;
	    case CODES_WK_END:
	    {
161
162
163
164
165
166
167
		/* 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)
			qhash_finalize(rank_tbl);
168
169
170
171
	    }
	    break;
	    case CODES_WK_CLOSE:
	    {
172
	        op->u.close.file_id = (next_wrkld->next_event).var[0];
173
174
175
176
	    }
	    break;
	    case CODES_WK_BARRIER:
	    {
177
	       op->u.barrier.count = num_ranks;
178
179
180
181
182
	       op->u.barrier.root = 0;
	    }
	    break;
	    case CODES_WK_OPEN:
	    {
183
	        op->u.open.file_id =  (next_wrkld->next_event).var[0];
184
185
186
187
	    }
	    break;
	    case CODES_WK_READ:
	    {
188
                op->u.read.file_id = (next_wrkld->next_event).var[0];
189
		op->u.read.offset = (next_wrkld->next_event).var[2];
190
		op->u.read.size = (next_wrkld->next_event).var[1];
191
192
193
194
195
196
197
198
199
200
	    }
	    break;
	    default:
	     {
		// Return error code
		//printf("\n Invalid operation specified %d ", op->op_type);
	     }
	}
    return;
}
201
202
203
204
205
206
207
208
209
210
211
212
213

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

    tmp = qhash_entry(link, codes_bgp_wrkld_state_per_rank, hash_link);
    if (tmp->rank == *in_rank)
	return 1;

    return 0;
}