Browse Source

generalize job list into multilist

Samuel Thibault 8 years ago
parent
commit
cda9181705
3 changed files with 140 additions and 101 deletions
  1. 34 34
      src/common/graph.c
  2. 95 0
      src/common/list.h
  3. 11 67
      src/core/jobs.h

+ 34 - 34
src/common/graph.c

@@ -30,27 +30,27 @@ static starpu_pthread_rwlock_t graph_lock;
 int _starpu_graph_record;
 
 /* This list contains all jobs without incoming dependency */
-struct _starpu_job_list top;
+struct _starpu_job_multilist_top top;
 /* This list contains all jobs without outgoing dependency */
-struct _starpu_job_list bottom;
+struct _starpu_job_multilist_bottom bottom;
 /* This list contains all jobs */
-struct _starpu_job_list all;
+struct _starpu_job_multilist_all all;
 
 void _starpu_graph_init(void)
 {
 	STARPU_PTHREAD_RWLOCK_INIT(&graph_lock, NULL);
-	_starpu_job_list_init(&top);
-	_starpu_job_list_init(&bottom);
-	_starpu_job_list_init(&all);
+	_starpu_job_multilist_init_top(&top);
+	_starpu_job_multilist_init_bottom(&bottom);
+	_starpu_job_multilist_init_all(&all);
 }
 
 static void __starpu_graph_foreach(void (*func)(void *data, struct _starpu_job *job), void *data)
 {
 	struct _starpu_job *job;
 
-	for (job = _starpu_job_list_begin(&all, all);
-	     job != _starpu_job_list_end(&all, all);
-	     job = _starpu_job_list_next(&all, job, all))
+	for (job = _starpu_job_multilist_begin_all(&all);
+	     job != _starpu_job_multilist_end_all(&all);
+	     job = _starpu_job_multilist_next_all(job))
 		func(data, job);
 }
 
@@ -60,9 +60,9 @@ void _starpu_graph_add_job(struct _starpu_job *job)
 	STARPU_PTHREAD_RWLOCK_WRLOCK(&graph_lock);
 
 	/* It does not have any dependency yet, add to all lists */
-	_starpu_job_list_push_back(&top, job, top);
-	_starpu_job_list_push_back(&bottom, job, bottom);
-	_starpu_job_list_push_back(&all, job, all);
+	_starpu_job_multilist_push_back_top(&top, job);
+	_starpu_job_multilist_push_back_bottom(&bottom, job);
+	_starpu_job_multilist_push_back_all(&all, job);
 
 	STARPU_PTHREAD_RWLOCK_UNLOCK(&graph_lock);
 }
