Parcourir la source

refactoring worker_collections - have an iterator for normal cases and an iterator for schedulers dealing potentially with parallel tasks

Andra Hugo il y a 10 ans
Parent
commit
4680541d43

+ 2 - 4
include/starpu_worker.h

@@ -43,6 +43,7 @@ struct starpu_sched_ctx_iterator
 	void *value;
 	void *possible_value;
 	int visited[STARPU_NMAXWORKERS];
+	int possibly_parallel; 
 };
 
 enum starpu_worker_collection_type
@@ -66,15 +67,12 @@ struct starpu_worker_collection
 	enum starpu_worker_collection_type type;
 	unsigned (*has_next)(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it);
 	int (*get_next)(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it);
-	unsigned (*has_next_unblocked_worker)(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it);
-	int (*get_next_unblocked_worker)(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it);
-	unsigned (*has_next_master)(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it);
-	int (*get_next_master)(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it);
 	int (*add)(struct starpu_worker_collection *workers, int worker);
 	int (*remove)(struct starpu_worker_collection *workers, int worker);
 	void (*init)(struct starpu_worker_collection *workers);
 	void (*deinit)(struct starpu_worker_collection *workers);
 	void (*init_iterator)(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it);
+	void (*init_iterator_for_parallel_tasks)(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it, unsigned possibly_parallel);
 };
 
 extern struct starpu_worker_collection worker_list;

+ 5 - 11
src/core/sched_ctx.c

