modelnet-p2p-bw.c 9.56 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/*
 * Copyright (C) 2013 University of Chicago.
 * See COPYRIGHT notice in top-level directory.
 *
 */

/* SUMMARY:
 *
 * This test program will execute a one way, point to point bandwidth test
 * between two hosts using the specified modelnet method.  The intention is
 * to roughly mimic the behavior of a standard bandwidth test such as
12 13 14
 * mpptest.  Output is presented in the same format as the default mpptest
 * parameters with two nodes, testing a range of sizes from 4 bytes to 64
 * MiB.
15 16 17 18 19 20 21 22 23 24 25 26 27
 */

#include <string.h>
#include <assert.h>
#include <ross.h>

#include "codes/model-net.h"
#include "codes/lp-io.h"
#include "codes/codes.h"
#include "codes/codes_mapping.h"
#include "codes/configuration.h"
#include "codes/lp-type-lookup.h"

Philip Carns's avatar
Philip Carns committed
28 29 30 31
/* TODO: these things should probably be configurable */
#define NUM_PINGPONGS 1000 /* number of pingpong exchanges per msg size */
#define MIN_SZ 4
#define NUM_SZS 25
32 33 34 35 36 37 38 39 40

static int net_id = 0;
static int num_routers = 0;
static int num_servers = 0;
static int offset = 2;

typedef struct svr_msg svr_msg;
typedef struct svr_state svr_state;

Philip Carns's avatar
Philip Carns committed
41 42 43 44 45 46 47 48
struct pingpong_stat
{
    int msg_sz;
    tw_stime start_time;
    tw_stime end_time;
};
struct pingpong_stat stat_array[25];

49 50 51
/* types of events that will constitute triton requests */
enum svr_event
{
Philip Carns's avatar
Philip Carns committed
52 53
    PING = 1,        /* request event */
    PONG,        /* ack event */
54 55 56 57
};

struct svr_state
{
58
    int pingpongs_completed;
Philip Carns's avatar
Philip Carns committed
59
    int svr_idx;
60 61 62 63 64 65
};

struct svr_msg
{
    enum svr_event svr_event_type;
    tw_lpid src;          /* source of this request or ack */
66
    model_net_event_return ret;
Philip Carns's avatar
Philip Carns committed
67
    int size;
Philip Carns's avatar
Philip Carns committed
68
    int sent_size;        /* for rc */
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
};

static void svr_init(
    svr_state * ns,
    tw_lp * lp);
static void svr_event(
    svr_state * ns,
    tw_bf * b,
    svr_msg * m,
    tw_lp * lp);
static void svr_rev_event(
    svr_state * ns,
    tw_bf * b,
    svr_msg * m,
    tw_lp * lp);
static void svr_finalize(
    svr_state * ns,
    tw_lp * lp);

tw_lptype svr_lp = {
89 90 91 92
    (init_f) svr_init,
    (pre_run_f) NULL,
    (event_f) svr_event,
    (revent_f) svr_rev_event,
93 94
    (commit_f) NULL,
    (final_f)  svr_finalize,
95 96
    (map_f) codes_mapping,
    sizeof(svr_state),
97 98 99 100 101 102
};

extern const tw_lptype* svr_get_lp_type();
static void svr_add_lp_type();
static tw_stime ns_to_s(tw_stime ns);
static tw_stime s_to_ns(tw_stime ns);
Philip Carns's avatar
Philip Carns committed
103
static void handle_pong_event(
104 105 106
    svr_state * ns,
    svr_msg * m,
    tw_lp * lp);
Philip Carns's avatar
Philip Carns committed
107
static void handle_ping_event(
108 109 110
    svr_state * ns,
    svr_msg * m,
    tw_lp * lp);
Philip Carns's avatar
Philip Carns committed
111
static void handle_pong_rev_event(
112 113 114
    svr_state * ns,
    svr_msg * m,
    tw_lp * lp);
