worker_tree.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2013 Université de Bordeaux 1
  4. * Copyright (C) 2012-2014 Centre National de la Recherche Scientifique
  5. * Copyright (C) 2011-2013 INRIA
  6. *
  7. * StarPU is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License as published by
  9. * the Free Software Foundation; either version 2.1 of the License, or (at
  10. * your option) any later version.
  11. *
  12. * StarPU is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. *
  16. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  17. */
  18. #include <starpu.h>
  19. #ifdef STARPU_HAVE_HWLOC
  20. #include <hwloc.h>
  21. #include "core/workers.h"
  22. static unsigned tree_has_next(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
  23. {
  24. STARPU_ASSERT(it != NULL);
  25. if(workers->nworkers == 0)
  26. return 0;
  27. struct starpu_tree *tree = (struct starpu_tree*)workers->workerids;
  28. struct starpu_tree *neighbour = starpu_tree_get_neighbour(tree, (struct starpu_tree*)it->value, it->visited, workers->present);
  29. if(!neighbour)
  30. {
  31. starpu_tree_reset_visited(tree, it->visited);
  32. it->value = NULL;
  33. it->possible_value = NULL;
  34. return 0;
  35. }
  36. int id = -1;
  37. int workerids[STARPU_NMAXWORKERS];
  38. int nworkers = _starpu_worker_get_workerids(neighbour->id, workerids);
  39. int w;
  40. for(w = 0; w < nworkers; w++)
  41. {
  42. if(!it->visited[workerids[w]] && workers->present[workerids[w]])
  43. {
  44. id = workerids[w];
  45. it->possible_value = neighbour;
  46. }
  47. }
  48. STARPU_ASSERT_MSG(id != -1, "bind id (%d) for workerid (%d) not correct", neighbour->id, id);
  49. return 1;
  50. }
  51. static int tree_get_next(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
  52. {
  53. int ret = -1;
  54. struct starpu_tree *tree = (struct starpu_tree *)workers->workerids;
  55. struct starpu_tree *neighbour = NULL;
  56. if(it->possible_value)
  57. {
  58. neighbour = it->possible_value;
  59. it->possible_value = NULL;
  60. }
  61. else
  62. neighbour = starpu_tree_get_neighbour(tree, (struct starpu_tree*)it->value, it->visited, workers->present);
  63. STARPU_ASSERT_MSG(neighbour, "no element anymore");
  64. int workerids[STARPU_NMAXWORKERS];
  65. int nworkers = _starpu_worker_get_workerids(neighbour->id, workerids);
  66. int w;
  67. for(w = 0; w < nworkers; w++)
  68. {
  69. if(!it->visited[workerids[w]] && workers->present[workerids[w]])
  70. {
  71. ret = workerids[w];
  72. it->visited[workerids[w]] = 1;
  73. it->value = neighbour;
  74. }
  75. }
  76. STARPU_ASSERT_MSG(ret != -1, "bind id not correct");
  77. return ret;
  78. }
  79. static unsigned tree_has_next_master(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
  80. {
  81. STARPU_ASSERT(it != NULL);
  82. if(workers->nworkers == 0)
  83. return 0;
  84. struct starpu_tree *tree = (struct starpu_tree*)workers->workerids;
  85. struct starpu_tree *neighbour = starpu_tree_get_neighbour(tree, (struct starpu_tree*)it->value, it->visited, workers->is_master);
  86. if(!neighbour)
  87. {
  88. starpu_tree_reset_visited(tree, it->visited);
  89. it->value = NULL;
  90. it->possible_value = NULL;
  91. return 0;
  92. }
  93. int id = -1;
  94. int workerids[STARPU_NMAXWORKERS];
  95. int nworkers = _starpu_worker_get_workerids(neighbour->id, workerids);
  96. int w;
  97. for(w = 0; w < nworkers; w++)
  98. {
  99. if(!it->visited[workerids[w]] && workers->is_master[workerids[w]])
  100. {
  101. id = workerids[w];
  102. it->possible_value = neighbour;
  103. }
  104. }
  105. STARPU_ASSERT_MSG(id != -1, "bind id (%d) for workerid (%d) not correct", neighbour->id, id);
  106. return 1;
  107. }
  108. static int tree_get_next_master(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
  109. {
  110. int ret = -1;
  111. struct starpu_tree *tree = (struct starpu_tree *)workers->workerids;
  112. struct starpu_tree *neighbour = NULL;
  113. if(it->possible_value)
  114. {
  115. neighbour = it->possible_value;
  116. it->possible_value = NULL;
  117. }
  118. else
  119. neighbour = starpu_tree_get_neighbour(tree, (struct starpu_tree*)it->value, it->visited, workers->is_master);
  120. STARPU_ASSERT_MSG(neighbour, "no element anymore");
  121. int workerids[STARPU_NMAXWORKERS];
  122. int nworkers = _starpu_worker_get_workerids(neighbour->id, workerids);
  123. int w;
  124. for(w = 0; w < nworkers; w++)
  125. {
  126. if(!it->visited[workerids[w]] && workers->is_master[workerids[w]])
  127. {
  128. ret = workerids[w];
  129. it->visited[workerids[w]] = 1;
  130. it->value = neighbour;
  131. }
  132. }
  133. STARPU_ASSERT_MSG(ret != -1, "bind id not correct");
  134. return ret;
  135. }
  136. static int tree_add(struct starpu_worker_collection *workers, int worker)
  137. {
  138. if(!workers->present[worker])
  139. {
  140. workers->present[worker] = 1;
  141. workers->nworkers++;
  142. return worker;
  143. }
  144. else
  145. return -1;
  146. }
  147. static int tree_remove(struct starpu_worker_collection *workers, int worker)
  148. {
  149. if(workers->present[worker])
  150. {
  151. workers->present[worker] = 0;
  152. workers->is_master[worker] = 0;
  153. workers->nworkers--;
  154. return worker;
  155. }
  156. else
  157. return -1;
  158. }
  159. static void tree_init(struct starpu_worker_collection *workers)
  160. {
  161. workers->workerids = (void*)starpu_workers_get_tree();
  162. workers->nworkers = 0;
  163. int i;
  164. int nworkers = starpu_worker_get_count();
  165. for(i = 0; i < nworkers; i++)
  166. {
  167. workers->present[i] = 0;
  168. workers->is_master[i] = 0;
  169. }
  170. return;
  171. }
  172. static void tree_deinit(struct starpu_worker_collection *workers)
  173. {
  174. // free(workers->workerids);
  175. }
  176. static void tree_init_iterator(struct starpu_worker_collection *workers, struct starpu_sched_ctx_iterator *it)
  177. {
  178. it->value = NULL;
  179. it->possible_value = NULL;
  180. int i;
  181. int nworkers = starpu_worker_get_count();
  182. for(i = 0; i < nworkers; i++)
  183. {
  184. workers->is_master[i] = (workers->present[i] && !starpu_worker_is_slave(i));
  185. it->visited[i] = 0;
  186. }
  187. }
  188. struct starpu_worker_collection worker_tree =
  189. {
  190. .has_next = tree_has_next,
  191. .get_next = tree_get_next,
  192. .has_next_master = tree_has_next_master,
  193. .get_next_master = tree_get_next_master,
  194. .add = tree_add,
  195. .remove = tree_remove,
  196. .init = tree_init,
  197. .deinit = tree_deinit,
  198. .init_iterator = tree_init_iterator,
  199. .type = STARPU_WORKER_TREE
  200. };
  201. #endif// STARPU_HAVE_HWLOC