Просмотр исходного кода

build hwloc tree and iterate on the list of workers in the hwloc order

Andra Hugo лет назад: 11
Родитель
Сommit
29fe510ea0

+ 2 - 1
Makefile.am

@@ -83,7 +83,8 @@ versinclude_HEADERS = 				\
 	include/starpu_driver.h			\
 	include/starpu_stdlib.h			\
 	include/starpu_thread.h			\
-	include/starpu_thread_util.h
+	include/starpu_thread_util.h		\
+	include/starpu_tree.h
 
 nodist_versinclude_HEADERS = 			\
 	include/starpu_config.h

+ 4 - 0
examples/Makefile.am

@@ -188,6 +188,8 @@ examplebin_PROGRAMS +=				\
 	sched_ctx/parallel_code			\
 	sched_ctx/dummy_sched_with_ctx		\
 	sched_ctx/prio				\
+	worker_collections/worker_tree_example  \
+	worker_collections/worker_list_example  \
 	reductions/dot_product			\
 	reductions/minmax_reduction		\
 	mandelbrot/mandelbrot			\
@@ -265,6 +267,8 @@ STARPU_EXAMPLES +=				\
 	sched_ctx/sched_ctx			\
 	sched_ctx/prio				\
 	sched_ctx/dummy_sched_with_ctx		\
+	worker_collections/worker_tree_example  \
+	worker_collections/worker_list_example  \
 	reductions/dot_product			\
 	reductions/minmax_reduction
 

+ 86 - 0
examples/worker_collections/worker_list_example.c

@@ -0,0 +1,86 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.                                                                                                                                            
+ *                                                                                                                                                                                                                 
+ * Copyright (C) 2010-2013  Université de Bordeaux 1                                                                                                                                                               
+ * Copyright (C) 2010-2013  Centre National de la Recherche Scientifique                                                                                                                                           
+ *                                                                                                                                                                                                                 
+ * 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 <starpu.h>
+
+int main()
+{
+	starpu_init(NULL);
+
+	int procs[STARPU_NMAXWORKERS];
+	unsigned ncpus =  starpu_cpu_worker_get_count();
+        starpu_worker_get_ids_by_type(STARPU_CPU_WORKER, procs, ncpus);
+
+	struct starpu_worker_collection *co = (struct starpu_worker_collection*)malloc(sizeof(struct starpu_worker_collection));
+	co->has_next = worker_list.has_next;
+	co->get_next = worker_list.get_next;
+	co->add = worker_list.add;
+	co->remove = worker_list.remove;
+	co->init = worker_list.init;
+	co->deinit = worker_list.deinit;
+	co->init_iterator = worker_list.init_iterator;
+	co->type = STARPU_WORKER_LIST;
+
+	printf("ncpus %d \n", ncpus);
+
+	struct timeval start_time;
+        struct timeval end_time;
+        gettimeofday(&start_time, NULL);
+
+	co->init(co);
+
+	gettimeofday(&end_time, NULL);
+
+        long diff_s = end_time.tv_sec  - start_time.tv_sec;
+        long diff_us = end_time.tv_usec  - start_time.tv_usec;
+
+	float timing = (float)(diff_s*1000000 + diff_us)/1000;
+
+	int i;
+	for(i = 0; i < ncpus; i++)
+	{
+		int added = co->add(co, procs[i]);
+		printf("added proc %d to the tree \n", added);
+	}
+
+	struct starpu_sched_ctx_iterator it;
+        if(co->init_iterator)
+                co->init_iterator(co, &it);
+	
+	int pu;
+	while(co->has_next(co, &it))
+	{
+		pu = co->get_next(co, &it);
+		printf("pu = %d out of %d workers \n", pu, co->nworkers);
+	}
+	
+	for(i = 0; i < 6; i++)
+	{
+		co->remove(co, i);
+		printf("remove %d out of %d workers\n", i, co->nworkers);
+	}
+
+	while(co->has_next(co, &it))
+	{
+		pu = co->get_next(co, &it);
+		printf("pu = %d out of %d workers \n", pu, co->nworkers);
+	}
+	
+	printf("timing init = %lf \n", timing);
+	co->deinit(co);
+	starpu_shutdown();
+}

+ 87 - 0
examples/worker_collections/worker_tree_example.c

