/* StarPU --- Runtime system for heterogeneous multicore architectures. * * Copyright (C) 2015 Université de Bordeaux * Copyright (C) 2015 Anthony Simonet * * StarPU is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at * your option) any later version. * * StarPU is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU Lesser General Public License in COPYING.LGPL for more details. */ #include #include #include #include #include "starpu_fxt.h" static struct component { UT_hash_handle hh; char *name; int workerid; uint64_t ptr; unsigned nchildren; struct component **children; struct component *parent; unsigned ntasks; unsigned npriotasks; } *components; static unsigned global_state = 1; static unsigned nsubmitted; static unsigned curq_size; static unsigned nflowing; #define COMPONENT_ADD(head, field, add) HASH_ADD(hh, head, field, sizeof(uint64_t), add); #define COMPONENT_FIND(head, find, out) HASH_FIND(hh, head, &find, sizeof(uint64_t), out); static struct component *fxt_component_root(void) { struct component *comp, *tmp; HASH_ITER(hh, components, comp, tmp) { while (comp->parent) comp = comp->parent; return comp; } return NULL; } void _starpu_fxt_component_new(uint64_t component, char *name) { struct component *comp = malloc(sizeof(*comp)); if (!strncmp(name, "worker ", 7)) { comp->name = strdup("worker"); comp->workerid = atoi(name+7); } else { comp->name = strdup(name); comp->workerid = -1; } comp->ptr = component; comp->nchildren = 0; comp->children = NULL; comp->parent = NULL; comp->ntasks = 0; comp->npriotasks = 0; COMPONENT_ADD(components, ptr, comp); } static void fxt_component_dump(FILE *file, struct component *comp, unsigned depth) { unsigned i; fprintf(file,"%*s%s (%d %"PRIx64", %d tasks %d prio tasks)\n", 2*depth, "", comp->name, depth, comp->ptr, comp->ntasks, comp->npriotasks); for (i = 0; i < comp->nchildren; i++) if (comp->children[i]->parent == comp) fxt_component_dump(file, comp->children[i], depth+1); } void _starpu_fxt_component_dump(FILE *file) { fxt_component_dump(file, fxt_component_root(), 0); } static void fxt_worker_print(FILE *file, struct starpu_fxt_options *options, int workerid, unsigned comp_workerid, unsigned depth) { fprintf(file, "\t\t\t%*s\n", 2*depth, ""); fprintf(file, "\t\t\t%*s
%s\n", 2*depth, "", (int) comp_workerid == workerid ? "_sched":"", options->worker_names[comp_workerid]); if (_starpu_last_codelet_symbol[comp_workerid][0]) fprintf(file, "\t\t\t%*s
%s
\n", 2*(depth+1), "", _starpu_last_codelet_symbol[comp_workerid]); else fprintf(file, "\t\t\t%*s
\n", 2*(depth+1), ""); fprintf(file, "\t\t\t%*s
", 2*depth, ""); } static void fxt_component_print(FILE *file, struct starpu_fxt_options *options, int workerid, struct component *from, struct component *to, struct component *comp, unsigned depth) { unsigned i, n; unsigned ntasks = comp->ntasks + comp->npriotasks; if (from == comp) /* Additionally show now-empty slot */ ntasks++; for (i = 0, n = 0; i < comp->nchildren; i++) if (comp->children[i]->parent == comp) n++; fprintf(file, "\t\t\t%*s\n", 2*depth, ""); if (comp->nchildren > 0) { fprintf(file, "\t\t\t%*s\n", 2*depth, ""); for (i = 0; i < comp->nchildren; i++) if (comp->children[i]->parent == comp) { fprintf(file, "\t\t\t%*s\n", 2*depth, ""); } fprintf(file, "\t\t\t%*s\n", 2*depth, ""); } if (!strcmp(comp->name, "worker")) { fprintf(file, "\t\t\t%*s\n", 2*depth, ""); fprintf(file, "\t\t\t%*s\n", 2*depth, ""); fprintf(file, "\t\t\t%*s\n", 2*depth, ""); } fprintf(file, "\t\t\t%*s
%s\n", 2*depth, "", n, comp->name); if (!strcmp(comp->name,"prio") || !strcmp(comp->name,"fifo") || !strcmp(comp->name,"heft") || !strcmp(comp->name,"work_stealing")) { /* Show task queue */ #define N 3 n = ntasks; if (n > N) n = N; for (i = 0; i < N-n; i++) fprintf(file, "\t\t\t%*s
\n", 2*depth, ""); if (ntasks) { if (ntasks > N) fprintf(file, "\t\t\t%*s
%d
\n", 2*depth, "", from == comp ? (comp->npriotasks >= N ? "last_task_full_prio" : "last_task_full") : (comp->npriotasks >= N ? "task_prio" : "task"), comp->ntasks + comp->npriotasks); else fprintf(file, "\t\t\t%*s
\n", 2*depth, "", from == comp ? "last_task_empty" : (comp->ntasks ? "task" : "task_prio")); for (i = 1; i < n; i++) fprintf(file, "\t\t\t%*s
\n", 2*depth, "", n - i > comp->npriotasks ? "task" : "task_prio"); } } else { if (ntasks == 0) fprintf(file, "\t\t\t%*s
\n", 2*depth, ""); else if (ntasks == 1) fprintf(file, "\t\t\t%*s
\n", 2*depth, "", from == comp ? "last_task_empty" : (comp->npriotasks ? "task_prio" : "task")); else fprintf(file, "\t\t\t%*s
%d
\n", 2*depth, "", from == comp ? (comp->npriotasks ? "last_task_full_prio" : "last_task_full") : (comp->npriotasks ? "task_prio" : "task"), comp->ntasks + comp->npriotasks); } fprintf(file, "\t\t\t%*s
\n", 2*depth, ""); fxt_component_print(file, options, workerid, from, to, comp->children[i], depth+1); fprintf(file, "\t\t\t%*s
\n", 2*depth, ""); fxt_worker_print(file, options, workerid, comp->workerid, depth+1); fprintf(file, "\t\t\t%*s
", 2*depth, ""); } void _starpu_fxt_component_print(FILE *file, struct starpu_fxt_options *options, int workerid, struct component *from, struct component *to) { fprintf(file, "
\n"); fxt_component_print(file, options, workerid, from, to, fxt_component_root(), 0); fprintf(file, "
\n"); } void _starpu_fxt_component_print_header(FILE *file) { /* CSS and Javascript code from Anthony Simonet */ fprintf(file, "\n"); fprintf(file, "\n"); fprintf(file, "\t\n"); fprintf(file, "\t\t\n"); fprintf(file, "\t\t\n"); fprintf(file, "\t\t\n"); fprintf(file, "\t\t\n"); //fprintf(file, "\t\t\n"); //fprintf(file, "\t\t\n"); fprintf(file, "\t\t\n"); fprintf(file, "\t\t\n"); fprintf(file, "\t\t\n"); fprintf(file, "\t\n"); fprintf(file, "\t\n"); } static void fxt_component_print_step(FILE *file, struct starpu_fxt_options *options, double timestamp, int workerid, unsigned push, struct component *from, struct component *to) { fprintf(file, "\t\t
\n", global_state, global_state > 1 ? "none":"block", global_state); fprintf(file, "\t\t

