Преглед на файлове

Add generatation of animated html trace of modular schedulers, with code from Anthony Simonet

Samuel Thibault преди 10 години
родител
ревизия
ce9464d6b7

+ 1 - 0
AUTHORS

@@ -26,6 +26,7 @@ Cyril Roelandt <cyril.roelandt@inria.fr>
 Anthony Roy <theanthony33@gmail.com>
 Corentin Salingue <corentin.salingue@gmail.com>
 Marc Sergent <marc.sergent@inria.fr>
+Anthony Simonet <anthony.simonet@etu.u-bordeaux.fr>
 Luka Stanisic <luka.stanisic@imag.fr>
 Ludovic Stordeur <ludovic.stordeur@inria.fr>
 François Tessier <francois.tessier@inria.fr>

+ 1 - 0
ChangeLog

@@ -106,6 +106,7 @@ New features:
   * Add tasks.rec trace output to make scheduling analysis easier.
   * Add Fortran 90 module and example using it
   * New StarPU-MPI gdb debug functions
+  * Generate animated html trace of modular schedulers.
 
 Small features:
   * Tasks can now have a name (via the field const char *name of

+ 25 - 12
doc/doxygen/chapters/13offline_performance_tools.doxy

@@ -96,11 +96,11 @@ the execution.
 
 \subsection CreatingAGanttDiagram Creating a Gantt Diagram
 
-When the FxT trace file <c>filename</c> has been generated, it is possible to
+When the FxT trace file <c>prof_file_something</c> has been generated, it is possible to
 generate a trace in the Paje format by calling:
 
 \verbatim
-$ starpu_fxt_tool -i filename
+$ starpu_fxt_tool -i /tmp/prof_file_something
 \endverbatim
 
 Or alternatively, setting the environment variable \ref STARPU_GENERATE_TRACE
@@ -127,7 +127,7 @@ In the MPI execution case, collect the trace files from the MPI nodes, and
 specify them all on the command <c>starpu_fxt_tool</c>, for instance:
 
 \verbatim
-$ starpu_fxt_tool -i filename1 -i filename2
+$ starpu_fxt_tool -i /tmp/prof_file_something1 -i /tmp/prof_file_something2
 \endverbatim
 
 By default, all tasks are displayed using a green color. To display tasks with
@@ -142,18 +142,18 @@ StarPU configure option, the value of the tag will show up in the trace.
 Traces can also be inspected by hand by using the tool <c>fxt_print</c>, for instance:
 
 \verbatim
-$ fxt_print -o -f filename
+$ fxt_print -o -f /tmp/prof_file_something
 \endverbatim
 
 Timings are in nanoseconds (while timings as seen in <c>vite</c> are in milliseconds).
 
 \subsection CreatingADAGWithGraphviz Creating a DAG With Graphviz
 
-When the FxT trace file <c>filename</c> has been generated, it is possible to
+When the FxT trace file <c>prof_file_something</c> has been generated, it is possible to
 generate a task graph in the DOT format by calling:
 
 \verbatim
-$ starpu_fxt_tool -i filename
+$ starpu_fxt_tool -i /tmp/prof_file_something
 \endverbatim
 
 This will create a <c>dag.dot</c> file in the current directory. This file is a
@@ -166,11 +166,11 @@ $ dot -Tpdf dag.dot -o output.pdf
 
 \subsection TraceTaskDetails Getting task details
 
-When the FxT trace file <c>filename</c> has been generated, details on the
+When the FxT trace file <c>prof_file_something</c> has been generated, details on the
 executed tasks can be retrieved by calling:
 
 \verbatim
-$ starpu_fxt_tool -i filename
+$ starpu_fxt_tool -i /tmp/prof_file_something
 \endverbatim
 
 This will create a <c>tasks.rec</c> file in the current directory.  This file
@@ -182,11 +182,11 @@ analysis tools.  The performance models can be opened for instance by using
 
 \subsection MonitoringActivity Monitoring Activity
 
-When the FxT trace file <c>filename</c> has been generated, it is possible to
+When the FxT trace file <c>prof_file_something</c> has been generated, it is possible to
 generate an activity trace by calling:
 
 \verbatim
-$ starpu_fxt_tool -i filename
+$ starpu_fxt_tool -i /tmp/prof_file_something
 \endverbatim
 
 This will create a file <c>activity.data</c> in the current
@@ -213,6 +213,19 @@ evolution of the number of tasks available in the system during the execution.
 Ready tasks are shown in black, and tasks that are submitted but not
 schedulable yet are shown in grey.
 
+\subsection Animation Getting modular schedular animation
+
+When using modular schedulers (i.e. schedulers which use a modular architecture,
+and whose name start with "modular-"), the command
+
+\verbatim
+$ starpu_fxt_tool -i /tmp/prof_file_something
+\endverbatim
+
+will also produce a <c>trace.html</c> file which can be viewed in a
+javascript-enabled web browser. It shows the flow of tasks between the
+components of the modular scheduler.
+
 \section PerformanceOfCodelets Performance Of Codelets
 
 The performance model of codelets (see \ref PerformanceModelExample)
@@ -299,11 +312,11 @@ compute GFlops.
 \image html starpu_chol_model_11_type.png
 \image latex starpu_chol_model_11_type.eps "" width=\textwidth
 
-When the FxT trace file <c>filename</c> has been generated, it is possible to
+When the FxT trace file <c>prof_file_something</c> has been generated, it is possible to
 get a profiling of each codelet by calling:
 
 \verbatim
-$ starpu_fxt_tool -i filename
+$ starpu_fxt_tool -i /tmp/prof_file_something
 $ starpu_codelet_profile distrib.data codelet_name
 \endverbatim
 

+ 3 - 1
include/starpu_fxt.h

@@ -1,6 +1,6 @@
 /* StarPU --- Runtime system for heterogeneous multicore architectures.
  *
- * Copyright (C) 2010-2011, 2013  Université de Bordeaux
+ * Copyright (C) 2010-2011, 2013, 2015  Université de Bordeaux
  * Copyright (C) 2010, 2011, 2013, 2014  CNRS
  *
  * StarPU is free software; you can redistribute it and/or modify
@@ -48,6 +48,8 @@ struct starpu_fxt_options
 	char *distrib_time_path;
 	char *activity_path;
 	char *dag_path;
+	char *tasks_path;
+	char *anim_path;
 
 	char *file_prefix;
 	uint64_t file_offset;

+ 3 - 3
include/starpu_sched_component.h

@@ -90,13 +90,13 @@ struct starpu_sched_tree *starpu_sched_tree_get(unsigned sched_ctx_id);
 void starpu_sched_tree_update_workers(struct starpu_sched_tree *t);
 void starpu_sched_tree_update_workers_in_ctx(struct starpu_sched_tree *t);
 int starpu_sched_tree_push_task(struct starpu_task *task);
-int starpu_sched_component_push_task(struct starpu_sched_component *component, struct starpu_task *task);
+int starpu_sched_component_push_task(struct starpu_sched_component *from, struct starpu_sched_component *to, struct starpu_task *task);
 struct starpu_task *starpu_sched_tree_pop_task(unsigned sched_ctx);
-struct starpu_task *starpu_sched_component_pull_task(struct starpu_sched_component * component);
+struct starpu_task *starpu_sched_component_pull_task(struct starpu_sched_component *from, struct starpu_sched_component *to);
 void starpu_sched_tree_add_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers);
 void starpu_sched_tree_remove_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers);
 
-struct starpu_sched_component *starpu_sched_component_create(struct starpu_sched_tree *tree);
+struct starpu_sched_component *starpu_sched_component_create(struct starpu_sched_tree *tree, const char *name);
 void starpu_sched_component_destroy(struct starpu_sched_component *component);
 void starpu_sched_component_destroy_rec(struct starpu_sched_component *component);
 int starpu_sched_component_can_execute_task(struct starpu_sched_component *component, struct starpu_task *task);

+ 1 - 0
src/Makefile.am

@@ -240,6 +240,7 @@ libstarpu_@STARPU_EFFECTIVE_VERSION@_la_SOURCES = 		\
 	debug/traces/starpu_fxt_mpi.c				\
 	debug/traces/starpu_fxt_dag.c				\
 	debug/traces/starpu_paje.c				\
+	debug/traces/anim.c					\
 	debug/latency.c						\
 	debug/structures_size.c					\
 	profiling/profiling.c					\

+ 21 - 0
src/common/fxt.h

@@ -176,6 +176,11 @@
 #define	_STARPU_FUT_START_EXECUTING	0x5168
 #define	_STARPU_FUT_END_EXECUTING	0x5169
 
+#define _STARPU_FUT_SCHED_COMPONENT_NEW		0x516a
+#define _STARPU_FUT_SCHED_COMPONENT_CONNECT	0x516b
+#define _STARPU_FUT_SCHED_COMPONENT_PUSH	0x516c
+#define _STARPU_FUT_SCHED_COMPONENT_PULL	0x516d
+
 #ifdef STARPU_USE_FXT
 #include <fxt/fxt.h>
 #include <fxt/fut.h>
@@ -830,6 +835,18 @@ do {										\
 #define _STARPU_TRACE_SCHED_COMPONENT_POP_PRIO(workerid, ntasks, exp_len)		\
 	FUT_DO_PROBE4(_STARPU_FUT_SCHED_COMPONENT_POP_PRIO, _starpu_gettid(), workerid, ntasks, exp_len);
 
+#define _STARPU_TRACE_SCHED_COMPONENT_NEW(component)		\
+	_STARPU_FUT_DO_PROBE1STR(_STARPU_FUT_SCHED_COMPONENT_NEW, component, (component)->name);
+
+#define _STARPU_TRACE_SCHED_COMPONENT_CONNECT(parent, child)		\
+	FUT_DO_PROBE2(_STARPU_FUT_SCHED_COMPONENT_CONNECT, parent, child);
+
+#define _STARPU_TRACE_SCHED_COMPONENT_PUSH(from, to, task)		\
+	FUT_DO_PROBE5(_STARPU_FUT_SCHED_COMPONENT_PUSH, _starpu_gettid(), from, to, task, (task)->priority);
+
+#define _STARPU_TRACE_SCHED_COMPONENT_PULL(from, to, task)		\
+	FUT_DO_PROBE5(_STARPU_FUT_SCHED_COMPONENT_PULL, _starpu_gettid(), from, to, task, (task)->priority);
+
 #else // !STARPU_USE_FXT
 
 /* Dummy macros in case FxT is disabled */
@@ -919,6 +936,10 @@ do {										\
 #define _STARPU_TRACE_SCHED_COMPONENT_POP_PRIO(workerid, ntasks, exp_len)	do {} while(0)
 #define _STARPU_TRACE_HYPERVISOR_BEGIN()        do {} while(0)
 #define _STARPU_TRACE_HYPERVISOR_END()                  do {} while(0)
+#define _STARPU_TRACE_SCHED_COMPONENT_NEW(component)	do {} while (0)
+#define _STARPU_TRACE_SCHED_COMPONENT_CONNECT(parent, child)	do {} while (0)
+#define _STARPU_TRACE_SCHED_COMPONENT_PUSH(from, to, task)	do {} while (0)
+#define _STARPU_TRACE_SCHED_COMPONENT_PULL(from, to, task)	do {} while (0)
 
 #endif // STARPU_USE_FXT
 

+ 513 - 0
src/debug/traces/anim.c

@@ -0,0 +1,513 @@
+/* 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 <stdint.h>
+#include <stdlib.h>
+#include <common/uthash.h>
+#include <starpu.h>
+#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<table><tr><td class='worker_box%s'><center>%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<table><tr><td class='run_task'>%s</td></tr></table>\n", 2*(depth+1), "", _starpu_last_codelet_symbol[comp_workerid]);
+	else
+		fprintf(file, "\t\t\t%*s<table><tr><td class='fake_task'></td></tr></table>\n", 2*(depth+1), "");
+	fprintf(file, "\t\t\t%*s</center></td></tr>\n", 2*depth, "");
+	fprintf(file, "\t\t\t%*s</table>", 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<table><tr><td class='box' colspan=%d><center>%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<table><tr><td class='fake_task'></td></tr></table>\n", 2*depth, "");
+		if (ntasks)
+		{
+			if (ntasks > N)
+				fprintf(file, "\t\t\t%*s<table><tr><td class='%s'>%d</td></tr></table>\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<table><tr><td class='%s'></td></tr></table>\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<table><tr><td class='%s'></td></tr></table>\n", 2*depth, "",
+					n - i > comp->npriotasks ? "task" : "task_prio");
+		}
+	}
+	else
+	{
+		if (ntasks == 0)
+			fprintf(file, "\t\t\t%*s<table><tr><td class='fake_task'></td></tr></table>\n", 2*depth, "");
+		else if (ntasks == 1)
+			fprintf(file, "\t\t\t%*s<table><tr><td class='%s'></td></tr></table>\n", 2*depth, "",
+				from == comp
+					? "last_task_empty"
+					: (comp->npriotasks ? "task_prio" : "task"));
+		else
+			fprintf(file, "\t\t\t%*s<table><tr><td class='%s'>%d</td></tr></table>\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</center></td></tr>\n", 2*depth, "");
+
+	if (comp->nchildren > 0)
+	{
+		fprintf(file, "\t\t\t%*s<tr>\n", 2*depth, "");
+		for (i = 0; i < comp->nchildren; i++)
+			if (comp->children[i]->parent == comp)
+			{
+				fprintf(file, "\t\t\t%*s<td>\n", 2*depth, "");
+				fxt_component_print(file, options, workerid, from, to, comp->children[i], depth+1);
+				fprintf(file, "\t\t\t%*s</td>\n", 2*depth, "");
+			}
+		fprintf(file, "\t\t\t%*s</tr>\n", 2*depth, "");
+	}
+
+	if (!strcmp(comp->name, "worker"))
+	{
+		fprintf(file, "\t\t\t%*s<tr>\n", 2*depth, "");
+		fprintf(file, "\t\t\t%*s<td>\n", 2*depth, "");
+		fxt_worker_print(file, options, workerid, comp->workerid, depth+1);
+		fprintf(file, "\t\t\t%*s</td>\n", 2*depth, "");
+		fprintf(file, "\t\t\t%*s</tr>\n", 2*depth, "");
+	}
+
+	fprintf(file, "\t\t\t%*s</table>", 2*depth, "");
+}
+
+void _starpu_fxt_component_print(FILE *file, struct starpu_fxt_options *options, int workerid, struct component *from, struct component *to)
+{
+	fprintf(file, "<center>\n");
+	fxt_component_print(file, options, workerid, from, to, fxt_component_root(), 0);
+	fprintf(file, "</center>\n");
+}
+
+void _starpu_fxt_component_print_header(FILE *file)
+{
+	/* CSS and Javascript code from Anthony Simonet */
+	fprintf(file, "<!DOCTYPE html>\n");
+	fprintf(file, "<html lang='fr'>\n");
+	
+	fprintf(file, "\t<head>\n");
+	fprintf(file, "\t\t<meta charset='utf-8'>\n");
+	fprintf(file, "\t\t<link rel='stylesheet' href='http://code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css'>\n");
+	fprintf(file, "\t\t<script src='http://code.jquery.com/jquery-1.10.2.js'></script>\n");
+	fprintf(file, "\t\t<script src='http://code.jquery.com/ui/1.11.2/jquery-ui.js'></script>\n");
+	//fprintf(file, "\t\t<link rel='stylesheet' href='/resources/demos/style.css'>\n");
+	//fprintf(file, "\t\t<link rel='stylesheet' type='text/css' href='../styles.css'>\n");
+
+	fprintf(file, "\t\t<style>\n");
+
+	fprintf(file, "\t\t\ttable {\n");
+	fprintf(file, "\t\t\t\tmargin: 0;\n");
+	fprintf(file, "\t\t\t\tpadding: 0;\n");
+	fprintf(file, "\t\t\t}\n");
+
+	fprintf(file, "\t\t\ttd {\n");
+	fprintf(file, "\t\t\t\tmargin: 0;\n");
+	fprintf(file, "\t\t\t\tpadding: 0;\n");
+	fprintf(file, "\t\t\t\tvertical-align: top;\n");
+	fprintf(file, "\t\t\t\ttext-align: center;\n");
+	fprintf(file, "\t\t\t}\n");
+
+	fprintf(file, "\t\t\ttd.box {\n");
+	fprintf(file, "\t\t\t\tborder: solid 1px;\n");
+	fprintf(file, "\t\t\t}\n");
+
+	fprintf(file, "\t\t\ttd.worker_box {\n");
+	fprintf(file, "\t\t\t\tborder: solid 1px;\n");
+	/* Fixed width to make output more homogeneous */
+	fprintf(file, "\t\t\t\twidth: 75px;\n");
+	fprintf(file, "\t\t\t}\n");
+
+	fprintf(file, "\t\t\ttd.worker_box_sched {\n");
+	fprintf(file, "\t\t\t\tborder: solid 1px;\n");
+	/* Fixed width to make output more homogeneous */
+	fprintf(file, "\t\t\t\twidth: 75px;\n");
+	fprintf(file, "\t\t\t\tbackground-color: lightgreen;\n");
+	fprintf(file, "\t\t\t}\n");
+
+	/* Task */
+	fprintf(file, "\t\t\ttd.task {\n");
+	fprintf(file, "\t\t\t\tborder: solid 1px;\n");
+	fprintf(file, "\t\t\t\twidth: 23px;\n");
+	fprintf(file, "\t\t\t\theight: 23px;\n");
+	fprintf(file, "\t\t\t\tbackground-color: #87CEEB;\n");
+	fprintf(file, "\t\t\t}\n");
+
+	/* Task being run (with codelet name) */
+	fprintf(file, "\t\t\ttd.run_task {\n");
+	fprintf(file, "\t\t\t\tborder: solid 1px;\n");
+	fprintf(file, "\t\t\t\twidth: 69px;\n");
+	fprintf(file, "\t\t\t\tmax-width: 69px;\n");
+	fprintf(file, "\t\t\t\toverflow: hidden;\n");
+	fprintf(file, "\t\t\t\tfont-size: 50%%;\n");
+	fprintf(file, "\t\t\t\theight: 23px;\n");
+	fprintf(file, "\t\t\t\tbackground-color: #87CEEB;\n");
+	fprintf(file, "\t\t\t}\n");
+
+	/* Prioritized Task */
+	fprintf(file, "\t\t\ttd.task_prio {\n");
+	fprintf(file, "\t\t\t\tborder: solid 1px;\n");
+	fprintf(file, "\t\t\t\twidth: 23px;\n");
+	fprintf(file, "\t\t\t\theight: 23px;\n");
+	fprintf(file, "\t\t\t\tbackground-color: red;\n");
+	fprintf(file, "\t\t\t}\n");
+
+	/* Slot of previous task */
+	fprintf(file, "\t\t\ttd.last_task_empty {\n");
+	fprintf(file, "\t\t\t\tborder: dashed 1px;\n");
+	fprintf(file, "\t\t\t\twidth: 23px;\n");
+	fprintf(file, "\t\t\t\theight: 23px;\n");
+	fprintf(file, "\t\t\t\tbackground-color: white;\n");
+	fprintf(file, "\t\t\t}\n");
+
+	/* Slot of previous task (but still other tasks) */
+	fprintf(file, "\t\t\ttd.last_task_full {\n");
+	fprintf(file, "\t\t\t\tborder: dashed 1px;\n");
+	fprintf(file, "\t\t\t\twidth: 23px;\n");
+	fprintf(file, "\t\t\t\theight: 23px;\n");
+	fprintf(file, "\t\t\t\tbackground-color: #87CEEB;\n");
+	fprintf(file, "\t\t\t}\n");
+
+	/* Slot of previous task (but still other prioritized) */
+	fprintf(file, "\t\t\ttd.last_task_full_prio {\n");
+	fprintf(file, "\t\t\t\tborder: dashed 1px;\n");
+	fprintf(file, "\t\t\t\twidth: 23px;\n");
+	fprintf(file, "\t\t\t\theight: 23px;\n");
+	fprintf(file, "\t\t\t\tbackground-color: red;\n");
+	fprintf(file, "\t\t\t}\n");
+
+	/* Empty task slot */
+	fprintf(file, "\t\t\ttd.fake_task {\n");
+	fprintf(file, "\t\t\t\twidth: 25px;\n");
+	fprintf(file, "\t\t\t\theight: 25px;\n");
+	fprintf(file, "\t\t\t}\n");
+
+	fprintf(file, "\t\t</style>\n");
+
+	fprintf(file, "\t\t<script>\n");
+	fprintf(file, "\t\t\tfunction getInput(){\n");
+	fprintf(file, "\t\t\t\tvar input = document.getElementById('input').value;\n");
+	fprintf(file, "\t\t\t\tif (input <= 0 || input > $('#slider').slider('option', 'max')){\n");
+	fprintf(file, "\t\t\t\t\talert('Invalid state value');\n");
+	fprintf(file, "\t\t\t\t}\n");
+	fprintf(file, "\t\t\t\tdocument.getElementById('et' + document.getElementById('etape').value).style.display = 'none';\n");
+	fprintf(file, "\t\t\t\tdocument.getElementById('et' + input).style.display = 'block';\n");
+	fprintf(file, "\t\t\t\t$('#etape').val(input);\n");
+	fprintf(file, "\t\t\t\t$('#slider').slider('value', input);\n");
+	fprintf(file, "\t\t\t}\n");
+	fprintf(file, "\t\t</script>\n");
+
+	fprintf(file, "\t\t<script>\n");
+	fprintf(file, "\t\t\tvar myVar = null;\n");
+	fprintf(file, "\t\t\tfunction changeState(number){\n");
+	fprintf(file, "\t\t\t\tvar state = document.getElementById('etape').value;\n");
+	fprintf(file, "\t\t\t\tvar state2 = parseInt(state) + parseInt(number);\n");
+	fprintf(file, "\t\t\t\tvar min = $('#slider').slider('option', 'min');\n");
+	fprintf(file, "\t\t\t\tvar max = $('#slider').slider('option', 'max');\n");
+	fprintf(file, "\t\t\t\t\tdocument.getElementById('et' + document.getElementById('etape').value).style.display = 'none';\n");
+	fprintf(file, "\t\t\t\tif (state2 >= min && state2 <= max){\n");
+	fprintf(file, "\t\t\t\t\tdocument.getElementById('et' + state2).style.display = 'block';\n");
+	fprintf(file, "\t\t\t\t\t$('#etape').val(state2);\n");
+	fprintf(file, "\t\t\t\t\t$('#slider').slider('value', state2);\n");
+	fprintf(file, "\t\t\t\t}\n");
+	fprintf(file, "\t\t\t\telse if (state2 < min){\n");
+	fprintf(file, "\t\t\t\t\tdocument.getElementById('et' + min).style.display = 'block';\n");
+	fprintf(file, "\t\t\t\t\t$('#etape').val(min);\n");
+	fprintf(file, "\t\t\t\t\t$('#slider').slider('value', min);\n");
+	fprintf(file, "\t\t\t\t}\n");
+	fprintf(file, "\t\t\t\telse if (state2 > max){\n");
+	fprintf(file, "\t\t\t\t\tdocument.getElementById('et' + max).style.display = 'block';\n");
+	fprintf(file, "\t\t\t\t\t$('#etape').val(max);\n");
+	fprintf(file, "\t\t\t\t\t$('#slider').slider('value', max);\n");
+	fprintf(file, "\t\t\t\t}\n");
+	fprintf(file, "\t\t\t}\n");
+	fprintf(file, "\t\t</script>\n");
+
+	fprintf(file, "\t</head>\n");
+
+	fprintf(file, "\t<body>\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<div id='et%d' style='display:%s;'><center><!-- Étape %d -->\n",
+			global_state, global_state > 1 ? "none":"block", global_state);
+	fprintf(file, "\t\t<p>Time %f, %d submitted %d ready, %s</p>\n", timestamp, nsubmitted, curq_size-nflowing, push?"push":"pull");
+	//fprintf(file, "\t\t\t<tt><pre>\n");
+	//_starpu_fxt_component_dump(file);
+	//fprintf(file, "\t\t\t</pre></tt>\n");
+	_starpu_fxt_component_print(file, options, workerid, from, to);
+	fprintf(file,"\t\t</center></div>");
+
+	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<script>\n");
+	fprintf(file, "\t\t\t$(function(){\n");
+	fprintf(file, "\t\t\t\tsliderDiv = $('#slider') <!-- Alias -->\n");
+	fprintf(file, "\t\t\t\tsliderDiv.slider({\n");
+	fprintf(file, "\t\t\t\t\tvalue: 1,\n");
+	fprintf(file, "\t\t\t\t\tmin: 1,\n");
+	fprintf(file, "\t\t\t\t\tmax: %d,\n", global_state-1);
+	fprintf(file, "\t\t\t\t\tstep: 1,\n");
+	fprintf(file, "\t\t\t\t\tanimate: 'fast',\n");
+	fprintf(file, "\t\t\t\t\tslide: function(event, ui){\n");
+	fprintf(file, "\t\t\t\t\t\tvar l_value = sliderDiv.slider('option', 'value');\n");
+	fprintf(file, "\t\t\t\t\t\t$('#etape').val(ui.value);\n");
+	fprintf(file, "\t\t\t\t\t\tdocument.getElementById('et' + l_value).style.display = 'none';\n");
+	fprintf(file, "\t\t\t\t\t\tdocument.getElementById('et' + ui.value).style.display = 'block';\n");
+	fprintf(file, "\t\t\t\t\t}\n");
+	fprintf(file, "\t\t\t\t});\n");
+	fprintf(file, "\t\t\t\t$('#etape').val(sliderDiv.slider('value')); <!-- Initialisation au lancement de la page -->\n");
+	fprintf(file, "\t\t\t\t$('#max').val(sliderDiv.slider('option', 'max'));\n");
+	fprintf(file, "\t\t\t});\n");
+	fprintf(file, "\t\t</script>\n");
+
+	fprintf(file, "\t\t<div id ='slider'></div>\n");
+	fprintf(file, "\t\t<center>\n");
+	fprintf(file, "\t\t\t<p>\n");
+	fprintf(file, "\t\t\t\t<input type='button' value='-100' onclick=\"changeState(-100);\"/>\n");
+	fprintf(file, "\t\t\t\t<input type='button' value='<<' onmousedown=\"myVar = setInterval('changeState(-1)', 50)\" onmouseup=\"clearInterval(myVar)\" onmouseout=\"clearInterval(myVar)\"/>\n");
+	fprintf(file, "\t\t\t\t<input type='button' value='<' onclick=\"changeState(-1);\"/>\n");
+	fprintf(file, "\t\t\t\t<label for='etape'>State</label>\n");
+	fprintf(file, "\t\t\t\t<input type='text' id='etape' size='3mm' readonly style='border:0;'>\n");
+	fprintf(file, "\t\t\t\t<label for='max'>in</label>\n");
+	fprintf(file, "\t\t\t\t<input type='text' id='max' size='3mm' readonly style='border:0;'>\n");
+	fprintf(file, "\t\t\t\t<input type='button' value='>' onclick=\"changeState(1);\" />\n");
+	fprintf(file, "\t\t\t\t<input type='button' value='>>' onmousedown=\"myVar = setInterval('changeState(1)', 50)\" onmouseup=\"clearInterval(myVar)\" onmouseout=\"clearInterval(myVar)\"/>\n");
+	fprintf(file, "\t\t\t\t<input type='button' value='+100' onclick=\"changeState(100);\"/>\n");
+	fprintf(file, "\t\t\t</p>\n");
+	fprintf(file, "\t\t\t\t<span id='range'>Auto speed (state/s): 4</span>\n");
+	fprintf(file, "\t\t\t\t<input type='range' id='autoRange' min='1' max='50' value='4' step='1' onchange=\"showValue(this.value); clearInterval(myVar);\"  />\n");
+	fprintf(file, "\t\t\t\t<script>\n");
+	fprintf(file, "\t\t\t\t\tdocument.getElementById('autoRange').value = 4;\n");
+	fprintf(file, "\t\t\t\t\tfunction showValue(newValue)\n");
+	fprintf(file, "\t\t\t\t\t{\n");
+	fprintf(file, "\t\t\t\t\t\tdocument.getElementById('range').innerHTML='Auto speed (state/s): '+ newValue;\n");
+	fprintf(file, "\t\t\t\t\t}\n");
+	fprintf(file, "\t\t\t\t</script>\n");
+	fprintf(file, "\t\t\t\t<input type='button' value='Auto' onclick=\"if(myVar){ clearInterval(myVar); myVar = null;}changeState(1); myVar = setInterval('changeState(1)', 1000/document.getElementById('autoRange').value);\"/>\n");
+	fprintf(file, "\t\t\t\t<input type='button' value='Stop' onclick=\"clearInterval(myVar);\"/>\n");
+	fprintf(file, "\t\t\t<p>\n");
+	fprintf(file, "\t\t\t</p>\n");
+	fprintf(file, "\t\t\t<FORM>\n");
+	fprintf(file, "\t\t\t\t<span>Go to state</span>\n");
+	fprintf(file, "\t\t\t\t<input type='text' name='setinput' id='input' value='' onKeyPress=\"if(event.keyCode == 13){ getInput(); javascript:this.value=''}\" onFocus=\"javascript:this.value=''\"/>\n");
+	fprintf(file, "\t\t\t\t<input type='text' name='message' id='' value='' style='display:none'>\n"); /* Dummy input preventing the page from being refreshed when enter is pressed. */
+	fprintf(file, "\t\t\t\t<input type='button' value='Go' onclick=\"getInput(); javascript:input.value=''\"/>\n");
+	fprintf(file, "\t\t\t</FORM>\n");
+	fprintf(file, "\t\t\t<br />\n");
+	fprintf(file, "\t\t</center>\n");
+	fprintf(file, "\t</body>\n");
+	fprintf(file, "</html>\n");
+}

+ 76 - 15
src/debug/traces/starpu_fxt.c

@@ -58,6 +58,7 @@ static unsigned other_index = 0;
 static FILE *out_paje_file;
 static FILE *distrib_time;
 static FILE *activity_file;
+static FILE *anim_file;
 static FILE *tasks_file;
 
 struct data_info {
@@ -256,7 +257,7 @@ static unsigned get_colour_symbol_blue(char *name)
 
 static double last_codelet_start[STARPU_NMAXWORKERS];
 /* _STARPU_FUT_DO_PROBE4STR records only 4 longs */
-static char last_codelet_symbol[STARPU_NMAXWORKERS][4*sizeof(unsigned long)];
+char _starpu_last_codelet_symbol[STARPU_NMAXWORKERS][4*sizeof(unsigned long)];
 static int last_codelet_parameter[STARPU_NMAXWORKERS];
 #define MAX_PARAMETERS 8
 static char last_codelet_parameter_description[STARPU_NMAXWORKERS][MAX_PARAMETERS][FXT_MAX_PARAMS*sizeof(unsigned long)];
@@ -869,7 +870,7 @@ static void handle_start_codelet_body(struct fxt_ev_64 *ev, struct starpu_fxt_op
 	unsigned long has_name = ev->param[3];
 	char *name = has_name?(char *)&ev->param[4]:"unknown";
 
-	snprintf(last_codelet_symbol[worker], sizeof(last_codelet_symbol[worker]), "%s", name);
+	snprintf(_starpu_last_codelet_symbol[worker], sizeof(_starpu_last_codelet_symbol[worker]), "%s", name);
 	last_codelet_parameter[worker] = 0;
 
 	double start_codelet_time = get_event_time_stamp(ev, options);
@@ -971,7 +972,7 @@ static void handle_codelet_details(struct fxt_ev_64 *ev STARPU_ATTRIBUTE_UNUSED,
 		char *prefix = options->file_prefix;
 		unsigned sched_ctx = ev->param[1];
 
-		worker_set_detailed_state(last_codelet_start[worker], prefix, worker, last_codelet_symbol[worker], ev->param[2], parameters, ev->param[3], ev->param[4], job_id);
+		worker_set_detailed_state(last_codelet_start[worker], prefix, worker, _starpu_last_codelet_symbol[worker], ev->param[2], parameters, ev->param[3], ev->param[4], job_id);
 		if (sched_ctx != 0)
 		{
 #ifdef STARPU_HAVE_POTI
@@ -979,9 +980,9 @@ static void handle_codelet_details(struct fxt_ev_64 *ev STARPU_ATTRIBUTE_UNUSED,
 			char ctx[6];
 			snprintf(ctx, sizeof(ctx), "Ctx%d", sched_ctx);
 			worker_container_alias(container, STARPU_POTI_STR_LEN, prefix, ev->param[5]);
-			poti_SetState(last_codelet_start[worker], container, ctx, last_codelet_symbol[worker]);
+			poti_SetState(last_codelet_start[worker], container, ctx, _starpu_last_codelet_symbol[worker]);
 #else
-			fprintf(out_paje_file, "20	%.9f	%sw%"PRIu64"	Ctx%d	%s	%lu	%s	%08lx	%016llx	%lu\n", last_codelet_start[worker], prefix, ev->param[2], sched_ctx, last_codelet_symbol[worker], (unsigned long) ev->param[2], parameters, (unsigned long) ev->param[3], (unsigned long long) ev->param[4], job_id);
+			fprintf(out_paje_file, "20	%.9f	%sw%"PRIu64"	Ctx%d	%s	%lu	%s	%08lx	%016llx	%lu\n", last_codelet_start[worker], prefix, ev->param[2], sched_ctx, _starpu_last_codelet_symbol[worker], (unsigned long) ev->param[2], parameters, (unsigned long) ev->param[3], (unsigned long long) ev->param[4], job_id);
 #endif
 		}
 #endif /* STARPU_ENABLE_PAJE_CODELET_DETAILS */
@@ -1013,7 +1014,7 @@ static void handle_end_codelet_body(struct fxt_ev_64 *ev, struct starpu_fxt_opti
 	update_accumulated_time(worker, 0.0, codelet_length, end_codelet_time, 0);
 
 	if (distrib_time)
-	     fprintf(distrib_time, "%s\t%s%d\t%ld\t%"PRIx32"\t%.9f\n", last_codelet_symbol[worker],
+	     fprintf(distrib_time, "%s\t%s%d\t%ld\t%"PRIx32"\t%.9f\n", _starpu_last_codelet_symbol[worker],
 		     prefix, worker, (unsigned long) codelet_size, codelet_hash, codelet_length);
 
 	if (options->dumped_codelets)
@@ -1021,13 +1022,14 @@ static void handle_end_codelet_body(struct fxt_ev_64 *ev, struct starpu_fxt_opti
 		dumped_codelets_count++;
 		dumped_codelets = realloc(dumped_codelets, dumped_codelets_count*sizeof(struct starpu_fxt_codelet_event));
 
-		snprintf(dumped_codelets[dumped_codelets_count - 1].symbol, 256, "%s", last_codelet_symbol[worker]);
+		snprintf(dumped_codelets[dumped_codelets_count - 1].symbol, 256, "%s", _starpu_last_codelet_symbol[worker]);
 		dumped_codelets[dumped_codelets_count - 1].workerid = worker;
 		snprintf(dumped_codelets[dumped_codelets_count - 1].perfmodel_archname, 256, "%s", (char *)&ev->param[4]);
 		dumped_codelets[dumped_codelets_count - 1].size = codelet_size;
 		dumped_codelets[dumped_codelets_count - 1].hash = codelet_hash;
 		dumped_codelets[dumped_codelets_count - 1].time = codelet_length;
 	}
+	_starpu_last_codelet_symbol[worker][0] = 0;
 }
 
 static void handle_start_executing(struct fxt_ev_64 *ev, struct starpu_fxt_options *options)
@@ -1388,6 +1390,8 @@ static void handle_job_push(struct fxt_ev_64 *ev, struct starpu_fxt_options *opt
 
 	curq_size++;
 
+	_starpu_fxt_component_update_ntasks(nsubmitted, curq_size);
+
 	if (!options->no_counter && out_paje_file)
 	{
 #ifdef STARPU_HAVE_POTI
@@ -1410,6 +1414,7 @@ static void handle_job_pop(struct fxt_ev_64 *ev, struct starpu_fxt_options *opti
 
 	curq_size--;
 	nsubmitted--;
+	_starpu_fxt_component_update_ntasks(nsubmitted, curq_size);
 
 	if (!options->no_counter && out_paje_file)
 	{
@@ -1431,12 +1436,37 @@ static void handle_job_pop(struct fxt_ev_64 *ev, struct starpu_fxt_options *opti
 	}
 }
 
+static void handle_component_new(struct fxt_ev_64 *ev, struct starpu_fxt_options *options STARPU_ATTRIBUTE_UNUSED)
+{
+	_starpu_fxt_component_new(ev->param[0], (char *)&ev->param[1]);
+}
+
+static void handle_component_connect(struct fxt_ev_64 *ev, struct starpu_fxt_options *options STARPU_ATTRIBUTE_UNUSED)
+{
+	_starpu_fxt_component_connect(ev->param[0], ev->param[1]);
+}
+
+static void handle_component_push(struct fxt_ev_64 *ev, struct starpu_fxt_options *options)
+{
+	double current_timestamp = get_event_time_stamp(ev, options);
+	int workerid = find_worker_id(ev->param[0]);
+	_starpu_fxt_component_push(anim_file, options, current_timestamp, workerid, ev->param[1], ev->param[2], ev->param[3], ev->param[4]);
+}
+
+static void handle_component_pull(struct fxt_ev_64 *ev, struct starpu_fxt_options *options)
+{
+	double current_timestamp = get_event_time_stamp(ev, options);
+	int workerid = find_worker_id(ev->param[0]);
+	_starpu_fxt_component_pull(anim_file, options, current_timestamp, workerid, ev->param[1], ev->param[2], ev->param[3], ev->param[4]);
+}
+
 static
 void handle_update_task_cnt(struct fxt_ev_64 *ev, struct starpu_fxt_options *options)
 {
 	double current_timestamp = get_event_time_stamp(ev, options);
 
 	nsubmitted++;
+	_starpu_fxt_component_update_ntasks(nsubmitted, curq_size);
 	if (!options->no_counter && out_paje_file)
 	{
 #ifdef STARPU_HAVE_POTI
@@ -1985,6 +2015,19 @@ void _starpu_fxt_parse_new_file(char *filename_in, struct starpu_fxt_options *op
 				handle_job_pop(&ev, options);
 				break;
 
+			case _STARPU_FUT_SCHED_COMPONENT_NEW:
+				handle_component_new(&ev, options);
+				break;
+			case _STARPU_FUT_SCHED_COMPONENT_CONNECT:
+				handle_component_connect(&ev, options);
+				break;
+			case _STARPU_FUT_SCHED_COMPONENT_PUSH:
+				handle_component_push(&ev, options);
+				break;
+			case _STARPU_FUT_SCHED_COMPONENT_PULL:
+				handle_component_pull(&ev, options);
+				break;
+
 			/* check the memory transfer overhead */
 			case _STARPU_FUT_START_FETCH_INPUT:
 				handle_worker_status(&ev, options, "Fi");
@@ -2380,8 +2423,8 @@ void starpu_fxt_options_init(struct starpu_fxt_options *options)
 	options->ninputfiles = 0;
 	options->out_paje_path = "paje.trace";
 	options->dag_path = "dag.dot";
-	/* TODO */
-	/* options->tasks_path = "tasks.rec"; */
+	options->tasks_path = "tasks.rec";
+	options->anim_path = "trace.html";
 	options->distrib_time_path = "distrib.data";
 	options->dumped_codelets = NULL;
 	options->activity_path = "activity.data";
@@ -2426,17 +2469,24 @@ void _starpu_fxt_activity_file_init(struct starpu_fxt_options *options)
 }
 
 static
+void _starpu_fxt_anim_file_init(struct starpu_fxt_options *options)
+{
+	if (options->anim_path)
+	{
+		anim_file = fopen(options->anim_path, "w+");
+		_starpu_fxt_component_print_header(anim_file);
+	}
+	else
+		anim_file = NULL;
+}
+
+static
 void _starpu_fxt_tasks_file_init(struct starpu_fxt_options *options)
 {
-#if 0
-	//TODO
-	if (options->activity_path)
+	if (options->tasks_path)
 		tasks_file = fopen(options->tasks_path, "w+");
 	else
 		tasks_file = NULL;
-#endif
-
-	tasks_file = fopen("tasks.rec", "w+");
 }
 
 static
@@ -2447,6 +2497,15 @@ void _starpu_fxt_activity_file_close(void)
 }
 
 static
+void _starpu_fxt_anim_file_close(void)
+{
+	//_starpu_fxt_component_dump(stderr);
+	_starpu_fxt_component_finish(anim_file);
+	if (anim_file)
+		fclose(anim_file);
+}
+
+static
 void _starpu_fxt_tasks_file_close(void)
 {
 	if (tasks_file)
@@ -2527,6 +2586,7 @@ void starpu_fxt_generate_trace(struct starpu_fxt_options *options)
 	_starpu_fxt_dag_init(options->dag_path);
 	_starpu_fxt_distrib_file_init(options);
 	_starpu_fxt_activity_file_init(options);
+	_starpu_fxt_anim_file_init(options);
 	_starpu_fxt_tasks_file_init(options);
 
 	_starpu_fxt_paje_file_init(options);
@@ -2655,6 +2715,7 @@ void starpu_fxt_generate_trace(struct starpu_fxt_options *options)
 	_starpu_fxt_paje_file_close();
 	_starpu_fxt_activity_file_close();
 	_starpu_fxt_distrib_file_close(options);
+	_starpu_fxt_anim_file_close();
 	_starpu_fxt_tasks_file_close();
 
 	_starpu_fxt_dag_terminate();

+ 15 - 1
src/debug/traces/starpu_fxt.h

@@ -1,6 +1,6 @@
 /* StarPU --- Runtime system for heterogeneous multicore architectures.
  *
- * Copyright (C) 2009-2012  Université de Bordeaux
+ * Copyright (C) 2009-2012, 2015  Université de Bordeaux
  *
  * 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
@@ -38,6 +38,8 @@
 #include <starpu.h>
 #include "../../../include/starpu_fxt.h"
 
+extern char _starpu_last_codelet_symbol[STARPU_NMAXWORKERS][4*sizeof(unsigned long)];
+
 void _starpu_fxt_dag_init(char *dag_filename);
 void _starpu_fxt_dag_terminate(void);
 void _starpu_fxt_dag_add_tag(uint64_t tag, unsigned long job_id);
@@ -58,6 +60,18 @@ void _starpu_fxt_display_mpi_transfers(struct starpu_fxt_options *options, int *
 
 void _starpu_fxt_write_paje_header(FILE *file);
 
+/*
+ * Animation
+ */
+void _starpu_fxt_component_print_header(FILE *output);
+void _starpu_fxt_component_new(uint64_t component, char *name);
+void _starpu_fxt_component_connect(uint64_t parent, uint64_t child);
+void _starpu_fxt_component_update_ntasks(unsigned nsubmitted, unsigned 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, unsigned prio);
+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, unsigned prio);
+void _starpu_fxt_component_dump(FILE *output);
+void _starpu_fxt_component_finish(FILE *output);
+
 #endif // STARPU_USE_FXT
 
 #endif // __STARPU__FXT_H__

+ 3 - 4
src/sched_policies/component_best_implementation.c

@@ -75,7 +75,7 @@ static int best_implementation_push_task(struct starpu_sched_component * compone
 {
 	STARPU_ASSERT(component->nchildren == 1);
 	select_best_implementation_and_set_preds(component->tree->sched_ctx_id, component->workers_in_ctx, task);
-	return starpu_sched_component_push_task(component->children[0],task);
+	return starpu_sched_component_push_task(component,component->children[0],task);
 }
 
 int starpu_sched_component_is_best_implementation(struct starpu_sched_component * component)
@@ -93,7 +93,7 @@ static struct starpu_task * best_implementation_pull_task(struct starpu_sched_co
 			continue;
 		else
 		{
-			task = starpu_sched_component_pull_task(component->parents[i]);
+			task = starpu_sched_component_pull_task(component->parents[i], component);
 			if(task)
 				break;
 		}
@@ -106,9 +106,8 @@ static struct starpu_task * best_implementation_pull_task(struct starpu_sched_co
 
 struct starpu_sched_component * starpu_sched_component_best_implementation_create(struct starpu_sched_tree *tree, void * arg STARPU_ATTRIBUTE_UNUSED)
 {
-	struct starpu_sched_component * component = starpu_sched_component_create(tree);
+	struct starpu_sched_component * component = starpu_sched_component_create(tree, "best_impl");
 	component->push_task = best_implementation_push_task;
 	component->pull_task = best_implementation_pull_task;
-	component->name = "best_implementation";
 	return component;
 }

+ 4 - 5
src/sched_policies/component_composed.c

@@ -120,14 +120,14 @@ struct composed_component create_composed_component(struct starpu_sched_tree *tr
 static int composed_component_push_task(struct starpu_sched_component * component, struct starpu_task * task)
 {
 	struct composed_component *c = component->data;
-	return starpu_sched_component_push_task(c->top,task);
+	return starpu_sched_component_push_task(component,c->top,task);
 }
 struct starpu_task * composed_component_pull_task(struct starpu_sched_component *component)
 {
 	struct composed_component *c = component->data;
 	struct starpu_task * task = NULL;
 	
-	task = starpu_sched_component_pull_task(c->bottom);
+	task = starpu_sched_component_pull_task(c->bottom,component);
 	if(task)
 		return task;
 
@@ -138,7 +138,7 @@ struct starpu_task * composed_component_pull_task(struct starpu_sched_component
 			continue;
 		else
 		{
-			task = starpu_sched_component_pull_task(component->parents[i]);
+			task = starpu_sched_component_pull_task(component->parents[i],component);
 			if(task)
 				break;
 		}
@@ -209,7 +209,7 @@ struct starpu_sched_component * starpu_sched_component_composed_component_create
 	struct fun_create_component_list * l = &recipe->list;
 	if(l->_head == l->_tail)
 		return l->_head->create_component(tree, l->_head->arg);
-	struct starpu_sched_component * component = starpu_sched_component_create(tree);
+	struct starpu_sched_component * component = starpu_sched_component_create(tree, "composed");
 
 	struct composed_component * c = malloc(sizeof(struct composed_component));
 	*c = create_composed_component(tree, recipe
@@ -229,6 +229,5 @@ struct starpu_sched_component * starpu_sched_component_composed_component_create
 	component->add_child = composed_component_add_child;
 	component->remove_child = composed_component_remove_child;
 	component->notify_change_workers = composed_component_notify_change_workers;
-	component->name = "composed";
 	return component;
 }

+ 2 - 3
src/sched_policies/component_eager.c

@@ -49,7 +49,7 @@ static int eager_push_task(struct starpu_sched_component * component, struct sta
 								return 1;
 							}
 							else
-								return starpu_sched_component_push_task(component->children[i],task);
+								return starpu_sched_component_push_task(component,component->children[i],task);
 						}
 					}
 				}
@@ -66,9 +66,8 @@ int starpu_sched_component_is_eager(struct starpu_sched_component * component)
 
 struct starpu_sched_component * starpu_sched_component_eager_create(struct starpu_sched_tree *tree, void * arg STARPU_ATTRIBUTE_UNUSED)
 {
-	struct starpu_sched_component * component = starpu_sched_component_create(tree);
+	struct starpu_sched_component * component = starpu_sched_component_create(tree, "eager");
 	component->push_task = eager_push_task;
-	component->name = "eager";
 
 	return component;
 }

+ 2 - 3
src/sched_policies/component_eager_calibration.c

@@ -61,7 +61,7 @@ static int eager_calibration_push_task(struct starpu_sched_component * component
 									return 1;
 								}
 								else
-									return starpu_sched_component_push_task(component->children[i],task);
+									return starpu_sched_component_push_task(component,component->children[i],task);
 							}
 						}
 					}
@@ -79,9 +79,8 @@ int starpu_sched_component_is_eager_calibration(struct starpu_sched_component *
 
 struct starpu_sched_component * starpu_sched_component_eager_calibration_create(struct starpu_sched_tree *tree, void * arg STARPU_ATTRIBUTE_UNUSED)
 {
-	struct starpu_sched_component * component = starpu_sched_component_create(tree);
+	struct starpu_sched_component * component = starpu_sched_component_create(tree, "eager_calibration");
 	component->push_task = eager_calibration_push_task;
-	component->name = "eager_calibration";
 
 	return component;
 }

+ 5 - 6
src/sched_policies/component_fifo.c

@@ -214,17 +214,17 @@ static int fifo_can_push(struct starpu_sched_component * component)
 	STARPU_ASSERT(component->nchildren == 1);
 	struct starpu_sched_component * child = component->children[0];
 
-	struct starpu_task * task = starpu_sched_component_pull_task(component);
+	struct starpu_task * task = starpu_sched_component_pull_task(component,NULL);
 	if(task)
-		ret = starpu_sched_component_push_task(child,task);	
+		ret = starpu_sched_component_push_task(NULL,child,task);	
 	while(task && !ret) 
 	{
 		if(!res)
 			res = 1;
 
-		task = starpu_sched_component_pull_task(component);
+		task = starpu_sched_component_pull_task(component,NULL);
 		if(task)
-			ret = starpu_sched_component_push_task(child,task);	
+			ret = starpu_sched_component_push_task(NULL,child,task);	
 	}
 	if(task && ret)
 		fifo_push_local_task(component,task,1); 
@@ -239,7 +239,7 @@ int starpu_sched_component_is_fifo(struct starpu_sched_component * component)
 
 struct starpu_sched_component * starpu_sched_component_fifo_create(struct starpu_sched_tree *tree, struct starpu_sched_component_fifo_data * params)
 {
-	struct starpu_sched_component * component = starpu_sched_component_create(tree);
+	struct starpu_sched_component * component = starpu_sched_component_create(tree, "fifo");
 	struct _starpu_fifo_data * data = malloc(sizeof(*data));
 	data->fifo = _starpu_create_fifo();
 	STARPU_PTHREAD_MUTEX_INIT(&data->mutex,NULL);
@@ -250,7 +250,6 @@ struct starpu_sched_component * starpu_sched_component_fifo_create(struct starpu
 	component->pull_task = fifo_pull_task;
 	component->can_push = fifo_can_push;
 	component->deinit_data = fifo_component_deinit_data;
-	component->name = "fifo";
 
 	if(params)
 	{

+ 2 - 3
src/sched_policies/component_heft.c

@@ -153,7 +153,7 @@ static int heft_progress_one(struct starpu_sched_component *component)
 			return 1;
 		}
 
-		int ret = starpu_sched_component_push_task(best_component, tasks[best_task]);
+		int ret = starpu_sched_component_push_task(component, best_component, tasks[best_task]);
 
 		if (ret)
 		{
@@ -226,7 +226,7 @@ int starpu_sched_component_is_heft(struct starpu_sched_component * component)
 
 struct starpu_sched_component * starpu_sched_component_heft_create(struct starpu_sched_tree *tree, struct starpu_sched_component_mct_data * params)
 {
-	struct starpu_sched_component * component = starpu_sched_component_create(tree);
+	struct starpu_sched_component * component = starpu_sched_component_create(tree, "heft");
 	struct _starpu_mct_data *mct_data = starpu_mct_init_parameters(params);
 	struct _starpu_heft_data *data = malloc(sizeof(*data));
 
@@ -238,7 +238,6 @@ struct starpu_sched_component * starpu_sched_component_heft_create(struct starpu
 	component->push_task = heft_push_task;
 	component->can_push = heft_can_push;
 	component->deinit_data = heft_component_deinit_data;
-	component->name = "heft";
 
 	return component;
 }

+ 2 - 3
src/sched_policies/component_mct.c

@@ -99,7 +99,7 @@ static int mct_push_task(struct starpu_sched_component * component, struct starp
 		return 1;
 	}
 
-	int ret = starpu_sched_component_push_task(best_component, task);
+	int ret = starpu_sched_component_push_task(component, best_component, task);
 	return ret;
 }
 
@@ -117,14 +117,13 @@ int starpu_sched_component_is_mct(struct starpu_sched_component * component)
 
 struct starpu_sched_component * starpu_sched_component_mct_create(struct starpu_sched_tree *tree, struct starpu_sched_component_mct_data * params)
 {
-	struct starpu_sched_component * component = starpu_sched_component_create(tree);
+	struct starpu_sched_component * component = starpu_sched_component_create(tree, "mct");
 	struct _starpu_mct_data *data = starpu_mct_init_parameters(params);
 
 	component->data = data;
 
 	component->push_task = mct_push_task;
 	component->deinit_data = mct_component_deinit_data;
-	component->name = "mct";
 
 	return component;
 }

+ 4 - 5
src/sched_policies/component_perfmodel_select.c

@@ -44,10 +44,10 @@ static int perfmodel_select_push_task(struct starpu_sched_component * component,
 	if(can_execute)
 	{
 		if(isnan(length))
-			return starpu_sched_component_push_task(data->calibrator_component,task);
+			return starpu_sched_component_push_task(component,data->calibrator_component,task);
 		if(_STARPU_IS_ZERO(length))
-			return starpu_sched_component_push_task(data->no_perfmodel_component,task);
-		return starpu_sched_component_push_task(data->perfmodel_component,task);
+			return starpu_sched_component_push_task(component,data->no_perfmodel_component,task);
+		return starpu_sched_component_push_task(component,data->perfmodel_component,task);
 	}
 	else
 		return 1;
@@ -70,7 +70,7 @@ struct starpu_sched_component * starpu_sched_component_perfmodel_select_create(s
 {
 	STARPU_ASSERT(params);
 	STARPU_ASSERT(params->calibrator_component && params->no_perfmodel_component && params->perfmodel_component);
-	struct starpu_sched_component * component = starpu_sched_component_create(tree);
+	struct starpu_sched_component * component = starpu_sched_component_create(tree, "perfmodel_selector");
 
 	struct _starpu_perfmodel_select_data * data = malloc(sizeof(*data));
 	data->calibrator_component = params->calibrator_component;
@@ -80,7 +80,6 @@ struct starpu_sched_component * starpu_sched_component_perfmodel_select_create(s
 	component->data = data;
 	component->push_task = perfmodel_select_push_task;
 	component->deinit_data = perfmodel_select_component_deinit_data;
-	component->name = "perfmodel_selector";
 
 	return component;
 }

+ 5 - 6
src/sched_policies/component_prio.c

@@ -236,17 +236,17 @@ static int prio_can_push(struct starpu_sched_component * component)
 	STARPU_ASSERT(component->nchildren == 1);
 	struct starpu_sched_component * child = component->children[0];
 
-	struct starpu_task * task = starpu_sched_component_pull_task(component);
+	struct starpu_task * task = starpu_sched_component_pull_task(component, component);
 	if(task)
-		ret = starpu_sched_component_push_task(child,task);	
+		ret = starpu_sched_component_push_task(component,child,task);	
 	while(task && !ret) 
 	{
 		if(!res)
 			res = 1;
 
-		task = starpu_sched_component_pull_task(component);
+		task = starpu_sched_component_pull_task(component,component);
 		if(task)
-			ret = starpu_sched_component_push_task(child,task);	
+			ret = starpu_sched_component_push_task(component,child,task);	
 	}
 	if(task && ret)
 		prio_push_local_task(component,task,1); 
@@ -261,7 +261,7 @@ int starpu_sched_component_is_prio(struct starpu_sched_component * component)
 
 struct starpu_sched_component * starpu_sched_component_prio_create(struct starpu_sched_tree *tree, struct starpu_sched_component_prio_data * params)
 {
-	struct starpu_sched_component * component = starpu_sched_component_create(tree);
+	struct starpu_sched_component * component = starpu_sched_component_create(tree, "prio");
 	struct _starpu_prio_data * data = malloc(sizeof(*data));
 	_starpu_prio_deque_init(&data->prio);
 	STARPU_PTHREAD_MUTEX_INIT(&data->mutex,NULL);
@@ -273,7 +273,6 @@ struct starpu_sched_component * starpu_sched_component_prio_create(struct starpu
 	component->can_push = prio_can_push;
 	component->deinit_data = prio_component_deinit_data;
 
-	component->name = "prio";
 	if(params)
 	{
 		data->ntasks_threshold=params->ntasks_threshold;

+ 2 - 3
src/sched_policies/component_random.c

@@ -90,7 +90,7 @@ static int random_push_task(struct starpu_sched_component * component, struct st
 		return 1;
 	}
 
-	int ret_val = starpu_sched_component_push_task(select,task);
+	int ret_val = starpu_sched_component_push_task(component,select,task);
 	return ret_val;
 }
 
@@ -113,9 +113,8 @@ int starpu_sched_component_is_random(struct starpu_sched_component *component)
 
 struct starpu_sched_component * starpu_sched_component_random_create(struct starpu_sched_tree *tree, void * arg STARPU_ATTRIBUTE_UNUSED)
 {
-	struct starpu_sched_component * component = starpu_sched_component_create(tree);
+	struct starpu_sched_component * component = starpu_sched_component_create(tree, "random");
 	component->estimated_end = random_estimated_end;
 	component->push_task = random_push_task;
-	component->name = "random";
 	return component;
 }

+ 16 - 9
src/sched_policies/component_sched.c

@@ -192,6 +192,7 @@ void starpu_sched_component_destroy(struct starpu_sched_component *component)
 	component->deinit_data(component);
 	free(component->children);
 	free(component->parents);
+	free(component->name);
 	starpu_bitmap_destroy(component->workers);
 	starpu_bitmap_destroy(component->workers_in_ctx);
 	free(component);
@@ -326,6 +327,7 @@ void starpu_sched_component_connect(struct starpu_sched_component *parent, struc
 {
 	parent->add_child(parent, child);
 	child->add_parent(child, parent);
+	_STARPU_TRACE_SCHED_COMPONENT_CONNECT(parent,child);
 }
 
 int starpu_sched_tree_push_task(struct starpu_task * task)
@@ -334,14 +336,15 @@ int starpu_sched_tree_push_task(struct starpu_task * task)
 	unsigned sched_ctx_id = task->sched_ctx;
 	struct starpu_sched_tree *tree = starpu_sched_ctx_get_policy_data(sched_ctx_id);
 
-	int ret_val = starpu_sched_component_push_task(tree->root,task);
+	int ret_val = starpu_sched_component_push_task(NULL, tree->root,task);
 	
 	return ret_val;
 }
 
-int starpu_sched_component_push_task(struct starpu_sched_component *component, struct starpu_task *task)
+int starpu_sched_component_push_task(struct starpu_sched_component *from STARPU_ATTRIBUTE_UNUSED, struct starpu_sched_component *to, struct starpu_task *task)
 {
-	return component->push_task(component, task);
+	_STARPU_TRACE_SCHED_COMPONENT_PUSH(from, to, task);
+	return to->push_task(to, task);
 }
 
 struct starpu_task * starpu_sched_tree_pop_task(unsigned sched_ctx)
@@ -351,13 +354,16 @@ struct starpu_task * starpu_sched_tree_pop_task(unsigned sched_ctx)
 
 	/* _starpu_sched_component_lock_worker(workerid) is called by component->pull_task()
 	 */
-	struct starpu_task * task = starpu_sched_component_pull_task(component);
+	struct starpu_task * task = starpu_sched_component_pull_task(component,NULL);
 	return task;
 }
 
-struct starpu_task * starpu_sched_component_pull_task(struct starpu_sched_component *component)
+struct starpu_task * starpu_sched_component_pull_task(struct starpu_sched_component *from, struct starpu_sched_component *to STARPU_ATTRIBUTE_UNUSED)
 {
-	return component->pull_task(component);
+	struct starpu_task *task = from->pull_task(from);
+	if (task)
+		_STARPU_TRACE_SCHED_COMPONENT_PULL(from, to, task);
+	return task;
 }
 
 void starpu_sched_tree_add_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers)
@@ -505,7 +511,7 @@ static struct starpu_task * starpu_sched_component_parents_pull_task(struct star
 			continue;
 		else
 		{
-			task = starpu_sched_component_pull_task(component->parents[i]);
+			task = starpu_sched_component_pull_task(component->parents[i], component);
 			if(task)
 				break;
 		}
@@ -579,7 +585,7 @@ static void take_component_and_does_nothing(struct starpu_sched_component * comp
 {
 }
 
-struct starpu_sched_component * starpu_sched_component_create(struct starpu_sched_tree *tree)
+struct starpu_sched_component * starpu_sched_component_create(struct starpu_sched_tree *tree, const char *name)
 {
 	struct starpu_sched_component * component = malloc(sizeof(*component));
 	memset(component,0,sizeof(*component));
@@ -597,6 +603,7 @@ struct starpu_sched_component * starpu_sched_component_create(struct starpu_sche
 	component->estimated_end = starpu_sched_component_estimated_end_min;
 	component->deinit_data = take_component_and_does_nothing;
 	component->notify_change_workers = take_component_and_does_nothing;
-	component->name = "sched";
+	component->name = strdup(name);
+	_STARPU_TRACE_SCHED_COMPONENT_NEW(component);
 	return component;
 }

+ 3 - 4
src/sched_policies/component_work_stealing.c

@@ -161,7 +161,7 @@ static struct starpu_task * pull_task(struct starpu_sched_component * component)
 			continue;
 		else
 		{
-			task = starpu_sched_component_pull_task(component->parents[i]);
+			task = starpu_sched_component_pull_task(component->parents[i],component);
 			if(task)
 				break;
 		}
@@ -319,7 +319,7 @@ void _ws_remove_child(struct starpu_sched_component * component, struct starpu_s
 	struct starpu_task * task;
 	while((task = _starpu_prio_deque_pop_task(tmp_fifo)))
 	{
-		starpu_sched_component_push_task(component, task);
+		starpu_sched_component_push_task(NULL, component, task);
 	}
 	_starpu_prio_deque_destroy(tmp_fifo);
 	free(tmp_fifo);
@@ -337,7 +337,7 @@ int starpu_sched_component_is_work_stealing(struct starpu_sched_component * comp
 
 struct starpu_sched_component * starpu_sched_component_work_stealing_create(struct starpu_sched_tree *tree, void * arg STARPU_ATTRIBUTE_UNUSED)
 {
-	struct starpu_sched_component * component = starpu_sched_component_create(tree);
+	struct starpu_sched_component * component = starpu_sched_component_create(tree, "work_stealing");
 	struct _starpu_work_stealing_data * wsd = malloc(sizeof(*wsd));
 	memset(wsd, 0, sizeof(*wsd));
 	component->pull_task = pull_task;
@@ -348,6 +348,5 @@ struct starpu_sched_component * starpu_sched_component_work_stealing_create(stru
 	component->estimated_load = _ws_estimated_load;
 	component->deinit_data = _work_stealing_component_deinit_data;
 	component->data = wsd;
-	component->name = "work_stealing";
 	return  component;
 }

+ 6 - 6
src/sched_policies/component_worker.c

@@ -501,7 +501,7 @@ static struct starpu_task * simple_worker_pull_task(struct starpu_sched_componen
 			else
 			{
 				_starpu_sched_component_worker_unlock_scheduling(component->tree->sched_ctx_id);
-				task = starpu_sched_component_pull_task(component->parents[i]);
+				task = starpu_sched_component_pull_task(component->parents[i],component);
 				_starpu_sched_component_worker_lock_scheduling(component->tree->sched_ctx_id);
 				if(task)
 					break;
@@ -521,7 +521,7 @@ static struct starpu_task * simple_worker_pull_task(struct starpu_sched_componen
 			return task;
 		}
 		struct starpu_sched_component * combined_worker_component = starpu_sched_component_worker_get(component->tree->sched_ctx_id, workerid);
-		starpu_sched_component_push_task(combined_worker_component, task);
+		starpu_sched_component_push_task(component, combined_worker_component, task);
 		/* we have pushed a task in queue, so can make a recursive call */
 		return simple_worker_pull_task(component);
 
@@ -588,7 +588,9 @@ static struct starpu_sched_component * starpu_sched_component_worker_create(stru
 	struct _starpu_worker * worker = _starpu_get_worker_struct(workerid);
 	if(worker == NULL)
 		return NULL;
-	struct starpu_sched_component * component = starpu_sched_component_create(tree);
+	char name[32];
+	snprintf(name, sizeof(name), "worker %u", workerid);
+	struct starpu_sched_component * component = starpu_sched_component_create(tree, name);
 	struct _starpu_worker_component_data * data = malloc(sizeof(*data));
 	memset(data, 0, sizeof(*data));
 
@@ -607,7 +609,6 @@ static struct starpu_sched_component * starpu_sched_component_worker_create(stru
 	starpu_bitmap_set(component->workers, workerid);
 	starpu_bitmap_or(component->workers_in_ctx, component->workers);
 	_worker_components[tree->sched_ctx_id][workerid] = component;
-	component->name = "worker";
 
 	/*
 #ifdef STARPU_HAVE_HWLOC
@@ -770,7 +771,7 @@ static struct starpu_sched_component  * starpu_sched_component_combined_worker_c
 	struct _starpu_combined_worker * combined_worker = _starpu_get_combined_worker_struct(workerid);
 	if(combined_worker == NULL)
 		return NULL;
-	struct starpu_sched_component * component = starpu_sched_component_create(tree);
+	struct starpu_sched_component * component = starpu_sched_component_create(tree, "combined_worker");
 	struct _starpu_worker_component_data * data = malloc(sizeof(*data));
 	memset(data, 0, sizeof(*data));
 	data->combined_worker = combined_worker;
@@ -786,7 +787,6 @@ static struct starpu_sched_component  * starpu_sched_component_combined_worker_c
 	starpu_bitmap_set(component->workers, workerid);
 	starpu_bitmap_or(component->workers_in_ctx, component->workers);
 	_worker_components[tree->sched_ctx_id][workerid] = component;
-	component->name = "combined worker";
 
 #ifdef STARPU_HAVE_HWLOC
 	struct _starpu_machine_config *config = _starpu_get_machine_config();

+ 2 - 2
src/sched_policies/modular_heft.c

@@ -1,6 +1,6 @@
 /* StarPU --- Runtime system for heterogeneous multicore architectures.
  *
- * Copyright (C) 2013-2014  Université de Bordeaux
+ * Copyright (C) 2013-2015  Université de Bordeaux
  * Copyright (C) 2013  INRIA
  * Copyright (C) 2013  Simon Archipoff
  *
@@ -87,8 +87,8 @@ static void initialize_heft_center_policy(unsigned sched_ctx_id)
 	t->root = window_component;
 	starpu_sched_component_connect(window_component, perfmodel_select_component);
 
-	starpu_sched_component_connect(perfmodel_select_component, calibrator_component);
 	starpu_sched_component_connect(perfmodel_select_component, perfmodel_component);
+	starpu_sched_component_connect(perfmodel_select_component, calibrator_component);
 	starpu_sched_component_connect(perfmodel_select_component, no_perfmodel_component);
 
 	struct starpu_sched_component_prio_data prio_data =

+ 2 - 2
src/sched_policies/modular_heft2.c

@@ -1,6 +1,6 @@
 /* StarPU --- Runtime system for heterogeneous multicore architectures.
  *
- * Copyright (C) 2013-2014  Université de Bordeaux
+ * Copyright (C) 2013-2015  Université de Bordeaux
  * Copyright (C) 2013  INRIA
  * Copyright (C) 2013  Simon Archipoff
  *
@@ -61,8 +61,8 @@ static void initialize_heft2_center_policy(unsigned sched_ctx_id)
 	t->root = window_component;
 	starpu_sched_component_connect(window_component, perfmodel_select_component);
 
-	starpu_sched_component_connect(perfmodel_select_component, calibrator_component);
 	starpu_sched_component_connect(perfmodel_select_component, perfmodel_component);
+	starpu_sched_component_connect(perfmodel_select_component, calibrator_component);
 	starpu_sched_component_connect(perfmodel_select_component, no_perfmodel_component);
 
 	struct starpu_sched_component_prio_data prio_data =