feft_lp_policy.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2011-2020 Université de Bordeaux, CNRS (LaBRI UMR 5800), Inria
  4. *
  5. * StarPU is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU Lesser General Public License as published by
  7. * the Free Software Foundation; either version 2.1 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * StarPU is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. *
  14. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  15. */
  16. #include "sc_hypervisor_lp.h"
  17. #include "sc_hypervisor_policy.h"
  18. #include <starpu_config.h>
  19. #include <sys/time.h>
  20. unsigned long resize_no = 0;
  21. #ifdef STARPU_HAVE_GLPK_H
  22. static void _try_resizing(unsigned *sched_ctxs, int nsched_ctxs, int *workers, int nworkers)
  23. {
  24. /* for vite */
  25. int ns = sched_ctxs == NULL ? sc_hypervisor_get_nsched_ctxs() : nsched_ctxs;
  26. #ifdef STARPU_SC_HYPERVISOR_DEBUG
  27. printf("resize_no = %lu %d ctxs\n", resize_no, ns);
  28. #endif
  29. if(ns <= 0) return;
  30. unsigned *curr_sched_ctxs = sched_ctxs == NULL ? sc_hypervisor_get_sched_ctxs() : sched_ctxs;
  31. unsigned curr_nworkers = nworkers == -1 ? starpu_worker_get_count() : (unsigned)nworkers;
  32. struct types_of_workers *tw = sc_hypervisor_get_types_of_workers(workers, curr_nworkers);
  33. int nw = tw->nw;
  34. double nworkers_per_ctx[ns][nw];
  35. int total_nw[nw];
  36. sc_hypervisor_group_workers_by_type(tw, total_nw);
  37. struct timeval start_time;
  38. struct timeval end_time;
  39. gettimeofday(&start_time, NULL);
  40. double vmax = sc_hypervisor_lp_get_nworkers_per_ctx(ns, nw, nworkers_per_ctx, total_nw, tw, sched_ctxs);
  41. gettimeofday(&end_time, NULL);
  42. long diff_s = end_time.tv_sec - start_time.tv_sec;
  43. long diff_us = end_time.tv_usec - start_time.tv_usec;
  44. __attribute__((unused)) float timing = (float)(diff_s*1000000 + diff_us)/1000.0;
  45. if(vmax != -1.0)
  46. {
  47. /* int nworkers_per_ctx_rounded[ns][nw]; */
  48. /* sc_hypervisor_lp_round_double_to_int(ns, nw, nworkers_per_ctx, nworkers_per_ctx_rounded); */
  49. /* // sc_hypervisor_lp_redistribute_resources_in_ctxs(ns, nw, nworkers_per_ctx_rounded, nworkers_per_ctx, curr_sched_ctxs, tw); */
  50. /* sc_hypervisor_lp_distribute_resources_in_ctxs(curr_sched_ctxs, ns, nw, nworkers_per_ctx_rounded, nworkers_per_ctx, workers, curr_nworkers, tw); */
  51. sc_hypervisor_lp_distribute_floating_no_resources_in_ctxs(curr_sched_ctxs, ns, nw, nworkers_per_ctx, workers, curr_nworkers, tw);
  52. sc_hypervisor_lp_share_remaining_resources(ns, curr_sched_ctxs, curr_nworkers, workers);
  53. }
  54. #ifdef STARPU_SC_HYPERVISOR_DEBUG
  55. printf("*****finished resize \n");
  56. #endif
  57. free(tw);
  58. return;
  59. }
  60. static void _try_resizing_hierarchically(unsigned levels, unsigned current_level, unsigned *sched_ctxs, unsigned nsched_ctxs, int *pus, int npus)
  61. {
  62. if(levels == 0)
  63. return;
  64. _try_resizing(sched_ctxs, nsched_ctxs, pus, npus);
  65. int s;
  66. for(s = 0; s < nsched_ctxs; s++)
  67. {
  68. unsigned *sched_ctxs_child;
  69. int nsched_ctxs_child = 0;
  70. sc_hypervisor_get_ctxs_on_level(&sched_ctxs_child, &nsched_ctxs_child, current_level+1, sched_ctxs[s]);
  71. if(nsched_ctxs_child > 0)
  72. {
  73. int *pus_father;
  74. unsigned npus_father = 0;
  75. npus_father = starpu_sched_ctx_get_workers_list(sched_ctxs[s], &pus_father);
  76. _try_resizing_hierarchically(levels-1, current_level+1, sched_ctxs_child, nsched_ctxs_child, pus_father, npus_father);
  77. free(pus_father);
  78. free(sched_ctxs_child);
  79. }
  80. }
  81. return;
  82. }
  83. static int _get_min_level(unsigned *sched_ctxs, int nsched_ctxs)
  84. {
  85. int min = sc_hypervisor_get_nhierarchy_levels();
  86. int s;
  87. for(s = 0; s < nsched_ctxs; s++)
  88. {
  89. int level = starpu_sched_ctx_get_hierarchy_level(sched_ctxs[s]);
  90. if(level < min)
  91. min = level;
  92. }
  93. return min;
  94. }
  95. static int _get_first_level(unsigned *sched_ctxs, int nsched_ctxs, unsigned *first_level, int *nsched_ctxs_first_level)
  96. {
  97. int min = _get_min_level(sched_ctxs, nsched_ctxs);
  98. int s;
  99. for(s = 0; s < nsched_ctxs; s++)
  100. if(starpu_sched_ctx_get_hierarchy_level(sched_ctxs[s]) == min)
  101. first_level[(*nsched_ctxs_first_level)++] = sched_ctxs[s];
  102. return min;
  103. }
  104. static void _resize(unsigned *sched_ctxs, int nsched_ctxs, int *workers, int nworkers)
  105. {
  106. starpu_fxt_trace_user_event(resize_no);
  107. unsigned nhierarchy_levels = sc_hypervisor_get_nhierarchy_levels();
  108. if(nhierarchy_levels > 1)
  109. {
  110. if(nsched_ctxs == -1)
  111. {
  112. unsigned *sched_ctxs2;
  113. int nsched_ctxs2;
  114. sc_hypervisor_get_ctxs_on_level(&sched_ctxs2, &nsched_ctxs2, 0, STARPU_NMAX_SCHED_CTXS);
  115. if(nsched_ctxs2 > 0)
  116. {
  117. _try_resizing_hierarchically(nhierarchy_levels, 0, sched_ctxs2, nsched_ctxs2, workers, nworkers);
  118. free(sched_ctxs2);
  119. }
  120. }
  121. else
  122. {
  123. unsigned first_level[nsched_ctxs];
  124. int nsched_ctxs_first_level = 0;
  125. int min = _get_first_level(sched_ctxs, nsched_ctxs, first_level, &nsched_ctxs_first_level);
  126. _try_resizing_hierarchically(nhierarchy_levels, min, first_level, nsched_ctxs_first_level, workers, nworkers);
  127. }
  128. }
  129. else
  130. _try_resizing(sched_ctxs, nsched_ctxs, workers, nworkers);
  131. resize_no++;
  132. }
  133. static void _resize_if_speed_diff(unsigned sched_ctx, int worker)
  134. {
  135. unsigned nhierarchy_levels = sc_hypervisor_get_nhierarchy_levels();
  136. if(nhierarchy_levels > 1)
  137. {
  138. unsigned current_level = starpu_sched_ctx_get_hierarchy_level(sched_ctx);
  139. if(current_level == 0)
  140. {
  141. _resize(NULL, -1, NULL, -1);
  142. return;
  143. }
  144. unsigned father = starpu_sched_ctx_get_inheritor(sched_ctx);
  145. int level;
  146. int *pus_father_old = NULL;
  147. unsigned npus_father_old = 0;
  148. unsigned *sched_ctxs_old = NULL;
  149. int nsched_ctxs_old = 0;
  150. unsigned is_speed_diff = 0;
  151. for(level = current_level ; level >= 0; level--)
  152. {
  153. int *pus_father = NULL;
  154. int npus_father = -1;
  155. if(level > 0)
  156. npus_father = starpu_sched_ctx_get_workers_list(father, &pus_father);
  157. unsigned *sched_ctxs = NULL;
  158. int nsched_ctxs = 0;
  159. is_speed_diff = sc_hypervisor_check_speed_gap_btw_ctxs_on_level(level, pus_father, npus_father, father, &sched_ctxs, &nsched_ctxs);
  160. if(!is_speed_diff)
  161. {
  162. if(level == current_level)
  163. {
  164. if(pus_father)
  165. free(pus_father);
  166. if(sched_ctxs)
  167. free(sched_ctxs);
  168. pus_father = NULL;
  169. sched_ctxs = NULL;
  170. break;
  171. }
  172. else
  173. {
  174. _resize(sched_ctxs_old, nsched_ctxs_old, pus_father_old, npus_father_old);
  175. if(pus_father_old)
  176. free(pus_father_old);
  177. if(sched_ctxs_old)
  178. free(sched_ctxs_old);
  179. pus_father_old = NULL;
  180. sched_ctxs_old = NULL;
  181. if(pus_father)
  182. free(pus_father);
  183. if(nsched_ctxs > 0)
  184. free(sched_ctxs);
  185. pus_father = NULL;
  186. sched_ctxs = NULL;
  187. break;
  188. }
  189. }
  190. if(pus_father_old)
  191. free(pus_father_old);
  192. if(sched_ctxs_old)
  193. free(sched_ctxs_old);
  194. pus_father_old = pus_father;
  195. sched_ctxs_old = sched_ctxs;
  196. npus_father_old = npus_father;
  197. nsched_ctxs_old = nsched_ctxs;
  198. father = level > 1 ? starpu_sched_ctx_get_inheritor(father) : STARPU_NMAX_SCHED_CTXS;
  199. }
  200. if(is_speed_diff)
  201. {
  202. if(pus_father_old)
  203. free(pus_father_old);
  204. if(sched_ctxs_old)
  205. free(sched_ctxs_old);
  206. _resize(NULL, -1, NULL, -1);
  207. }
  208. }
  209. else
  210. {
  211. unsigned criteria = sc_hypervisor_get_resize_criteria();
  212. if(criteria != SC_NOTHING && criteria == SC_IDLE)
  213. {
  214. _resize(NULL, -1, NULL, -1);
  215. }
  216. else
  217. {
  218. if(sc_hypervisor_check_speed_gap_btw_ctxs(NULL, -1, NULL, -1))
  219. _resize(NULL, -1, NULL, -1);
  220. }
  221. }
  222. return;
  223. }
  224. static void feft_lp_handle_poped_task(unsigned sched_ctx, int worker,
  225. __attribute__((unused))struct starpu_task *task, __attribute__((unused))uint32_t footprint)
  226. {
  227. if(worker == -2) return;
  228. unsigned criteria = sc_hypervisor_get_resize_criteria();
  229. if(criteria != SC_NOTHING && criteria == SC_SPEED)
  230. {
  231. int ret = starpu_pthread_mutex_trylock(&act_hypervisor_mutex);
  232. if(ret != EBUSY)
  233. {
  234. _resize_if_speed_diff(sched_ctx, worker);
  235. STARPU_PTHREAD_MUTEX_UNLOCK(&act_hypervisor_mutex);
  236. }
  237. }
  238. }
  239. static void feft_lp_size_ctxs(unsigned *sched_ctxs, int nsched_ctxs, int *workers, int nworkers)
  240. {
  241. STARPU_PTHREAD_MUTEX_LOCK(&act_hypervisor_mutex);
  242. struct sc_hypervisor_wrapper* sc_w = NULL;
  243. int s = 0;
  244. for(s = 0; s < nsched_ctxs; s++)
  245. {
  246. sc_w = sc_hypervisor_get_wrapper(sched_ctxs[s]);
  247. sc_w->to_be_sized = 1;
  248. }
  249. _resize(sched_ctxs, nsched_ctxs, workers, nworkers);
  250. #ifdef STARPU_SC_HYPERVISOR_DEBUG
  251. printf("finished size ctxs\n");
  252. #endif
  253. STARPU_PTHREAD_MUTEX_UNLOCK(&act_hypervisor_mutex);
  254. }
  255. static void _resize_leaves(int worker)
  256. {
  257. unsigned s;
  258. unsigned *sched_ctxs = NULL;
  259. unsigned nsched_ctxs = starpu_worker_get_sched_ctx_list(worker, &sched_ctxs);
  260. unsigned workers_sched_ctxs[nsched_ctxs];
  261. unsigned nworkers_sched_ctxs = 0;
  262. struct sc_hypervisor_wrapper *sc_w = NULL;
  263. for(s = 0; s < nsched_ctxs; s++)
  264. {
  265. sc_w = sc_hypervisor_get_wrapper(sched_ctxs[s]);
  266. if(sc_w->sched_ctx != STARPU_NMAX_SCHED_CTXS)
  267. {
  268. workers_sched_ctxs[nworkers_sched_ctxs++] = sched_ctxs[s];
  269. }
  270. }
  271. free(sched_ctxs);
  272. unsigned leaves[nsched_ctxs];
  273. unsigned nleaves = 0;
  274. sc_hypervisor_get_leaves(workers_sched_ctxs, nworkers_sched_ctxs, leaves, &nleaves);
  275. for(s = 0; s < nleaves; s++)
  276. _resize_if_speed_diff(leaves[s], worker);
  277. }
  278. static void feft_lp_handle_idle_cycle(unsigned sched_ctx, int worker)
  279. {
  280. unsigned criteria = sc_hypervisor_get_resize_criteria();
  281. if(criteria != SC_NOTHING)// && criteria == SC_IDLE)
  282. {
  283. int ret = starpu_pthread_mutex_trylock(&act_hypervisor_mutex);
  284. if(ret != EBUSY)
  285. {
  286. _resize_leaves(worker);
  287. STARPU_PTHREAD_MUTEX_UNLOCK(&act_hypervisor_mutex);
  288. }
  289. }
  290. }
  291. static void feft_lp_resize_ctxs(unsigned *sched_ctxs, int nsched_ctxs ,
  292. int *workers, int nworkers)
  293. {
  294. int ret = starpu_pthread_mutex_trylock(&act_hypervisor_mutex);
  295. if(ret != EBUSY)
  296. {
  297. struct sc_hypervisor_wrapper* sc_w = NULL;
  298. int s = 0;
  299. for(s = 0; s < nsched_ctxs; s++)
  300. {
  301. sc_w = sc_hypervisor_get_wrapper(sched_ctxs[s]);
  302. if((sc_w->submitted_flops + (0.1*sc_w->total_flops)) < sc_w->total_flops)
  303. {
  304. STARPU_PTHREAD_MUTEX_UNLOCK(&act_hypervisor_mutex);
  305. return;
  306. }
  307. }
  308. _resize(sched_ctxs, nsched_ctxs, workers, nworkers);
  309. STARPU_PTHREAD_MUTEX_UNLOCK(&act_hypervisor_mutex);
  310. }
  311. }
  312. struct sc_hypervisor_policy feft_lp_policy = {
  313. .size_ctxs = feft_lp_size_ctxs,
  314. .resize_ctxs = feft_lp_resize_ctxs,
  315. .handle_poped_task = feft_lp_handle_poped_task,
  316. .handle_pushed_task = NULL,
  317. .handle_idle_cycle = feft_lp_handle_idle_cycle,
  318. .handle_idle_end = NULL,
  319. .handle_post_exec_hook = NULL,
  320. .handle_submitted_job = NULL,
  321. .end_ctx = NULL,
  322. .init_worker = NULL,
  323. .custom = 0,
  324. .name = "feft_lp"
  325. };
  326. #endif /* STARPU_HAVE_GLPK_H */