Time %f, %d submitted %d ready, %s

\n", timestamp, nsubmitted, curq_size-nflowing, push?"push":"pull"); //fprintf(file, "\t\t\t
\n");
	//_starpu_fxt_component_dump(file);
	//fprintf(file, "\t\t\t
\n"); _starpu_fxt_component_print(file, options, workerid, from, to); fprintf(file,"\t\t
"); global_state++; } void _starpu_fxt_component_connect(uint64_t parent, uint64_t child) { struct component *parent_p, *child_p; unsigned n; COMPONENT_FIND(components, parent, parent_p); COMPONENT_FIND(components, child, child_p); STARPU_ASSERT(parent_p); STARPU_ASSERT(child_p); n = ++parent_p->nchildren; parent_p->children = realloc(parent_p->children, n * sizeof(*parent_p->children)); parent_p->children[n-1] = child_p; if (!child_p->parent) child_p->parent = parent_p; } void _starpu_fxt_component_update_ntasks(unsigned _nsubmitted, unsigned _curq_size) { nsubmitted = _nsubmitted; curq_size = _curq_size; } void _starpu_fxt_component_push(FILE *output, struct starpu_fxt_options *options, double timestamp, int workerid, uint64_t from, uint64_t to, uint64_t task STARPU_ATTRIBUTE_UNUSED, unsigned prio) { struct component *from_p = NULL, *to_p = NULL; if (to == from) return; if (from) { COMPONENT_FIND(components, from, from_p); STARPU_ASSERT(from_p); } if (to) { COMPONENT_FIND(components, to, to_p); STARPU_ASSERT(to_p); } if (from_p) { if (prio) from_p->npriotasks--; else from_p->ntasks--; } else nflowing++; if (prio) to_p->npriotasks++; else to_p->ntasks++; // fprintf(stderr,"push from %s to %s\n", from_p?from_p->name:"none", to_p?to_p->name:"none"); fxt_component_print_step(output, options, timestamp, workerid, 1, from_p, to_p); } void _starpu_fxt_component_pull(FILE *output, struct starpu_fxt_options *options, double timestamp, int workerid, uint64_t from, uint64_t to, uint64_t task STARPU_ATTRIBUTE_UNUSED, unsigned prio) { struct component *from_p = NULL, *to_p = NULL; if (to == from) return; if (from) { COMPONENT_FIND(components, from, from_p); STARPU_ASSERT(from_p); } if (to) { COMPONENT_FIND(components, to, to_p); STARPU_ASSERT(to_p); } if (prio) from_p->npriotasks--; else from_p->ntasks--; if (to_p) { if (prio) to_p->npriotasks++; else to_p->ntasks++; } else nflowing--; // fprintf(stderr,"pull from %s to %s\n", from_p?from_p->name:"none", to_p?to_p->name:"none"); fxt_component_print_step(output, options, timestamp, workerid, 0, from_p, to_p); } void _starpu_fxt_component_finish(FILE *file) { /* Javascript code from Anthony Simonet */ fprintf(file, "\t\t\n"); fprintf(file, "\t\t
\n"); fprintf(file, "\t\t
\n"); fprintf(file, "\t\t\t

