ispeed_policy.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2011-2013,2015 Inria
  4. * Copyright (C) 2013,2016-2017 CNRS
  5. * Copyright (C) 2014 Université de Bordeaux
  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 "sc_hypervisor_policy.h"
  19. static unsigned _get_fastest_sched_ctx(void)
  20. {
  21. unsigned *sched_ctxs = sc_hypervisor_get_sched_ctxs();
  22. int nsched_ctxs = sc_hypervisor_get_nsched_ctxs();
  23. int fastest_sched_ctx = STARPU_NMAX_SCHED_CTXS;
  24. double curr_speed = 0.0;
  25. double biggest_speed = 0.0;
  26. int i;
  27. for(i = 0; i < nsched_ctxs; i++)
  28. {
  29. curr_speed = sc_hypervisor_get_ctx_speed(sc_hypervisor_get_wrapper(sched_ctxs[i]));
  30. if( curr_speed > biggest_speed)
  31. {
  32. fastest_sched_ctx = sched_ctxs[i];
  33. biggest_speed = curr_speed;
  34. }
  35. }
  36. return fastest_sched_ctx;
  37. }
  38. static unsigned _get_slowest_sched_ctx(void)
  39. {
  40. unsigned *sched_ctxs = sc_hypervisor_get_sched_ctxs();
  41. int nsched_ctxs = sc_hypervisor_get_nsched_ctxs();
  42. double smallest_speed = sc_hypervisor_get_ctx_speed(sc_hypervisor_get_wrapper(sched_ctxs[0]));
  43. unsigned slowest_sched_ctx = smallest_speed == -1.0 ? STARPU_NMAX_SCHED_CTXS : sched_ctxs[0];
  44. double curr_speed = 0.0;
  45. int i;
  46. for(i = 1; i < nsched_ctxs; i++)
  47. {
  48. curr_speed = sc_hypervisor_get_ctx_speed(sc_hypervisor_get_wrapper(sched_ctxs[i]));
  49. if((curr_speed < smallest_speed || smallest_speed == 0.0) && curr_speed != -1.0)
  50. {
  51. smallest_speed = curr_speed;
  52. slowest_sched_ctx = sched_ctxs[i];
  53. }
  54. }
  55. return slowest_sched_ctx;
  56. }
  57. /* get first nworkers with the highest idle time in the context */
  58. static int* _get_slowest_workers(unsigned sched_ctx, int *nworkers, enum starpu_worker_archtype arch)
  59. {
  60. struct sc_hypervisor_wrapper* sc_w = sc_hypervisor_get_wrapper(sched_ctx);
  61. struct sc_hypervisor_policy_config *config = sc_hypervisor_get_config(sched_ctx);
  62. int *curr_workers = (int*)malloc((*nworkers) * sizeof(int));
  63. int i;
  64. for(i = 0; i < *nworkers; i++)
  65. curr_workers[i] = -1;
  66. struct starpu_worker_collection *workers = starpu_sched_ctx_get_worker_collection(sched_ctx);
  67. int index;
  68. int worker;
  69. int considered = 0;
  70. struct starpu_sched_ctx_iterator it;
  71. workers->init_iterator(workers, &it);
  72. for(index = 0; index < *nworkers; index++)
  73. {
  74. while(workers->has_next(workers, &it))
  75. {
  76. considered = 0;
  77. worker = workers->get_next(workers, &it);
  78. enum starpu_worker_archtype curr_arch = starpu_worker_get_type(worker);
  79. if(arch == STARPU_ANY_WORKER || curr_arch == arch)
  80. {
  81. if(!config->fixed_workers[worker])
  82. {
  83. for(i = 0; i < index; i++)
  84. {
  85. if(curr_workers[i] == worker)
  86. {
  87. considered = 1;
  88. break;
  89. }
  90. }
  91. if(!considered)
  92. {
  93. double worker_speed = sc_hypervisor_get_speed_per_worker(sc_w, worker);
  94. if(worker_speed != -1.0)
  95. {
  96. /* the first iteration*/
  97. if(curr_workers[index] < 0)
  98. curr_workers[index] = worker;
  99. /* small priority worker is the first to leave the ctx*/
  100. else if(config->priority[worker] <
  101. config->priority[curr_workers[index]])
  102. curr_workers[index] = worker;
  103. /* if we don't consider priorities check for the workers
  104. with the biggest idle time */
  105. else if(config->priority[worker] ==
  106. config->priority[curr_workers[index]])
  107. {
  108. double curr_worker_speed = sc_hypervisor_get_speed_per_worker(sc_w, curr_workers[index]);
  109. // printf("speed[%d] = %lf speed[%d] = %lf\n", worker, worker_speed, curr_workers[index], curr_worker_speed);
  110. if(worker_speed < curr_worker_speed && curr_worker_speed != -1.0)
  111. {
  112. curr_workers[index] = worker;
  113. }
  114. }
  115. }
  116. }
  117. }
  118. }
  119. }
  120. if(curr_workers[index] < 0)
  121. {
  122. *nworkers = index;
  123. break;
  124. }
  125. }
  126. return curr_workers;
  127. }
  128. static void ispeed_handle_poped_task(unsigned sched_ctx, int worker, __attribute__((unused))struct starpu_task *task, __attribute__((unused))uint32_t footprint)
  129. {
  130. int ret = starpu_pthread_mutex_trylock(&act_hypervisor_mutex);
  131. if(ret != EBUSY)
  132. {
  133. if(sc_hypervisor_criteria_fulfilled(sched_ctx, worker))
  134. {
  135. unsigned fastest_sched_ctx = _get_fastest_sched_ctx();
  136. unsigned slowest_sched_ctx = _get_slowest_sched_ctx();
  137. if(fastest_sched_ctx != STARPU_NMAX_SCHED_CTXS && slowest_sched_ctx != STARPU_NMAX_SCHED_CTXS && fastest_sched_ctx != slowest_sched_ctx)
  138. {
  139. int nworkers_to_move = sc_hypervisor_compute_nworkers_to_move(fastest_sched_ctx);
  140. if(nworkers_to_move > 0)
  141. {
  142. int *workers_to_move = _get_slowest_workers(fastest_sched_ctx, &nworkers_to_move, STARPU_ANY_WORKER);
  143. if(nworkers_to_move > 0)
  144. {
  145. double new_speed = 0.0;
  146. int i;
  147. for(i = 0; i < nworkers_to_move; i++)
  148. new_speed += sc_hypervisor_get_speed_per_worker(sc_hypervisor_get_wrapper(fastest_sched_ctx), workers_to_move[i]);
  149. double fastest_speed = sc_hypervisor_get_ctx_speed(sc_hypervisor_get_wrapper(fastest_sched_ctx));
  150. double slowest_speed = sc_hypervisor_get_ctx_speed(sc_hypervisor_get_wrapper(slowest_sched_ctx));
  151. // printf("fast_speed(%d) %lf slow_speed(%d) %lf new speed(%d) %lf \n", fastest_sched_ctx, fastest_speed, slowest_sched_ctx,
  152. // slowest_speed, workers_to_move[0], new_speed);
  153. if(fastest_speed != -1.0 && slowest_speed != -1.0 && (slowest_speed + new_speed) <= (fastest_speed - new_speed))
  154. {
  155. sc_hypervisor_move_workers(fastest_sched_ctx, slowest_sched_ctx, workers_to_move, nworkers_to_move, 0);
  156. }
  157. }
  158. free(workers_to_move);
  159. }
  160. }
  161. }
  162. STARPU_PTHREAD_MUTEX_UNLOCK(&act_hypervisor_mutex);
  163. }
  164. }
  165. struct sc_hypervisor_policy ispeed_policy = {
  166. .size_ctxs = NULL,
  167. .handle_poped_task = ispeed_handle_poped_task,
  168. .handle_pushed_task = NULL,
  169. .handle_idle_cycle = NULL,
  170. .handle_idle_end = NULL,
  171. .handle_post_exec_hook = NULL,
  172. .handle_submitted_job = NULL,
  173. .end_ctx = NULL,
  174. .init_worker = NULL,
  175. .custom = 0,
  176. .name = "ispeed"
  177. };