ispeed_policy.c 6.1 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. int *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_velocity = 0.0;
  23. double biggest_velocity = 0.0;
  24. int i;
  25. for(i = 0; i < nsched_ctxs; i++)
  26. {
  27. curr_velocity = _get_ctx_velocity(sc_hypervisor_get_wrapper(sched_ctxs[i]));
  28. if( curr_velocity > biggest_velocity)
  29. {
  30. fastest_sched_ctx = sched_ctxs[i];
  31. biggest_velocity = curr_velocity;
  32. }
  33. }
  34. return fastest_sched_ctx;
  35. }
  36. static unsigned _get_slowest_sched_ctx(void)
  37. {
  38. int *sched_ctxs = sc_hypervisor_get_sched_ctxs();
  39. int nsched_ctxs = sc_hypervisor_get_nsched_ctxs();
  40. double smallest_velocity = _get_ctx_velocity(sc_hypervisor_get_wrapper(sched_ctxs[0]));
  41. unsigned slowest_sched_ctx = smallest_velocity == -1.0 ? STARPU_NMAX_SCHED_CTXS : sched_ctxs[0];
  42. double curr_velocity = 0.0;
  43. int i;
  44. for(i = 1; i < nsched_ctxs; i++)
  45. {
  46. curr_velocity = _get_ctx_velocity(sc_hypervisor_get_wrapper(sched_ctxs[i]));
  47. if((curr_velocity < smallest_velocity || smallest_velocity == 0.0) && curr_velocity != -1.0)
  48. {
  49. smallest_velocity = curr_velocity;
  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_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. if(workers->init_iterator)
  70. workers->init_iterator(workers, &it);
  71. for(index = 0; index < *nworkers; index++)
  72. {
  73. while(workers->has_next(workers, &it))
  74. {
  75. considered = 0;
  76. worker = workers->get_next(workers, &it);
  77. enum starpu_archtype curr_arch = starpu_worker_get_type(worker);
  78. if(arch == STARPU_ANY_WORKER || curr_arch == arch)
  79. {
  80. if(!config->fixed_workers[worker])
  81. {
  82. for(i = 0; i < index; i++)
  83. {
  84. if(curr_workers[i] == worker)
  85. {
  86. considered = 1;
  87. break;
  88. }
  89. }
  90. if(!considered)
  91. {
  92. double worker_velocity = _get_velocity_per_worker(sc_w, worker);
  93. if(worker_velocity != -1.0)
  94. {
  95. /* the first iteration*/
  96. if(curr_workers[index] < 0)
  97. curr_workers[index] = worker;
  98. /* small priority worker is the first to leave the ctx*/
  99. else if(config->priority[worker] <
  100. config->priority[curr_workers[index]])
  101. curr_workers[index] = worker;
  102. /* if we don't consider priorities check for the workers
  103. with the biggest idle time */
  104. else if(config->priority[worker] ==
  105. config->priority[curr_workers[index]])
  106. {
  107. double curr_worker_velocity = _get_velocity_per_worker(sc_w, curr_workers[index]);
  108. // printf("speed[%d] = %lf speed[%d] = %lf\n", worker, worker_velocity, curr_workers[index], curr_worker_velocity);
  109. if(worker_velocity < curr_worker_velocity && curr_worker_velocity != -1.0)
  110. {
  111. curr_workers[index] = worker;
  112. }
  113. }
  114. }
  115. }
  116. }
  117. }
  118. }
  119. if(curr_workers[index] < 0)
  120. {
  121. *nworkers = index;
  122. break;
  123. }
  124. }
  125. return curr_workers;
  126. }
  127. static void ispeed_handle_poped_task(unsigned sched_ctx, int worker, struct starpu_task *task, uint32_t footprint)
  128. {
  129. int ret = starpu_pthread_mutex_trylock(&act_hypervisor_mutex);
  130. if(ret != EBUSY)
  131. {
  132. if(_velocity_gap_btw_ctxs())
  133. {
  134. unsigned fastest_sched_ctx = _get_fastest_sched_ctx();
  135. unsigned slowest_sched_ctx = _get_slowest_sched_ctx();
  136. if(fastest_sched_ctx != STARPU_NMAX_SCHED_CTXS && slowest_sched_ctx != STARPU_NMAX_SCHED_CTXS && fastest_sched_ctx != slowest_sched_ctx)
  137. {
  138. int nworkers_to_move = sc_hypervisor_compute_nworkers_to_move(fastest_sched_ctx);
  139. if(nworkers_to_move > 0)
  140. {
  141. int *workers_to_move = _get_slowest_workers(fastest_sched_ctx, &nworkers_to_move, STARPU_ANY_WORKER);
  142. if(nworkers_to_move > 0)
  143. {
  144. double new_speed = 0.0;
  145. int i;
  146. for(i = 0; i < nworkers_to_move; i++)
  147. new_speed += _get_velocity_per_worker(sc_hypervisor_get_wrapper(fastest_sched_ctx), workers_to_move[i]);
  148. double fastest_speed = _get_ctx_velocity(sc_hypervisor_get_wrapper(fastest_sched_ctx));
  149. double slowest_speed = _get_ctx_velocity(sc_hypervisor_get_wrapper(slowest_sched_ctx));
  150. // printf("fast_speed(%d) %lf slow_speed(%d) %lf new speed(%d) %lf \n", fastest_sched_ctx, fastest_speed, slowest_sched_ctx,
  151. // slowest_speed, workers_to_move[0], new_speed);
  152. if(fastest_speed != -1.0 && slowest_speed != -1.0 && (slowest_speed + new_speed) <= (fastest_speed - new_speed))
  153. {
  154. sc_hypervisor_move_workers(fastest_sched_ctx, slowest_sched_ctx, workers_to_move, nworkers_to_move, 0);
  155. }
  156. }
  157. free(workers_to_move);
  158. }
  159. }
  160. }
  161. starpu_pthread_mutex_unlock(&act_hypervisor_mutex);
  162. }
  163. }
  164. struct sc_hypervisor_policy ispeed_policy = {
  165. .size_ctxs = NULL,
  166. .handle_poped_task = ispeed_handle_poped_task,
  167. .handle_pushed_task = NULL,
  168. .handle_idle_cycle = NULL,
  169. .handle_idle_end = NULL,
  170. .handle_post_exec_hook = NULL,
  171. .handle_submitted_job = NULL,
  172. .end_ctx = NULL,
  173. .custom = 0,
  174. .name = "ispeed"
  175. };