debit_lp_policy.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2011, 2013 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 <starpu_config.h>
  17. #include "sc_hypervisor_lp.h"
  18. #include "sc_hypervisor_policy.h"
  19. #include <math.h>
  20. #include <sys/time.h>
  21. static double _glp_resolve(int ns, int nw, double velocity[ns][nw], double w_in_s[ns][nw], int *workers, unsigned integer);
  22. static unsigned _compute_max_velocity(int ns, int nw, double w_in_s[ns][nw], int *in_sched_ctxs, int *workers)
  23. {
  24. double velocity[ns][nw];
  25. int *sched_ctxs = in_sched_ctxs == NULL ? sc_hypervisor_get_sched_ctxs() : in_sched_ctxs;
  26. int w,s;
  27. struct sc_hypervisor_wrapper* sc_w = NULL;
  28. for(s = 0; s < ns; s++)
  29. {
  30. sc_w = sc_hypervisor_get_wrapper(sched_ctxs[s]);
  31. for(w = 0; w < nw; w++)
  32. {
  33. w_in_s[s][w] = 0.0;
  34. int worker = workers == NULL ? w : workers[w];
  35. enum starpu_worker_archtype arch = starpu_worker_get_type(worker);
  36. velocity[s][w] = sc_hypervisor_get_velocity(sc_w, arch);
  37. }
  38. }
  39. struct timeval start_time;
  40. struct timeval end_time;
  41. gettimeofday(&start_time, NULL);
  42. double res = _glp_resolve(ns, nw, velocity, w_in_s, workers, 1);
  43. gettimeofday(&end_time, NULL);
  44. long diff_s = end_time.tv_sec - start_time.tv_sec;
  45. long diff_us = end_time.tv_usec - start_time.tv_usec;
  46. float timing = (float)(diff_s*1000000 + diff_us)/1000;
  47. if(res > 0.0)
  48. return 1;
  49. return 0;
  50. }
  51. /*
  52. * GNU Linear Programming Kit backend
  53. */
  54. #ifdef STARPU_HAVE_GLPK_H
  55. #include <glpk.h>
  56. static double _glp_resolve(int ns, int nw, double velocity[ns][nw], double w_in_s[ns][nw], int *workers, unsigned integer)
  57. {
  58. int w, s;
  59. glp_prob *lp;
  60. lp = glp_create_prob();
  61. glp_set_prob_name(lp, "StarPU theoretical bound");
  62. glp_set_obj_dir(lp, GLP_MAX);
  63. glp_set_obj_name(lp, "total velocity");
  64. {
  65. int ne = 2 * ns * nw /* worker execution time */
  66. + 1
  67. + 1 ; /* glp dumbness */
  68. int n = 1;
  69. int ia[ne], ja[ne];
  70. double ar[ne];
  71. /* Variables: x[s][w]
  72. the acknwoledgment that the worker w belongs to the context s */
  73. glp_add_cols(lp, nw*ns + 1);
  74. for(s = 0; s < ns; s++)
  75. for(w = 0; w < nw; w++)
  76. {
  77. char name[32];
  78. snprintf(name, sizeof(name), "w%ds%dn", w, s);
  79. glp_set_col_name(lp, s*nw+w+1, name);
  80. if (integer)
  81. {
  82. glp_set_col_kind(lp, s*nw+w+1, GLP_IV);
  83. glp_set_col_bnds(lp, s*nw+w+1, GLP_DB, 0, 1);
  84. }
  85. else
  86. glp_set_col_bnds(lp, s*nw+w+1, GLP_DB, 0.0, 1.0);
  87. }
  88. /* vmax should be positif */
  89. /* Z = vmax structural variable, x[s][w] are auxiliar variables */
  90. glp_set_col_name(lp, nw*ns+1, "vmax");
  91. glp_set_col_bnds(lp, nw*ns+1, GLP_LO, 0.0, 0.0);
  92. glp_set_obj_coef(lp, nw*ns+1, 1.);
  93. int curr_row_idx = 0;
  94. /* Total worker velocity */
  95. glp_add_rows(lp, 1);
  96. /*sum(x[s][w]*velocity[s][w]) >= vmax */
  97. char name[32], title[64];
  98. starpu_worker_get_name(w, name, sizeof(name));
  99. snprintf(title, sizeof(title), "worker %s", name);
  100. glp_set_row_name(lp, curr_row_idx + 1, title);
  101. for(s = 0; s < ns; s++)
  102. {
  103. for (w = 0; w < nw; w++)
  104. {
  105. /* x[s][w] */
  106. ia[n] = curr_row_idx + 1;
  107. ja[n] = s*nw+w+1;
  108. ar[n] = velocity[s][w];
  109. n++;
  110. }
  111. }
  112. /* vmax */
  113. ia[n] = curr_row_idx + 1;
  114. ja[n] = nw*ns+1;
  115. ar[n] = (-1);
  116. n++;
  117. glp_set_row_bnds(lp, curr_row_idx + 1, GLP_LO, 0.0, 0.0);
  118. curr_row_idx += 1 ;
  119. /* sum(x[s][w]) = 1 */
  120. glp_add_rows(lp, nw);
  121. for (w = 0; w < nw; w++)
  122. {
  123. char name[32], title[64];
  124. starpu_worker_get_name(w, name, sizeof(name));
  125. snprintf(title, sizeof(title), "w%x", w);
  126. glp_set_row_name(lp, curr_row_idx+w+1, title);
  127. for(s = 0; s < ns; s++)
  128. {
  129. ia[n] = curr_row_idx+w+1;
  130. ja[n] = s*nw+w+1;
  131. ar[n] = 1;
  132. n++;
  133. }
  134. if(integer)
  135. glp_set_row_bnds(lp, curr_row_idx+w+1, GLP_FX, 1, 1);
  136. else
  137. glp_set_row_bnds(lp, curr_row_idx+w+1, GLP_FX, 1.0, 1.0);
  138. }
  139. if(n != ne)
  140. printf("ns= %d nw = %d n = %d ne = %d\n", ns, nw, n, ne);
  141. STARPU_ASSERT(n == ne);
  142. glp_load_matrix(lp, ne-1, ia, ja, ar);
  143. }
  144. glp_smcp parm;
  145. glp_init_smcp(&parm);
  146. parm.msg_lev = GLP_MSG_OFF;
  147. int ret = glp_simplex(lp, &parm);
  148. if (ret)
  149. {
  150. glp_delete_prob(lp);
  151. lp = NULL;
  152. return 0.0;
  153. }
  154. if (integer)
  155. {
  156. glp_iocp iocp;
  157. glp_init_iocp(&iocp);
  158. iocp.msg_lev = GLP_MSG_OFF;
  159. glp_intopt(lp, &iocp);
  160. int stat = glp_mip_status(lp);
  161. /* if we don't have a solution return */
  162. if(stat == GLP_NOFEAS)
  163. {
  164. glp_delete_prob(lp);
  165. lp = NULL;
  166. return 0.0;
  167. }
  168. }
  169. int stat = glp_get_prim_stat(lp);
  170. /* if we don't have a solution return */
  171. if(stat == GLP_NOFEAS)
  172. {
  173. glp_delete_prob(lp);
  174. lp = NULL;
  175. printf("No sol!!!\n");
  176. return 0.0;
  177. }
  178. double res = glp_get_obj_val(lp);
  179. for(s = 0; s < ns; s++)
  180. for(w = 0; w < nw; w++)
  181. {
  182. if (integer)
  183. w_in_s[s][w] = (double)glp_mip_col_val(lp, s*nw+w+1);
  184. else
  185. w_in_s[s][w] = glp_get_col_prim(lp, s*nw+w+1);
  186. }
  187. glp_delete_prob(lp);
  188. return res;
  189. }
  190. static void _try_resizing(void)
  191. {
  192. int ns = sc_hypervisor_get_nsched_ctxs();
  193. int nw = starpu_worker_get_count(); /* Number of different workers */
  194. double w_in_s[ns][nw];
  195. unsigned found_sol = _compute_max_velocity(ns, nw, w_in_s, NULL, NULL);
  196. /* if we did find at least one solution redistribute the resources */
  197. if(found_sol)
  198. {
  199. int w, s;
  200. double nworkers[ns][2];
  201. int nworkers_rounded[ns][2];
  202. for(s = 0; s < ns; s++)
  203. {
  204. nworkers[s][0] = 0.0;
  205. nworkers[s][1] = 0.0;
  206. nworkers_rounded[s][0] = 0;
  207. nworkers_rounded[s][1] = 0;
  208. }
  209. for(s = 0; s < ns; s++)
  210. {
  211. for(w = 0; w < nw; w++)
  212. {
  213. enum starpu_worker_archtype arch = starpu_worker_get_type(w);
  214. if(arch == STARPU_CUDA_WORKER)
  215. {
  216. nworkers[s][0] += w_in_s[s][w];
  217. if(w_in_s[s][w] >= 0.3)
  218. nworkers_rounded[s][0]++;
  219. }
  220. else
  221. {
  222. nworkers[s][1] += w_in_s[s][w];
  223. if(w_in_s[s][w] > 0.5)
  224. nworkers_rounded[s][1]++;
  225. }
  226. }
  227. }
  228. /* for(s = 0; s < ns; s++) */
  229. /* printf("%d: cpus = %lf gpus = %lf cpus_round = %d gpus_round = %d\n", s, nworkers[s][1], nworkers[s][0], */
  230. /* nworkers_rounded[s][1], nworkers_rounded[s][0]); */
  231. sc_hypervisor_lp_redistribute_resources_in_ctxs(ns, 2, nworkers_rounded, nworkers);
  232. }
  233. }
  234. static void debit_lp_handle_poped_task(unsigned sched_ctx, int worker, struct starpu_task *task, uint32_t footprint)
  235. {
  236. int ret = starpu_pthread_mutex_trylock(&act_hypervisor_mutex);
  237. if(ret != EBUSY)
  238. {
  239. unsigned criteria = sc_hypervisor_get_resize_criteria();
  240. if(criteria != SC_NOTHING && criteria == SC_VELOCITY)
  241. {
  242. if(sc_hypervisor_check_velocity_gap_btw_ctxs())
  243. {
  244. _try_resizing();
  245. }
  246. }
  247. starpu_pthread_mutex_unlock(&act_hypervisor_mutex);
  248. }
  249. }
  250. static debit_lp_handle_idle_cycle(unsigned sched_ctx, int worker)
  251. {
  252. int ret = starpu_pthread_mutex_trylock(&act_hypervisor_mutex);
  253. if(ret != EBUSY)
  254. {
  255. unsigned criteria = sc_hypervisor_get_resize_criteria();
  256. if(criteria != SC_NOTHING && criteria == SC_IDLE)
  257. {
  258. if(sc_hypervisor_check_idle(sched_ctx, worker))
  259. {
  260. _try_resizing();
  261. // sc_hypervisor_move_workers(sched_ctx, 3 - sched_ctx, &worker, 1, 1); \
  262. }
  263. }
  264. starpu_pthread_mutex_unlock(&act_hypervisor_mutex);
  265. }
  266. }
  267. static void debit_lp_end_ctx(unsigned sched_ctx)
  268. {
  269. struct sc_hypervisor_wrapper* sc_w = sc_hypervisor_get_wrapper(sched_ctx);
  270. int worker;
  271. /* for(worker = 0; worker < 12; worker++) */
  272. /* printf("%d/%d: speed %lf\n", worker, sched_ctx, sc_w->ref_velocity[worker]); */
  273. return;
  274. }
  275. struct sc_hypervisor_policy debit_lp_policy = {
  276. .size_ctxs = NULL,
  277. .handle_poped_task = debit_lp_handle_poped_task,
  278. .handle_pushed_task = NULL,
  279. .handle_idle_cycle = debit_lp_handle_idle_cycle,
  280. .handle_idle_end = NULL,
  281. .handle_post_exec_hook = NULL,
  282. .handle_submitted_job = NULL,
  283. .end_ctx = debit_lp_end_ctx,
  284. .custom = 0,
  285. .name = "debit_lp"
  286. };
  287. #endif /* STARPU_HAVE_GLPK_H */