node_sched.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. #include <core/jobs.h>
  2. #include <core/workers.h>
  3. #include "node_sched.h"
  4. static void available(struct _starpu_sched_node * node)
  5. {
  6. int i;
  7. for(i = 0; i < node->nchilds; i++)
  8. node->childs[i]->available(node->childs[i]);
  9. }
  10. static struct starpu_task * pop_task_node(struct _starpu_sched_node * node, unsigned sched_ctx_id)
  11. {
  12. if(node->fathers[sched_ctx_id] == NULL)
  13. return NULL;
  14. else
  15. return node->fathers[sched_ctx_id]->pop_task(node->fathers[sched_ctx_id], sched_ctx_id);
  16. }
  17. struct _starpu_sched_node * _starpu_sched_node_create(void)
  18. {
  19. struct _starpu_sched_node * node = malloc(sizeof(*node));
  20. memset(node,0,sizeof(*node));
  21. STARPU_PTHREAD_MUTEX_INIT(&node->mutex,NULL);
  22. node->available = available;
  23. node->pop_task = pop_task_node;
  24. node->destroy_node = _starpu_sched_node_destroy;
  25. node->add_child = _starpu_sched_node_add_child;
  26. node->remove_child = _starpu_sched_node_remove_child;
  27. return node;
  28. }
  29. void _starpu_sched_node_destroy(struct _starpu_sched_node *node)
  30. {
  31. int i,j;
  32. for(i = 0; i < node->nchilds; i++)
  33. {
  34. struct _starpu_sched_node * child = node->childs[i];
  35. for(j = 0; j < STARPU_NMAX_SCHED_CTXS; j++)
  36. if(child->fathers[i] == node)
  37. child->fathers[i] = NULL;
  38. }
  39. free(node->childs);
  40. free(node);
  41. }
  42. void _starpu_sched_node_set_father(struct _starpu_sched_node *node,
  43. struct _starpu_sched_node *father_node,
  44. unsigned sched_ctx_id)
  45. {
  46. STARPU_ASSERT(sched_ctx_id < STARPU_NMAX_SCHED_CTXS);
  47. node->fathers[sched_ctx_id] = father_node;
  48. }
  49. struct starpu_task * pop_task(unsigned sched_ctx_id)
  50. {
  51. //struct _starpu_sched_tree * t = starpu_sched_ctx_get_policy_data(sched_ctx_id);
  52. int workerid = starpu_worker_get_id();
  53. struct _starpu_sched_node * wn = _starpu_sched_node_worker_get(workerid);
  54. return wn->pop_task(wn, sched_ctx_id);
  55. }
  56. int push_task(struct starpu_task * task)
  57. {
  58. unsigned sched_ctx_id = task->sched_ctx;
  59. struct _starpu_sched_tree * t = starpu_sched_ctx_get_policy_data(sched_ctx_id);
  60. return t->root->push_task(t->root, task);
  61. }
  62. void _starpu_node_destroy_rec(struct _starpu_sched_node * node, unsigned sched_ctx_id)
  63. {
  64. struct _starpu_sched_node ** stack = NULL;
  65. int top = -1;
  66. #define PUSH(n) do{ \
  67. stack = realloc(stack, sizeof(*stack) * (top + 2)); \
  68. stack[++top] = n;}while(0)
  69. #define POP() stack[top--]
  70. #define EMPTY() (top == -1)
  71. //we want to delete all subtrees exept if a pointer in fathers point in an other tree
  72. //ie an other context
  73. node->fathers[sched_ctx_id] = NULL;
  74. int shared = 0;
  75. {
  76. int i;
  77. for(i = 0; i < STARPU_NMAX_SCHED_CTXS; i++)
  78. if(node->fathers[i] != NULL)
  79. shared = 1;
  80. }
  81. if(!shared)
  82. PUSH(node);
  83. while(!EMPTY())
  84. {
  85. struct _starpu_sched_node * n = POP();
  86. int i;
  87. for(i = 0; i < n->nchilds; i++)
  88. {
  89. struct _starpu_sched_node * child = n->childs[i];
  90. int j;
  91. shared = 0;
  92. STARPU_ASSERT(child->fathers[sched_ctx_id] == n);
  93. child->fathers[sched_ctx_id] = NULL;
  94. for(j = 0; j < STARPU_NMAX_SCHED_CTXS; j++)
  95. {
  96. if(child->fathers[j] != NULL)//child is shared
  97. shared = 1;
  98. }
  99. if(!shared)//if not shared we want to destroy it and his childs
  100. PUSH(child);
  101. }
  102. n->destroy_node(n);
  103. }
  104. free(stack);
  105. }
  106. void _starpu_tree_destroy(struct _starpu_sched_tree * tree, unsigned sched_ctx_id)
  107. {
  108. _starpu_node_destroy_rec(tree->root, sched_ctx_id);
  109. STARPU_PTHREAD_MUTEX_DESTROY(&tree->mutex);
  110. free(tree);
  111. }
  112. void _starpu_sched_node_add_child(struct _starpu_sched_node* node, struct _starpu_sched_node * child,unsigned sched_ctx_id)
  113. {
  114. STARPU_ASSERT(!_starpu_sched_node_is_worker(node));
  115. STARPU_PTHREAD_MUTEX_LOCK(&node->mutex);
  116. node->childs = realloc(node->childs, sizeof(struct _starpu_sched_node *) * (node->nchilds + 1));
  117. node->childs[node->nchilds] = child;
  118. child->fathers[sched_ctx_id] = node;
  119. node->nchilds++;
  120. STARPU_PTHREAD_MUTEX_UNLOCK(&node->mutex);
  121. }
  122. void _starpu_sched_node_remove_child(struct _starpu_sched_node * node, struct _starpu_sched_node * child,unsigned sched_ctx_id)
  123. {
  124. STARPU_PTHREAD_MUTEX_LOCK(&node->mutex);
  125. int pos;
  126. for(pos = 0; pos < node->nchilds; pos++)
  127. if(node->childs[pos] == child)
  128. break;
  129. node->childs[pos] = node->childs[--node->nchilds];
  130. STARPU_ASSERT(child->fathers[sched_ctx_id] == node);
  131. child->fathers[sched_ctx_id] = NULL;
  132. STARPU_PTHREAD_MUTEX_UNLOCK(&node->mutex);
  133. }
  134. int _starpu_tree_push_task(struct starpu_task * task)
  135. {
  136. unsigned sched_ctx_id = task->sched_ctx;
  137. struct _starpu_sched_tree *tree = starpu_sched_ctx_get_policy_data(sched_ctx_id);
  138. STARPU_PTHREAD_MUTEX_LOCK(&tree->mutex);
  139. int ret_val = tree->root->push_task(tree->root,task);
  140. // starpu_push_task_end(task);
  141. STARPU_PTHREAD_MUTEX_UNLOCK(&tree->mutex);
  142. return ret_val;
  143. }
  144. struct starpu_task * _starpu_tree_pop_task(unsigned sched_ctx_id)
  145. {
  146. int workerid = starpu_worker_get_id();
  147. struct _starpu_sched_node * node = _starpu_sched_node_worker_get(workerid);
  148. return node->pop_task(node, sched_ctx_id);
  149. }
  150. int _starpu_sched_node_can_execute_task(struct _starpu_sched_node * node, struct starpu_task * task)
  151. {
  152. unsigned nimpl;
  153. int worker;
  154. STARPU_ASSERT(task);
  155. for (nimpl = 0; nimpl < STARPU_MAXIMPLEMENTATIONS; nimpl++)
  156. for(worker = 0; worker < node->nworkers; worker++)
  157. if (starpu_worker_can_execute_task(worker, task, nimpl))
  158. return 1;
  159. return 0;
  160. }
  161. int _starpu_sched_node_can_execute_task_with_impl(struct _starpu_sched_node * node, struct starpu_task * task, unsigned nimpl)
  162. {
  163. int worker;
  164. STARPU_ASSERT(task);
  165. STARPU_ASSERT(nimpl < STARPU_MAXIMPLEMENTATIONS);
  166. for(worker = 0; worker < node->nworkers; worker++)
  167. if (starpu_worker_can_execute_task(worker, task, nimpl))
  168. return 1;
  169. return 0;
  170. }
  171. static int is_homogeneous(int * workerids, int nworkers)
  172. {
  173. if(nworkers == 0)
  174. return 1;
  175. int i = 0;
  176. uint32_t last_worker = _starpu_get_worker_struct(workerids[i])->worker_mask;
  177. for(i = 1; i < nworkers; i++)
  178. {
  179. if(last_worker != _starpu_get_worker_struct(workerids[i])->worker_mask)
  180. return 0;
  181. last_worker = _starpu_get_worker_struct(workerids[i])->worker_mask;
  182. }
  183. return 1;
  184. }
  185. static int in_tab(int elem, int * tab, int size)
  186. {
  187. for(size--;size >= 0; size--)
  188. if(tab[size] == elem)
  189. return 1;
  190. return 0;
  191. }
  192. static void _update_workerids_after_tree_modification(struct _starpu_sched_node * node)
  193. {
  194. if(_starpu_sched_node_is_worker(node))
  195. {
  196. node->nworkers = 1;
  197. node->workerids[0] = _starpu_sched_node_worker_get_workerid(node);
  198. }
  199. else
  200. {
  201. int i;
  202. node->nworkers = 0;
  203. for(i = 0; i < node->nchilds; i++)
  204. {
  205. struct _starpu_sched_node * child = node->childs[i];
  206. _update_workerids_after_tree_modification(child);
  207. int j;
  208. for(j = 0; j < child->nworkers; j++)
  209. {
  210. int id = child->workerids[j];
  211. if(!in_tab(id, node->workerids, node->nworkers))
  212. node->workerids[node->nworkers++] = id;
  213. }
  214. }
  215. }
  216. node->is_homogeneous = is_homogeneous(node->workerids, node->nworkers);
  217. }
  218. void _starpu_tree_update_after_modification(struct _starpu_sched_tree * tree)
  219. {
  220. _update_workerids_after_tree_modification(tree->root);
  221. }