瀏覽代碼

new implementation of prio deque that fix the performance problem

Simon Archipoff 12 年之前
父節點
當前提交
0f5de01f92
共有 2 個文件被更改,包括 41 次插入78 次删除
  1. 39 76
      src/sched_policies/prio_deque.c
  2. 2 2
      src/sched_policies/prio_deque.h

+ 39 - 76
src/sched_policies/prio_deque.c

@@ -8,79 +8,48 @@ void _starpu_prio_deque_init(struct _starpu_prio_deque * pdeque)
 }
 void _starpu_prio_deque_destroy(struct _starpu_prio_deque * pdeque)
 {
-	while(pdeque->list)
+	int i;
+	for(i = 0; i < pdeque->size_array; i++)
 	{
-		struct _starpu_prio_list * l = pdeque->list;
-		pdeque->list = l->next;
-		STARPU_ASSERT(starpu_task_list_empty(&l->list));
-		free(l);
+		STARPU_ASSERT(starpu_task_list_empty(&pdeque->array[i].list));
 	}
+	free(pdeque->array);
 }
 
 int _starpu_prio_deque_is_empty(struct _starpu_prio_deque * pdeque)
 {
-	
 	return pdeque->ntasks == 0;
-/*
-	struct _starpu_prio_list * l = pdeque->list;
-	while(l)
-	{
-		if(!starpu_task_list_empty(&l->list))
-			return 0;
-		l = l->next;
-	}
-	return 1;
-*/
 }
 
-
-static struct _starpu_prio_list * _starpu_prio_list_create(int prio)
+static struct starpu_task_list * get_prio(struct _starpu_prio_deque * pdeque, int prio)
 {
-	struct _starpu_prio_list * l = malloc(sizeof(*l));
-	memset(l, 0, sizeof(*l));
-	l->prio = prio;
-	return l;
+	int i;
+	for(i = 0; i < pdeque->size_array; i++)
+	{
+		if(pdeque->array[i].prio == prio)
+		{
+			return &pdeque->array[i].list;
+		}
+		else
+			if(pdeque->array[i].prio < prio)
+				break;
+	}
+	pdeque->size_array++;
+	pdeque->array = realloc(pdeque->array, sizeof(struct _starpu_prio_list) * (pdeque->size_array));
+	memmove(pdeque->array + i + 1,
+		pdeque->array + i,
+		(pdeque->size_array - i - 1) * sizeof(struct _starpu_prio_list));
+	pdeque->array[i].prio = prio;
+	starpu_task_list_init(&pdeque->array[i].list);
+	return &pdeque->array[i].list;
 }
 
 
 
 int _starpu_prio_deque_push_task(struct _starpu_prio_deque * pdeque, struct starpu_task * task)
 {
-	STARPU_ASSERT(task != NULL);
-        struct _starpu_prio_list * l;
-	if(pdeque->list == NULL)
-		pdeque->list =  l = _starpu_prio_list_create(task->priority);
-	else
-	{
-		struct _starpu_prio_list * current = pdeque->list;
-		struct _starpu_prio_list * prev  = NULL;
-		while(current)
-		{
-			if(current->prio <= task->priority)
-				break;
-			prev = current;
-			current = current->next;
-		}
-		if(!current)
-			prev->next = current = l = _starpu_prio_list_create(task->priority);
-		if(current->prio == task->priority)
-			l = current;
-		if(prev == NULL)
-		{
-			l = pdeque->list;
-			pdeque->list = _starpu_prio_list_create(task->priority);
-			pdeque->list->next = l;
-			l = pdeque->list;
-		}
-		else
-		{
-			l = _starpu_prio_list_create(task->priority);
-			l->next = current;
-			prev->next = l;
-		}
-	}
-	
-	starpu_task_list_push_back(&l->list, task);
+	struct starpu_task_list * list = get_prio(pdeque, task->priority);
+	starpu_task_list_push_back(list, task);
 	pdeque->ntasks++;
 	return 0;
 }
@@ -102,46 +71,40 @@ static inline int pred_can_execute(struct starpu_task * t, void * pworkerid)
 
 
 #define REMOVE_TASK(pdeque, first_task_field, next_task_field, predicate, parg)	\
-	({								\
-		struct _starpu_prio_list * l = pdeque->list;		\
+	{								\
+		int i;							\
 		struct starpu_task * t = NULL;				\
-		while(l)						\
+		for(i = 0; i < pdeque->size_array; i++)			\
 		{							\
-			t = l->list.first_task_field;			\
+			t = pdeque->array[i].list.first_task_field;	\
 			while(t && !predicate(t,parg))			\
 				t = t->next_task_field;			\
 			if(t)						\
 			{						\
-				starpu_task_list_erase(&l->list, t);	\
-				l = NULL;				\
+				starpu_task_list_erase(&pdeque->array[i].list, t); \
+				pdeque->ntasks--;			\
+				return t;				\
 			}						\
-			if(l)						\
-				l = l->next;				\
 		}							\
-		if(t)							\
-		{							\
-			pdeque->ntasks--;				\
-		}							\
-		t;							\
-	})
+		return NULL;						\
+	}
 
 struct starpu_task * _starpu_prio_deque_pop_task(struct _starpu_prio_deque * pdeque)
 {
-	struct starpu_task * task = REMOVE_TASK(pdeque, head, prev, pred_true, STARPU_POISON_PTR);
-	return task;
+	REMOVE_TASK(pdeque, head, prev, pred_true, STARPU_POISON_PTR);
 }
 struct starpu_task * _starpu_prio_deque_pop_task_for_worker(struct _starpu_prio_deque * pdeque, int workerid)
 {
-	return REMOVE_TASK(pdeque, head, prev, pred_can_execute, &workerid);
+	REMOVE_TASK(pdeque, head, prev, pred_can_execute, &workerid);
 }
 
 // deque a task of the higher priority available
 struct starpu_task * _starpu_prio_deque_deque_task(struct _starpu_prio_deque * pdeque)
 {
-	return REMOVE_TASK(pdeque, tail, next, pred_true, STARPU_POISON_PTR);
+	REMOVE_TASK(pdeque, tail, next, pred_true, STARPU_POISON_PTR);
 }
 
 struct starpu_task * _starpu_prio_deque_deque_task_for_worker(struct _starpu_prio_deque * pdeque, int workerid)
 {
-	return REMOVE_TASK(pdeque, tail, next, pred_can_execute, &workerid);
+	REMOVE_TASK(pdeque, tail, next, pred_can_execute, &workerid);
 }

+ 2 - 2
src/sched_policies/prio_deque.h

@@ -8,12 +8,12 @@ struct _starpu_prio_list
 {
 	int prio;
 	struct starpu_task_list list;
-	struct _starpu_prio_list * next;
 };
 
 struct _starpu_prio_deque
 {
-	struct _starpu_prio_list * list;
+	struct _starpu_prio_list * array;
+	int size_array;
 	unsigned ntasks;
 	unsigned nprocessed;
 	double exp_start, exp_end, exp_len;