model-net.c 15.9 KB
Newer Older
1
/*
Philip Carns's avatar
Philip Carns committed
2
 * Copyright (C) 2013 University of Chicago.
3
 * See COPYRIGHT notice in top-level directory.
Philip Carns's avatar
Philip Carns committed
4
 *
5
 */
Philip Carns's avatar
Philip Carns committed
6

7
8
9
#include <string.h>
#include <assert.h>

10
#include "codes/model-net.h"
11
#include "codes/model-net-method.h"
12
#include "codes/model-net-lp.h"
13
#include "codes/model-net-sched.h"
14
#include "codes/codes.h"
15
#include <codes/codes_mapping.h>
16

17
18
19
20
#define STR_SIZE 16
#define PROC_TIME 10.0

extern struct model_net_method simplenet_method;
Jonathan Jenkins's avatar
Jonathan Jenkins committed
21
extern struct model_net_method simplep2p_method;
22
extern struct model_net_method torus_method;
23
extern struct model_net_method dragonfly_method;
Philip Carns's avatar
Philip Carns committed
24
extern struct model_net_method loggp_method;
25

26
27
28
29
30
31
32
33
34
35
36
37
#define X(a,b,c,d) b,
char * model_net_lp_config_names[] = {
    NETWORK_DEF
};
#undef X

#define X(a,b,c,d) c,
char * model_net_method_names[] = {
    NETWORK_DEF
};
#undef X

38
/* Global array initialization, terminated with a NULL entry */
39
40
41
42
43
#define X(a,b,c,d) d,
struct model_net_method* method_array[] = { 
    NETWORK_DEF
};
#undef X
44

45
// counter and offset for the MN_START_SEQ / MN_END_SEQ macros
46
int mn_in_seqence = 0;
47
48
tw_stime mn_msg_offset = 0.0;

49
50
51
52
// message parameters for use via model_net_set_msg_param
static int is_msg_params_set[MAX_MN_MSG_PARAM_TYPES];
static mn_sched_params sched_params;

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
// global listing of lp types found by model_net_register
// - needs to be held between the register and configure calls
static int do_config_nets[MAX_NETS];

void model_net_register(){
    // first set up which networks need to be registered, then pass off to base
    // LP to do its thing
    memset(do_config_nets, 0, MAX_NETS * sizeof(*do_config_nets));
    for (int grp = 0; grp < lpconf.lpgroups_count; grp++){
        config_lpgroup_t *lpgroup = &lpconf.lpgroups[grp];
        for (int lpt = 0; lpt < lpgroup->lptypes_count; lpt++){
            char *nm = lpgroup->lptypes[lpt].name;
            for (int n = 0; n < MAX_NETS; n++){
                if (!do_config_nets[n] && 
                        strcmp(model_net_lp_config_names[n], nm) == 0){
                    do_config_nets[n] = 1;
                    break;
                }
            }
        }
    }
    model_net_base_register(do_config_nets);
}

int* model_net_configure(int *id_count){
    // first call the base LP configure, which sets up the general parameters
    model_net_base_configure();

    // do network-specific configures
    *id_count = 0;
    for (int i = 0; i < MAX_NETS; i++) {
        if (do_config_nets[i]){
            method_array[i]->mn_configure();
            (*id_count)++;
        }
    }

    // allocate the output
    int *ids = malloc(*id_count * sizeof(int));
    // read the ordering provided by modelnet_order
    char **values;
    size_t length;
    int ret = configuration_get_multivalue(&config, "PARAMS", "modelnet_order",
            NULL, &values, &length);
    if (ret != 1){
        tw_error(TW_LOC, "unable to read PARAMS:modelnet_order variable\n");
    }
    if (length != (size_t) *id_count){
        tw_error(TW_LOC, "number of networks in PARAMS:modelnet_order "
                "do not match number in LPGROUPS\n");
    }
    // set the index
    for (int i = 0; i < *id_count; i++){
        ids[i] = -1;
        for (int n = 0; n < MAX_NETS; n++){
            if (strcmp(values[i], model_net_method_names[n]) == 0){
                if (!do_config_nets[n]){
                    tw_error(TW_LOC, "network in PARAMS:modelnet_order not "
                            "present in LPGROUPS: %s\n", values[i]);
                }
                ids[i] = n;
                break;
            }
        }
        if (ids[i] == -1){
            tw_error(TW_LOC, "unknown network in PARAMS:modelnet_order: %s\n",
                    values[i]);
        }
        free(values[i]);
    }
    free(values);

125
126
127
128
    // init the per-msg params here
    memset(is_msg_params_set, 0,
            MAX_MN_MSG_PARAM_TYPES*sizeof(*is_msg_params_set));

129
    return ids;
130
131
}