Philip Carns's avatar
Philip Carns committed
115
static void handle_ping_rev_event(
116 117 118 119 120
    svr_msg * m,
    tw_lp * lp);

const tw_optdef app_opt [] =
{
Philip Carns's avatar
Philip Carns committed
121
	TWOPT_GROUP("Model net point to point ping pong benchmark" ),
122 123 124 125 126 127 128 129 130
	TWOPT_END()
};

int main(
    int argc,
    char **argv)
{
    int nprocs;
    int rank;
131 132
    int num_nets;
    int *net_ids;
133
    g_tw_ts_end = s_to_ns(60*60*24*365); /* one year, in nsecs */
134
    lp_io_handle handle;
135 136 137 138 139 140

    tw_opt_add(app_opt);
    tw_init(&argc, &argv);

    if(argc < 2)
    {
Philip Carns's avatar
Philip Carns committed
141
	    printf("\n Usage: mpirun <args> --sync=2/3 -- mapping_file_name.conf\n");
142 143 144 145 146
	    MPI_Finalize();
	    return 0;
    }
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
147

148 149
    configuration_load(argv[2], MPI_COMM_WORLD, &config);
    svr_add_lp_type();
150
    model_net_register();
151

152
    codes_mapping_setup();
153

154 155 156 157
    net_ids = model_net_configure(&num_nets);
    assert(num_nets==1);
    net_id = *net_ids;
    free(net_ids);
158 159
    num_servers = codes_mapping_get_lp_count("MODELNET_GRP", 0, "server",
            NULL, 1);
160 161 162
    assert(num_servers == 2);
    if(net_id == DRAGONFLY)
    {
163
	  num_routers = codes_mapping_get_lp_count("MODELNET_GRP", 0,
164
                  "dragonfly_router", NULL, 1);
165 166 167
	  offset = 1;
    }

168 169 170 171 172
    if(lp_io_prepare("modelnet-p2p-bw", LP_IO_UNIQ_SUFFIX, &handle, MPI_COMM_WORLD) < 0)
    {
        return(-1);
    }

173 174 175
    tw_run();
    model_net_report_stats(net_id);

176 177 178 179 180
    if(lp_io_flush(handle, MPI_COMM_WORLD) < 0)
    {
        return(-1);
    }

181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
    tw_end();
    return 0;
}

const tw_lptype* svr_get_lp_type()
{
	    return(&svr_lp);
}

static void svr_add_lp_type()
{
  lp_type_register("server", svr_get_lp_type());
}

static void svr_init(
    svr_state * ns,
    tw_lp * lp)
{
    tw_event *e;
    svr_msg *m;
    tw_stime kickoff_time;
Philip Carns's avatar
Philip Carns committed
202 203
    char grp_name[MAX_NAME_LENGTH];
    char lp_type_name[MAX_NAME_LENGTH];
204
    int grp_id, lp_type_id, grp_rep_id, off;
Philip Carns's avatar
Philip Carns committed
205
    int i;
206

207 208
    memset(ns, 0, sizeof(*ns));

Philip Carns's avatar
Philip Carns committed
209 210
    /* find my own server index */
    codes_mapping_get_lp_info(lp->gid, grp_name, &grp_id,
211
            lp_type_name, &lp_type_id, NULL, &grp_rep_id, &off);
Philip Carns's avatar
Philip Carns committed
212 213 214
    ns->svr_idx = grp_rep_id;

    /* first server sends a dummy event to itself that will kick off the real
215 216
     * simulation
     */
Philip Carns's avatar
Philip Carns committed
217 218 219 220 221 222 223 224 225
    if(ns->svr_idx == 0)
    {
        /* initialize statistics; measured only at first server */
        ns->pingpongs_completed = -1;
        stat_array[0].msg_sz = MIN_SZ;
        for(i=1; i<NUM_SZS; i++)
            stat_array[i].msg_sz = stat_array[i-1].msg_sz * 2;

        /* skew each kickoff event slightly to help avoid event ties later on */
226
        kickoff_time = g_tw_lookahead + tw_rand_unif(lp->rng);
Philip Carns's avatar
Philip Carns committed
227

228
        e = tw_event_new(lp->gid, kickoff_time, lp);
Philip Carns's avatar
Philip Carns committed
229 230 231 232
        m = tw_event_data(e);
        m->svr_event_type = PONG;
        tw_event_send(e);
    }
233 234 235 236 237 238 239 240 241 242

    return;
}