@@ -92,13 +92,13 @@ void _starpu_graph_add_job_dep(struct _starpu_job *job, struct _starpu_job *prev
 	unsigned rank_incoming, rank_outgoing;
 	STARPU_PTHREAD_RWLOCK_WRLOCK(&graph_lock);
 
-	if (_starpu_job_list_queued(prev_job, bottom))
+	if (_starpu_job_multilist_queued_bottom(prev_job))
 		/* Previous job is not at bottom any more */
-		_starpu_job_list_erase(bottom, prev_job, bottom);
+		_starpu_job_multilist_erase_bottom(&bottom, prev_job);
 
-	if (_starpu_job_list_queued(job, top))
+	if (_starpu_job_multilist_queued_top(job))
 		/* Next job is not at top any more */
-		_starpu_job_list_erase(top, job, top);
+		_starpu_job_multilist_erase_top(&top, job);
 
 	rank_incoming = add_job(prev_job, &job->incoming, &job->n_incoming, &job->alloc_incoming, NULL);
 	rank_outgoing = add_job(job, &prev_job->outgoing, &prev_job->n_outgoing, &prev_job->alloc_outgoing, &prev_job->outgoing_slot);
@@ -113,12 +113,12 @@ void _starpu_graph_drop_job(struct _starpu_job *job)
 	unsigned i;
 	STARPU_PTHREAD_RWLOCK_WRLOCK(&graph_lock);
 
-	if (_starpu_job_list_queued(job, bottom))
-		_starpu_job_list_erase(bottom, job, bottom);
-	if (_starpu_job_list_queued(job, top))
-		_starpu_job_list_erase(top, job, top);
-	if (_starpu_job_list_queued(job, all))
-		_starpu_job_list_erase(all, job, all);
+	if (_starpu_job_multilist_queued_bottom(job))
+		_starpu_job_multilist_erase_bottom(&bottom, job);
+	if (_starpu_job_multilist_queued_top(job))
+		_starpu_job_multilist_erase_top(&top, job);
+	if (_starpu_job_multilist_queued_all(job))
+		_starpu_job_multilist_erase_all(&all, job);
 
 	/* Drop ourself from the incoming part of the outgoing jobs */
 	for (i = 0; i < job->n_outgoing; i++)
@@ -160,9 +160,9 @@ static void _starpu_graph_compute_bottom_up(void (*func)(struct _starpu_job *nex
 
 	/* Start with the bottom of the graph */
 	current_n = 0;
-	for (job = _starpu_job_list_begin(&bottom, bottom);
-	     job != _starpu_job_list_end(&bottom, bottom);
-	     job = _starpu_job_list_next(&bottom, job, bottom))
+	for (job = _starpu_job_multilist_begin_bottom(&bottom);
+	     job != _starpu_job_multilist_end_bottom(&bottom);
+	     job = _starpu_job_multilist_next_bottom(job))
 		add_job(job, &current_set, &current_n, &current_alloc, NULL);
 
 	/* Now propagate to top as long as we have current nodes */
@@ -216,9 +216,9 @@ void _starpu_graph_compute_depths(void)
 	STARPU_PTHREAD_RWLOCK_WRLOCK(&graph_lock);
 
 	/* The bottom of the graph has depth 0 */
-	for (job = _starpu_job_list_begin(&bottom, bottom);
-	     job != _starpu_job_list_end(&bottom, bottom);
-	     job = _starpu_job_list_next(&bottom, job, bottom))
+	for (job = _starpu_job_multilist_begin_bottom(&bottom);
+	     job != _starpu_job_multilist_end_bottom(&bottom);
+	     job = _starpu_job_multilist_next_bottom(job))
 		job->depth = 0;
 
 	_starpu_graph_compute_bottom_up(compute_depth, NULL);
@@ -243,14 +243,14 @@ void _starpu_graph_compute_descendants(void)
 	 * |E| is usually O(|V|), though (bounded number of data dependencies,
 	 * and we use synchronization tasks) */
 
-	for (job = _starpu_job_list_begin(&all, all);
-	     job != _starpu_job_list_end(&all, all);
-	     job = _starpu_job_list_next(&all, job, all))
+	for (job = _starpu_job_multilist_begin_all(&all);
+	     job != _starpu_job_multilist_end_all(&all);
+	     job = _starpu_job_multilist_next_all(job))
 	{
 		/* Mark all nodes as unseen */
-		for (job2 = _starpu_job_list_begin(&all, all);
-		     job2 != _starpu_job_list_end(&all, all);
-		     job2 = _starpu_job_list_next(&all, job2, all))
+		for (job2 = _starpu_job_multilist_begin_all(&all);
+		     job2 != _starpu_job_multilist_end_all(&all);
+		     job2 = _starpu_job_multilist_next_all(job2))
 			job2->graph_n = 0;
 
 		/* Start with the node we want to compute the number of descendants of */

+ 95 - 0
src/common/list.h

@@ -15,6 +15,9 @@
  * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  */
 
+#ifndef __LIST_H__
+#define __LIST_H__
+
 /** @file
  * @brief Listes doublement chainées automatiques
  */
@@ -193,3 +196,95 @@
     { if ((i->_next == NULL) && i != l->_tail) return 0; \
       if (i->_next == i) return 0; \
       i=i->_next;} return 1; }
+
+
+#ifdef STARPU_DEBUG
+#define STARPU_ASSERT_MULTILIST(expr) STARPU_ASSERT(expr)
+#else
+#define STARPU_ASSERT_MULTILIST(expr) ((void) 0)
+#endif
+
+/*
+ * This is an implementation of list allowing to be member of several lists.
+ * - One should first call MULTILIST_CREATE_TYPE for the ENAME and for each
+ *   MEMBER type
+ * - Then the main element type should include fields of type
+ *   ENAME_multilist_MEMBER
+ * - Then one should call MULTILIST_CREATE_INLINES to create the inlines which
+ *   manipulate lists for this MEMBER type.
+ */
+
+/* Create the ENAME_multilist_MEMBER, to be used both as head and as member of main element type */
+#define MULTILIST_CREATE_TYPE(ENAME, MEMBER) \
+struct ENAME##_multilist_##MEMBER { \
+	struct ENAME##_multilist_##MEMBER *next; \
+	struct ENAME##_multilist_##MEMBER *prev; \
+};
+
+/* Create the inlines */
+#define MULTILIST_CREATE_INLINES(TYPE, ENAME, MEMBER) \
+/* Cast from list element to real type.  */ \
+static inline TYPE *ENAME##_of_multilist_##MEMBER(struct ENAME##_multilist_##MEMBER *elt) { \
+	return ((TYPE *) ((uintptr_t) (elt) - ((uintptr_t) (&((TYPE *) 0)->MEMBER)))); \
+} \
+\
+/* Initialize a list head.  */ \
+static inline void ENAME##_multilist_init_##MEMBER(struct ENAME##_multilist_##MEMBER *head) { \
+	head->next = head; \
+	head->prev = head; \
+} \
+\
+/* Push element to head of a list.  */ \
+static inline void ENAME##_multilist_push_front_##MEMBER(struct ENAME##_multilist_##MEMBER *head, TYPE *e) { \
+	STARPU_ASSERT_MULTILIST(e->MEMBER.prev == NULL); \
+	STARPU_ASSERT_MULTILIST(e->MEMBER.next == NULL); \
+	e->MEMBER.next = head->next; \
+	e->MEMBER.prev = head; \
+	head->next->prev = &e->MEMBER; \
+	head->next = &e->MEMBER; \
+} \
+\
+/* Push element to tail of a list.  */ \
+static inline void ENAME##_multilist_push_back_##MEMBER(struct ENAME##_multilist_##MEMBER *head, TYPE *e) { \
+	STARPU_ASSERT_MULTILIST(e->MEMBER.prev == NULL); \
+	STARPU_ASSERT_MULTILIST(e->MEMBER.next == NULL); \
+	e->MEMBER.prev = head->prev; \
+	e->MEMBER.next = head; \
+	head->prev->next = &e->MEMBER; \
+	head->prev = &e->MEMBER; \
+} \
+\
+/* Erase element from a list.  */ \
+static inline void ENAME##_multilist_erase_##MEMBER(struct ENAME##_multilist_##MEMBER *head STARPU_ATTRIBUTE_UNUSED, TYPE *e) { \
+	STARPU_ASSERT_MULTILIST(e->MEMBER.next->prev == &e->MEMBER); \
+	e->MEMBER.next->prev = e->MEMBER.prev; \
+	STARPU_ASSERT_MULTILIST(e->MEMBER.prev->next == &e->MEMBER); \
+	e->MEMBER.prev->next = e->MEMBER.next; \
+	e->MEMBER.next = NULL; \
+	e->MEMBER.prev = NULL; \
+} \
+\
+/* Test whether the element was queued on the list.  */ \
+static inline int ENAME##_multilist_queued_##MEMBER(TYPE *e) { \
+	return ((e)->MEMBER.next != NULL); \
+} \
+\
+/* Test whether the list is empty.  */ \
+static inline int ENAME##_multilist_empty_##MEMBER(struct ENAME##_multilist_##MEMBER *head) { \
+	return head->next != head; \
+} \
+\
+/* Return the first element of the list.  */ \
+static inline TYPE *ENAME##_multilist_begin_##MEMBER(struct ENAME##_multilist_##MEMBER *head) { \
+	return ENAME##_of_multilist_##MEMBER(head->next); \
+} \
+/* Return the value to be tested at the end of the list.  */ \
+static inline TYPE *ENAME##_multilist_end_##MEMBER(struct ENAME##_multilist_##MEMBER *head) { \
+	return ENAME##_of_multilist_##MEMBER(head); \
+} \
+/* Return the next element of the list.  */ \
+static inline TYPE *ENAME##_multilist_next_##MEMBER(TYPE *e) { \
+	return ENAME##_of_multilist_##MEMBER(e->MEMBER.next); \
+}
+
+#endif /* __LIST_H__ */