132
133
134
int model_net_get_id(char *name){
    int i;
    for(i=0; method_array[i] != NULL; i++) {
135
        if(strcmp(model_net_method_names[i], name) == 0) {
136
137
138
139
140
141
            return i;
        }
    }
    return -1;
}

142
143
144
void model_net_write_stats(tw_lpid lpid, struct mn_stats* stat)
{
    int ret;
145
    char id[19+CATEGORY_NAME_MAX+1];
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
    char data[1024];

    sprintf(id, "model-net-category-%s", stat->category);
    sprintf(data, "lp:%ld\tsend_count:%ld\tsend_bytes:%ld\tsend_time:%f\t" 
        "recv_count:%ld\trecv_bytes:%ld\trecv_time:%f\tmax_event_size:%ld\n",
        (long)lpid,
        stat->send_count,
        stat->send_bytes,
        stat->send_time,
        stat->recv_count,
        stat->recv_bytes,
        stat->recv_time,
        stat->max_event_size);

    ret = lp_io_write(lpid, id, strlen(data), data);
    assert(ret == 0);

    return;
}

void model_net_print_stats(tw_lpid lpid, mn_stats mn_stats_array[])
{

    int i;
    struct mn_stats all;

    memset(&all, 0, sizeof(all));
    sprintf(all.category, "all");

    for(i=0; i<CATEGORY_MAX; i++)
    {
        if(strlen(mn_stats_array[i].category) > 0)
        {
            all.send_count += mn_stats_array[i].send_count;
            all.send_bytes += mn_stats_array[i].send_bytes;
            all.send_time += mn_stats_array[i].send_time;
            all.recv_count += mn_stats_array[i].recv_count;
            all.recv_bytes += mn_stats_array[i].recv_bytes;
            all.recv_time += mn_stats_array[i].recv_time;
            if(mn_stats_array[i].max_event_size > all.max_event_size)
                all.max_event_size = mn_stats_array[i].max_event_size;

            model_net_write_stats(lpid, &mn_stats_array[i]);
        }
    }
    model_net_write_stats(lpid, &all);
}

194
struct mn_stats* model_net_find_stats(char const * category, mn_stats mn_stats_array[])
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
{
    int i;
    int new_flag = 0;
    int found_flag = 0;

    for(i=0; i<CATEGORY_MAX; i++)
    {
        if(strlen(mn_stats_array[i].category) == 0)
        {
            found_flag = 1;
            new_flag = 1;
            break;
        }
        if(strcmp(category, mn_stats_array[i].category) == 0)
        {
            found_flag = 1;
            new_flag = 0;
            break;
        }
    }
    assert(found_flag);

    if(new_flag)
    {
        strcpy(mn_stats_array[i].category, category);
    }
    return(&mn_stats_array[i]);
}

224
static void model_net_event_impl_base(
225
        int net_id,
226
        char const * annotation,
227
        int ignore_annotations,
228
        char const * category, 
229
230
231
232
233
        tw_lpid final_dest_lp, 
        uint64_t message_size, 
        int is_pull,
        tw_stime offset,
        int remote_event_size,
234
        void const * remote_event,
235
        int self_event_size,
236
        void const * self_event,
237
        tw_lp *sender) {
238

239
240
241
242
243
244
245
246
    if (remote_event_size + self_event_size + sizeof(model_net_wrap_msg) 
            > g_tw_msg_sz){
        tw_error(TW_LOC, "Error: model_net trying to transmit an event of size "
                         "%d but ROSS is configured for events of size %zd\n",
                         remote_event_size+self_event_size+sizeof(model_net_wrap_msg),
                         g_tw_msg_sz);
        return;
    }
247

248
    tw_lpid mn_lp = model_net_find_local_device(net_id, annotation, 
249
            ignore_annotations, sender->gid);
250
    tw_stime poffset = codes_local_latency(sender);
251
    if (mn_in_seqence){
252
253
254
255
256
257
258
        tw_stime tmp = mn_msg_offset;
        mn_msg_offset += poffset;
        poffset += tmp;
    }
    tw_event *e = codes_event_new(mn_lp, poffset+offset, sender);

    model_net_wrap_msg *m = tw_event_data(e);
259
    msg_set_header(model_net_base_magic, MN_BASE_NEW_MSG, sender->gid, &m->h);
260
261

    // set the request struct 
262
    model_net_request *r = &m->msg.m_base.req;
263
264
    r->net_id = net_id;
    r->final_dest_lp = final_dest_lp;
265
    r->src_lp = sender->gid;
266
267
268
    r->msg_size = message_size;
    r->remote_event_size = remote_event_size;
    r->self_event_size = self_event_size;
269
    r->is_pull = is_pull;
270
271
    strncpy(r->category, category, CATEGORY_NAME_MAX-1);
    r->category[CATEGORY_NAME_MAX-1]='\0';
272
273
274

    // this is an outgoing message
    m->msg.m_base.is_from_remote = 0;
275
    
276
277
278
279
    // set the msg-specific params
    if (is_msg_params_set[MN_SCHED_PARAM_PRIO])
        m->msg.m_base.sched_params = sched_params;
    else // set the default
280
        model_net_sched_set_default_params(&m->msg.m_base.sched_params);
281
282
283
284
    // once params are set, clear the flags 
    memset(is_msg_params_set, 0,
            MAX_MN_MSG_PARAM_TYPES*sizeof(*is_msg_params_set));

285
286
287
288
289
290
291
292
    void *e_msg = (m+1);
    if (remote_event_size > 0){
        memcpy(e_msg, remote_event, remote_event_size);
        e_msg = (char*)e_msg + remote_event_size; 
    }
    if (self_event_size > 0){
        memcpy(e_msg, self_event, self_event_size);
    }
293

294
295
296
297
298
    //print_base(m);
    tw_event_send(e);
}
static void model_net_event_impl_base_rc(tw_lp *sender){
    codes_local_latency_reverse(sender);
299
}
300
301
302

