|
@@ -57,7 +57,7 @@ static unsigned _find_poor_sched_ctx(unsigned req_sched_ctx, int nworkers_to_mov
|
|
return sched_ctx;
|
|
return sched_ctx;
|
|
}
|
|
}
|
|
|
|
|
|
-int* _get_first_workers(unsigned sched_ctx, unsigned *nworkers)
|
|
|
|
|
|
+int* _get_first_workers(unsigned sched_ctx, unsigned *nworkers, enum starpu_archtype arch)
|
|
{
|
|
{
|
|
struct policy_config *config = sched_ctx_hypervisor_get_config(sched_ctx);
|
|
struct policy_config *config = sched_ctx_hypervisor_get_config(sched_ctx);
|
|
|
|
|
|
@@ -80,40 +80,45 @@ int* _get_first_workers(unsigned sched_ctx, unsigned *nworkers)
|
|
{
|
|
{
|
|
considered = 0;
|
|
considered = 0;
|
|
worker = workers->get_next(workers);
|
|
worker = workers->get_next(workers);
|
|
- if(!config->fixed_workers[worker])
|
|
|
|
|
|
+ enum starpu_archtype curr_arch = starpu_worker_get_type(worker);
|
|
|
|
+ if(arch == 0 || curr_arch == arch)
|
|
{
|
|
{
|
|
- for(i = 0; i < index; i++)
|
|
|
|
|
|
+
|
|
|
|
+ if(!config->fixed_workers[worker])
|
|
{
|
|
{
|
|
- if(curr_workers[i] == worker)
|
|
|
|
|
|
+ for(i = 0; i < index; i++)
|
|
{
|
|
{
|
|
- considered = 1;
|
|
|
|
- break;
|
|
|
|
|
|
+ if(curr_workers[i] == worker)
|
|
|
|
+ {
|
|
|
|
+ considered = 1;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- }
|
|
|
|
-
|
|
|
|
- if(!considered)
|
|
|
|
- {
|
|
|
|
- /* the first iteration*/
|
|
|
|
- if(curr_workers[index] < 0)
|
|
|
|
|
|
+
|
|
|
|
+ if(!considered)
|
|
|
|
+ {
|
|
|
|
+ /* the first iteration*/
|
|
|
|
+ if(curr_workers[index] < 0)
|
|
curr_workers[index] = worker;
|
|
curr_workers[index] = worker;
|
|
- /* small priority worker is the first to leave the ctx*/
|
|
|
|
- else if(config->priority[worker] <
|
|
|
|
- config->priority[curr_workers[index]])
|
|
|
|
|
|
+ /* small priority worker is the first to leave the ctx*/
|
|
|
|
+ else if(config->priority[worker] <
|
|
|
|
+ config->priority[curr_workers[index]])
|
|
curr_workers[index] = worker;
|
|
curr_workers[index] = worker;
|
|
- /* if we don't consider priorities check for the workers
|
|
|
|
- with the biggest idle time */
|
|
|
|
- else if(config->priority[worker] ==
|
|
|
|
- config->priority[curr_workers[index]])
|
|
|
|
- {
|
|
|
|
- double worker_idle_time = sched_ctx_hypervisor_get_idle_time(sched_ctx, worker);
|
|
|
|
- double curr_worker_idle_time = sched_ctx_hypervisor_get_idle_time(sched_ctx, curr_workers[index]);
|
|
|
|
- if(worker_idle_time > curr_worker_idle_time)
|
|
|
|
- curr_workers[index] = worker;
|
|
|
|
|
|
+ /* if we don't consider priorities check for the workers
|
|
|
|
+ with the biggest idle time */
|
|
|
|
+ else if(config->priority[worker] ==
|
|
|
|
+ config->priority[curr_workers[index]])
|
|
|
|
+ {
|
|
|
|
+ double worker_idle_time = sched_ctx_hypervisor_get_idle_time(sched_ctx, worker);
|
|
|
|
+ double curr_worker_idle_time = sched_ctx_hypervisor_get_idle_time(sched_ctx, curr_workers[index]);
|
|
|
|
+ if(worker_idle_time > curr_worker_idle_time)
|
|
|
|
+ curr_workers[index] = worker;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
if(curr_workers[index] < 0)
|
|
if(curr_workers[index] < 0)
|
|
{
|
|
{
|
|
*nworkers = index;
|
|
*nworkers = index;
|
|
@@ -127,7 +132,7 @@ int* _get_first_workers(unsigned sched_ctx, unsigned *nworkers)
|
|
return curr_workers;
|
|
return curr_workers;
|
|
}
|
|
}
|
|
|
|
|
|
-static unsigned _get_potential_nworkers(struct policy_config *config, unsigned sched_ctx)
|
|
|
|
|
|
+static unsigned _get_potential_nworkers(struct policy_config *config, unsigned sched_ctx, enum starpu_archtype arch)
|
|
{
|
|
{
|
|
struct worker_collection *workers = starpu_get_worker_collection_of_sched_ctx(sched_ctx);
|
|
struct worker_collection *workers = starpu_get_worker_collection_of_sched_ctx(sched_ctx);
|
|
|
|
|
|
@@ -139,8 +144,12 @@ static unsigned _get_potential_nworkers(struct policy_config *config, unsigned s
|
|
while(workers->has_next(workers))
|
|
while(workers->has_next(workers))
|
|
{
|
|
{
|
|
worker = workers->get_next(workers);
|
|
worker = workers->get_next(workers);
|
|
- if(!config->fixed_workers[worker])
|
|
|
|
- potential_workers++;
|
|
|
|
|
|
+ enum starpu_archtype curr_arch = starpu_worker_get_type(worker);
|
|
|
|
+ if(arch == 0 || curr_arch == arch)
|
|
|
|
+ {
|
|
|
|
+ if(!config->fixed_workers[worker])
|
|
|
|
+ potential_workers++;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
if(workers->init_cursor)
|
|
if(workers->init_cursor)
|
|
workers->deinit_cursor(workers);
|
|
workers->deinit_cursor(workers);
|
|
@@ -154,7 +163,7 @@ static unsigned _get_nworkers_to_move(unsigned req_sched_ctx)
|
|
unsigned nworkers = starpu_get_nworkers_of_sched_ctx(req_sched_ctx);
|
|
unsigned nworkers = starpu_get_nworkers_of_sched_ctx(req_sched_ctx);
|
|
unsigned nworkers_to_move = 0;
|
|
unsigned nworkers_to_move = 0;
|
|
|
|
|
|
- unsigned potential_moving_workers = _get_potential_nworkers(config, req_sched_ctx);
|
|
|
|
|
|
+ unsigned potential_moving_workers = _get_potential_nworkers(config, req_sched_ctx, 0);
|
|
if(potential_moving_workers > 0)
|
|
if(potential_moving_workers > 0)
|
|
{
|
|
{
|
|
if(potential_moving_workers <= config->min_nworkers)
|
|
if(potential_moving_workers <= config->min_nworkers)
|
|
@@ -213,15 +222,16 @@ static unsigned _simple_resize(unsigned sender_sched_ctx, unsigned receiver_sche
|
|
poor_sched_ctx = receiver_sched_ctx;
|
|
poor_sched_ctx = receiver_sched_ctx;
|
|
struct policy_config *config = sched_ctx_hypervisor_get_config(poor_sched_ctx);
|
|
struct policy_config *config = sched_ctx_hypervisor_get_config(poor_sched_ctx);
|
|
unsigned nworkers = starpu_get_nworkers_of_sched_ctx(poor_sched_ctx);
|
|
unsigned nworkers = starpu_get_nworkers_of_sched_ctx(poor_sched_ctx);
|
|
- if((nworkers+nworkers_to_move) > config->max_nworkers)
|
|
|
|
- nworkers_to_move = nworkers > config->max_nworkers ? 0 : (config->max_nworkers - nworkers);
|
|
|
|
|
|
+ unsigned nshared_workers = starpu_get_nshared_workers(sender_sched_ctx, poor_sched_ctx);
|
|
|
|
+ if((nworkers+nworkers_to_move-nshared_workers) > config->max_nworkers)
|
|
|
|
+ nworkers_to_move = nworkers > config->max_nworkers ? 0 : (config->max_nworkers - nworkers+nshared_workers);
|
|
if(nworkers_to_move == 0) poor_sched_ctx = STARPU_NMAX_SCHED_CTXS;
|
|
if(nworkers_to_move == 0) poor_sched_ctx = STARPU_NMAX_SCHED_CTXS;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
if(poor_sched_ctx != STARPU_NMAX_SCHED_CTXS)
|
|
if(poor_sched_ctx != STARPU_NMAX_SCHED_CTXS)
|
|
{
|
|
{
|
|
- int *workers_to_move = _get_first_workers(sender_sched_ctx, &nworkers_to_move);
|
|
|
|
|
|
+ int *workers_to_move = _get_first_workers(sender_sched_ctx, &nworkers_to_move, 0);
|
|
sched_ctx_hypervisor_move_workers(sender_sched_ctx, poor_sched_ctx, workers_to_move, nworkers_to_move);
|
|
sched_ctx_hypervisor_move_workers(sender_sched_ctx, poor_sched_ctx, workers_to_move, nworkers_to_move);
|
|
|
|
|
|
struct policy_config *new_config = sched_ctx_hypervisor_get_config(poor_sched_ctx);
|
|
struct policy_config *new_config = sched_ctx_hypervisor_get_config(poor_sched_ctx);
|
|
@@ -239,6 +249,108 @@ static unsigned _simple_resize(unsigned sender_sched_ctx, unsigned receiver_sche
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int* _get_workers_to_move(unsigned sender_sched_ctx, unsigned receiver_sched_ctx, int *nworkers)
|
|
|
|
+{
|
|
|
|
+ int *workers = NULL;
|
|
|
|
+ double v_receiver = sched_ctx_hypervisor_get_ctx_velocity(receiver_sched_ctx);
|
|
|
|
+ double receiver_remainig_flops = sched_ctx_hypervisor_get_flops_left(receiver_sched_ctx);
|
|
|
|
+ double sender_exp_end = sched_ctx_hypervisor_get_exp_end(sender_sched_ctx);
|
|
|
|
+ double sender_v_cpu = sched_ctx_hypervisor_get_cpu_velocity(sender_sched_ctx);
|
|
|
|
+// double v_gcpu = sched_ctx_hypervisor_get_gpu_velocity(sender_sched_ctx);
|
|
|
|
+
|
|
|
|
+ double v_for_rctx = (receiver_remainig_flops/(sender_exp_end - starpu_timing_now())) - v_receiver;
|
|
|
|
+// v_for_rctx /= 2;
|
|
|
|
+
|
|
|
|
+ int nworkers_needed = v_for_rctx/sender_v_cpu;
|
|
|
|
+/* printf("%d->%d: v_rec %lf v %lf v_cpu %lf w_needed %d \n", sender_sched_ctx, receiver_sched_ctx, */
|
|
|
|
+/* v_receiver, v_for_rctx, sender_v_cpu, nworkers_needed); */
|
|
|
|
+ if(nworkers_needed > 0)
|
|
|
|
+ {
|
|
|
|
+ struct policy_config *sender_config = sched_ctx_hypervisor_get_config(sender_sched_ctx);
|
|
|
|
+ unsigned potential_moving_cpus = _get_potential_nworkers(sender_config, sender_sched_ctx, STARPU_CPU_WORKER);
|
|
|
|
+ unsigned potential_moving_gpus = _get_potential_nworkers(sender_config, sender_sched_ctx, STARPU_CUDA_WORKER);
|
|
|
|
+ unsigned sender_nworkers = starpu_get_nworkers_of_sched_ctx(sender_sched_ctx);
|
|
|
|
+ struct policy_config *config = sched_ctx_hypervisor_get_config(receiver_sched_ctx);
|
|
|
|
+ unsigned nworkers_ctx = starpu_get_nworkers_of_sched_ctx(receiver_sched_ctx);
|
|
|
|
+
|
|
|
|
+ if(nworkers_needed < (potential_moving_cpus + 5 * potential_moving_gpus))
|
|
|
|
+ {
|
|
|
|
+ if((sender_nworkers - nworkers_needed) >= sender_config->min_nworkers)
|
|
|
|
+ {
|
|
|
|
+ if((nworkers_ctx + nworkers_needed) > config->max_nworkers)
|
|
|
|
+ nworkers_needed = nworkers_ctx > config->max_nworkers ? 0 : (config->max_nworkers - nworkers_ctx);
|
|
|
|
+
|
|
|
|
+ if(nworkers_needed > 0)
|
|
|
|
+ {
|
|
|
|
+ int ngpus = nworkers_needed / 5;
|
|
|
|
+ int *gpus;
|
|
|
|
+ gpus = _get_first_workers(sender_sched_ctx, &ngpus, STARPU_CUDA_WORKER);
|
|
|
|
+ int ncpus = nworkers_needed - ngpus;
|
|
|
|
+ int *cpus;
|
|
|
|
+ cpus = _get_first_workers(sender_sched_ctx, &ncpus, STARPU_CPU_WORKER);
|
|
|
|
+ workers = (int*)malloc(nworkers_needed*sizeof(int));
|
|
|
|
+ int i;
|
|
|
|
+ for(i = 0; i < ngpus; i++)
|
|
|
|
+ workers[(*nworkers)++] = gpus[i];
|
|
|
|
+
|
|
|
|
+ for(i = 0; i < ncpus; i++)
|
|
|
|
+ workers[(*nworkers)++] = cpus[i];
|
|
|
|
+
|
|
|
|
+ free(gpus);
|
|
|
|
+ free(cpus);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ int nworkers_to_move = _get_nworkers_to_move(sender_sched_ctx);
|
|
|
|
+
|
|
|
|
+ if(sender_nworkers - nworkers_to_move >= sender_config->min_nworkers)
|
|
|
|
+ {
|
|
|
|
+ unsigned nshared_workers = starpu_get_nshared_workers(sender_sched_ctx, receiver_sched_ctx);
|
|
|
|
+ if((nworkers_ctx + nworkers_to_move - nshared_workers) > config->max_nworkers)
|
|
|
|
+ nworkers_to_move = nworkers_ctx > config->max_nworkers ? 0 : (config->max_nworkers - nworkers_ctx + nshared_workers);
|
|
|
|
+
|
|
|
|
+ if(nworkers_to_move > 0)
|
|
|
|
+ {
|
|
|
|
+ workers = _get_first_workers(sender_sched_ctx, &nworkers_to_move, 0);
|
|
|
|
+ *nworkers = nworkers_to_move;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return workers;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static unsigned _simple_resize2(unsigned sender_sched_ctx, unsigned receiver_sched_ctx, unsigned force_resize)
|
|
|
|
+{
|
|
|
|
+ int ret = 1;
|
|
|
|
+ if(force_resize)
|
|
|
|
+ pthread_mutex_lock(&act_hypervisor_mutex);
|
|
|
|
+ else
|
|
|
|
+ ret = pthread_mutex_trylock(&act_hypervisor_mutex);
|
|
|
|
+ if(ret != EBUSY)
|
|
|
|
+ {
|
|
|
|
+ int nworkers_to_move = 0;
|
|
|
|
+ int *workers_to_move = _get_workers_to_move(sender_sched_ctx, receiver_sched_ctx, &nworkers_to_move);
|
|
|
|
+ if(nworkers_to_move > 0)
|
|
|
|
+ {
|
|
|
|
+ sched_ctx_hypervisor_move_workers(sender_sched_ctx, receiver_sched_ctx, workers_to_move, nworkers_to_move);
|
|
|
|
+
|
|
|
|
+ struct policy_config *new_config = sched_ctx_hypervisor_get_config(receiver_sched_ctx);
|
|
|
|
+ int i;
|
|
|
|
+ for(i = 0; i < nworkers_to_move; i++)
|
|
|
|
+ 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;
|
|
|
|
+
|
|
|
|
+ free(workers_to_move);
|
|
|
|
+ }
|
|
|
|
+ pthread_mutex_unlock(&act_hypervisor_mutex);
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
static unsigned simple_resize(unsigned sender_sched_ctx)
|
|
static unsigned simple_resize(unsigned sender_sched_ctx)
|
|
{
|
|
{
|
|
return _simple_resize(sender_sched_ctx, STARPU_NMAX_SCHED_CTXS, 1);
|
|
return _simple_resize(sender_sched_ctx, STARPU_NMAX_SCHED_CTXS, 1);
|