ispeed_policy.c 6.2 KB

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