void model_net_event(
    int net_id,
303
    char const * category, 
304
305
306
307
    tw_lpid final_dest_lp, 
    uint64_t message_size, 
    tw_stime offset,
    int remote_event_size,
308
    void const * remote_event,
309
    int self_event_size,
310
    void const * self_event,
311
312
    tw_lp *sender)
{
313
314
315
316
317
318
319
    model_net_event_impl_base(net_id, NULL, 1, category, final_dest_lp,
            message_size, 0, offset, remote_event_size, remote_event,
            self_event_size, self_event, sender);
}

void model_net_event_annotated(
        int net_id,
320
321
        char const * annotation,
        char const * category, 
322
323
324
325
        tw_lpid final_dest_lp, 
        uint64_t message_size, 
        tw_stime offset,
        int remote_event_size,
326
        void const * remote_event,
327
        int self_event_size,
328
        void const * self_event,
329
330
331
332
        tw_lp *sender){
    model_net_event_impl_base(net_id, annotation, 0, category, final_dest_lp,
            message_size, 0, offset, remote_event_size, remote_event,
            self_event_size, self_event, sender);
333
334
335
336
}

void model_net_pull_event(
        int net_id,
337
        char const *category,
338
339
340
341
        tw_lpid final_dest_lp,
        uint64_t message_size,
        tw_stime offset,
        int self_event_size,
342
        void const *self_event,
343
344
345
        tw_lp *sender){
    /* NOTE: for a pull, we are filling the *remote* event - it will be remote
     * from the destination's POV */
346
347
348
349
350
351
352
    model_net_event_impl_base(net_id, NULL, 0, category, final_dest_lp,
            message_size, 1, offset, self_event_size, self_event, 0, NULL,
            sender);
}

void model_net_pull_event_annotated(
        int net_id,
353
354
        char const * annotation,
        char const *category,
355
356
357
358
        tw_lpid final_dest_lp,
        uint64_t message_size,
        tw_stime offset,
        int self_event_size,
359
        void const *self_event,
360
361
362
363
364
365
        tw_lp *sender){
    /* NOTE: for a pull, we are filling the *remote* event - it will be remote
     * from the destination's POV */
    model_net_event_impl_base(net_id, annotation, 1, category, final_dest_lp,
            message_size, 1, offset, self_event_size, self_event, 0, NULL,
            sender);
366
367
368
369
370
371
}

void model_net_event_rc(
        int net_id,
        tw_lp *sender,
        uint64_t message_size){
372
    model_net_event_impl_base_rc(sender);
373
374
375
376
377
}

void model_net_pull_event_rc(
        int net_id,
        tw_lp *sender) {
378
    model_net_event_impl_base_rc(sender);
379
380
}

381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
void model_net_set_msg_param(
        enum msg_param_type type,
        int sub_type,
        const void * params){
    switch(type){
        case MN_MSG_PARAM_SCHED:
            is_msg_params_set[MN_MSG_PARAM_SCHED] = 1;
            switch(sub_type){
                case MN_SCHED_PARAM_PRIO:
                    sched_params.prio = *(int*)params;
                    break;
                default:
                    tw_error(TW_LOC, "unknown or unsupported "
                            "MN_MSG_PARAM_SCHED parameter type");
            }
            break;
        default:
            tw_error(TW_LOC, "unknown or unsupported msg_param_type");
    }
}