static void svr_event(
    svr_state * ns,
    tw_bf * b,
    svr_msg * m,
    tw_lp * lp)
{
243
    (void)b;
244 245
   switch (m->svr_event_type)
    {
Philip Carns's avatar
Philip Carns committed
246
        case PING:
247
            handle_ping_event(ns, m, lp);
248
            break;
Philip Carns's avatar
Philip Carns committed
249
        case PONG:
250
            handle_pong_event(ns, m, lp);
251 252 253 254 255 256 257 258 259 260 261 262 263 264
            break;
        default:
	    printf("\n Invalid message type %d ", m->svr_event_type);
            assert(0);
        break;
    }
}

static void svr_rev_event(
    svr_state * ns,
    tw_bf * b,
    svr_msg * m,
    tw_lp * lp)
{
265 266
    (void)ns;
    (void)b;
267 268
    switch (m->svr_event_type)
    {
Philip Carns's avatar
Philip Carns committed
269
        case PING:
270
            handle_ping_rev_event(m, lp);
271
            break;
Philip Carns's avatar
Philip Carns committed
272
        case PONG:
273
            handle_pong_rev_event(ns, m, lp);
274 275 276 277 278 279 280 281 282 283 284 285 286
            break;
        default:
            assert(0);
            break;
    }

    return;
}

static void svr_finalize(
    svr_state * ns,
    tw_lp * lp)
{
287
    (void)lp;
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
    int i;
    double avg_time_us;
    double rate_b_s;
    double elapsed_s;

    if(ns->svr_idx != 0)
        return;

    printf("#p0\tp1\tdist\tlen\tave time (us)\trate\n");
    for(i=0; i<NUM_SZS; i++)
    {
        avg_time_us = stat_array[i].end_time - stat_array[i].start_time;
        avg_time_us /= 1000.0; /* ns to us */
        avg_time_us /= (double)NUM_PINGPONGS; /* avg */
        avg_time_us /= 2.0; /* divide by 2, to replicate scaling factor as in mpptest */

        /* rate is reported in bytes/s */
        elapsed_s = ns_to_s(stat_array[i].end_time - stat_array[i].start_time);
        rate_b_s = (double)stat_array[i].msg_sz * (double)NUM_PINGPONGS * 2.0;
        rate_b_s /= elapsed_s;
        printf("0\t1\t1\t%d\t%f\t%e\n", stat_array[i].msg_sz, avg_time_us, rate_b_s);
    }

311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
    return;
}

/* convert ns to seconds */
static tw_stime ns_to_s(tw_stime ns)
{
    return(ns / (1000.0 * 1000.0 * 1000.0));
}

/* convert seconds to ns */
static tw_stime s_to_ns(tw_stime ns)
{
    return(ns * (1000.0 * 1000.0 * 1000.0));
}

Philip Carns's avatar
Philip Carns committed
326 327
/* reverse handler for ping event */
static void handle_ping_rev_event(
328 329 330
    svr_msg * m,
    tw_lp * lp)
{
331
    model_net_event_rc2(lp, &m->ret);
332 333 334
    return;
}