\n"); fprintf(file, "\t\t\t\t\n"); fprintf(file, "\t\t\t\t\n"); fprintf(file, "\t\t\t\t\n"); fprintf(file, "\t\t\t\t\n"); fprintf(file, "\t\t\t\t\n"); fprintf(file, "\t\t\t\t\n"); fprintf(file, "\t\t\t\t\n"); fprintf(file, "\t\t\t\t\n"); fprintf(file, "\t\t\t\t\n"); fprintf(file, "\t\t\t\t\n"); fprintf(file, "\t\t\t

\n"); fprintf(file, "\t\t\t\tAuto speed (state/s): 4\n"); fprintf(file, "\t\t\t\t\n"); fprintf(file, "\t\t\t\t\n"); fprintf(file, "\t\t\t\t\n"); fprintf(file, "\t\t\t\t\n"); fprintf(file, "\t\t\t

\n"); fprintf(file, "\t\t\t

\n"); fprintf(file, "\t\t\t
\n"); fprintf(file, "\t\t\t\tGo to state\n"); fprintf(file, "\t\t\t\t\n"); fprintf(file, "\t\t\t\t\n"); /* Dummy input preventing the page from being refreshed when enter is pressed. */ fprintf(file, "\t\t\t\t\n"); fprintf(file, "\t\t\t
\n"); fprintf(file, "\t\t\t
\n"); fprintf(file, "\t\t
\n"); fprintf(file, "\t\n"); fprintf(file, "\n"); }