402
/* returns the message size, can be either simplenet, dragonfly or torus message size*/
403
int model_net_get_msg_sz(int net_id)
404
405
406
{
   // TODO: Add checks on network name
   // TODO: Add dragonfly and torus network models
407
408
   return sizeof(model_net_wrap_msg);
#if 0
409
   if(net_id < 0 || net_id >= MAX_NETS)
410
411
412
413
414
415
     {
      printf("%s Error: Uninitializied modelnet network, call modelnet_init first\n", __FUNCTION__);
      exit(-1);
     }

       return method_array[net_id]->mn_get_msg_sz();
416
#endif
417
418
419
}

/* returns the packet size in the modelnet struct */
420
uint64_t model_net_get_packet_size(int net_id)
421
{
422
  if(net_id < 0 || net_id >= MAX_NETS)
423
424
425
426
427
428
429
     {
       fprintf(stderr, "%s Error: Uninitializied modelnet network, call modelnet_init first\n", __FUNCTION__);
       exit(-1);
     }
  return method_array[net_id]->packet_size; // TODO: where to set the packet size?
}

430
/* This event does a collective operation call for model-net */
431
void model_net_event_collective(int net_id, char const * category, int message_size, int remote_event_size, const void* remote_event, tw_lp* sender)
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
{
  if(net_id < 0 || net_id > MAX_NETS)
     {
       fprintf(stderr, "%s Error: Uninitializied modelnet network, call modelnet_init first\n", __FUNCTION__);
       exit(-1);
     }
  return method_array[net_id]->mn_collective_call(category, message_size, remote_event_size, remote_event, sender);
}

/* reverse event of the collective operation call */
void model_net_event_collective_rc(int net_id, int message_size, tw_lp* sender)
{
  if(net_id < 0 || net_id > MAX_NETS)
     {
       fprintf(stderr, "%s Error: Uninitializied modelnet network, call modelnet_init first\n", __FUNCTION__);
       exit(-1);
     }
  return method_array[net_id]->mn_collective_call_rc(message_size, sender);
}

452
453
454
/* returns lp type for modelnet */
const tw_lptype* model_net_get_lp_type(int net_id)
{
455
    if(net_id < 0 || net_id >= MAX_NETS)
456
457
458
459
460
461
462
463
464
465
     {
       fprintf(stderr, "%s Error: Uninitializied modelnet network, call modelnet_init first\n", __FUNCTION__);
       exit(-1);
     }

   // TODO: ADd checks by network names
   // Add dragonfly and torus network models
   return method_array[net_id]->mn_get_lp_type();
}

466
467
void model_net_report_stats(int net_id)
{
468
  if(net_id < 0 || net_id >= MAX_NETS)
469
470
471
472
473
474
475
  {
    fprintf(stderr, "%s Error: Uninitializied modelnet network, call modelnet_init first\n", __FUNCTION__);
    exit(-1);
   }

     // TODO: ADd checks by network names
     //    // Add dragonfly and torus network models
476
477
   method_array[net_id]->mn_report_stats();
   return;
478
}
479

480
481
482
483
484
485
486
487
488
489
490
491
492
493
static tw_lpid model_net_find_local_device_default(
        int          net_id,
        const char * annotation,
        int          ignore_annotations,
        tw_lpid      sender_gid) {
    char group_name[MAX_NAME_LENGTH];
    int dummy, mapping_rep, mapping_offset;
    int num_mn_lps;
    tw_lpid rtn;

    codes_mapping_get_lp_info(sender_gid, group_name, &dummy, NULL, &dummy,
            NULL, &mapping_rep, &mapping_offset);
    num_mn_lps = codes_mapping_get_lp_count(group_name, 1,
            model_net_lp_config_names[net_id], annotation, ignore_annotations);
494
495
496
497
498
499
500
    if (num_mn_lps <= 0) {
        tw_error(TW_LOC,
                "ERROR: Found no modelnet lps in group %s "
                "(source lpid %lu) with network type %s, annotation %s\n",
                group_name, sender_gid, model_net_lp_config_names[net_id],
                (ignore_annotations) ? "<ignored>" : annotation);
    }
501
502
503
504
505
506
    codes_mapping_get_lp_id(group_name, model_net_lp_config_names[net_id],
            annotation, ignore_annotations, mapping_rep,
            mapping_offset % num_mn_lps, &rtn);
    return rtn;
}

507
508
509
510
tw_lpid model_net_find_local_device(
        int          net_id,
        const char * annotation,
        int          ignore_annotations,
511
        tw_lpid      sender_gid)
512
{
513
514
515
516
517
518
    if (method_array[net_id]->model_net_method_find_local_device == NULL)
        return model_net_find_local_device_default(net_id, annotation,
                ignore_annotations, sender_gid);
    else
        return(method_array[net_id]->model_net_method_find_local_device(
                    annotation, ignore_annotations, sender_gid));
519
520
}

521
522
523
524
525
526
527
528
/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 * End:
 *
 * vim: ft=c ts=8 sts=4 sw=4 expandtab
 */