+ 11 - 67
src/core/jobs.h

@@ -40,6 +40,7 @@
 #include <core/errorcheck.h>
 #include <common/barrier.h>
 #include <common/utils.h>
+#include <common/list.h>
 
 #ifdef STARPU_USE_CUDA
 #include <cuda.h>
@@ -63,70 +64,9 @@ struct _starpu_data_descr
 	int node;
 };
 
-struct _starpu_job_list {
-	struct _starpu_job_list *next;
-	struct _starpu_job_list *prev;
-};
-
-#ifdef STARPU_DEBUG
-#define STARPU_ASSERT_JOB_LIST(expr) STARPU_ASSERT(expr)
-#else
-#define STARPU_ASSERT_JOB_LIST(expr) ((void) 0)
-#endif
-
-#define _starpu_job_of(elt, member) \
-	((struct _starpu_job *) ((uintptr_t) (elt) - ((uintptr_t) (&((struct _starpu_job *) 0)->member))))
-
-#define _starpu_job_list_init(head) do { \
-	struct _starpu_job_list *_head = (head); \
-	_head->next = _head; \
-	_head->prev = _head; \
-} while (0)
-
-#define _starpu_job_list_push_front(head, j, member) do { \
-	struct _starpu_job *_j = (j); \
-	struct _starpu_job_list *_head = (head); \
-	STARPU_ASSERT_JOB_LIST(_j->member.prev == NULL); \
-	STARPU_ASSERT_JOB_LIST(_j->member.next == NULL); \
-	_j->member.next = _head->next; \
-	_j->member.prev = _head; \
-	_head->next->prev = &_j->member; \
-	_head->next = &_j->member; \
-} while (0)
-
-#define _starpu_job_list_push_back(head, j, member) do { \
-	struct _starpu_job *_j = (j); \
-	struct _starpu_job_list *_head = (head); \
-	STARPU_ASSERT_JOB_LIST(_j->member.prev == NULL); \
-	STARPU_ASSERT_JOB_LIST(_j->member.next == NULL); \
-	_j->member.prev = _head->prev; \
-	_j->member.next = _head; \
-	_head->prev->next = &_j->member; \
-	_head->prev = &_j->member; \
-} while (0)
-
-#define _starpu_job_list_erase(head, j, member) do { \
-	struct _starpu_job *_j = (j); \
-	STARPU_ASSERT_JOB_LIST(_j->member.next->prev == &_j->member); \
-	_j->member.next->prev = _j->member.prev; \
-	STARPU_ASSERT_JOB_LIST(_j->member.prev->next == &_j->member); \
-	_j->member.prev->next = _j->member.next; \
-	_j->member.next = NULL; \
-	_j->member.prev = NULL; \
-} while (0)
-
-#define _starpu_job_list_queued(j, member) \
-	((j)->member.next != NULL)
-
-#define _starpu_job_list_empty(head) \
-	((head)->next != head)
-
-#define _starpu_job_list_begin(head, member) \
-	_starpu_job_of((head)->next, member)
-#define _starpu_job_list_next(head, j, member) \
-	_starpu_job_of((j)->member.next, member)
-#define _starpu_job_list_end(head, member) \
-	_starpu_job_of(head, member)
+MULTILIST_CREATE_TYPE(_starpu_job, all)
+MULTILIST_CREATE_TYPE(_starpu_job, top)
+MULTILIST_CREATE_TYPE(_starpu_job, bottom)
 
 /* A job is the internal representation of a task. */
 struct _starpu_job {
@@ -256,11 +196,11 @@ struct _starpu_job {
 	 * Fields for graph analysis for scheduling heuristics
 	 */
 	/* Member of list of all jobs without incoming dependency */
-	struct _starpu_job_list top;
+	struct _starpu_job_multilist_top top;
 	/* Member of list of all jobs without outgoing dependency */
-	struct _starpu_job_list bottom;
+	struct _starpu_job_multilist_bottom bottom;
 	/* Member of list of all jobs */
-	struct _starpu_job_list all;
+	struct _starpu_job_multilist_all all;
 
 	/* set of incoming dependencies */
 	struct _starpu_job **incoming;	/* May contain NULLs for terminated jobs */
@@ -285,6 +225,10 @@ struct _starpu_job {
 #endif
 };
 
+MULTILIST_CREATE_INLINES(struct _starpu_job, _starpu_job, all)
+MULTILIST_CREATE_INLINES(struct _starpu_job, _starpu_job, top)
+MULTILIST_CREATE_INLINES(struct _starpu_job, _starpu_job, bottom)
+
 void _starpu_job_init(void);
 void _starpu_job_fini(void);