@@ -1149,10 +1149,10 @@ int _starpu_nworkers_able_to_execute_task(struct starpu_task *task, struct _star
 
 	struct starpu_sched_ctx_iterator it;
 
-	workers->init_iterator(workers, &it);
-	while(workers->has_next_master(workers, &it))
+	workers->init_iterator_for_parallel_tasks(workers, &it, task->possibly_parallel);
+	while(workers->has_next(workers, &it))
 	{
-		worker = workers->get_next_master(workers, &it);
+		worker = workers->get_next(workers, &it);
 		STARPU_ASSERT_MSG(worker < STARPU_NMAXWORKERS, "worker id %d", worker);
 		if (starpu_worker_can_execute_task_first_impl(worker, task, NULL))
 			nworkers++;
@@ -1465,15 +1465,12 @@ struct starpu_worker_collection* starpu_sched_ctx_create_worker_collection(unsig
 	case STARPU_WORKER_TREE:
 		sched_ctx->workers->has_next = worker_tree.has_next;
 		sched_ctx->workers->get_next = worker_tree.get_next;
-		sched_ctx->workers->has_next_unblocked_worker = worker_tree.has_next_unblocked_worker;
-		sched_ctx->workers->get_next_unblocked_worker = worker_tree.get_next_unblocked_worker;
-		sched_ctx->workers->has_next_master = worker_tree.has_next_master;
-		sched_ctx->workers->get_next_master = worker_tree.get_next_master;
 		sched_ctx->workers->add = worker_tree.add;
 		sched_ctx->workers->remove = worker_tree.remove;
 		sched_ctx->workers->init = worker_tree.init;
 		sched_ctx->workers->deinit = worker_tree.deinit;
 		sched_ctx->workers->init_iterator = worker_tree.init_iterator;
+		sched_ctx->workers->init_iterator_for_parallel_tasks = worker_tree.init_iterator_for_parallel_tasks;
 		sched_ctx->workers->type = STARPU_WORKER_LIST;
 		break;
 #endif
@@ -1481,15 +1478,12 @@ struct starpu_worker_collection* starpu_sched_ctx_create_worker_collection(unsig
 	default:
 		sched_ctx->workers->has_next = worker_list.has_next;
 		sched_ctx->workers->get_next = worker_list.get_next;
-		sched_ctx->workers->has_next_unblocked_worker = worker_list.has_next_unblocked_worker;
-		sched_ctx->workers->get_next_unblocked_worker = worker_list.get_next_unblocked_worker;
-		sched_ctx->workers->has_next_master = worker_list.has_next_master;
-		sched_ctx->workers->get_next_master = worker_list.get_next_master;
 		sched_ctx->workers->add = worker_list.add;
 		sched_ctx->workers->remove = worker_list.remove;
 		sched_ctx->workers->init = worker_list.init;
 		sched_ctx->workers->deinit = worker_list.deinit;
 		sched_ctx->workers->init_iterator = worker_list.init_iterator;
+		sched_ctx->workers->init_iterator_for_parallel_tasks = worker_list.init_iterator_for_parallel_tasks;
 		sched_ctx->workers->type = STARPU_WORKER_LIST;
 		break;
 

+ 9 - 54
src/sched_policies/deque_modeling_policy_data_aware.c

@@ -475,24 +475,10 @@ static int _dm_push_task(struct starpu_task *task, unsigned prio, unsigned sched
 
 	struct starpu_sched_ctx_iterator it;
 
-	workers->init_iterator(workers, &it);
-	while(1)
+	workers->init_iterator_for_parallel_tasks(workers, &it, task->possibly_parallel);
+	while(workers->has_next(workers, &it))
 	{
-		if(task->possibly_parallel)
-		{
-			if(workers->has_next_master(workers, &it))
-				worker = workers->get_next_master(workers, &it);
-			else
-				break;	
-		}
-		else
-		{
-			if(workers->has_next_unblocked_worker(workers, &it))
-				worker = workers->get_next_unblocked_worker(workers, &it);
-			else
-				break;	
-		}
-
+		worker = workers->get_next(workers, &it);
 		struct _starpu_fifo_taskq *fifo  = dt->queue_array[worker];
 		unsigned memory_node = starpu_worker_get_memory_node(worker);
 		struct starpu_perfmodel_arch* perf_arch = starpu_worker_get_perf_archtype(worker, sched_ctx_id);
@@ -634,26 +620,10 @@ static void compute_all_performance_predictions(struct starpu_task *task,
 	struct starpu_worker_collection *workers = starpu_sched_ctx_get_worker_collection(sched_ctx_id);
 
 	struct starpu_sched_ctx_iterator it;
-
-	workers->init_iterator(workers, &it);
-	while(1)
+	workers->init_iterator_for_parallel_tasks(workers, &it, task->possibly_parallel);
+	while(workers->has_next(workers, &it))
 	{
-		if(task->possibly_parallel)
-		{
-			if(workers->has_next_master(workers, &it))
-				worker = workers->get_next_master(workers, &it);
-			else
-				break;	
-		}
-		else
-		{
-			if(workers->has_next_unblocked_worker(workers, &it))
-				worker = workers->get_next_unblocked_worker(workers, &it);
-			else
-				break;	
-		}
-
-
+		worker = workers->get_next(workers, &it);
 		struct _starpu_fifo_taskq *fifo = dt->queue_array[worker];
 		struct starpu_perfmodel_arch* perf_arch = starpu_worker_get_perf_archtype(worker, sched_ctx_id);
 		unsigned memory_node = starpu_worker_get_memory_node(worker);
@@ -844,25 +814,10 @@ static double _dmda_push_task(struct starpu_task *task, unsigned prio, unsigned
 	if (forced_best == -1)
 	{
 		struct starpu_sched_ctx_iterator it;
-
-		workers->init_iterator(workers, &it);
-		
-		while(1)
+		workers->init_iterator_for_parallel_tasks(workers, &it, task->possibly_parallel);
+		while(workers->has_next(workers, &it))
 		{
-			if(task->possibly_parallel)
-			{
-				if(workers->has_next_master(workers, &it))
-					worker = workers->get_next_master(workers, &it);
-				else
-					break;	
-			}
-			else
-			{
-				if(workers->has_next_unblocked_worker(workers, &it))
-					worker = workers->get_next_unblocked_worker(workers, &it);
-				else
-					break;	
-			}
+			worker = workers->get_next(workers, &it);
 
 			if (!starpu_worker_can_execute_task_impl(worker, task, &impl_mask))
 				continue;

+ 5 - 18
src/sched_policies/eager_central_policy.c

@@ -95,24 +95,10 @@ static int push_task_eager_policy(struct starpu_task *task)
 	char dowake[STARPU_NMAXWORKERS] = { 0 };
 #endif
 
-	workers->init_iterator(workers, &it);
-	while(1)
+	workers->init_iterator_for_parallel_tasks(workers, &it, task->possibly_parallel);
+	while(workers->has_next(workers, &it))
 	{
-		if(task->possibly_parallel)
-		{
-			if(workers->has_next_master(workers, &it))
-				worker = workers->get_next_master(workers, &it);
-			else
-				break;	
-		}
-		else
-		{
-			if(workers->has_next_unblocked_worker(workers, &it))
-				worker = workers->get_next_unblocked_worker(workers, &it);
-			else
-				break;	
-		}
-
+		worker = workers->get_next(workers, &it);
 
 #ifdef STARPU_NON_BLOCKING_DRIVERS
 		if (!starpu_bitmap_get(data->waiters, worker))
@@ -138,7 +124,8 @@ static int push_task_eager_policy(struct starpu_task *task)
 #ifndef STARPU_NON_BLOCKING_DRIVERS
 	/* Now that we have a list of potential workers, try to wake one */
 
-	workers->init_iterator(workers, &it);
+//	workers->init_iterator(workers, &it);
+	workers->init_iterator_for_parallel_tasks(workers, &it, task->possibly_parallel);
 	while(workers->has_next(workers, &it))
 	{
 		worker = workers->get_next(workers, &it);

+ 7 - 21
src/sched_policies/eager_central_priority_policy.c

@@ -142,24 +142,10 @@ static int _starpu_priority_push_task(struct starpu_task *task)
 #ifndef STARPU_NON_BLOCKING_DRIVERS
 	char dowake[STARPU_NMAXWORKERS] = { 0 };
 #endif
-
-	workers->init_iterator(workers, &it);
-	while(1)
+	workers->init_iterator_for_parallel_tasks(workers, &it, task->possibly_parallel);
+	while(workers->has_next(workers, &it))
 	{
-		if(task->possibly_parallel)
-		{
-			if(workers->has_next_master(workers, &it))
-				worker = workers->get_next_master(workers, &it);
-			else
-				break;	
-		}
-		else
-		{
-			if(workers->has_next_unblocked_worker(workers, &it))
-				worker = workers->get_next(workers, &it);
-			else
-				break;	
-		}
+		worker = workers->get_next(workers, &it);
 
 #ifdef STARPU_NON_BLOCKING_DRIVERS
 		if (!starpu_bitmap_get(data->waiters, worker))
@@ -268,11 +254,11 @@ static struct starpu_task *_starpu_priority_pop_task(unsigned sched_ctx_id)
 		struct starpu_worker_collection *workers = starpu_sched_ctx_get_worker_collection(sched_ctx_id);
 
 		struct starpu_sched_ctx_iterator it;
-
-		workers->init_iterator(workers, &it);
-		while(workers->has_next_unblocked_worker(workers, &it))
+		workers->init_iterator_for_parallel_tasks(workers, &it, chosen_task->possibly_parallel);
+		while(workers->has_next(workers, &it))
 		{
-			worker = workers->get_next_unblocked_worker(workers, &it);
+			worker = workers->get_next(workers, &it);
+
 			if(worker != workerid)
 			{
 #ifdef STARPU_NON_BLOCKING_DRIVERS

+ 6 - 6
src/sched_policies/heteroprio.c

@@ -380,9 +380,9 @@ static int push_task_heteroprio_policy(struct starpu_task *task)
 #endif
 
 	workers->init_iterator(workers, &it);
-	while(workers->has_next_master(workers, &it))
+	while(workers->has_next(workers, &it))
 	{
-		worker = workers->get_next_master(workers, &it);
+		worker = workers->get_next(workers, &it);
 
 #ifdef STARPU_NON_BLOCKING_DRIVERS
 		if (!starpu_bitmap_get(hp->waiters, worker))
@@ -531,9 +531,9 @@ static struct starpu_task *pop_task_heteroprio_policy(unsigned sched_ctx_id)
 		workers->init_iterator(workers, &it);
 		unsigned victim = workerid;
 		unsigned current_worker;
-		while(workers->has_next_master(workers, &it))
+		while(workers->has_next(workers, &it))
 		{
-			current_worker = workers->get_next_master(workers, &it);
+			current_worker = workers->get_next(workers, &it);
 			if(current_worker == victim)
 				break;
 		}
@@ -541,9 +541,9 @@ static struct starpu_task *pop_task_heteroprio_policy(unsigned sched_ctx_id)
 		/* circular loop */
 		while(1)
 		{
-			while(workers->has_next_master(workers, &it))
+			while(workers->has_next(workers, &it))
 			{
-				victim = workers->get_next_master(workers, &it);
+				victim = workers->get_next(workers, &it);
 				if(victim == workerid)
 					continue;
 

+ 38 - 22
src/worker_collection/worker_list.c

@@ -18,9 +18,9 @@
 
 #include <starpu.h>
 
-static unsigned list_has_next(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
+static unsigned list_has_next_unblocked_worker(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
 {
-	int nworkers = workers->nworkers;
+	int nworkers = workers->nunblocked_workers;
 	STARPU_ASSERT(it != NULL);
 
 	unsigned ret = it->cursor < nworkers ;
@@ -30,10 +30,10 @@ static unsigned list_has_next(struct starpu_worker_collection *workers, struct s
 	return ret;
 }
 
-static int list_get_next(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
+static int list_get_next_unblocked_worker(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
 {
-	int *workerids = (int *)workers->workerids;
-	int nworkers = (int)workers->nworkers;
+	int *workerids = (int *)workers->unblocked_workers;
+	int nworkers = (int)workers->nunblocked_workers;
 
 	STARPU_ASSERT(it->cursor < nworkers);
 
@@ -42,9 +42,9 @@ static int list_get_next(struct starpu_worker_collection *workers, struct starpu
 	return ret;
 }
 
-static unsigned list_has_next_unblocked_worker(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
+static unsigned list_has_next_master(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
 {
-	int nworkers = workers->nunblocked_workers;
+	int nworkers = workers->nmasters;
 	STARPU_ASSERT(it != NULL);
 
 	unsigned ret = it->cursor < nworkers ;
@@ -54,21 +54,26 @@ static unsigned list_has_next_unblocked_worker(struct starpu_worker_collection *
 	return ret;
 }
 
-static int list_get_next_unblocked_worker(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
+static int list_get_next_master(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
 {
-	int *workerids = (int *)workers->unblocked_workers;
-	int nworkers = (int)workers->nunblocked_workers;
+	int *workerids = (int *)workers->masters;
+	int nworkers = (int)workers->nmasters;
 
-	STARPU_ASSERT(it->cursor < nworkers);
+	STARPU_ASSERT_MSG(it->cursor < nworkers, "cursor %d nworkers %d\n", it->cursor, nworkers);
 
 	int ret = workerids[it->cursor++];
 
 	return ret;
 }
 
-static unsigned list_has_next_master(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
+static unsigned list_has_next(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
 {
-	int nworkers = workers->nmasters;
+	if(it->possibly_parallel == 1)
+		return list_has_next_master(workers, it);
+	else if(it->possibly_parallel == 0)
+		return list_has_next_unblocked_worker(workers, it);
+
+	int nworkers = workers->nworkers;
 	STARPU_ASSERT(it != NULL);
 
 	unsigned ret = it->cursor < nworkers ;
@@ -78,12 +83,17 @@ static unsigned list_has_next_master(struct starpu_worker_collection *workers, s
 	return ret;
 }
 
-static int list_get_next_master(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
+static int list_get_next(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
 {
-	int *workerids = (int *)workers->masters;
-	int nworkers = (int)workers->nmasters;
+	if(it->possibly_parallel == 1)
+		return list_get_next_master(workers, it);
+	else if(it->possibly_parallel == 0)
+		return list_get_next_unblocked_worker(workers, it);
 
-	STARPU_ASSERT_MSG(it->cursor < nworkers, "cursor %d nworkers %d\n", it->cursor, nworkers);
+	int *workerids = (int *)workers->workerids;
+	int nworkers = (int)workers->nworkers;
+
+	STARPU_ASSERT(it->cursor < nworkers);
 
 	int ret = workerids[it->cursor++];
 
@@ -250,6 +260,14 @@ static void list_deinit(struct starpu_worker_collection *workers)
 static void list_init_iterator(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
 {
 	it->cursor = 0;
+	it->possibly_parallel = -1; /* -1 => we don't care about this field */
+
+}
+
+static void list_init_iterator_for_parallel_tasks(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it, unsigned possibly_parallel)
+{
+	list_init_iterator(workers, it);
+	it->possibly_parallel = possibly_parallel; /* 0/1 => this field indicates if we consider masters only or slaves not blocked too */
 
 	int *workerids = (int *)workers->workerids;
 	unsigned nworkers = workers->nworkers;
@@ -260,28 +278,26 @@ static void list_init_iterator(struct starpu_worker_collection *workers, struct
 		if(!starpu_worker_is_blocked(workerids[i]))
 		{
 			((int*)workers->unblocked_workers)[nub++] = workerids[i];
+			if(!possibly_parallel) /* don't bother filling the table with masters we won't use it anyway */
+				continue;
 			if(!starpu_worker_is_slave_somewhere(workerids[i]))
 				((int*)workers->masters)[nm++] = workerids[i];
 		}
 	}
 	workers->nmasters = nm;
 	workers->nunblocked_workers = nub;
-
 }
 
 struct starpu_worker_collection worker_list =
 {
 	.has_next = list_has_next,
 	.get_next = list_get_next,
-	.has_next_unblocked_worker = list_has_next_unblocked_worker,
-	.get_next_unblocked_worker = list_get_next_unblocked_worker,
-	.has_next_master = list_has_next_master,
-	.get_next_master = list_get_next_master,
 	.add = list_add,
 	.remove = list_remove,
 	.init = list_init,
 	.deinit = list_deinit,
 	.init_iterator = list_init_iterator,
+	.init_iterator_for_parallel_tasks = list_init_iterator_for_parallel_tasks,
 	.type = STARPU_WORKER_LIST
 };
 

+ 40 - 23
src/worker_collection/worker_tree.c

@@ -21,7 +21,7 @@
 #include <hwloc.h>
 #include "core/workers.h"
 
-static unsigned tree_has_next(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
+static unsigned tree_has_next_unblocked_worker(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
 {
 	STARPU_ASSERT(it != NULL);
 	if(workers->nworkers == 0)
@@ -43,7 +43,7 @@ static unsigned tree_has_next(struct starpu_worker_collection *workers, struct s
 	int w;
 	for(w = 0; w < nworkers; w++)
 	{
-		if(!it->visited[workerids[w]] && workers->present[workerids[w]])
+		if(!it->visited[workerids[w]] && workers->present[workerids[w]] && workers->is_unblocked[workerids[w]])
 		{
 			id = workerids[w];
 			it->possible_value = neighbour;
@@ -55,7 +55,7 @@ static unsigned tree_has_next(struct starpu_worker_collection *workers, struct s
 	return 1;
 }
 
-static int tree_get_next(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
+static int tree_get_next_unblocked_worker(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
 {
 	int ret = -1;
 
@@ -77,7 +77,7 @@ static int tree_get_next(struct starpu_worker_collection *workers, struct starpu
 	int w;
 	for(w = 0; w < nworkers; w++)
 	{
-		if(!it->visited[workerids[w]] && workers->present[workerids[w]] )
+		if(!it->visited[workerids[w]] && workers->present[workerids[w]] && workers->is_unblocked[workerids[w]])
 		{
 			ret = workerids[w];
 			it->visited[workerids[w]] = 1;
@@ -85,18 +85,17 @@ static int tree_get_next(struct starpu_worker_collection *workers, struct starpu
 		}
 	}
 	STARPU_ASSERT_MSG(ret != -1, "bind id not correct");
-
 	return ret;
 }
 
-static unsigned tree_has_next_unblocked_worker(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
+static unsigned tree_has_next_master(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
 {
 	STARPU_ASSERT(it != NULL);
 	if(workers->nworkers == 0)
 		return 0;
 
 	struct starpu_tree *tree = (struct starpu_tree*)workers->workerids;
-	struct starpu_tree *neighbour = starpu_tree_get_neighbour(tree, (struct starpu_tree*)it->value, it->visited, workers->present);
+	struct starpu_tree *neighbour = starpu_tree_get_neighbour(tree, (struct starpu_tree*)it->value, it->visited, workers->is_master);
 
 	if(!neighbour)
 	{
@@ -111,7 +110,7 @@ static unsigned tree_has_next_unblocked_worker(struct starpu_worker_collection *
 	int w;
 	for(w = 0; w < nworkers; w++)
 	{
-		if(!it->visited[workerids[w]] && workers->present[workerids[w]] && workers->is_unblocked[workerids[w]])
+		if(!it->visited[workerids[w]] && workers->is_master[workerids[w]])
 		{
 			id = workerids[w];
 			it->possible_value = neighbour;
@@ -123,7 +122,7 @@ static unsigned tree_has_next_unblocked_worker(struct starpu_worker_collection *
 	return 1;
 }
 
-static int tree_get_next_unblocked_worker(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
+static int tree_get_next_master(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
 {
 	int ret = -1;
 
@@ -135,7 +134,7 @@ static int tree_get_next_unblocked_worker(struct starpu_worker_collection *worke
 		it->possible_value = NULL;
 	}
 	else
-		neighbour = starpu_tree_get_neighbour(tree, (struct starpu_tree*)it->value, it->visited, workers->present);
+		neighbour = starpu_tree_get_neighbour(tree, (struct starpu_tree*)it->value, it->visited, workers->is_master);
 
 	STARPU_ASSERT_MSG(neighbour, "no element anymore");
 
@@ -145,7 +144,7 @@ static int tree_get_next_unblocked_worker(struct starpu_worker_collection *worke
 	int w;
 	for(w = 0; w < nworkers; w++)
 	{
-		if(!it->visited[workerids[w]] && workers->present[workerids[w]] && workers->is_unblocked[workerids[w]])
+		if(!it->visited[workerids[w]] && workers->is_master[workerids[w]])
 		{
 			ret = workerids[w];
 			it->visited[workerids[w]] = 1;
@@ -157,14 +156,19 @@ static int tree_get_next_unblocked_worker(struct starpu_worker_collection *worke
 	return ret;
 }
 
-static unsigned tree_has_next_master(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
+static unsigned tree_has_next(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
 {
+	if(it->possibly_parallel == 1)
+                return tree_has_next_master(workers, it);
+        else if(it->possibly_parallel == 0)
+                return tree_has_next_unblocked_worker(workers, it);
+
 	STARPU_ASSERT(it != NULL);
 	if(workers->nworkers == 0)
 		return 0;
 
 	struct starpu_tree *tree = (struct starpu_tree*)workers->workerids;
-	struct starpu_tree *neighbour = starpu_tree_get_neighbour(tree, (struct starpu_tree*)it->value, it->visited, workers->is_master);
+	struct starpu_tree *neighbour = starpu_tree_get_neighbour(tree, (struct starpu_tree*)it->value, it->visited, workers->present);
 
 	if(!neighbour)
 	{
@@ -179,7 +183,7 @@ static unsigned tree_has_next_master(struct starpu_worker_collection *workers, s
 	int w;
 	for(w = 0; w < nworkers; w++)
 	{
-		if(!it->visited[workerids[w]] && workers->is_master[workerids[w]])
+		if(!it->visited[workerids[w]] && workers->present[workerids[w]])
 		{
 			id = workerids[w];
 			it->possible_value = neighbour;
@@ -191,8 +195,13 @@ static unsigned tree_has_next_master(struct starpu_worker_collection *workers, s
 	return 1;
 }
 
-static int tree_get_next_master(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
+static int tree_get_next(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
 {
+	if(it->possibly_parallel == 1)
+                return tree_get_next_master(workers, it);
+        else if(it->possibly_parallel == 0)
+                return tree_get_next_unblocked_worker(workers, it);
+
 	int ret = -1;
 
 	struct starpu_tree *tree = (struct starpu_tree *)workers->workerids;
@@ -203,7 +212,7 @@ static int tree_get_next_master(struct starpu_worker_collection *workers, struct
 		it->possible_value = NULL;
 	}
 	else
-		neighbour = starpu_tree_get_neighbour(tree, (struct starpu_tree*)it->value, it->visited, workers->is_master);
+		neighbour = starpu_tree_get_neighbour(tree, (struct starpu_tree*)it->value, it->visited, workers->present);
 
 	STARPU_ASSERT_MSG(neighbour, "no element anymore");
 
@@ -213,7 +222,7 @@ static int tree_get_next_master(struct starpu_worker_collection *workers, struct
 	int w;
 	for(w = 0; w < nworkers; w++)
 	{
-		if(!it->visited[workerids[w]] && workers->is_master[workerids[w]])
+		if(!it->visited[workerids[w]] && workers->present[workerids[w]] )
 		{
 			ret = workerids[w];
 			it->visited[workerids[w]] = 1;
@@ -225,7 +234,6 @@ static int tree_get_next_master(struct starpu_worker_collection *workers, struct
 	return ret;
 }
 
-
 static int tree_add(struct starpu_worker_collection *workers, int worker)
 {
 	if(!workers->present[worker])
@@ -279,13 +287,25 @@ static void tree_init_iterator(struct starpu_worker_collection *workers, struct
 {
 	it->value = NULL;
 	it->possible_value = NULL;
+	it->possibly_parallel = -1;
+	int i;
+	int nworkers = starpu_worker_get_count();
+	for(i = 0; i < nworkers; i++)
+		it->visited[i] = 0;
+}
+
+static void tree_init_iterator_for_parallel_tasks(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it, unsigned possibly_parallel)
+{
+	tree_init_iterator(workers, it);
+	it->possibly_parallel = possibly_parallel;
 	int i;
 	int nworkers = starpu_worker_get_count();
 	for(i = 0; i < nworkers; i++)
 	{
 		workers->is_unblocked[i] = (workers->present[i] && !starpu_worker_is_blocked(i));
+		if(!possibly_parallel) /* don't bother filling the table with masters we won't use it anyway */
+			continue;
 		workers->is_master[i] = (workers->present[i] && !starpu_worker_is_blocked(i) && !starpu_worker_is_slave_somewhere(i));
-		it->visited[i] = 0;
 	}
 }
 
@@ -293,15 +313,12 @@ struct starpu_worker_collection worker_tree =
 {
 	.has_next = tree_has_next,
 	.get_next = tree_get_next,
-	.has_next_unblocked_worker = tree_has_next_unblocked_worker,
-	.get_next_unblocked_worker = tree_get_next_unblocked_worker,
-	.has_next_master = tree_has_next_master,
-	.get_next_master = tree_get_next_master,
 	.add = tree_add,
 	.remove = tree_remove,
 	.init = tree_init,
 	.deinit = tree_deinit,
 	.init_iterator = tree_init_iterator,
+	.init_iterator_for_parallel_tasks = tree_init_iterator_for_parallel_tasks,
 	.type = STARPU_WORKER_TREE
 };