2 % (c) The GRASP/AQUA Project, Glasgow University, 1995
4 %************************************************************************
6 \section[GranSim.lc]{Granularity Simulator Routines}
8 %************************************************************************
10 Macros for dealing with the new and improved GA field for simulating
11 parallel execution. Based on @CONCURRENT@ package. The GA field now
12 contains a mask, where the n-th bit stands for the n-th processor,
13 where this data can be found. In case of multiple copies, several bits
14 are set. The total number of processors is bounded by @MAX_PROC@,
15 which should be <= the length of a word in bits. -- HWL
18 #if defined(GRAN) || defined(PAR)
20 #define NON_POSIX_SOURCE /* gettimeofday */
27 #ifdef HAVE_SYS_TIMERS_H
29 #include <sys/timers.h>
33 #ifdef HAVE_GETTIMEOFDAY
35 #ifdef HAVE_SYS_TIME_H
48 void grputw PROTO((TIME v));
51 /* Pointer to the event queue; events are currently malloc'ed */
52 static eventq EventHd = NULL;
59 for (i = 0; i < MAX_PROC && !IS_LOCAL_TO(ga, i); i++);
64 /* NB: This takes a *node* rather than just a ga as input */
67 { return (ga_to_proc(PROCS(node))); } /* Access the GA field of the node */
71 no_of_copies(W_ ga) /* DaH lo'lu'Qo'; currently unused */
75 for (i = 0, n = 0; i < MAX_PROC; i++)
76 if (IS_LOCAL_TO(ga, i))
86 static eventq entry = NULL;
90 fprintf(stderr,"No next event\n");
91 exit(EXIT_FAILURE); /* why not EXIT??? WDP 95/07 */
97 #if defined(GRAN_CHECK) && defined(GRAN)
98 if (debug & 0x20) { /* count events */
100 event_counts[(EVENT_TYPE(EventHd)>=CONTINUETHREAD1) ?
102 EVENT_TYPE(EventHd)]++;
107 EventHd = EVENT_NEXT(EventHd);
111 /* ToDo: replace malloc/free with a free list */
113 /* NB: newevent unused (WDP 95/07) */
116 newevent(proc,creator,time,evttype,tso,node,spark)
123 eventq newentry = (eventq) stgMallocBytes(sizeof(struct event), "newevent");
125 EVENT_PROC(newentry) = proc;
126 EVENT_CREATOR(newentry) = creator;
127 EVENT_TIME(newentry) = time;
128 EVENT_TYPE(newentry) = evttype;
129 EVENT_TSO(newentry) = tso;
130 EVENT_NODE(newentry) = node;
131 EVENT_SPARK(newentry) = spark;
132 EVENT_NEXT(newentry) = NULL;
134 insert_event(newentry);
137 #endif /* GRAN ; HWL */
140 %****************************************************************************
142 \subsection[GrAnSim-profile]{Writing profiling info for GrAnSim}
144 %****************************************************************************
146 Event dumping routines.
150 FILE *gr_file = NULL;
152 char *gran_event_names[] = {
154 "STEALING", "STOLEN", "STOLEN(Q)",
155 "FETCH", "REPLY", "BLOCK", "RESUME", "RESUME(Q)",
156 "SCHEDULE", "DESCHEDULE",
158 "SPARK", "SPARKAT", "USED", "PRUNED", "EXPORTED", "ACQUIRED",
164 * If you're not using GNUC and you're on a 32-bit machine, you're
165 * probably out of luck here. However, since CONCURRENT currently
166 * requires GNUC, I'm not too worried about it. --JSM
171 static ullong startTime = 0;
176 # ifdef HAVE_GETCLOCK
179 if (getclock(TIMEOFDAY, &tv) != 0) {
181 fprintf(stderr, "Clock failed\n");
184 return tv.tv_sec * LL(1000) + tv.tv_nsec / LL(1000000) - startTime;
186 # ifdef HAVE_GETTIMEOFDAY
189 if (gettimeofday(&tv, NULL) != 0) {
191 fprintf(stderr, "Clock failed\n");
194 return tv.tv_sec * LL(1000) + tv.tv_usec / LL(1000) - startTime;
197 if ((t = time(NULL)) == (time_t) -1) {
199 fprintf(stderr, "Clock failed\n");
211 DumpGranEvent(name, tso)
212 enum gran_event_types name;
215 DumpRawGranEvent(CURRENT_PROC, name, TSO_ID(tso));
219 DumpSparkGranEvent(name, id)
220 enum gran_event_types name;
223 DumpRawGranEvent(CURRENT_PROC, name, id);
227 DumpGranEventAndNode(name, tso, node, proc)
228 enum gran_event_types name;
232 PROC pe = CURRENT_PROC;
235 char time_string[500]; /*ToDo: kill magic constant */
236 ullong_format_string(CURRENT_TIME, time_string, rtsFalse/*no commas!*/);
239 id = tso == NULL ? -1 : TSO_ID(tso);
243 if (name > GR_EVENT_MAX)
246 if (RTSflags.ParFlags.granSimStats_Binary) {
249 abort(); /* die please: a single word doesn't represent long long times */
250 grputw(CURRENT_TIME); /* this line is bound to do the wrong thing */
253 fprintf(gr_file, "PE %2u [%s]: %s %lx \t0x%lx\t(from %2u)\n",
254 pe, time_string, gran_event_names[name], id, (W_) node, proc);
258 DumpRawGranEvent(pe, name, id)
260 enum gran_event_types name;
263 char time_string[500]; /* ToDo: kill magic constant */
265 if (name > GR_EVENT_MAX)
268 ullong_format_string(CURRENT_TIME, time_string, rtsFalse/*no commas!*/);
270 if (RTSflags.ParFlags.granSimStats_Binary) {
273 abort(); /* die please: a single word doesn't represent long long times */
274 grputw(CURRENT_TIME); /* this line is bound to fail */
277 fprintf(gr_file, "PE %2u [%s]: %s %lx\n",
278 pe, time_string, gran_event_names[name], id);
282 DumpGranInfo(pe, tso, mandatory_thread)
285 rtsBool mandatory_thread;
287 char time_string[500]; /* ToDo: kill magic constant */
288 ullong_format_string(CURRENT_TIME, time_string, rtsFalse/*no commas!*/);
290 if (RTSflags.ParFlags.granSimStats_Binary) {
293 abort(); /* die please: a single word doesn't represent long long times */
294 grputw(CURRENT_TIME); /* this line is bound to fail */
310 grputw(TSO_SPARKNAME(tso));
311 grputw(TSO_STARTEDAT(tso));
312 grputw(TSO_EXPORTED(tso));
313 grputw(TSO_BASICBLOCKS(tso));
314 grputw(TSO_ALLOCS(tso));
315 grputw(TSO_EXECTIME(tso));
316 grputw(TSO_BLOCKTIME(tso));
317 grputw(TSO_BLOCKCOUNT(tso));
318 grputw(TSO_FETCHTIME(tso));
319 grputw(TSO_FETCHCOUNT(tso));
320 grputw(TSO_LOCALSPARKS(tso));
321 grputw(TSO_GLOBALSPARKS(tso));
323 grputw(mandatory_thread);
327 * NB: DumpGranEvent cannot be used because PE may be wrong (as well as the
330 fprintf(gr_file, "PE %2u [%s]: END %lx, SN %lu, ST %lu, EXP %c, BB %lu, HA %lu, RT %lu, BT %lu (%lu), FT %lu (%lu), LS %lu, GS %lu, MY %c\n"
336 ,TSO_EXPORTED(tso) ? 'T' : 'F'
337 ,TSO_BASICBLOCKS(tso)
344 ,TSO_LOCALSPARKS(tso)
345 ,TSO_GLOBALSPARKS(tso)
346 ,mandatory_thread ? 'T' : 'F'
352 Output a terminate event and an 8-byte time.
359 DumpGranEvent(GR_TERMINATE, 0);
361 if (sizeof(TIME) == 4) {
367 putc(v >> 56l, gr_file);
368 putc((v >> 48l) & 0xffl, gr_file);
369 putc((v >> 40l) & 0xffl, gr_file);
370 putc((v >> 32l) & 0xffl, gr_file);
372 putc((v >> 24l) & 0xffl, gr_file);
373 putc((v >> 16l) & 0xffl, gr_file);
374 putc((v >> 8l) & 0xffl, gr_file);
375 putc(v & 0xffl, gr_file);
379 Length-coded output: first 3 bits contain length coding
393 fputc(v & 0x3f, gr_file);
394 } else if (v <= 0x3fffl) {
395 fputc((v >> 8l) | 0x40l, gr_file);
396 fputc(v & 0xffl, gr_file);
397 } else if (v <= 0x3fffffffl) {
398 fputc((v >> 24l) | 0x80l, gr_file);
399 fputc((v >> 16l) & 0xffl, gr_file);
400 fputc((v >> 8l) & 0xffl, gr_file);
401 fputc(v & 0xffl, gr_file);
402 } else if (sizeof(TIME) == 4) {
403 fputc(0x70, gr_file);
404 fputc((v >> 24l) & 0xffl, gr_file);
405 fputc((v >> 16l) & 0xffl, gr_file);
406 fputc((v >> 8l) & 0xffl, gr_file);
407 fputc(v & 0xffl, gr_file);
409 if (v <= 0x3fffffffffffffl)
410 putc((v >> 56l) | 0x60l, gr_file);
413 putc((v >> 56l) & 0xffl, gr_file);
416 putc((v >> 48l) & 0xffl, gr_file);
417 putc((v >> 40l) & 0xffl, gr_file);
418 putc((v >> 32l) & 0xffl, gr_file);
419 putc((v >> 24l) & 0xffl, gr_file);
420 putc((v >> 16l) & 0xffl, gr_file);
421 putc((v >> 8l) & 0xffl, gr_file);
422 putc(v & 0xffl, gr_file);
428 %****************************************************************************
430 \subsection[gr-simulation]{Granularity Simulation}
432 %****************************************************************************
436 char gr_filename[STATS_FILENAME_MAXLEN];
440 init_gr_simulation(rts_argc, rts_argv, prog_argc, prog_argv)
441 char *prog_argv[], *rts_argv[];
442 int prog_argc, rts_argc;
447 char *extension = RTSflags.ParFlags.granSimStats_Binary ? "gb" : "gr";
449 sprintf(gr_filename, GR_FILENAME_FMT, prog_argv[0], extension);
451 if ((gr_file = fopen(gr_filename, "w")) == NULL) {
452 fprintf(stderr, "Can't open granularity simulation report file %s\n", gr_filename);
453 exit(EXIT_FAILURE); /* why not EXIT??? WDP 95/07 */
455 #if defined(GRAN_CHECK) && defined(GRAN)
456 if (DoReScheduleOnFetch)
457 setbuf(gr_file, NULL);
460 fputs("Granularity Simulation for ", gr_file);
461 for (i = 0; i < prog_argc; ++i) {
462 fputs(prog_argv[i], gr_file);
467 fputs("+RTS ", gr_file);
469 for (i = 0; i < rts_argc; ++i) {
470 fputs(rts_argv[i], gr_file);
474 fputs("\n\n--------------------\n\n", gr_file);
476 fputs("General Parameters:\n\n", gr_file);
478 fprintf(gr_file, "PEs %u, %s Scheduler, %sMigrate Threads%s ????? %s\n",
479 max_proc, DoFairSchedule ? "Fair" : "Unfair",
480 DoThreadMigration ? "" : "Don't ",
481 DoThreadMigration && DoStealThreadsFirst ? " Before Sparks" : "",
482 DoReScheduleOnFetch ? "" : "Don't ");
484 fprintf(gr_file, "%s, Fetch %s in Each Packet\n",
485 SimplifiedFetch ? "Simplified Fetch" : (DoReScheduleOnFetch ? "Reschedule on Fetch" : "Block on Fetch"),
486 DoGUMMFetching ? "Many Closures" : "Exactly One Closure");
487 fprintf(gr_file, "Fetch Strategy(%lu): If outstanding fetches %s\n",
489 FetchStrategy == 1 ? "only run runnable threads (don't create new ones" :
490 FetchStrategy == 2 ? "create threads only from local sparks" :
491 FetchStrategy == 3 ? "create threads from local or global sparks" :
492 FetchStrategy == 4 ? "create sparks and steal threads if necessary" :
495 fprintf(gr_file, "Thread Creation Time %lu, Thread Queue Time %lu\n",
496 gran_threadcreatetime, gran_threadqueuetime);
497 fprintf(gr_file, "Thread DeSchedule Time %lu, Thread Schedule Time %lu\n",
498 gran_threaddescheduletime, gran_threadscheduletime);
499 fprintf(gr_file, "Thread Context-Switch Time %lu\n",
500 gran_threadcontextswitchtime);
501 fputs("\n\n--------------------\n\n", gr_file);
503 fputs("Communication Metrics:\n\n", gr_file);
505 "Latency %lu (1st) %lu (rest), Fetch %lu, Notify %lu (Global) %lu (Local)\n",
506 gran_latency, gran_additional_latency, gran_fetchtime,
507 gran_gunblocktime, gran_lunblocktime);
509 "Message Creation %lu (+ %lu after send), Message Read %lu\n",
510 gran_mpacktime, gran_mtidytime, gran_munpacktime);
511 fputs("\n\n--------------------\n\n", gr_file);
513 fputs("Instruction Metrics:\n\n", gr_file);
514 fprintf(gr_file, "Arith %lu, Branch %lu, Load %lu, Store %lu, Float %lu, Alloc %lu\n",
515 gran_arith_cost, gran_branch_cost,
516 gran_load_cost, gran_store_cost, gran_float_cost, gran_heapalloc_cost);
517 fputs("\n\n++++++++++++++++++++\n\n", gr_file);
519 if (RTSflags.ParFlags.granSimStats_Binary)
520 grputw(sizeof(TIME));
527 end_gr_simulation(STG_NO_ARGS)
530 fprintf(stderr, "The simulation is finished. Look at %s for details.\n",
539 char gr_filename[STATS_FILENAME_MAXLEN];
541 I_ do_sp_profile = 0;
544 init_gr_profiling(rts_argc, rts_argv, prog_argc, prog_argv)
545 char *prog_argv[], *rts_argv[];
546 int prog_argc, rts_argc;
550 char *extension = RTSflags.ParFlags.granSimStats_Binary ? "gb" : "gr";
552 sprintf(gr_filename, GR_FILENAME_FMT_GUM, prog_argv[0], thisPE, extension);
554 if ((gr_file = fopen(gr_filename, "w")) == NULL) {
555 fprintf(stderr, "Can't open activity report file %s\n", gr_filename);
559 for (i = 0; i < prog_argc; ++i) {
560 fputs(prog_argv[i], gr_file);
565 fputs("+RTS ", gr_file);
567 for (i = 0; i < rts_argc; ++i) {
568 fputs(rts_argv[i], gr_file);
572 fputc('\n', gr_file);
574 startTime = CURRENT_TIME;
576 if (startTime > LL(1000000000)) {
577 /* This shouldn't overflow twice */
578 fprintf(gr_file, "PE %2u [%lu%lu]: TIME\n", thisPE,
579 (TIME) (startTime / LL(1000000000)),
580 (TIME) (startTime % LL(1000000000)));
582 fprintf(gr_file, "PE %2u [%lu]: TIME\n", thisPE, (TIME) startTime);
585 if (RTSflags.ParFlags.granSimStats_Binary)
586 grputw(sizeof(TIME));
590 #endif /* GRAN || PAR */