Philip Carns's avatar
Philip Carns committed
335 336
/* reverse handler for pong */
static void handle_pong_rev_event(
337 338 339 340
    svr_state * ns,
    svr_msg * m,
    tw_lp * lp)
{
Philip Carns's avatar
Philip Carns committed
341
    ns->pingpongs_completed--;
342
    model_net_event_rc2(lp, &m->ret);
343

Philip Carns's avatar
Philip Carns committed
344 345 346 347 348
    /* NOTE: we do not attempt to reverse timing information stored in
     * stat_array[].  This is will get rewritten with the correct value when
     * right forward event is processed, and we don't count on this value
     * being accurate until the simulation is complete.
     */
349 350 351
    return;
}

Philip Carns's avatar
Philip Carns committed
352 353
/* handle recving pong */
static void handle_pong_event(
354 355 356 357
    svr_state * ns,
    svr_msg * m,
    tw_lp * lp)
{
Philip Carns's avatar
Philip Carns committed
358 359 360
    svr_msg m_remote;
    int msg_sz_idx;
    tw_lpid peer_gid;
361

Philip Carns's avatar
Philip Carns committed
362
    /* printf("handle_pong_event(), lp %llu.\n", (unsigned long long)lp->gid); */
363

Philip Carns's avatar
Philip Carns committed
364 365
    assert(ns->svr_idx == 0);
    ns->pingpongs_completed++;
366

Philip Carns's avatar
Philip Carns committed
367 368
    /* which message size are we on now? */
    msg_sz_idx = ns->pingpongs_completed / NUM_PINGPONGS;
369

Philip Carns's avatar
Philip Carns committed
370
    if(ns->pingpongs_completed % NUM_PINGPONGS == 0)
371
    {
Philip Carns's avatar
Philip Carns committed
372 373 374 375
        /* finished one msg size range; record time */
        if(msg_sz_idx < NUM_SZS)
            stat_array[msg_sz_idx].start_time = tw_now(lp);
        if(msg_sz_idx > 0)
376
            stat_array[msg_sz_idx-1].end_time = tw_now(lp);
377
    }
Philip Carns's avatar
Philip Carns committed
378 379

    if(msg_sz_idx >= NUM_SZS)
380
    {
Philip Carns's avatar
Philip Carns committed
381 382
        /* done */
        return;
383 384
    }

385
    codes_mapping_get_lp_id("MODELNET_GRP", "server", NULL, 1, 1,
Philip Carns's avatar
Philip Carns committed
386 387 388 389 390 391 392
        0, &peer_gid);

    m_remote.svr_event_type = PING;
    m_remote.src = lp->gid;
    m_remote.size = stat_array[msg_sz_idx].msg_sz;

    /* send next ping */
Philip Carns's avatar
Philip Carns committed
393
    m->sent_size = m_remote.size;
394
    m->ret = model_net_event(net_id, "ping", peer_gid, stat_array[msg_sz_idx].msg_sz, 0.0, sizeof(m_remote), &m_remote, 0, NULL, lp);
Philip Carns's avatar
Philip Carns committed
395

396 397 398
    return;
}

Philip Carns's avatar
Philip Carns committed
399 400
/* handle receiving ping */
static void handle_ping_event(
401 402 403 404
    svr_state * ns,
    svr_msg * m,
    tw_lp * lp)
{
Philip Carns's avatar
Philip Carns committed
405
    svr_msg m_remote;
406

Philip Carns's avatar
Philip Carns committed
407
    assert(ns->svr_idx == 1);
408

Philip Carns's avatar
Philip Carns committed
409 410 411
    m_remote.svr_event_type = PONG;
    m_remote.src = lp->gid;
    m_remote.size = m->size;
412

Philip Carns's avatar
Philip Carns committed
413
    /* send pong msg back to sender */
Philip Carns's avatar
Philip Carns committed
414
    m->sent_size = m_remote.size;
415
    m->ret = model_net_event(net_id, "pong", m->src, m->size, 0.0, sizeof(m_remote), &m_remote, 0, NULL, lp);
416 417 418 419 420 421 422 423
    return;
}

/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 * End:
424

425 426
 * vim: ft=c ts=8 sts=4 sw=4 expandtab
 */