ROSS
mpi_allreduce.c
Go to the documentation of this file.
1#include <ross.h>
2#include <assert.h>
3
4#define TW_GVT_NORMAL 0
5#define TW_GVT_COMPUTE 1
6
7static unsigned int g_tw_gvt_max_no_change = 10000;
8static unsigned int g_tw_gvt_no_change = 0;
10static unsigned int gvt_cnt = 0;
11static unsigned int gvt_force = 0;
12void (*g_tw_gvt_hook) (tw_pe * pe, bool past_end_time) = NULL;
13// Holds one timestamp at which to trigger the arbitrary function
15
16// MPI configuration parameters for tw_event_sig
17#ifdef USE_RAND_TIEBREAKER
18MPI_Datatype event_sig_type;
19int event_sig_blocklengths[4] = {1, 1, MAX_TIE_CHAIN, 1};
20MPI_Aint event_sig_displacements[4];
21MPI_Datatype event_sig_types[4] = {MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_UNSIGNED};
22MPI_Aint event_sig_base_address;
23MPI_Op event_sig_min_op;
24tw_event_sig dummy_event_sig;
25
26void find_min_sig(void *in, void *inout, int *len, MPI_Datatype *datatype) {
27 (void) datatype;
28 tw_event_sig *in_sig = (tw_event_sig *)in;
29 tw_event_sig *inout_sig = (tw_event_sig *)inout;
30
31 for (int i=0; i < *len; i++) {
32 assert(in_sig->tie_lineage_length < MAX_TIE_CHAIN);
33 assert(inout_sig->tie_lineage_length < MAX_TIE_CHAIN);
34 if (tw_event_sig_compare_ptr(in_sig, inout_sig) < 0) {
35 inout_sig->recv_ts = in_sig->recv_ts;
36 inout_sig->priority = in_sig->priority;
37 inout_sig->tie_lineage_length = in_sig->tie_lineage_length;
38 for (unsigned int j = 0; j < in_sig->tie_lineage_length; j++) {
39 inout_sig->event_tiebreaker[j] = in_sig->event_tiebreaker[j];
40 }
41 }
42 in_sig++; inout_sig++;
43 }
44}
45#endif
46
47static const tw_optdef gvt_opts [] =
48{
49 TWOPT_GROUP("ROSS MPI GVT"),
50 TWOPT_UINT("gvt-interval", g_tw_gvt_interval, "GVT Interval: Iterations through scheduling loop (synch=1,2,3,4), or ms between GVTs (synch=5)"),
51 TWOPT_DOUBLE("report-interval", gvt_print_interval, "percent of runtime to print GVT"),
52 TWOPT_END()
53};
54
59
60const tw_optdef *
62{
63 gvt_cnt = 0;
64
65 return gvt_opts;
66}
67
68void
70{
71#ifdef USE_RAND_TIEBREAKER
72 MPI_Get_address(&dummy_event_sig, &event_sig_base_address);
73 MPI_Get_address(&dummy_event_sig.recv_ts, &event_sig_displacements[0]);
74 MPI_Get_address(&dummy_event_sig.priority, &event_sig_displacements[1]);
75 MPI_Get_address(&dummy_event_sig.event_tiebreaker, &event_sig_displacements[2]);
76 MPI_Get_address(&dummy_event_sig.tie_lineage_length, &event_sig_displacements[3]);
77
78 for (int i = 0; i < 4; i++) {
79 event_sig_displacements[i] = MPI_Aint_diff(event_sig_displacements[i], event_sig_base_address);
80 }
81
82 MPI_Type_create_struct(4, event_sig_blocklengths, event_sig_displacements, event_sig_types, &event_sig_type);
83 MPI_Type_commit(&event_sig_type);
84 MPI_Op_create(find_min_sig, 1, &event_sig_min_op); // 1 means operation is commutative
85#endif
86}
87
88void
90{
91#ifdef USE_RAND_TIEBREAKER
92 MPI_Op_free(&event_sig_min_op);
93 MPI_Type_free(&event_sig_type);
94#endif
95}
96
97void
103
104void
106{
107 gvt_force++;
108 g_tw_gvt_interval_start_cycles = 0; // reset to start of time
109}
110
111void
113{
114 fprintf(f, "\nTW GVT Statistics: MPI AllReduce\n");
115 fprintf(f, "\t%-50s %11d\n", "GVT Interval", g_tw_gvt_interval);
116 fprintf(f, "\t%-50s %llu\n", "GVT Real Time Interval (cycles)", g_tw_gvt_realtime_interval);
117 fprintf(f, "\t%-50s %11.8lf\n", "GVT Real Time Interval (sec)", (double)g_tw_gvt_realtime_interval/(double)g_tw_clock_rate);
118 fprintf(f, "\t%-50s %11d\n", "Batch Size", g_tw_mblock);
119 fprintf(f, "\n");
120 fprintf(f, "\t%-50s %11d\n", "Forced GVT", gvt_force);
121 fprintf(f, "\t%-50s %11d\n", "Total GVT Computations", g_tw_gvt_done);
122 fprintf(f, "\t%-50s %11lld\n", "Total All Reduce Calls", all_reduce_cnt);
123 fprintf(f, "\t%-50s %11.2lf\n", "Average Reduction / GVT",
124 (double) ((double) all_reduce_cnt / (double) g_tw_gvt_done));
125}
126
127// To use in `tw_gvt_step1` and `tw_gvt_step1_realtime`
128#ifdef USE_RAND_TIEBREAKER
129#define NOT_PAST_LOOKAHEAD(pe) (TW_STIME_DBL(tw_pq_minimum_sig_ptr(pe->pq)->recv_ts) - TW_STIME_DBL(pe->GVT_sig.recv_ts) < g_tw_max_opt_lookahead)
130#define PAST_GVT_HOOK_ACTIVATION(pe) (\
131 g_tw_gvt_hook_trigger.status == GVT_HOOK_STATUS_timestamp \
132 && tw_event_sig_compare_ptr(tw_pq_minimum_sig_ptr(pe->pq), &g_tw_gvt_hook_trigger.sig_at) >= 0)
133#else
134#define NOT_PAST_LOOKAHEAD(pe) (TW_STIME_DBL(tw_pq_minimum(pe->pq)) - TW_STIME_DBL(pe->GVT) < g_tw_max_opt_lookahead)
135#define PAST_GVT_HOOK_ACTIVATION(pe) (\
136 g_tw_gvt_hook_trigger.status == GVT_HOOK_STATUS_timestamp \
137 && tw_pq_minimum(me->pq) >= g_tw_gvt_hook_trigger.at)
138#endif
139
140void
142{
143 if (me->gvt_status == TW_GVT_COMPUTE) {
144 return;
145 }
146
147 int const still_within_interval = ++gvt_cnt < g_tw_gvt_interval;
148 if (still_within_interval && NOT_PAST_LOOKAHEAD(me) && !PAST_GVT_HOOK_ACTIVATION(me)) {
149 return;
150 }
151
153}
154
155void
157{
158 if (me->gvt_status == TW_GVT_COMPUTE) {
159 return;
160 }
161 int const still_within_interval = tw_clock_read() - g_tw_gvt_interval_start_cycles < g_tw_gvt_realtime_interval;
162 if (still_within_interval && NOT_PAST_LOOKAHEAD(me) && !PAST_GVT_HOOK_ACTIVATION(me)) {
163 return;
164 }
165
167}
168
169#ifdef USE_RAND_TIEBREAKER
170//This function had so many interweavings of USE_RAND_TIEBREAKER that it was simpler to duplicate the function
171void
173{
174 if(me->gvt_status != TW_GVT_COMPUTE)
175 return;
176
177 long long local_white = 0;
178 long long total_white = 0;
179
180 tw_event_sig pq_min_sig;
181 tw_event_sig net_min_sig;
182 tw_copy_event_sig(&pq_min_sig, &g_tw_max_sig);
183 tw_copy_event_sig(&net_min_sig, &g_tw_max_sig);
184
185 tw_event_sig lvt_sig;
186 tw_event_sig gvt_sig;
187
188 tw_clock net_start;
189 tw_clock start = tw_clock_read();
190
191 while(1)
192 {
193 net_start = tw_clock_read();
194 tw_net_read(me);
195 me->stats.s_net_read += tw_clock_read() - net_start;
196
197 // send message counts to create consistent cut
198 local_white = me->s_nwhite_sent - me->s_nwhite_recv;
200 if(MPI_Allreduce(
201 &local_white,
202 &total_white,
203 1,
204 MPI_LONG_LONG,
205 MPI_SUM,
206 MPI_COMM_ROSS) != MPI_SUCCESS)
207 tw_error(TW_LOC, "MPI_Allreduce for GVT failed");
208
209 if(total_white == 0)
210 break;
211 }
212 tw_copy_event_sig(&pq_min_sig, tw_pq_minimum_sig_ptr(me->pq));
214
215 lvt_sig = me->trans_msg_sig;
216 if(tw_event_sig_compare_ptr(&lvt_sig, &pq_min_sig) > 0)
217 {
218 tw_copy_event_sig(&lvt_sig, &pq_min_sig);
219 }
220 if(tw_event_sig_compare_ptr(&lvt_sig, &net_min_sig) > 0)
221 {
222 tw_copy_event_sig(&lvt_sig, &net_min_sig);
223 }
224
226 if(MPI_Allreduce(
227 &lvt_sig,
228 &gvt_sig,
229 1,
230 event_sig_type,
231 event_sig_min_op,
233 ) != MPI_SUCCESS) {
234 tw_error(TW_LOC, "MPI_Allreduce for GVT event signatures failed");
235 }
236
237 if(tw_event_sig_compare_ptr(&gvt_sig, &me->GVT_prev_sig) < 0)
238 {
240 } else
241 {
242 tw_copy_event_sig(&gvt_sig, &me->GVT_prev_sig);
245 tw_error(
246 TW_LOC,
247 "GVT computed %d times in a row"
248 " without changing: GVT = %14.14lf, PREV %14.14lf"
249 " -- GLOBAL SYNCH -- out of memory!",
251 }
252 }
253
254 if (tw_event_sig_compare_ptr(&me->GVT_sig, &gvt_sig) > 0)
255 {
256 tw_error(TW_LOC, "PE %u GVT decreased %g -> %g",
257 me->id, me->GVT_sig.recv_ts, gvt_sig.recv_ts);
258
259 }
260
262 {
263 gvt_print(gvt_sig.recv_ts);
264 }
265
266 me->s_nwhite_sent = 0;
267 me->s_nwhite_recv = 0;
269 //tw_copy_event_sig(&me->GVT_prev_sig, &me->GVT_sig); // Disabled checking previous timestamp
270 tw_copy_event_sig(&me->GVT_sig, &gvt_sig);
272
273 gvt_cnt = 0;
274
275 // update GVT timing stats
276 me->stats.s_gvt += tw_clock_read() - start;
277
278 // only FC if OPTIMISTIC or REALTIME, do not do for DEBUG MODE
281 {
282 start = tw_clock_read();
284 me->stats.s_fossil_collect += tw_clock_read() - start;
285 }
286
287 // do any necessary instrumentation calls
290 {
291#ifdef USE_DAMARIS
292 if (g_st_damaris_enabled)
293 {
294 st_damaris_expose_data(me, gvt, GVT_COL);
295 st_damaris_end_iteration();
296 }
297 else
299#else
301#endif
302 }
303#ifdef USE_DAMARIS
304 // need to make sure damaris_end_iteration is called if GVT instrumentation not turned on
305 //if (!g_st_stats_enabled && g_st_real_time_samp) //need to make sure if one PE enters this, all do; otherwise deadlock
306 if (g_st_damaris_enabled && (g_st_engine_stats == RT_STATS || g_st_engine_stats == VT_STATS))
307 {
308 st_damaris_end_iteration();
309 }
310#endif
311
314
315 st_inst_dump();
316 // done with instrumentation related stuff
317
319
320 // reset for the next gvt round -- for use in realtime GVT mode only!!
322 }
323#else
324void
326{
327 long long local_white = 0;
328 long long total_white = 0;
329
330 tw_stime pq_min = TW_STIME_MAX;
331 tw_stime net_min = TW_STIME_MAX;
332
333 tw_stime lvt;
334 tw_stime gvt;
335
336 tw_clock net_start;
337 tw_clock start = tw_clock_read();
338
339 if(me->gvt_status != TW_GVT_COMPUTE)
340 return;
341 while(1)
342 {
343 net_start = tw_clock_read();
344 tw_net_read(me);
345 me->stats.s_net_read += tw_clock_read() - net_start;
346
347 // send message counts to create consistent cut
348 local_white = me->s_nwhite_sent - me->s_nwhite_recv;
350 if(MPI_Allreduce(
351 &local_white,
352 &total_white,
353 1,
354 MPI_LONG_LONG,
355 MPI_SUM,
356 MPI_COMM_ROSS) != MPI_SUCCESS)
357 tw_error(TW_LOC, "MPI_Allreduce for GVT failed");
358
359 if(total_white == 0)
360 break;
361 }
362
363 pq_min = tw_pq_minimum(me->pq);
364 net_min = tw_net_minimum();
365
366 lvt = me->trans_msg_ts;
367 if(TW_STIME_CMP(lvt, pq_min) > 0)
368 lvt = pq_min;
369 if(TW_STIME_CMP(lvt, net_min) > 0)
370 lvt = net_min;
371
373
374 if(MPI_Allreduce(
375 &lvt,
376 &gvt,
377 1,
379 MPI_MIN,
380 MPI_COMM_ROSS) != MPI_SUCCESS)
381 tw_error(TW_LOC, "MPI_Allreduce for GVT failed");
382
383 if(TW_STIME_CMP(gvt, me->GVT_prev) < 0)
384 {
386 } else
387 {
388 gvt = me->GVT_prev;
391 tw_error(
392 TW_LOC,
393 "GVT computed %d times in a row"
394 " without changing: GVT = %14.14lf, PREV %14.14lf"
395 " -- GLOBAL SYNCH -- out of memory!",
396 g_tw_gvt_no_change, gvt, me->GVT_prev);
397 }
398 }
399
400 if (TW_STIME_CMP(me->GVT, gvt) > 0)
401 {
402 tw_error(TW_LOC, "PE %u GVT decreased %g -> %g",
403 me->id, me->GVT, gvt);
404 }
405
407 {
408 gvt_print(gvt);
409 }
410
411 me->s_nwhite_sent = 0;
412 me->s_nwhite_recv = 0;
414 // me->GVT_prev = me->GVT;
415 me->GVT = gvt;
417
418 gvt_cnt = 0;
419
420 // update GVT timing stats
421 me->stats.s_gvt += tw_clock_read() - start;
422
423 // only FC if OPTIMISTIC or REALTIME, do not do for DEBUG MODE
426 {
427 start = tw_clock_read();
429 me->stats.s_fossil_collect += tw_clock_read() - start;
430 }
431
432 // do any necessary instrumentation calls
435 {
436#ifdef USE_DAMARIS
437 if (g_st_damaris_enabled)
438 {
439 st_damaris_expose_data(me, gvt, GVT_COL);
440 st_damaris_end_iteration();
441 }
442 else
444#else
446#endif
447 }
448#ifdef USE_DAMARIS
449 // need to make sure damaris_end_iteration is called if GVT instrumentation not turned on
450 //if (!g_st_stats_enabled && g_st_real_time_samp) //need to make sure if one PE enters this, all do; otherwise deadlock
451 if (g_st_damaris_enabled && (g_st_engine_stats == RT_STATS || g_st_engine_stats == VT_STATS))
452 {
453 st_damaris_end_iteration();
454 }
455#endif
456
459
460 st_inst_dump();
461 // done with instrumentation related stuff
462
464
465 // reset for the next gvt round -- for use in realtime GVT mode only!!
467 }
468#endif
469
470
471#ifdef USE_RAND_TIEBREAKER
473 tw_event_sig now = g_tw_pe->GVT_sig;
474 tw_event_sig time_sig = {
475 .recv_ts = time,
476 .priority = 0.0,
477 .event_tiebreaker = {0.0},
478 .tie_lineage_length = 1};
479
480 if (now.recv_ts >= time) {
481 tw_warning(TW_LOC, "Trying to schedule arbitrary function trigger at a time in the past %e, current GVT %e\n", time, now.recv_ts);
482 }
483
485 g_tw_gvt_hook_trigger.sig_at = time_sig;
486}
487#else
489 tw_stime now = g_tw_pe->GVT;
490
491 if (now >= time) {
492 tw_warning(TW_LOC, "Trying to schedule arbitrary function trigger at a time in the past %e, current GVT %e\n", time, now);
493 }
494
496 g_tw_gvt_hook_trigger.at = time;
497}
498#endif
499
500#ifdef USE_RAND_TIEBREAKER
502 tw_event_sig now = g_tw_pe->GVT_sig;
503
504 if (tw_event_sig_compare_ptr(&now, &time) >= 0) {
505 tw_warning(TW_LOC, "Trying to schedule arbitrary function trigger at a time in the past %e, current GVT %e\n", time.recv_ts, now.recv_ts);
506 }
507
509 g_tw_gvt_hook_trigger.sig_at = time;
510 //g_tw_gvt_hook_trigger.at = time;
511}
512#endif
513
514void tw_trigger_gvt_hook_every(int num_gvt_calls) {
515 if (num_gvt_calls <= 0) {
516 tw_error(TW_LOC, "`tw_trigger_gvt_hook_every` has been called with a non-positive argument: %d", num_gvt_calls);
517 }
519 g_tw_gvt_hook_trigger.every_n_gvt.starting_at = g_tw_gvt_done;
520 g_tw_gvt_hook_trigger.every_n_gvt.nums = num_gvt_calls;
521}
522
525 // timestamp is the largest signature
527}
528
531 return; // An LP can only force the GVT hook call on sequential and parallel optimistic simulations
532 }
534 tw_error(TW_LOC, "`tw_trigger_gvt_hook_now` called but `g_tw_gvt_hook_trigger.status != GVT_HOOK_STATUS_model_call`. Either `tw_trigger_gvt_hook_when_model_calls` was not called or another trigger function has been");
535 }
536 tw_event_sig * now = &lp->kp->last_sig; // tw_now_sig(lp);
538
539 // Forcing GVT to happen now (possibly triggering gvt hook)
540 lp->pe->gvt_status = TW_GVT_COMPUTE; // same behavior as if calling `tw_gvt_force_update()`
541 lp->triggered_gvt_hook++;
542}
543
tw_pe * pe
Definition avl_tree.c:10
static tw_clock tw_clock_read(void)
Definition aarch64.h:8
uint64_t tw_clock
Definition aarch64.h:6
static double percent_complete
static double gvt_print_interval
static void gvt_print(tw_stime gvt)
@ GVT_STATS
@ ALL_STATS
int g_st_model_stats
void st_inst_dump()
@ GVT_COL
void st_collect_engine_data(tw_pe *me, int col_type)
void st_collect_model_data(tw_pe *pe, double current_rt, int stats_type)
int g_st_engine_stats
int g_st_num_gvt
void tw_net_read(tw_pe *)
starts service_queues() to poll network
tw_event_sig const * tw_net_minimum_sig_ptr(void)
Obtain the event signature for the lowest ordered event inside the network buffers.
tw_stime tw_net_minimum(void)
Obtain the lowest timestamp inside the network buffers.
MPI_Comm MPI_COMM_ROSS
Definition network-mpi.c:4
tw_stime tw_pq_minimum(tw_pq *)
Definition splay.c:398
#define TW_STIME_DBL(x)
Definition ross-base.h:42
#define TW_STIME_MAX
Definition ross-base.h:45
#define MPI_TYPE_TW_STIME
Definition ross-base.h:40
#define TW_STIME_CMP(x, y)
Definition ross-base.h:43
double tw_stime
Definition ross-base.h:39
tw_pe * g_tw_pe
Definition ross-global.c:79
void tw_pe_fossil_collect(void)
Definition tw-pe.c:68
unsigned long long g_tw_clock_rate
unsigned long long g_tw_gvt_interval_start_cycles
Definition ross-global.c:70
void tw_error(const char *file, int line, const char *fmt,...)
Definition tw-util.c:77
tw_peid g_tw_mynode
Definition ross-global.c:92
unsigned int g_tw_gvt_done
Definition ross-global.c:85
tw_peid g_tw_masternode
Definition ross-global.c:93
void tw_warning(const char *file, int line, const char *fmt,...)
Definition tw-util.c:93
unsigned int g_tw_gvt_interval
Definition ross-global.c:67
unsigned int g_tw_mblock
Definition ross-global.c:66
unsigned long long g_tw_gvt_realtime_interval
Definition ross-global.c:69
tw_synch g_tw_synchronization_protocol
Definition ross-global.c:19
double g_tw_ts_end
Definition ross-global.c:72
#define TW_LOC
void tw_trigger_gvt_hook_at_event_sig(tw_event_sig time)
@ GVT_HOOK_STATUS_disabled
@ GVT_HOOK_STATUS_timestamp
@ GVT_HOOK_STATUS_every_n_gvt
struct gvt_hook_trigger g_tw_gvt_hook_trigger
void(* g_tw_gvt_hook)(tw_pe *pe, bool is_queue_empty)
static int tw_event_sig_compare_ptr(tw_event_sig const *e_sig, tw_event_sig const *n_sig)
Definition ross-types.h:512
tw_event_sig const g_tw_max_sig
static void tw_copy_event_sig(tw_event_sig *e, tw_event_sig const *sig)
Definition ross-types.h:493
#define MAX_TIE_CHAIN
Definition ross-types.h:30
unsigned long long tw_stat
Definition ross-types.h:58
@ OPTIMISTIC_REALTIME
Definition ross-types.h:41
@ CONSERVATIVE
Definition ross-types.h:38
@ OPTIMISTIC
Definition ross-types.h:39
@ OPTIMISTIC_DEBUG
Definition ross-types.h:40
#define TWOPT_UINT(n, v, h)
Definition tw-opts.h:33
#define TWOPT_GROUP(h)
Definition tw-opts.h:30
#define TWOPT_END()
Definition tw-opts.h:39
#define TWOPT_DOUBLE(n, v, h)
Definition tw-opts.h:35
@ GVT_HOOK_STATUS_model_call
void tw_gvt_start(void)
static const tw_optdef gvt_opts[]
static unsigned int gvt_force
void tw_gvt_stats(FILE *f)
#define PAST_GVT_HOOK_ACTIVATION(pe)
void tw_gvt_force_update(void)
static tw_stat all_reduce_cnt
void tw_gvt_finish(void)
void tw_trigger_gvt_hook_now_rev(tw_lp *lp)
void tw_trigger_gvt_hook_at(tw_stime time)
void tw_trigger_gvt_hook_now(tw_lp *lp)
#define TW_GVT_COMPUTE
static unsigned int gvt_cnt
void tw_gvt_step1_realtime(tw_pe *me)
void tw_gvt_force_update_realtime(void)
static unsigned int g_tw_gvt_max_no_change
void tw_trigger_gvt_hook_every(int num_gvt_calls)
void tw_trigger_gvt_hook_when_model_calls(void)
void tw_gvt_step1(tw_pe *me)
tw_stat st_get_allreduce_count()
#define NOT_PAST_LOOKAHEAD(pe)
const tw_optdef * tw_gvt_setup(void)
static unsigned int g_tw_gvt_no_change
#define TW_GVT_NORMAL
void tw_gvt_step2(tw_pe *me)
double event_tiebreaker[20]
Definition ross-types.h:263
double priority
Definition ross-types.h:261
tw_stime recv_ts
Definition ross-types.h:260
unsigned int tie_lineage_length
Definition ross-types.h:262
tw_event_sig last_sig
Event signature of the current event being processed.
Definition ross-types.h:398
LP State Structure.
Definition ross-types.h:336
tw_pe * pe
Definition ross-types.h:340
tw_kp * kp
kp – Kernel process that we belong to (must match pe).
Definition ross-types.h:345
unsigned int triggered_gvt_hook
Definition ross-types.h:369
Holds the entire PE state.
Definition ross-types.h:416
tw_pq * pq
Priority queue used to sort events.
Definition ross-types.h:422
tw_event_sig trans_msg_sig
Last transient messages' time signature.
Definition ross-types.h:444
tw_stime GVT
Global Virtual Time.
Definition ross-types.h:451
tw_stime GVT_prev
Definition ross-types.h:452
tw_stime trans_msg_ts
Last transient messages' time stamp.
Definition ross-types.h:450
tw_peid id
Definition ross-types.h:417
unsigned char gvt_status
Bits available for gvt computation.
Definition ross-types.h:441
long long s_nwhite_recv
Definition ross-types.h:457
tw_statistics stats
per PE counters
Definition ross-types.h:463
tw_event_sig GVT_sig
Global Virtual Time Signature.
Definition ross-types.h:445
long long s_nwhite_sent
Definition ross-types.h:456
tw_event_sig GVT_prev_sig
Definition ross-types.h:446
tw_clock s_net_read
Definition ross-types.h:146
tw_clock s_gvt
Definition ross-types.h:148
tw_clock s_fossil_collect
Definition ross-types.h:149