sc_hypervisor.c 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2011, 2012 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_intern.h>
  17. #include <sc_hypervisor_policy.h>
  18. #include <common/uthash.h>
  19. #include <starpu_config.h>
  20. unsigned imposed_resize = 0;
  21. unsigned type_of_tasks_known = 0;
  22. struct starpu_sched_ctx_performance_counters* perf_counters = NULL;
  23. static void notify_idle_cycle(unsigned sched_ctx, int worker, double idle_time);
  24. static void notify_pushed_task(unsigned sched_ctx, int worker);
  25. static void notify_poped_task(unsigned sched_ctx, int worker, struct starpu_task *task, size_t data_size, uint32_t footprint);
  26. static void notify_post_exec_hook(unsigned sched_ctx, int taskid);
  27. static void notify_idle_end(unsigned sched_ctx, int worker);
  28. static void notify_submitted_job(struct starpu_task *task, unsigned footprint, size_t data_size);
  29. static void notify_delete_context(unsigned sched_ctx);
  30. extern struct sc_hypervisor_policy idle_policy;
  31. extern struct sc_hypervisor_policy app_driven_policy;
  32. extern struct sc_hypervisor_policy gflops_rate_policy;
  33. #ifdef STARPU_HAVE_GLPK_H
  34. extern struct sc_hypervisor_policy feft_lp_policy;
  35. extern struct sc_hypervisor_policy teft_lp_policy;
  36. extern struct sc_hypervisor_policy ispeed_lp_policy;
  37. extern struct sc_hypervisor_policy debit_lp_policy;
  38. #endif // STARPU_HAVE_GLPK_
  39. extern struct sc_hypervisor_policy ispeed_policy;
  40. static struct sc_hypervisor_policy *predefined_policies[] =
  41. {
  42. &idle_policy,
  43. &app_driven_policy,
  44. #ifdef STARPU_HAVE_GLPK_H
  45. &feft_lp_policy,
  46. &teft_lp_policy,
  47. &ispeed_lp_policy,
  48. &debit_lp_policy,
  49. #endif // STARPU_HAVE_GLPK_H
  50. &gflops_rate_policy,
  51. &ispeed_policy
  52. };
  53. static void _load_hypervisor_policy(struct sc_hypervisor_policy *policy)
  54. {
  55. STARPU_ASSERT(policy);
  56. hypervisor.policy.name = policy->name;
  57. hypervisor.policy.size_ctxs = policy->size_ctxs;
  58. hypervisor.policy.resize_ctxs = policy->resize_ctxs;
  59. hypervisor.policy.handle_poped_task = policy->handle_poped_task;
  60. hypervisor.policy.handle_pushed_task = policy->handle_pushed_task;
  61. hypervisor.policy.handle_idle_cycle = policy->handle_idle_cycle;
  62. hypervisor.policy.handle_idle_end = policy->handle_idle_end;
  63. hypervisor.policy.handle_post_exec_hook = policy->handle_post_exec_hook;
  64. hypervisor.policy.handle_submitted_job = policy->handle_submitted_job;
  65. hypervisor.policy.end_ctx = policy->end_ctx;
  66. }
  67. static struct sc_hypervisor_policy *_find_hypervisor_policy_from_name(const char *policy_name)
  68. {
  69. if (!policy_name)
  70. return NULL;
  71. unsigned i;
  72. for (i = 0; i < sizeof(predefined_policies)/sizeof(predefined_policies[0]); i++)
  73. {
  74. struct sc_hypervisor_policy *p;
  75. p = predefined_policies[i];
  76. if (p->name)
  77. {
  78. if (strcmp(policy_name, p->name) == 0) {
  79. /* we found a policy with the requested name */
  80. return p;
  81. }
  82. }
  83. }
  84. fprintf(stderr, "Warning: hypervisor policy \"%s\" was not found, try \"help\" to get a list\n", policy_name);
  85. /* nothing was found */
  86. return NULL;
  87. }
  88. static struct sc_hypervisor_policy *_select_hypervisor_policy(struct sc_hypervisor_policy* hypervisor_policy)
  89. {
  90. struct sc_hypervisor_policy *selected_policy = NULL;
  91. if(hypervisor_policy && hypervisor_policy->custom)
  92. return hypervisor_policy;
  93. /* we look if the application specified the name of a policy to load */
  94. const char *policy_name;
  95. if (hypervisor_policy && hypervisor_policy->name)
  96. {
  97. policy_name = hypervisor_policy->name;
  98. }
  99. else
  100. {
  101. policy_name = getenv("SC_HYPERVISOR_POLICY");
  102. }
  103. if (policy_name)
  104. selected_policy = _find_hypervisor_policy_from_name(policy_name);
  105. /* Perhaps there was no policy that matched the name */
  106. if (selected_policy)
  107. return selected_policy;
  108. /* If no policy was specified, we use the idle policy as a default */
  109. return &idle_policy;
  110. }
  111. /* initializez the performance counters that starpu will use to retrive hints for resizing */
  112. struct starpu_sched_ctx_performance_counters* sc_hypervisor_init(struct sc_hypervisor_policy *hypervisor_policy)
  113. {
  114. hypervisor.min_tasks = 0;
  115. hypervisor.nsched_ctxs = 0;
  116. char* vel_gap = getenv("SC_HYPERVISOR_MAX_SPEED_GAP");
  117. hypervisor.max_speed_gap = vel_gap ? atof(vel_gap) : SC_SPEED_MAX_GAP_DEFAULT;
  118. char* crit = getenv("SC_HYPERVISOR_TRIGGER_RESIZE");
  119. hypervisor.resize_criteria = !crit ? SC_IDLE : strcmp(crit,"idle") == 0 ? SC_IDLE : (strcmp(crit,"speed") == 0 ? SC_SPEED : SC_NOTHING);
  120. starpu_pthread_mutex_init(&act_hypervisor_mutex, NULL);
  121. hypervisor.start_executing_time = starpu_timing_now();
  122. int i;
  123. for(i = 0; i < STARPU_NMAX_SCHED_CTXS; i++)
  124. {
  125. hypervisor.resize[i] = 0;
  126. hypervisor.allow_remove[i] = 1;
  127. hypervisor.configurations[i] = NULL;
  128. hypervisor.sr = NULL;
  129. hypervisor.check_min_tasks[i] = 1;
  130. hypervisor.sched_ctxs[i] = STARPU_NMAX_SCHED_CTXS;
  131. hypervisor.sched_ctx_w[i].sched_ctx = STARPU_NMAX_SCHED_CTXS;
  132. hypervisor.sched_ctx_w[i].config = NULL;
  133. hypervisor.sched_ctx_w[i].total_flops = 0.0;
  134. hypervisor.sched_ctx_w[i].submitted_flops = 0.0;
  135. hypervisor.sched_ctx_w[i].remaining_flops = 0.0;
  136. hypervisor.sched_ctx_w[i].start_time = 0.0;
  137. hypervisor.sched_ctx_w[i].real_start_time = 0.0;
  138. hypervisor.sched_ctx_w[i].resize_ack.receiver_sched_ctx = -1;
  139. hypervisor.sched_ctx_w[i].resize_ack.moved_workers = NULL;
  140. hypervisor.sched_ctx_w[i].resize_ack.nmoved_workers = 0;
  141. hypervisor.sched_ctx_w[i].resize_ack.acked_workers = NULL;
  142. starpu_pthread_mutex_init(&hypervisor.sched_ctx_w[i].mutex, NULL);
  143. hypervisor.optimal_v[i] = 0.0;
  144. hypervisor.sched_ctx_w[i].ref_speed[0] = -1.0;
  145. hypervisor.sched_ctx_w[i].ref_speed[1] = -1.0;
  146. int j;
  147. for(j = 0; j < STARPU_NMAXWORKERS; j++)
  148. {
  149. hypervisor.sched_ctx_w[i].current_idle_time[j] = 0.0;
  150. hypervisor.sched_ctx_w[i].idle_time[j] = 0.0;
  151. hypervisor.sched_ctx_w[i].idle_start_time[j] = 0.0;
  152. hypervisor.sched_ctx_w[i].pushed_tasks[j] = 0;
  153. hypervisor.sched_ctx_w[i].poped_tasks[j] = 0;
  154. hypervisor.sched_ctx_w[i].elapsed_flops[j] = 0.0;
  155. hypervisor.sched_ctx_w[i].elapsed_data[j] = 0;
  156. hypervisor.sched_ctx_w[i].elapsed_tasks[j] = 0;
  157. hypervisor.sched_ctx_w[i].total_elapsed_flops[j] = 0.0;
  158. hypervisor.sched_ctx_w[i].worker_to_be_removed[j] = 0;
  159. }
  160. }
  161. struct sc_hypervisor_policy *selected_hypervisor_policy = _select_hypervisor_policy(hypervisor_policy);
  162. _load_hypervisor_policy(selected_hypervisor_policy);
  163. perf_counters = (struct starpu_sched_ctx_performance_counters*)malloc(sizeof(struct starpu_sched_ctx_performance_counters));
  164. perf_counters->notify_idle_cycle = notify_idle_cycle;
  165. perf_counters->notify_pushed_task = notify_pushed_task;
  166. perf_counters->notify_poped_task = notify_poped_task;
  167. perf_counters->notify_post_exec_hook = notify_post_exec_hook;
  168. perf_counters->notify_idle_end = notify_idle_end;
  169. perf_counters->notify_submitted_job = notify_submitted_job;
  170. perf_counters->notify_delete_context = notify_delete_context;
  171. starpu_sched_ctx_notify_hypervisor_exists();
  172. return perf_counters;
  173. }
  174. const char* sc_hypervisor_get_policy()
  175. {
  176. return hypervisor.policy.name;
  177. }
  178. /* the user can forbid the resizing process*/
  179. void sc_hypervisor_stop_resize(unsigned sched_ctx)
  180. {
  181. imposed_resize = 1;
  182. hypervisor.resize[sched_ctx] = 0;
  183. }
  184. /* the user can restart the resizing process*/
  185. void sc_hypervisor_start_resize(unsigned sched_ctx)
  186. {
  187. imposed_resize = 1;
  188. hypervisor.resize[sched_ctx] = 1;
  189. }
  190. static void _print_current_time()
  191. {
  192. if(!getenv("SC_HYPERVISOR_STOP_PRINT"))
  193. {
  194. double curr_time = starpu_timing_now();
  195. double elapsed_time = (curr_time - hypervisor.start_executing_time) / 1000000.0; /* in seconds */
  196. fprintf(stdout, "Time: %lf\n", elapsed_time);
  197. int i;
  198. for(i = 0; i < STARPU_NMAX_SCHED_CTXS; i++)
  199. {
  200. if(hypervisor.sched_ctxs[i] != STARPU_NMAX_SCHED_CTXS)
  201. {
  202. struct sc_hypervisor_wrapper *sc_w = &hypervisor.sched_ctx_w[hypervisor.sched_ctxs[i]];
  203. double cpu_speed = sc_hypervisor_get_speed(sc_w, STARPU_CPU_WORKER);
  204. double cuda_speed = sc_hypervisor_get_speed(sc_w, STARPU_CUDA_WORKER);
  205. int ncpus = sc_hypervisor_get_nworkers_ctx(sc_w->sched_ctx, STARPU_CPU_WORKER);
  206. int ncuda = sc_hypervisor_get_nworkers_ctx(sc_w->sched_ctx, STARPU_CUDA_WORKER);
  207. fprintf(stdout, "%d: cpu_v = %lf cuda_v = %lf ncpus = %d ncuda = %d\n", hypervisor.sched_ctxs[i], cpu_speed, cuda_speed, ncpus, ncuda);
  208. }
  209. }
  210. }
  211. return;
  212. }
  213. void sc_hypervisor_shutdown(void)
  214. {
  215. int i;
  216. for(i = 0; i < STARPU_NMAX_SCHED_CTXS; i++)
  217. {
  218. if(hypervisor.sched_ctxs[i] != STARPU_NMAX_SCHED_CTXS && hypervisor.nsched_ctxs > 0)
  219. {
  220. sc_hypervisor_stop_resize(hypervisor.sched_ctxs[i]);
  221. sc_hypervisor_unregister_ctx(hypervisor.sched_ctxs[i]);
  222. starpu_pthread_mutex_destroy(&hypervisor.sched_ctx_w[i].mutex);
  223. }
  224. }
  225. perf_counters->notify_idle_cycle = NULL;
  226. perf_counters->notify_pushed_task = NULL;
  227. perf_counters->notify_poped_task = NULL;
  228. perf_counters->notify_post_exec_hook = NULL;
  229. perf_counters->notify_idle_end = NULL;
  230. perf_counters->notify_delete_context = NULL;
  231. free(perf_counters);
  232. perf_counters = NULL;
  233. starpu_pthread_mutex_destroy(&act_hypervisor_mutex);
  234. }
  235. /* the hypervisor is in charge only of the contexts registered to it*/
  236. void sc_hypervisor_register_ctx(unsigned sched_ctx, double total_flops)
  237. {
  238. starpu_pthread_mutex_lock(&act_hypervisor_mutex);
  239. hypervisor.configurations[sched_ctx] = NULL;
  240. hypervisor.resize_requests[sched_ctx] = NULL;
  241. starpu_pthread_mutex_init(&hypervisor.conf_mut[sched_ctx], NULL);
  242. starpu_pthread_mutex_init(&hypervisor.resize_mut[sched_ctx], NULL);
  243. _add_config(sched_ctx);
  244. hypervisor.sched_ctx_w[sched_ctx].sched_ctx = sched_ctx;
  245. hypervisor.sched_ctxs[hypervisor.nsched_ctxs++] = sched_ctx;
  246. hypervisor.sched_ctx_w[sched_ctx].total_flops = total_flops;
  247. hypervisor.sched_ctx_w[sched_ctx].remaining_flops = total_flops;
  248. if(strcmp(hypervisor.policy.name, "app_driven") == 0)
  249. hypervisor.resize[sched_ctx] = 1;
  250. starpu_pthread_mutex_unlock(&act_hypervisor_mutex);
  251. }
  252. static int _get_first_free_sched_ctx(unsigned *sched_ctxs, int nsched_ctxs)
  253. {
  254. int i;
  255. for(i = 0; i < nsched_ctxs; i++)
  256. if(sched_ctxs[i] == STARPU_NMAX_SCHED_CTXS)
  257. return i;
  258. return STARPU_NMAX_SCHED_CTXS;
  259. }
  260. /* rearange array of sched_ctxs in order not to have {MAXVAL, MAXVAL, 5, MAXVAL, 7}
  261. and have instead {5, 7, MAXVAL, MAXVAL, MAXVAL}
  262. it is easier afterwards to iterate the array
  263. */
  264. static void _rearange_sched_ctxs(unsigned *sched_ctxs, int old_nsched_ctxs)
  265. {
  266. int first_free_id = STARPU_NMAX_SCHED_CTXS;
  267. int i;
  268. for(i = 0; i < old_nsched_ctxs; i++)
  269. {
  270. if(sched_ctxs[i] != STARPU_NMAX_SCHED_CTXS)
  271. {
  272. first_free_id = _get_first_free_sched_ctx(sched_ctxs, old_nsched_ctxs);
  273. if(first_free_id != STARPU_NMAX_SCHED_CTXS)
  274. {
  275. sched_ctxs[first_free_id] = sched_ctxs[i];
  276. sched_ctxs[i] = STARPU_NMAX_SCHED_CTXS;
  277. }
  278. }
  279. }
  280. }
  281. /* unregistered contexts will no longer be resized */
  282. void sc_hypervisor_unregister_ctx(unsigned sched_ctx)
  283. {
  284. if(hypervisor.policy.end_ctx)
  285. hypervisor.policy.end_ctx(sched_ctx);
  286. starpu_pthread_mutex_lock(&act_hypervisor_mutex);
  287. unsigned i;
  288. for(i = 0; i < hypervisor.nsched_ctxs; i++)
  289. {
  290. if(hypervisor.sched_ctxs[i] == sched_ctx)
  291. {
  292. hypervisor.sched_ctxs[i] = STARPU_NMAX_SCHED_CTXS;
  293. break;
  294. }
  295. }
  296. _rearange_sched_ctxs(hypervisor.sched_ctxs, hypervisor.nsched_ctxs);
  297. hypervisor.nsched_ctxs--;
  298. hypervisor.sched_ctx_w[sched_ctx].sched_ctx = STARPU_NMAX_SCHED_CTXS;
  299. _remove_config(sched_ctx);
  300. starpu_pthread_mutex_destroy(&hypervisor.conf_mut[sched_ctx]);
  301. starpu_pthread_mutex_destroy(&hypervisor.resize_mut[sched_ctx]);
  302. if(hypervisor.nsched_ctxs == 1)
  303. sc_hypervisor_stop_resize(hypervisor.sched_ctxs[0]);
  304. starpu_pthread_mutex_unlock(&act_hypervisor_mutex);
  305. }
  306. double _get_max_speed_gap()
  307. {
  308. return hypervisor.max_speed_gap;
  309. }
  310. unsigned sc_hypervisor_get_resize_criteria()
  311. {
  312. return hypervisor.resize_criteria;
  313. }
  314. static int get_ntasks( int *tasks)
  315. {
  316. int ntasks = 0;
  317. int j;
  318. for(j = 0; j < STARPU_NMAXWORKERS; j++)
  319. {
  320. ntasks += tasks[j];
  321. }
  322. return ntasks;
  323. }
  324. int sc_hypervisor_get_nworkers_ctx(unsigned sched_ctx, enum starpu_worker_archtype arch)
  325. {
  326. int nworkers_ctx = 0;
  327. struct starpu_worker_collection *workers = starpu_sched_ctx_get_worker_collection(sched_ctx);
  328. int worker;
  329. struct starpu_sched_ctx_iterator it;
  330. if(workers->init_iterator)
  331. workers->init_iterator(workers, &it);
  332. while(workers->has_next(workers, &it))
  333. {
  334. worker = workers->get_next(workers, &it);
  335. enum starpu_worker_archtype curr_arch = starpu_worker_get_type(worker);
  336. if(curr_arch == arch || arch == STARPU_ANY_WORKER)
  337. nworkers_ctx++;
  338. }
  339. return nworkers_ctx;
  340. }
  341. static void _set_elapsed_flops_per_sched_ctx(unsigned sched_ctx, double val)
  342. {
  343. int i;
  344. for(i = 0; i < STARPU_NMAXWORKERS; i++)
  345. {
  346. hypervisor.sched_ctx_w[sched_ctx].elapsed_flops[i] = val;
  347. if(val == 0)
  348. {
  349. hypervisor.sched_ctx_w[sched_ctx].elapsed_data[i] = 0;
  350. hypervisor.sched_ctx_w[sched_ctx].elapsed_tasks[i] = 0;
  351. }
  352. }
  353. }
  354. double sc_hypervisor_get_elapsed_flops_per_sched_ctx(struct sc_hypervisor_wrapper* sc_w)
  355. {
  356. double ret_val = 0.0;
  357. int i;
  358. for(i = 0; i < STARPU_NMAXWORKERS; i++)
  359. ret_val += sc_w->elapsed_flops[i];
  360. return ret_val;
  361. }
  362. double sc_hypervisor_get_total_elapsed_flops_per_sched_ctx(struct sc_hypervisor_wrapper* sc_w)
  363. {
  364. double ret_val = 0.0;
  365. int i;
  366. for(i = 0; i < STARPU_NMAXWORKERS; i++)
  367. ret_val += sc_w->total_elapsed_flops[i];
  368. return ret_val;
  369. }
  370. static void _reset_idle_time(unsigned sched_ctx)
  371. {
  372. int i;
  373. for(i = 0; i < STARPU_NMAXWORKERS; i++)
  374. {
  375. hypervisor.sched_ctx_w[sched_ctx].idle_time[i] = 0.0;
  376. }
  377. return;
  378. }
  379. void _reset_resize_sample_info(unsigned sender_sched_ctx, unsigned receiver_sched_ctx)
  380. {
  381. /* info concerning only the gflops_rate strateg */
  382. struct sc_hypervisor_wrapper *sender_sc_w = &hypervisor.sched_ctx_w[sender_sched_ctx];
  383. struct sc_hypervisor_wrapper *receiver_sc_w = &hypervisor.sched_ctx_w[receiver_sched_ctx];
  384. double start_time = starpu_timing_now();
  385. sender_sc_w->start_time = start_time;
  386. _set_elapsed_flops_per_sched_ctx(sender_sched_ctx, 0.0);
  387. _reset_idle_time(sender_sched_ctx);
  388. receiver_sc_w->start_time = start_time;
  389. _set_elapsed_flops_per_sched_ctx(receiver_sched_ctx, 0.0);
  390. _reset_idle_time(receiver_sched_ctx);
  391. }
  392. /* actually move the workers: the cpus are moved, gpus are only shared */
  393. /* forbids another resize request before this one is take into account */
  394. void sc_hypervisor_move_workers(unsigned sender_sched_ctx, unsigned receiver_sched_ctx, int* workers_to_move, unsigned nworkers_to_move, unsigned now)
  395. {
  396. if(nworkers_to_move > 0 && hypervisor.resize[sender_sched_ctx])
  397. {
  398. _print_current_time();
  399. unsigned j;
  400. printf("resize ctx %d with %d workers", sender_sched_ctx, nworkers_to_move);
  401. for(j = 0; j < nworkers_to_move; j++)
  402. printf(" %d", workers_to_move[j]);
  403. printf("\n");
  404. starpu_trace_user_event(1);
  405. hypervisor.allow_remove[receiver_sched_ctx] = 0;
  406. starpu_sched_ctx_add_workers(workers_to_move, nworkers_to_move, receiver_sched_ctx);
  407. if(now)
  408. {
  409. unsigned j;
  410. printf("remove now from ctx %d:", sender_sched_ctx);
  411. for(j = 0; j < nworkers_to_move; j++)
  412. printf(" %d", workers_to_move[j]);
  413. printf("\n");
  414. starpu_sched_ctx_remove_workers(workers_to_move, nworkers_to_move, sender_sched_ctx);
  415. hypervisor.allow_remove[receiver_sched_ctx] = 1;
  416. _reset_resize_sample_info(sender_sched_ctx, receiver_sched_ctx);
  417. }
  418. else
  419. {
  420. int ret = starpu_pthread_mutex_trylock(&hypervisor.sched_ctx_w[sender_sched_ctx].mutex);
  421. if(ret != EBUSY)
  422. {
  423. hypervisor.sched_ctx_w[sender_sched_ctx].resize_ack.receiver_sched_ctx = receiver_sched_ctx;
  424. hypervisor.sched_ctx_w[sender_sched_ctx].resize_ack.moved_workers = (int*)malloc(nworkers_to_move * sizeof(int));
  425. hypervisor.sched_ctx_w[sender_sched_ctx].resize_ack.nmoved_workers = nworkers_to_move;
  426. hypervisor.sched_ctx_w[sender_sched_ctx].resize_ack.acked_workers = (int*)malloc(nworkers_to_move * sizeof(int));
  427. unsigned i;
  428. for(i = 0; i < nworkers_to_move; i++)
  429. {
  430. hypervisor.sched_ctx_w[sender_sched_ctx].current_idle_time[workers_to_move[i]] = 0.0;
  431. hypervisor.sched_ctx_w[sender_sched_ctx].resize_ack.moved_workers[i] = workers_to_move[i];
  432. hypervisor.sched_ctx_w[sender_sched_ctx].resize_ack.acked_workers[i] = 0;
  433. }
  434. hypervisor.resize[sender_sched_ctx] = 0;
  435. if(imposed_resize) imposed_resize = 0;
  436. starpu_pthread_mutex_unlock(&hypervisor.sched_ctx_w[sender_sched_ctx].mutex);
  437. }
  438. }
  439. struct sc_hypervisor_policy_config *new_config = sc_hypervisor_get_config(receiver_sched_ctx);
  440. unsigned i;
  441. for(i = 0; i < nworkers_to_move; i++)
  442. new_config->max_idle[workers_to_move[i]] = new_config->max_idle[workers_to_move[i]] !=MAX_IDLE_TIME ? new_config->max_idle[workers_to_move[i]] : new_config->new_workers_max_idle;
  443. }
  444. return;
  445. }
  446. void sc_hypervisor_add_workers_to_sched_ctx(int* workers_to_add, unsigned nworkers_to_add, unsigned sched_ctx)
  447. {
  448. if(nworkers_to_add > 0 && hypervisor.resize[sched_ctx])
  449. {
  450. _print_current_time();
  451. unsigned j;
  452. printf("add to ctx %d:", sched_ctx);
  453. for(j = 0; j < nworkers_to_add; j++)
  454. printf(" %d", workers_to_add[j]);
  455. printf("\n");
  456. starpu_sched_ctx_add_workers(workers_to_add, nworkers_to_add, sched_ctx);
  457. struct sc_hypervisor_policy_config *new_config = sc_hypervisor_get_config(sched_ctx);
  458. unsigned i;
  459. for(i = 0; i < nworkers_to_add; i++)
  460. new_config->max_idle[workers_to_add[i]] = new_config->max_idle[workers_to_add[i]] != MAX_IDLE_TIME ? new_config->max_idle[workers_to_add[i]] : new_config->new_workers_max_idle;
  461. }
  462. return;
  463. }
  464. unsigned sc_hypervisor_can_resize(unsigned sched_ctx)
  465. {
  466. return hypervisor.resize[sched_ctx];
  467. }
  468. void sc_hypervisor_remove_workers_from_sched_ctx(int* workers_to_remove, unsigned nworkers_to_remove, unsigned sched_ctx, unsigned now)
  469. {
  470. if(nworkers_to_remove > 0 && hypervisor.resize[sched_ctx] && hypervisor.allow_remove[sched_ctx])
  471. {
  472. _print_current_time();
  473. unsigned nworkers = 0;
  474. int workers[nworkers_to_remove];
  475. if(now)
  476. {
  477. unsigned j;
  478. printf("remove explicitley now from ctx %d:", sched_ctx);
  479. for(j = 0; j < nworkers_to_remove; j++)
  480. printf(" %d", workers_to_remove[j]);
  481. printf("\n");
  482. starpu_sched_ctx_remove_workers(workers_to_remove, nworkers_to_remove, sched_ctx);
  483. }
  484. else
  485. {
  486. printf("try to remove from ctx %d: ", sched_ctx);
  487. unsigned j;
  488. for(j = 0; j < nworkers_to_remove; j++)
  489. printf(" %d", workers_to_remove[j]);
  490. printf("\n");
  491. int ret = starpu_pthread_mutex_trylock(&hypervisor.sched_ctx_w[sched_ctx].mutex);
  492. if(ret != EBUSY)
  493. {
  494. unsigned i;
  495. for(i = 0; i < nworkers_to_remove; i++)
  496. if(starpu_sched_ctx_contains_worker(workers_to_remove[i], sched_ctx))
  497. workers[nworkers++] = workers_to_remove[i];
  498. hypervisor.sched_ctx_w[sched_ctx].resize_ack.receiver_sched_ctx = -1;
  499. hypervisor.sched_ctx_w[sched_ctx].resize_ack.moved_workers = (int*)malloc(nworkers_to_remove * sizeof(int));
  500. hypervisor.sched_ctx_w[sched_ctx].resize_ack.nmoved_workers = (int)nworkers;
  501. hypervisor.sched_ctx_w[sched_ctx].resize_ack.acked_workers = (int*)malloc(nworkers_to_remove * sizeof(int));
  502. for(i = 0; i < nworkers; i++)
  503. {
  504. hypervisor.sched_ctx_w[sched_ctx].current_idle_time[workers[i]] = 0.0;
  505. hypervisor.sched_ctx_w[sched_ctx].resize_ack.moved_workers[i] = workers[i];
  506. hypervisor.sched_ctx_w[sched_ctx].resize_ack.acked_workers[i] = 0;
  507. }
  508. hypervisor.resize[sched_ctx] = 0;
  509. if(imposed_resize) imposed_resize = 0;
  510. starpu_pthread_mutex_unlock(&hypervisor.sched_ctx_w[sched_ctx].mutex);
  511. }
  512. }
  513. }
  514. return;
  515. }
  516. static unsigned _ack_resize_completed(unsigned sched_ctx, int worker)
  517. {
  518. if(worker != -1 && !starpu_sched_ctx_contains_worker(worker, sched_ctx))
  519. return 0;
  520. struct sc_hypervisor_resize_ack *resize_ack = NULL;
  521. unsigned sender_sched_ctx = STARPU_NMAX_SCHED_CTXS;
  522. int i;
  523. for(i = 0; i < STARPU_NMAX_SCHED_CTXS; i++)
  524. {
  525. if(hypervisor.sched_ctxs[i] != STARPU_NMAX_SCHED_CTXS)
  526. {
  527. struct sc_hypervisor_wrapper *sc_w = &hypervisor.sched_ctx_w[hypervisor.sched_ctxs[i]];
  528. starpu_pthread_mutex_lock(&sc_w->mutex);
  529. unsigned only_remove = 0;
  530. if(sc_w->resize_ack.receiver_sched_ctx == -1 && hypervisor.sched_ctxs[i] != sched_ctx &&
  531. sc_w->resize_ack.nmoved_workers > 0 && starpu_sched_ctx_contains_worker(worker, hypervisor.sched_ctxs[i]))
  532. {
  533. int j;
  534. for(j = 0; j < sc_w->resize_ack.nmoved_workers; j++)
  535. if(sc_w->resize_ack.moved_workers[j] == worker)
  536. {
  537. only_remove = 1;
  538. starpu_pthread_mutex_unlock(&sc_w->mutex);
  539. break;
  540. }
  541. }
  542. if(only_remove ||
  543. (sc_w->resize_ack.receiver_sched_ctx != -1 && sc_w->resize_ack.receiver_sched_ctx == (int)sched_ctx))
  544. {
  545. resize_ack = &sc_w->resize_ack;
  546. sender_sched_ctx = hypervisor.sched_ctxs[i];
  547. starpu_pthread_mutex_unlock(&sc_w->mutex);
  548. break;
  549. }
  550. starpu_pthread_mutex_unlock(&sc_w->mutex);
  551. }
  552. }
  553. /* if there is no ctx waiting for its ack return 1*/
  554. if(resize_ack == NULL)
  555. return 1;
  556. int ret = starpu_pthread_mutex_trylock(&hypervisor.sched_ctx_w[sender_sched_ctx].mutex);
  557. if(ret != EBUSY)
  558. {
  559. int *moved_workers = resize_ack->moved_workers;
  560. int nmoved_workers = resize_ack->nmoved_workers;
  561. int *acked_workers = resize_ack->acked_workers;
  562. if(worker != -1)
  563. {
  564. for(i = 0; i < nmoved_workers; i++)
  565. {
  566. int moved_worker = moved_workers[i];
  567. if(moved_worker == worker && acked_workers[i] == 0)
  568. {
  569. acked_workers[i] = 1;
  570. }
  571. }
  572. }
  573. int nacked_workers = 0;
  574. for(i = 0; i < nmoved_workers; i++)
  575. {
  576. nacked_workers += (acked_workers[i] == 1);
  577. }
  578. unsigned resize_completed = (nacked_workers == nmoved_workers);
  579. int receiver_sched_ctx = sched_ctx;
  580. if(resize_completed)
  581. {
  582. /* if the permission to resize is not allowed by the user don't do it
  583. whatever the application says */
  584. if(!((hypervisor.resize[sender_sched_ctx] == 0 || hypervisor.resize[receiver_sched_ctx] == 0) && imposed_resize))
  585. {
  586. /* int j; */
  587. /* printf("remove after ack from ctx %d:", sender_sched_ctx); */
  588. /* for(j = 0; j < nmoved_workers; j++) */
  589. /* printf(" %d", moved_workers[j]); */
  590. /* printf("\n"); */
  591. starpu_sched_ctx_remove_workers(moved_workers, nmoved_workers, sender_sched_ctx);
  592. _reset_resize_sample_info(sender_sched_ctx, receiver_sched_ctx);
  593. hypervisor.resize[sender_sched_ctx] = 1;
  594. hypervisor.allow_remove[receiver_sched_ctx] = 1;
  595. /* if the user allowed resizing leave the decisions to the application */
  596. if(imposed_resize) imposed_resize = 0;
  597. resize_ack->receiver_sched_ctx = -1;
  598. resize_ack->nmoved_workers = 0;
  599. free(resize_ack->moved_workers);
  600. free(resize_ack->acked_workers);
  601. }
  602. starpu_pthread_mutex_unlock(&hypervisor.sched_ctx_w[sender_sched_ctx].mutex);
  603. return resize_completed;
  604. }
  605. starpu_pthread_mutex_unlock(&hypervisor.sched_ctx_w[sender_sched_ctx].mutex);
  606. }
  607. return 0;
  608. }
  609. /* Enqueue a resize request for 'sched_ctx', to be executed when the
  610. * 'task_tag' tasks of 'sched_ctx' complete. */
  611. void sc_hypervisor_post_resize_request(unsigned sched_ctx, int task_tag)
  612. {
  613. struct resize_request_entry *entry;
  614. entry = malloc(sizeof *entry);
  615. STARPU_ASSERT(entry != NULL);
  616. entry->sched_ctx = sched_ctx;
  617. entry->task_tag = task_tag;
  618. starpu_pthread_mutex_lock(&hypervisor.resize_mut[sched_ctx]);
  619. HASH_ADD_INT(hypervisor.resize_requests[sched_ctx], task_tag, entry);
  620. starpu_pthread_mutex_unlock(&hypervisor.resize_mut[sched_ctx]);
  621. }
  622. void sc_hypervisor_resize_ctxs(unsigned *sched_ctxs, int nsched_ctxs , int *workers, int nworkers)
  623. {
  624. if(hypervisor.policy.resize_ctxs)
  625. hypervisor.policy.resize_ctxs(sched_ctxs, nsched_ctxs, workers, nworkers);
  626. }
  627. /* notifies the hypervisor that the worker is no longer idle and a new task was pushed on its queue */
  628. static void notify_idle_end(unsigned sched_ctx, int worker)
  629. {
  630. if(hypervisor.resize[sched_ctx])
  631. hypervisor.sched_ctx_w[sched_ctx].current_idle_time[worker] = 0.0;
  632. struct sc_hypervisor_wrapper *sc_w = &hypervisor.sched_ctx_w[sched_ctx];
  633. if(sc_w->idle_start_time[worker] != 0.0)
  634. {
  635. double end_time = starpu_timing_now();
  636. sc_w->idle_time[worker] += (end_time - sc_w->idle_start_time[worker]) / 1000000.0; /* in seconds */
  637. sc_w->idle_start_time[worker] = 0.0;
  638. }
  639. if(hypervisor.policy.handle_idle_end)
  640. hypervisor.policy.handle_idle_end(sched_ctx, worker);
  641. }
  642. /* notifies the hypervisor that the worker spent another cycle in idle time */
  643. static void notify_idle_cycle(unsigned sched_ctx, int worker, double idle_time)
  644. {
  645. if(hypervisor.resize[sched_ctx])
  646. {
  647. struct sc_hypervisor_wrapper *sc_w = &hypervisor.sched_ctx_w[sched_ctx];
  648. sc_w->current_idle_time[worker] += idle_time;
  649. if(sc_w->idle_start_time[worker] == 0.0)
  650. sc_w->idle_start_time[worker] = starpu_timing_now();
  651. if(hypervisor.policy.handle_idle_cycle)
  652. {
  653. hypervisor.policy.handle_idle_cycle(sched_ctx, worker);
  654. }
  655. }
  656. return;
  657. }
  658. /* notifies the hypervisor that a new task was pushed on the queue of the worker */
  659. static void notify_pushed_task(unsigned sched_ctx, int worker)
  660. {
  661. hypervisor.sched_ctx_w[sched_ctx].pushed_tasks[worker]++;
  662. if(hypervisor.sched_ctx_w[sched_ctx].total_flops != 0.0 && hypervisor.sched_ctx_w[sched_ctx].start_time == 0.0)
  663. hypervisor.sched_ctx_w[sched_ctx].start_time = starpu_timing_now();
  664. if(hypervisor.sched_ctx_w[sched_ctx].total_flops != 0.0 && hypervisor.sched_ctx_w[sched_ctx].real_start_time == 0.0)
  665. hypervisor.sched_ctx_w[sched_ctx].real_start_time = starpu_timing_now();
  666. int ntasks = get_ntasks(hypervisor.sched_ctx_w[sched_ctx].pushed_tasks);
  667. if((hypervisor.min_tasks == 0 || (!(hypervisor.resize[sched_ctx] == 0 && imposed_resize) && ntasks == hypervisor.min_tasks)) && hypervisor.check_min_tasks[sched_ctx])
  668. {
  669. hypervisor.resize[sched_ctx] = 1;
  670. if(imposed_resize) imposed_resize = 0;
  671. hypervisor.check_min_tasks[sched_ctx] = 0;
  672. }
  673. if(hypervisor.policy.handle_pushed_task)
  674. hypervisor.policy.handle_pushed_task(sched_ctx, worker);
  675. }
  676. /* notifies the hypervisor that a task was poped from the queue of the worker */
  677. static void notify_poped_task(unsigned sched_ctx, int worker, struct starpu_task *task, size_t data_size, uint32_t footprint)
  678. {
  679. hypervisor.sched_ctx_w[sched_ctx].poped_tasks[worker]++;
  680. hypervisor.sched_ctx_w[sched_ctx].elapsed_flops[worker] += task->flops;
  681. hypervisor.sched_ctx_w[sched_ctx].elapsed_data[worker] += data_size ;
  682. hypervisor.sched_ctx_w[sched_ctx].elapsed_tasks[worker]++ ;
  683. hypervisor.sched_ctx_w[sched_ctx].total_elapsed_flops[worker] += task->flops;
  684. starpu_pthread_mutex_lock(&act_hypervisor_mutex);
  685. hypervisor.sched_ctx_w[sched_ctx].remaining_flops -= task->flops;
  686. /* if(hypervisor.sched_ctx_w[sched_ctx].remaining_flops < 0.0) */
  687. /* hypervisor.sched_ctx_w[sched_ctx].remaining_flops = 0.0; */
  688. // double ctx_elapsed_flops = sc_hypervisor_get_elapsed_flops_per_sched_ctx(&hypervisor.sched_ctx_w[sched_ctx]);
  689. /* printf("*****************STARPU_STARPU_STARPU: decrement %lf flops remaining flops %lf total flops %lf elapseed flops %lf in ctx %d \n", */
  690. /* task->flops, hypervisor.sched_ctx_w[sched_ctx].remaining_flops, hypervisor.sched_ctx_w[sched_ctx].total_flops, ctx_elapsed_flops, sched_ctx); */
  691. starpu_pthread_mutex_unlock(&act_hypervisor_mutex);
  692. if(hypervisor.resize[sched_ctx])
  693. {
  694. if(hypervisor.policy.handle_poped_task)
  695. hypervisor.policy.handle_poped_task(sched_ctx, worker, task, footprint);
  696. }
  697. _ack_resize_completed(sched_ctx, worker);
  698. if(hypervisor.sched_ctx_w[sched_ctx].poped_tasks[worker] % 200 == 0)
  699. _print_current_time();
  700. }
  701. /* notifies the hypervisor that a tagged task has just been executed */
  702. static void notify_post_exec_hook(unsigned sched_ctx, int task_tag)
  703. {
  704. STARPU_ASSERT(task_tag > 0);
  705. unsigned conf_sched_ctx;
  706. unsigned i;
  707. starpu_pthread_mutex_lock(&act_hypervisor_mutex);
  708. unsigned ns = hypervisor.nsched_ctxs;
  709. starpu_pthread_mutex_unlock(&act_hypervisor_mutex);
  710. for(i = 0; i < ns; i++)
  711. {
  712. struct configuration_entry *entry;
  713. conf_sched_ctx = hypervisor.sched_ctxs[i];
  714. starpu_pthread_mutex_lock(&hypervisor.conf_mut[conf_sched_ctx]);
  715. HASH_FIND_INT(hypervisor.configurations[conf_sched_ctx], &task_tag, entry);
  716. if (entry != NULL)
  717. {
  718. struct sc_hypervisor_policy_config *config = entry->configuration;
  719. sc_hypervisor_set_config(conf_sched_ctx, config);
  720. HASH_DEL(hypervisor.configurations[conf_sched_ctx], entry);
  721. free(config);
  722. }
  723. starpu_pthread_mutex_unlock(&hypervisor.conf_mut[conf_sched_ctx]);
  724. }
  725. if(hypervisor.resize[sched_ctx])
  726. {
  727. starpu_pthread_mutex_lock(&hypervisor.resize_mut[sched_ctx]);
  728. if(hypervisor.policy.handle_post_exec_hook)
  729. {
  730. /* Check whether 'task_tag' is in the 'resize_requests' set. */
  731. struct resize_request_entry *entry;
  732. HASH_FIND_INT(hypervisor.resize_requests[sched_ctx], &task_tag, entry);
  733. if (entry != NULL)
  734. {
  735. hypervisor.policy.handle_post_exec_hook(sched_ctx, task_tag);
  736. HASH_DEL(hypervisor.resize_requests[sched_ctx], entry);
  737. free(entry);
  738. }
  739. }
  740. starpu_pthread_mutex_unlock(&hypervisor.resize_mut[sched_ctx]);
  741. }
  742. return;
  743. }
  744. static void notify_submitted_job(struct starpu_task *task, uint32_t footprint, size_t data_size)
  745. {
  746. starpu_pthread_mutex_lock(&act_hypervisor_mutex);
  747. hypervisor.sched_ctx_w[task->sched_ctx].submitted_flops += task->flops;
  748. starpu_pthread_mutex_unlock(&act_hypervisor_mutex);
  749. if(hypervisor.policy.handle_submitted_job && !type_of_tasks_known)
  750. hypervisor.policy.handle_submitted_job(task->cl, task->sched_ctx, footprint, data_size);
  751. }
  752. void sc_hypervisor_set_type_of_task(struct starpu_codelet *cl, unsigned sched_ctx, uint32_t footprint, size_t data_size)
  753. {
  754. type_of_tasks_known = 1;
  755. if(hypervisor.policy.handle_submitted_job)
  756. hypervisor.policy.handle_submitted_job(cl, sched_ctx, footprint, data_size);
  757. }
  758. static void notify_delete_context(unsigned sched_ctx)
  759. {
  760. _print_current_time();
  761. sc_hypervisor_unregister_ctx(sched_ctx);
  762. }
  763. void sc_hypervisor_size_ctxs(unsigned *sched_ctxs, int nsched_ctxs, int *workers, int nworkers)
  764. {
  765. starpu_pthread_mutex_lock(&act_hypervisor_mutex);
  766. unsigned curr_nsched_ctxs = sched_ctxs == NULL ? hypervisor.nsched_ctxs : (unsigned)nsched_ctxs;
  767. unsigned *curr_sched_ctxs = sched_ctxs == NULL ? hypervisor.sched_ctxs : sched_ctxs;
  768. starpu_pthread_mutex_unlock(&act_hypervisor_mutex);
  769. unsigned s;
  770. for(s = 0; s < curr_nsched_ctxs; s++)
  771. hypervisor.resize[curr_sched_ctxs[s]] = 1;
  772. if(hypervisor.policy.size_ctxs)
  773. hypervisor.policy.size_ctxs(curr_sched_ctxs, curr_nsched_ctxs, workers, nworkers);
  774. }
  775. struct sc_hypervisor_wrapper* sc_hypervisor_get_wrapper(unsigned sched_ctx)
  776. {
  777. return &hypervisor.sched_ctx_w[sched_ctx];
  778. }
  779. unsigned* sc_hypervisor_get_sched_ctxs()
  780. {
  781. return hypervisor.sched_ctxs;
  782. }
  783. int sc_hypervisor_get_nsched_ctxs()
  784. {
  785. int ns;
  786. ns = hypervisor.nsched_ctxs;
  787. return ns;
  788. }
  789. void sc_hypervisor_save_size_req(unsigned *sched_ctxs, int nsched_ctxs, int *workers, int nworkers)
  790. {
  791. hypervisor.sr = (struct size_request*)malloc(sizeof(struct size_request));
  792. hypervisor.sr->sched_ctxs = sched_ctxs;
  793. hypervisor.sr->nsched_ctxs = nsched_ctxs;
  794. hypervisor.sr->workers = workers;
  795. hypervisor.sr->nworkers = nworkers;
  796. }
  797. unsigned sc_hypervisor_get_size_req(unsigned **sched_ctxs, int* nsched_ctxs, int **workers, int *nworkers)
  798. {
  799. if(hypervisor.sr != NULL)
  800. {
  801. *sched_ctxs = hypervisor.sr->sched_ctxs;
  802. *nsched_ctxs = hypervisor.sr->nsched_ctxs;
  803. *workers = hypervisor.sr->workers;
  804. *nworkers = hypervisor.sr->nworkers;
  805. return 1;
  806. }
  807. return 0;
  808. }
  809. void sc_hypervisor_free_size_req(void)
  810. {
  811. if(hypervisor.sr != NULL)
  812. {
  813. free(hypervisor.sr);
  814. hypervisor.sr = NULL;
  815. }
  816. }
  817. double _get_optimal_v(unsigned sched_ctx)
  818. {
  819. return hypervisor.optimal_v[sched_ctx];
  820. }
  821. void _set_optimal_v(unsigned sched_ctx, double optimal_v)
  822. {
  823. hypervisor.optimal_v[sched_ctx] = optimal_v;
  824. }
  825. static struct types_of_workers* _init_structure_types_of_workers(void)
  826. {
  827. struct types_of_workers *tw = (struct types_of_workers*)malloc(sizeof(struct types_of_workers));
  828. tw->ncpus = 0;
  829. tw->ncuda = 0;
  830. tw->nw = 0;
  831. return tw;
  832. }
  833. struct types_of_workers* sc_hypervisor_get_types_of_workers(int *workers, unsigned nworkers)
  834. {
  835. struct types_of_workers *tw = _init_structure_types_of_workers();
  836. unsigned w;
  837. for(w = 0; w < nworkers; w++)
  838. {
  839. enum starpu_worker_archtype arch = workers == NULL ? starpu_worker_get_type((int)w) : starpu_worker_get_type(workers[w]);
  840. if(arch == STARPU_CPU_WORKER)
  841. tw->ncpus++;
  842. if(arch == STARPU_CUDA_WORKER)
  843. tw->ncuda++;
  844. }
  845. if(tw->ncpus > 0) tw->nw++;
  846. if(tw->ncuda > 0) tw->nw++;
  847. return tw;
  848. }
  849. void sc_hypervisor_update_diff_total_flops(unsigned sched_ctx, double diff_total_flops)
  850. {
  851. // double diff = total_flops - hypervisor.sched_ctx_w[sched_ctx].total_flops;
  852. // printf("*****************STARPU_STARPU_STARPU: update diff flops %lf to ctx %d \n", diff_total_flops, sched_ctx);
  853. starpu_pthread_mutex_lock(&act_hypervisor_mutex);
  854. hypervisor.sched_ctx_w[sched_ctx].total_flops += diff_total_flops;
  855. hypervisor.sched_ctx_w[sched_ctx].remaining_flops += diff_total_flops;
  856. /* printf("*****************STARPU_STARPU_STARPU: total flops %lf remaining flops %lf in ctx %d \n", */
  857. /* hypervisor.sched_ctx_w[sched_ctx].total_flops, hypervisor.sched_ctx_w[sched_ctx].remaining_flops, sched_ctx); */
  858. starpu_pthread_mutex_unlock(&act_hypervisor_mutex);
  859. }
  860. void sc_hypervisor_update_diff_elapsed_flops(unsigned sched_ctx, double diff_elapsed_flops)
  861. {
  862. int workerid = starpu_worker_get_id();
  863. if(workerid != -1)
  864. {
  865. starpu_pthread_mutex_lock(&act_hypervisor_mutex);
  866. hypervisor.sched_ctx_w[sched_ctx].elapsed_flops[workerid] += diff_elapsed_flops;
  867. hypervisor.sched_ctx_w[sched_ctx].total_elapsed_flops[workerid] += diff_elapsed_flops;
  868. starpu_pthread_mutex_unlock(&act_hypervisor_mutex);
  869. }
  870. }