@@ -0,0 +1,87 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.                                                                                                                                            
+ *                                                                                                                                                                                                                 
+ * Copyright (C) 2010-2013  Université de Bordeaux 1                                                                                                                                                               
+ * Copyright (C) 2010-2013  Centre National de la Recherche Scientifique                                                                                                                                           
+ *                                                                                                                                                                                                                 
+ * 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 <starpu.h>
+
+int main()
+{
+	starpu_init(NULL);
+
+	int procs[STARPU_NMAXWORKERS];
+	unsigned ncpus =  starpu_cpu_worker_get_count();
+        starpu_worker_get_ids_by_type(STARPU_CPU_WORKER, procs, ncpus);
+
+	struct starpu_worker_collection *co = (struct starpu_worker_collection*)malloc(sizeof(struct starpu_worker_collection));
+	co->has_next = worker_tree.has_next;
+	co->get_next = worker_tree.get_next;
+	co->add = worker_tree.add;
+	co->remove = worker_tree.remove;
+	co->init = worker_tree.init;
+	co->deinit = worker_tree.deinit;
+	co->init_iterator = worker_tree.init_iterator;
+	co->type = STARPU_WORKER_TREE;
+
+	printf("ncpus %d \n", ncpus);
+
+	struct timeval start_time;
+        struct timeval end_time;
+        gettimeofday(&start_time, NULL);
+
+	co->init(co);
+
+	gettimeofday(&end_time, NULL);
+
+        long diff_s = end_time.tv_sec  - start_time.tv_sec;
+        long diff_us = end_time.tv_usec  - start_time.tv_usec;
+
+	float timing = (float)(diff_s*1000000 + diff_us)/1000;
+	
+	int i;
+	for(i = 0; i < ncpus; i++)
+	{
+		int added = co->add(co, procs[i]);
+		printf("added proc %d to the tree \n", added);
+	}
+
+	struct starpu_sched_ctx_iterator it;
+        if(co->init_iterator)
+                co->init_iterator(co, &it);
+	
+	int pu;
+	while(co->has_next(co, &it))
+	{
+		pu = co->get_next(co, &it);
+		printf("pu = %d out of %d workers \n", pu, co->nworkers);
+	}
+	
+	for(i = 0; i < 6; i++)
+	{
+		co->remove(co, i);
+		printf("remove %d out of %d workers\n", i, co->nworkers);
+	}
+
+	while(co->has_next(co, &it))
+	{
+		pu = co->get_next(co, &it);
+		printf("pu = %d out of %d workers \n", pu, co->nworkers);
+	}
+	
+	printf("timing init = %lf \n", timing);
+
+	co->deinit(co);
+	starpu_shutdown();
+}

+ 1 - 0
include/starpu.h

@@ -65,6 +65,7 @@ typedef UINT_PTR uintptr_t;
 #include <starpu_top.h>
 #include <starpu_fxt.h>
 #include <starpu_driver.h>
+#include <starpu_tree.h>
 
 #ifdef __cplusplus
 extern "C"

+ 52 - 0
include/starpu_tree.h

@@ -0,0 +1,52 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2009-2013  Université de Bordeaux 1
+ * Copyright (C) 2010-2013  Centre National de la Recherche Scientifique
+ *
+ * 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.
+ */
+
+#ifndef __STARPU_TREE_H__
+#define __STARPU_TREE_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#include <stdlib.h>
+struct starpu_tree {
+	struct starpu_tree **nodes;
+	struct starpu_tree *father;
+	int arity;
+	int id;
+	int level;
+	int is_pu;
+};
+
+void starpu_tree_reset_visited(struct starpu_tree *tree, int *visited);
+ 
+void starpu_tree_insert(struct starpu_tree *tree, int id, int level, int is_pu, int arity, struct starpu_tree *father);
+
+struct starpu_tree* starpu_tree_get(struct starpu_tree *tree, int id);
+
+struct starpu_tree* starpu_tree_get_neighbour (struct starpu_tree *tree, struct starpu_tree *node, int *visited, int *present);
+
+int starpu_tree_free(struct starpu_tree *tree);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STARPU_TREE_H__ */
+

+ 12 - 0
include/starpu_worker.h

