codes-nw-workload.c 5.36 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 <assert.h>

#include "ross.h"
#include "codes/codes-nw-workload.h"
#include "codes-nw-workload-method.h"

/* list of available methods.  These are statically compiled for now, but we
 * could make generators optional via autoconf tests etc. if needed
 */
extern struct codes_nw_workload_method scala_trace_workload_method;
17
extern struct codes_nw_workload_method dumpi_trace_workload_method;
18 19 20 21

static struct codes_nw_workload_method *method_array[] =
{
    &scala_trace_workload_method,
22 23 24
#ifdef USE_DUMPI
    &dumpi_trace_workload_method,
#endif
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
    NULL};

/* This shim layer is responsible for queueing up reversed operations and
 * re-issuing them so that the underlying workload generator method doesn't
 * have to worry about reverse events.
 *
 * NOTE: we could make this faster with a smarter data structure.  For now
 * we just have a linked list of rank_queue structs, one per rank that has
 * opened the workload.  We then have a linked list off of each of those
 * to hold a lifo queue of operations that have been reversed for that rank.
 */

/* holds an operation that has been reversed */
struct rc_op
{
    struct mpi_event_list op;
    struct rc_op* next;
};

/* tracks lifo queue of reversed operations for a given rank */
struct rank_queue
{
    int rank;
    struct rc_op *lifo;
    struct rank_queue *next;
};

static struct rank_queue *ranks = NULL;

int codes_nw_workload_load(const char* type, const char* params, int rank)
{
    int i;
    int ret;
    struct rank_queue *tmp;

    for(i=0; method_array[i] != NULL; i++)
    {
        if(strcmp(method_array[i]->method_name, type) == 0)
        {
            /* load appropriate workload generator */
            ret = method_array[i]->codes_nw_workload_load(params, rank);
            if(ret < 0)
            {
                return(-1);
            }

            /* are we tracking information for this rank yet? */
            tmp = ranks;
            while(tmp)
            {
                if(tmp->rank == rank)
                    break;
                tmp = tmp->next;
            }
            if(tmp == NULL)
            {
                tmp = malloc(sizeof(*tmp));
                assert(tmp);
                tmp->rank = rank;
                tmp->lifo = NULL;
                tmp->next = ranks;
                ranks = tmp;
            }

            return(i);
        }
    }

    fprintf(stderr, "Error: failed to find workload generator %s\n", type);
    return(-1);
}

void codes_nw_workload_get_next(int wkld_id, int rank, struct mpi_event_list *op)
{
    struct rank_queue *tmp;
    struct rc_op *tmp_op;

    /* first look to see if we have a reversed operation that we can
     * re-issue
     */
    tmp = ranks;
    while(tmp)
    {
        if(tmp->rank == rank)
            break;
        tmp = tmp->next;
    }
    assert(tmp);
    if(tmp->lifo)
    {
        tmp_op = tmp->lifo;
        tmp->lifo = tmp_op->next;

        *op = tmp_op->op;
        free(tmp_op);
        //printf("codes_workload_get_next re-issuing reversed operation.\n");
        return;
    }

    /* ask generator for the next operation */
    //printf("codes_workload_get_next issuing new operation.\n");
    method_array[wkld_id]->codes_nw_workload_get_next(rank, op);

    return;
}

void codes_nw_workload_get_next_rc(int wkld_id, int rank, const struct mpi_event_list *op)
{
    struct rank_queue *tmp;
    struct rc_op *tmp_op;

    tmp = ranks;
    while(tmp)
    {
        if(tmp->rank == rank)
            break;
        tmp = tmp->next;
    }
    assert(tmp);

    tmp_op = malloc(sizeof(*tmp_op));
    assert(tmp_op);
    tmp_op->op = *op;
    tmp_op->next = tmp->lifo;
    tmp->lifo = tmp_op;

    return;
}

void codes_nw_workload_print_op(FILE *f, struct mpi_event_list *op, int rank){
    switch(op->op_type){
        case CODES_NW_END:
            fprintf(f, "op: rank:%d type:end\n", rank);
            break;
        case CODES_NW_DELAY:
160 161
            fprintf(f, "op: rank:%d type:delay seconds:%f \n",
                    rank, op->u.delay.nsecs);
162 163
            break;
        case CODES_NW_SEND:
164
	case CODES_NW_ISEND:
165
            fprintf(f, "op: rank:%d type:send "
166 167
                       "sender: %d receiver: %d blocking: %d number of bytes: %d "
			"start time: %f end time: %f \n",
168
                    rank, op->u.send.source_rank, op->u.send.dest_rank,
169 170
                    op->u.send.blocking, op->u.send.num_bytes,
		    op->start_time, op->end_time);
171 172
            break;
        case CODES_NW_RECV:
173
	case CODES_NW_IRECV:
174
            fprintf(f, "op: rank:%d type:recv "
175 176
                       "sender: %d receiver: %d blocking: %d number of bytes: %d "
			"start time: %f end time: %f \n",
177
                    rank, op->u.recv.source_rank, op->u.recv.dest_rank,
178 179
                    op->u.recv.blocking, op->u.recv.num_bytes,
		    op->start_time, op->end_time);
180
            break;
181 182 183 184 185 186 187 188 189 190 191 192
	case CODES_NW_COL:
	case CODES_NW_BCAST:
	case CODES_NW_ALLGATHER:
	case CODES_NW_ALLGATHERV:
	case CODES_NW_ALLTOALL:
	case CODES_NW_ALLTOALLV:
	case CODES_NW_REDUCE:
	case CODES_NW_ALLREDUCE:
            fprintf(f, "op: rank:%d type:collective "
                       "count: %d \n",
                    rank, op->u.collective.num_bytes);
            break;	    
193 194 195 196 197 198 199 200 201 202 203
    }
}

/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 * End:
 *
 * vim: ft=c ts=8 sts=4 sw=4 expandtab
 */