@@ -40,10 +40,16 @@ enum starpu_worker_archtype
 struct starpu_sched_ctx_iterator
 {
 	int cursor;
+	void *value;
+	void *possible_value;
+	int visited[STARPU_NMAXWORKERS];
 };
 
 enum starpu_worker_collection_type
 {
+#ifdef STARPU_HAVE_HWLOC
+	STARPU_WORKER_TREE,
+#endif
 	STARPU_WORKER_LIST
 };
 
@@ -51,6 +57,7 @@ struct starpu_worker_collection
 {
 	void *workerids;
 	unsigned nworkers;
+	unsigned present[STARPU_NMAXWORKERS];
 	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);
@@ -61,6 +68,9 @@ struct starpu_worker_collection
 	void (*init_iterator)(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it);
 };
 
+extern struct starpu_worker_collection worker_list;
+extern struct starpu_worker_collection worker_tree;
+
 unsigned starpu_worker_get_count(void);
 unsigned starpu_combined_worker_get_count(void);
 unsigned starpu_worker_is_combined_worker(int id);
@@ -101,6 +111,8 @@ void starpu_worker_set_flag_sched_mutex_locked(int workerid, unsigned flag);
 
 unsigned starpu_worker_mutex_is_sched_mutex(int workerid, starpu_pthread_mutex_t *mutex);
 
+struct starpu_tree* starpu_workers_get_tree(void);
+
 #ifdef __cplusplus
 }
 #endif

+ 15 - 0
sc_hypervisor/examples/hierarchical_ctxs/resize_hierarchical_ctxs.c

@@ -115,6 +115,21 @@ int main()
 	sc_hypervisor_register_ctx(sched_ctx1, flops1);
 	sc_hypervisor_register_ctx(sched_ctx2, flops2);
 	sc_hypervisor_register_ctx(sched_ctx3, flops3);
+
+	unsigned ncpus =  starpu_cpu_worker_get_count();
+
+	sc_hypervisor_ctl(sched_ctx1,
+			  SC_HYPERVISOR_MAX_WORKERS, ncpus,
+			  SC_HYPERVISOR_NULL);
+
+	sc_hypervisor_ctl(sched_ctx2,
+			  SC_HYPERVISOR_MAX_WORKERS, ncpus,
+			  SC_HYPERVISOR_NULL);
+
+	sc_hypervisor_ctl(sched_ctx3,
+			  SC_HYPERVISOR_MAX_WORKERS, ncpus,
+			  SC_HYPERVISOR_NULL);
+
         /* lp strategy allows sizing the contexts because we know the total number of flops
 	   to be executed */
 	sc_hypervisor_size_ctxs(NULL, -1, NULL, -1);

+ 5 - 3
src/Makefile.am

@@ -132,9 +132,9 @@ noinst_HEADERS = 						\
 	starpu_parameters.h					\
 	top/starpu_top_message_queue.h				\
 	top/starpu_top_connection.h				\
-	top/starpu_top_core.h
+	top/starpu_top_core.h					
 
-libstarpu_@STARPU_EFFECTIVE_VERSION@_la_SOURCES = 						\
+libstarpu_@STARPU_EFFECTIVE_VERSION@_la_SOURCES = 		\
 	common/barrier.c					\
 	common/bitmap.c						\
 	common/barrier_counter.c				\
@@ -148,6 +148,7 @@ libstarpu_@STARPU_EFFECTIVE_VERSION@_la_SOURCES = 						\
 	core/jobs.c						\
 	core/task.c						\
 	core/task_bundle.c					\
+	core/tree.c						\
 	core/workers.c						\
 	core/combined_workers.c					\
 	core/topology.c						\
@@ -239,7 +240,8 @@ libstarpu_@STARPU_EFFECTIVE_VERSION@_la_SOURCES = 						\
 	top/starpu_top_task.c					\
 	top/starpu_top_message_queue.c				\
 	top/starpu_top_connection.c                          	\
-	worker_collection/worker_list.c
+	worker_collection/worker_list.c				\
+	worker_collection/worker_tree.c				
 
 
 if STARPU_HAVE_LEVELDB

+ 24 - 5
src/core/sched_ctx.c

@@ -21,7 +21,6 @@
 
 starpu_pthread_rwlock_t changing_ctx_mutex[STARPU_NMAX_SCHED_CTXS];
 
-extern struct starpu_worker_collection worker_list;
 static starpu_pthread_mutex_t sched_ctx_manag = STARPU_PTHREAD_MUTEX_INITIALIZER;
 static starpu_pthread_mutex_t finished_submit_mutex = STARPU_PTHREAD_MUTEX_INITIALIZER;
 struct starpu_task stop_submission_task = STARPU_TASK_INITIALIZER;
@@ -464,7 +463,10 @@ unsigned starpu_sched_ctx_create_inside_interval(const char *policy_name, const
 	sched_ctx->min_ngpus = min_ngpus;
 	sched_ctx->max_ngpus = max_ngpus;
 	_starpu_unlock_mutex_if_prev_locked();
-	_starpu_update_workers_without_ctx(sched_ctx->workers->workerids, sched_ctx->workers->nworkers, sched_ctx->id, 0);
+	int *added_workerids;
+	unsigned nw_ctx = starpu_sched_ctx_get_workers_list(sched_ctx->id, &added_workerids);
+	_starpu_update_workers_without_ctx(added_workerids, nw_ctx, sched_ctx->id, 0);
+	free(added_workerids);
 	_starpu_relock_mutex_if_prev_locked();
 #ifdef STARPU_USE_SC_HYPERVISOR
 	sched_ctx->perf_counters = NULL;
@@ -524,7 +526,10 @@ unsigned starpu_sched_ctx_create(int *workerids, int nworkers, const char *sched
 	sched_ctx->hierarchy_level = hierarchy_level;
 
 	_starpu_unlock_mutex_if_prev_locked();
-	_starpu_update_workers_with_ctx(sched_ctx->workers->workerids, sched_ctx->workers->nworkers, sched_ctx->id);
+	int *added_workerids;
+	unsigned nw_ctx = starpu_sched_ctx_get_workers_list(sched_ctx->id, &added_workerids);
+	_starpu_update_workers_with_ctx(added_workerids, nw_ctx, sched_ctx->id);
+	free(added_workerids);
 	_starpu_relock_mutex_if_prev_locked();
 #ifdef STARPU_USE_SC_HYPERVISOR
 	sched_ctx->perf_counters = NULL;
@@ -767,7 +772,7 @@ int _starpu_nworkers_able_to_execute_task(struct starpu_task *task, struct _star
 
 	STARPU_PTHREAD_RWLOCK_WRLOCK(&changing_ctx_mutex[sched_ctx->id]);
 	struct starpu_worker_collection *workers = sched_ctx->workers;
-
+	
 	struct starpu_sched_ctx_iterator it;
 	if(workers->init_iterator)
 		workers->init_iterator(workers, &it);
@@ -1035,7 +1040,20 @@ struct starpu_worker_collection* starpu_sched_ctx_create_worker_collection(unsig
 
 	switch(worker_collection_type)
 	{
-	case STARPU_WORKER_LIST:
+#ifdef STARPU_HAVE_HWLOC
+	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->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->type = STARPU_WORKER_LIST;
+		break;
+#endif
+//	case STARPU_WORKER_LIST:
+	default:
 		sched_ctx->workers->has_next = worker_list.has_next;
 		sched_ctx->workers->get_next = worker_list.get_next;
 		sched_ctx->workers->add = worker_list.add;
@@ -1045,6 +1063,7 @@ struct starpu_worker_collection* starpu_sched_ctx_create_worker_collection(unsig
 		sched_ctx->workers->init_iterator = worker_list.init_iterator;
 		sched_ctx->workers->type = STARPU_WORKER_LIST;
 		break;
+
 	}
 
 	return sched_ctx->workers;

+ 129 - 0
src/core/tree.c

@@ -0,0 +1,129 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2014  INRIA
+ *
+ * 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 "starpu_tree.h"
+
+void starpu_tree_reset_visited(struct starpu_tree *tree, int *visited)
+{
+	if(tree->arity == 0)
+		visited[tree->id] = 0;
+	int i;
+	for(i = 0; i < tree->arity; i++)
+		starpu_tree_reset_visited(tree->nodes[i], visited);
+}
+
+void starpu_tree_insert(struct starpu_tree *tree, int id, int level, int is_pu, int arity, struct starpu_tree *father)
+{
+	tree->level = level;
+	tree->arity = arity;
+	tree->nodes = (struct starpu_tree**)malloc(arity*sizeof(struct starpu_tree*));
+	int i;
+	for(i = 0; i < arity; i++)
+		tree->nodes[i] = (struct starpu_tree*)malloc(sizeof(struct starpu_tree));
+
+	tree->id = is_pu ? id : level; 
+	tree->is_pu = is_pu;
+	tree->father = father;
+}
+
+struct starpu_tree* starpu_tree_get(struct starpu_tree *tree, int id)
+{
+	if(tree->arity == 0)
+	{
+		if(tree->is_pu && tree->id == id)
+			return tree;
+		else
+			return NULL;
+	}
+
+	struct starpu_tree *found_tree = NULL;
+	int i;
+	for(i = 0; i < tree->arity; i++)
+	{
+		found_tree = starpu_tree_get(tree->nodes[i], id);
+		if(found_tree)
+			return found_tree;
+	}
+
+	return NULL;
+}
+
+struct starpu_tree* _get_down_to_leaves(struct starpu_tree *node, int *visited, int *present)
+{
+	struct starpu_tree *found_tree = NULL;
+	int i;
+	for(i = 0; i < node->arity; i++)
+	{
+		if(node->nodes[i]->arity == 0)
+		{
+			if(!visited[node->nodes[i]->id] && present[node->nodes[i]->id] && node->nodes[i]->is_pu)
+				return node->nodes[i];
+		}
+		else
+		{
+			found_tree =_get_down_to_leaves(node->nodes[i], visited, present);
+			if(found_tree)
+				return found_tree;
+		}
+	}
+	return NULL;
+}
+
+struct starpu_tree* starpu_tree_get_neighbour(struct starpu_tree *tree, struct starpu_tree *node, int *visited, int *present)
+{
+	struct starpu_tree *father = node == NULL ? tree : node->father;
+	
+	int i;
+	for(i = 0; i < father->arity; i++)
+	{
+		if(father->nodes[i] != node)
+		{
+			if(father->nodes[i]->arity == 0)
+			{
+				if(!visited[father->nodes[i]->id] && present[father->nodes[i]->id] && father->nodes[i]->is_pu)
+					return father->nodes[i];
+			}
+			else
+			{
+				struct starpu_tree *leaf = _get_down_to_leaves(father->nodes[i], visited, present);
+				if(leaf)
+					return leaf;
+			}
+		}
+	}
+
+	if(tree == father)
+		return NULL;
+	
+	return starpu_tree_get_neighbour(tree, father, visited, present);
+}
+
+int starpu_tree_free(struct starpu_tree *tree)
+{
+	if(tree->arity == 0)
+		return 1;
+	int i;
+	for(i = 0; i < tree->arity; i++)
+	{
+		if(starpu_tree_free(tree->nodes[i]))
+		{
+			free(tree->nodes);
+			tree->arity = 0;
+			return 1;
+		}
+	}
+	return 0;
+}

+ 63 - 0
src/core/workers.c

@@ -870,6 +870,49 @@ void _starpu_conf_check_environment(struct starpu_conf *conf)
 	_starpu_conf_set_value_against_environment("STARPU_DISABLE_ASYNCHRONOUS_MIC_COPY", &conf->disable_asynchronous_mic_copy);
 }
 
+struct starpu_tree* starpu_workers_get_tree(void)
+{
+	return config.topology.tree;
+}
+
+static void _fill_tree(struct starpu_tree *tree, hwloc_obj_t curr_obj, unsigned depth, hwloc_topology_t topology)
+{
+#ifdef STARPU_HAVE_HWLOC
+	unsigned i;
+	for(i = 0; i < curr_obj->arity; i++)
+	{
+		starpu_tree_insert(tree->nodes[i], curr_obj->children[i]->os_index, depth, curr_obj->children[i]->type == HWLOC_OBJ_PU, curr_obj->children[i]->arity, tree);
+/* 		char string[128]; */
+/* 		hwloc_obj_snprintf(string, sizeof(string), topology, curr_obj->children[i], "#", 0); */
+/* 		printf("%*s%s %d is_pu %d \n", 0, "", string, curr_obj->children[i]->os_index, curr_obj->children[i]->type == HWLOC_OBJ_PU); */
+	
+		_fill_tree(tree->nodes[i], curr_obj->children[i], depth+1, topology);
+	}
+#endif
+}
+
+static void _starpu_build_tree(void)
+{
+#ifdef STARPU_HAVE_HWLOC
+	struct starpu_tree* tree = (struct starpu_tree*)malloc(sizeof(struct starpu_tree));
+	config.topology.tree = tree;
+
+	hwloc_topology_t topology;
+	hwloc_topology_init(&topology);
+	hwloc_topology_load(topology);
+
+	hwloc_obj_t root = hwloc_get_root_obj(topology);
+
+/* 	char string[128]; */
+/* 	hwloc_obj_snprintf(string, sizeof(string), topology, root, "#", 0); */
+/* 	printf("%*s%s %d is_pu = %d \n", 0, "", string, root->os_index, root->type == HWLOC_OBJ_PU); */
+
+	/* level, is_pu, is in the tree (it will be true only after add*/
+	starpu_tree_insert(tree, root->os_index, 0,root->type == HWLOC_OBJ_PU, root->arity, NULL);
+	_fill_tree(tree, root, 1, topology);
+#endif
+}
+
 int starpu_init(struct starpu_conf *user_conf)
 {
 	return starpu_initialize(user_conf, NULL, NULL);
@@ -1036,6 +1079,8 @@ int starpu_initialize(struct starpu_conf *user_conf, int *argc, char ***argv)
 
 	STARPU_PTHREAD_KEY_CREATE(&worker_key, NULL);
 
+	_starpu_build_tree();
+
 	if (!is_a_sink)
 	{
 		struct starpu_sched_policy *selected_policy = _starpu_select_sched_policy(&config, config.conf->sched_policy_name);
@@ -1538,6 +1583,24 @@ void starpu_worker_get_name(int id, char *dst, size_t maxlen)
 	snprintf(dst, maxlen, "%s", name);
 }
 
+int _starpu_worker_get_bindid(int workerid)
+{
+	return config.workers[workerid].bindid;
+}
+
+int _starpu_worker_get_workerid(int bindid)
+{
+	unsigned nworkers = starpu_worker_get_count();
+
+	unsigned id;
+	for (id = 0; id < nworkers; id++)
+		if (config.workers[id].bindid == bindid)
+			return id;
+
+	/* Not found */
+	return -1;
+}
+
 /* Retrieve the status which indicates what the worker is currently doing. */
 enum _starpu_worker_status _starpu_worker_get_status(int workerid)
 {

+ 9 - 0
src/core/workers.h

@@ -172,6 +172,9 @@ struct _starpu_machine_topology
 #ifdef STARPU_HAVE_HWLOC
 	/* Topology as detected by hwloc. */
 	hwloc_topology_t hwtopology;
+
+	/* custom hwloc tree*/
+	struct starpu_tree *tree;
 #else
 	/* We maintain ABI compatibility with and without hwloc */
 	void *dummy;
@@ -406,6 +409,12 @@ int starpu_worker_get_nids_by_type(enum starpu_worker_archtype type, int *worker
    the list might not be updated */
 int starpu_worker_get_nids_ctx_free_by_type(enum starpu_worker_archtype type, int *workerids, int maxsize);
 
+/* get the os physical id of the worker */
+int _starpu_worker_get_bindid(int workerid);
+
+/* geet starpu workerid corresponding to the os physical id bindid */
+int _starpu_worker_get_workerid(int bindid);
+
 /* if the current worker has the lock release it */
 void _starpu_unlock_mutex_if_prev_locked();
 

+ 3 - 3
src/worker_collection/worker_list.c

@@ -20,7 +20,7 @@
 
 static unsigned list_has_next(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
 {
-	int nworkers = (int)workers->nworkers;
+	int nworkers = workers->nworkers;
 	STARPU_ASSERT(it != NULL);
 
 	unsigned ret = it->cursor < nworkers ;
@@ -37,7 +37,7 @@ static int list_get_next(struct starpu_worker_collection *workers, struct starpu
 
 	STARPU_ASSERT(it->cursor < nworkers);
 
-	int ret = workerids[(it->cursor)++];
+	int ret = workerids[it->cursor++];
 
 	return ret;
 }
@@ -154,7 +154,7 @@ static void list_deinit(struct starpu_worker_collection *workers)
 
 static void list_init_iterator(struct starpu_worker_collection *workers STARPU_ATTRIBUTE_UNUSED, struct starpu_sched_ctx_iterator *it)
 {
-	*((int*)it) = 0;
+	it->cursor = 0;
 }
 
 struct starpu_worker_collection worker_list =

+ 140 - 0
src/worker_collection/worker_tree.c

@@ -0,0 +1,140 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2013  Université de Bordeaux 1
+ * Copyright (C) 2012-2013  Centre National de la Recherche Scientifique
+ * Copyright (C) 2011-2013  INRIA
+ *
+ * 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 <starpu.h>
+#ifdef STARPU_HAVE_HWLOC
+#include <hwloc.h>
+/* #include "tree.h" */
+/* #include "core/workers.h" */
+
+static unsigned tree_has_next(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
+{
+	STARPU_ASSERT(it != NULL);
+
+	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);
+	
+	if(!neighbour)
+	{
+		starpu_tree_reset_visited(tree, it->visited);
+		it->value = NULL;
+		it->possible_value = NULL;
+		return 0;
+	}
+
+	it->possible_value = neighbour;
+	int id = _starpu_worker_get_workerid(neighbour->id);
+
+	STARPU_ASSERT_MSG(id != -1, "bind id not correct");
+
+	return 1;
+}
+
+static int tree_get_next(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
+{
+	int ret = -1;
+	
+	struct starpu_tree *tree = (struct starpu_tree *)workers->workerids;
+	struct starpu_tree *neighbour = NULL;
+	if(it->possible_value)
+	{
+		neighbour = it->possible_value;
+		it->possible_value = NULL;
+	}
+	else
+		neighbour = starpu_tree_get_neighbour(tree, (struct starpu_tree*)it->value, it->visited, workers->present);
+	
+	STARPU_ASSERT_MSG(neighbour, "no element anymore");
+	
+	it->value = neighbour;
+
+	ret = _starpu_worker_get_workerid(neighbour->id);
+	STARPU_ASSERT_MSG(ret != -1, "bind id not correct");
+	it->visited[ret] = 1;
+
+	return ret;
+}
+
+static int tree_add(struct starpu_worker_collection *workers, int worker)
+{
+	struct starpu_tree *tree = (struct starpu_tree *)workers->workerids;
+
+	if(!workers->present[worker])
+	{
+		workers->present[worker] = 1;
+		workers->nworkers++;
+		return worker;
+	}
+	else 
+		return -1;
+}
+
+
+static int tree_remove(struct starpu_worker_collection *workers, int worker)
+{
+	struct starpu_tree *tree = (struct starpu_tree *)workers->workerids;
+
+	if(workers->present[worker])
+	{
+		workers->present[worker] = 0;
+		workers->nworkers--;
+		return worker;
+	}
+	else 
+		return -1;
+}
+
+static void tree_init(struct starpu_worker_collection *workers)
+{
+	workers->workerids = (void*)starpu_workers_get_tree();
+	workers->nworkers = 0;
+	
+	int i;
+	for(i = 0; i < STARPU_NMAXWORKERS; i++)
+		workers->present[i] = 0;
+	
+	return;
+}
+
+static void tree_deinit(struct starpu_worker_collection *workers)
+{
+//	free(workers->workerids);
+}
+
+static void tree_init_iterator(struct starpu_worker_collection *workers STARPU_ATTRIBUTE_UNUSED, struct starpu_sched_ctx_iterator *it)
+{
+	it->value = NULL;
+	it->possible_value = NULL;
+	int i;
+	for(i = 0; i < STARPU_NMAXWORKERS; i++)
+		it->visited[i] = 0;
+}
+
+struct starpu_worker_collection worker_tree =
+{
+	.has_next = tree_has_next,
+	.get_next = tree_get_next,
+	.add = tree_add,
+	.remove = tree_remove,
+	.init = tree_init,
+	.deinit = tree_deinit,
+	.init_iterator = tree_init_iterator,
+	.type = STARPU_WORKER_TREE
+};
+
+#endif// STARPU_HAVE_HWLOC