|
@@ -6,13 +6,13 @@
|
|
|
|
|
|
struct simple_policy_config {
|
|
|
|
|
|
- unsigned min_nprocs;
|
|
|
+ int min_nworkers;
|
|
|
|
|
|
|
|
|
- unsigned max_nprocs;
|
|
|
+ int max_nworkers;
|
|
|
|
|
|
|
|
|
- unsigned granularity;
|
|
|
+ int granularity;
|
|
|
|
|
|
|
|
|
|
|
@@ -26,27 +26,31 @@ struct simple_policy_config {
|
|
|
double min_working[STARPU_NMAXWORKERS];
|
|
|
|
|
|
|
|
|
- unsigned fixed_procs[STARPU_NMAXWORKERS];
|
|
|
+ int fixed_workers[STARPU_NMAXWORKERS];
|
|
|
|
|
|
|
|
|
double new_workers_max_idle;
|
|
|
+
|
|
|
+
|
|
|
+ double empty_ctx_max_idle[STARPU_NMAXWORKERS];
|
|
|
};
|
|
|
|
|
|
static struct simple_policy_config* _create_config(void)
|
|
|
{
|
|
|
struct simple_policy_config *config = (struct simple_policy_config *)malloc(sizeof(struct simple_policy_config));
|
|
|
- config->min_nprocs = 0;
|
|
|
- config->max_nprocs = 0;
|
|
|
- config->new_workers_max_idle = MAX_IDLE_TIME;
|
|
|
+ config->min_nworkers = -1;
|
|
|
+ config->max_nworkers = -1;
|
|
|
+ config->new_workers_max_idle = -1.0;
|
|
|
|
|
|
int i;
|
|
|
for(i = 0; i < STARPU_NMAXWORKERS; i++)
|
|
|
{
|
|
|
- config->granularity = 1;
|
|
|
- config->priority[i] = 0;
|
|
|
- config->fixed_procs[i] = 0;
|
|
|
- config->max_idle[i] = MAX_IDLE_TIME;
|
|
|
- config->min_working[i] = MIN_WORKING_TIME;
|
|
|
+ config->granularity = -1;
|
|
|
+ config->priority[i] = -1;
|
|
|
+ config->fixed_workers[i] = -1;
|
|
|
+ config->max_idle[i] = -1.0;
|
|
|
+ config->empty_ctx_max_idle[i] = -1.0;
|
|
|
+ config->min_working[i] = -1.0;
|
|
|
}
|
|
|
|
|
|
return config;
|
|
@@ -55,6 +59,21 @@ static struct simple_policy_config* _create_config(void)
|
|
|
static void simple_add_sched_ctx(unsigned sched_ctx)
|
|
|
{
|
|
|
struct simple_policy_config *config = _create_config();
|
|
|
+ config->min_nworkers = 0;
|
|
|
+ config->max_nworkers = 0;
|
|
|
+ config->new_workers_max_idle = MAX_IDLE_TIME;
|
|
|
+
|
|
|
+ int i;
|
|
|
+ for(i = 0; i < STARPU_NMAXWORKERS; i++)
|
|
|
+ {
|
|
|
+ config->granularity = 1;
|
|
|
+ config->priority[i] = 0;
|
|
|
+ config->fixed_workers[i] = 0;
|
|
|
+ config->max_idle[i] = MAX_IDLE_TIME;
|
|
|
+ config->empty_ctx_max_idle[i] = MAX_IDLE_TIME;
|
|
|
+ config->min_working[i] = MIN_WORKING_TIME;
|
|
|
+ }
|
|
|
+
|
|
|
sched_ctx_hypervisor_set_config(sched_ctx, config);
|
|
|
}
|
|
|
|
|
@@ -81,22 +100,29 @@ static int _compute_priority(unsigned sched_ctx)
|
|
|
return total_priority;
|
|
|
}
|
|
|
|
|
|
-static unsigned _get_highest_priority_sched_ctx(unsigned req_sched_ctx, int *sched_ctxs, int nsched_ctxs)
|
|
|
+static unsigned _find_poor_sched_ctx(unsigned req_sched_ctx, int *sched_ctxs, int nsched_ctxs, int nworkers_to_move)
|
|
|
{
|
|
|
int i;
|
|
|
int highest_priority = -1;
|
|
|
int current_priority = 0;
|
|
|
unsigned sched_ctx = STARPU_NMAX_SCHED_CTXS;
|
|
|
|
|
|
+ struct simple_policy_config *config = NULL;
|
|
|
+
|
|
|
for(i = 0; i < nsched_ctxs; i++)
|
|
|
{
|
|
|
if(sched_ctxs[i] != STARPU_NMAX_SCHED_CTXS && sched_ctxs[i] != req_sched_ctx)
|
|
|
{
|
|
|
- current_priority = _compute_priority(sched_ctxs[i]);
|
|
|
- if (highest_priority < current_priority)
|
|
|
+ unsigned nworkers = starpu_get_nworkers_of_sched_ctx(sched_ctxs[i]);
|
|
|
+ config = (struct simple_policy_config*)sched_ctx_hypervisor_get_config(sched_ctxs[i]);
|
|
|
+ if((nworkers + nworkers_to_move) <= config->max_nworkers)
|
|
|
{
|
|
|
- highest_priority = current_priority;
|
|
|
- sched_ctx = sched_ctxs[i];
|
|
|
+ current_priority = _compute_priority(sched_ctxs[i]);
|
|
|
+ if (highest_priority < current_priority)
|
|
|
+ {
|
|
|
+ highest_priority = current_priority;
|
|
|
+ sched_ctx = sched_ctxs[i];
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -104,13 +130,13 @@ static unsigned _get_highest_priority_sched_ctx(unsigned req_sched_ctx, int *sch
|
|
|
return sched_ctx;
|
|
|
}
|
|
|
|
|
|
-int* _get_first_workers(unsigned sched_ctx, int nworkers)
|
|
|
+int* _get_first_workers(unsigned sched_ctx, int *nworkers)
|
|
|
{
|
|
|
struct simple_policy_config *config = (struct simple_policy_config*)sched_ctx_hypervisor_get_config(sched_ctx);
|
|
|
|
|
|
- int *curr_workers = (int*)malloc(nworkers * sizeof(int));
|
|
|
+ int *curr_workers = (int*)malloc((*nworkers) * sizeof(int));
|
|
|
int i;
|
|
|
- for(i = 0; i < nworkers; i++)
|
|
|
+ for(i = 0; i < *nworkers; i++)
|
|
|
curr_workers[i] = -1;
|
|
|
|
|
|
struct worker_collection *workers = starpu_get_worker_collection_of_sched_ctx(sched_ctx);
|
|
@@ -121,13 +147,13 @@ int* _get_first_workers(unsigned sched_ctx, int nworkers)
|
|
|
if(workers->init_cursor)
|
|
|
workers->init_cursor(workers);
|
|
|
|
|
|
- for(index = 0; index < nworkers; index++)
|
|
|
+ for(index = 0; index < *nworkers; index++)
|
|
|
{
|
|
|
while(workers->has_next(workers))
|
|
|
{
|
|
|
considered = 0;
|
|
|
worker = workers->get_next(workers);
|
|
|
- if(!config->fixed_procs[worker])
|
|
|
+ if(!config->fixed_workers[worker])
|
|
|
{
|
|
|
for(i = 0; i < index; i++)
|
|
|
{
|
|
@@ -146,7 +172,10 @@ int* _get_first_workers(unsigned sched_ctx, int nworkers)
|
|
|
}
|
|
|
|
|
|
if(curr_workers[index] < 0)
|
|
|
+ {
|
|
|
+ *nworkers = index;
|
|
|
break;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if(workers->init_cursor)
|
|
@@ -155,11 +184,11 @@ int* _get_first_workers(unsigned sched_ctx, int nworkers)
|
|
|
return curr_workers;
|
|
|
}
|
|
|
|
|
|
-static int _get_potential_nworkers(struct simple_policy_config *config, unsigned sched_ctx)
|
|
|
+static unsigned _get_potential_nworkers(struct simple_policy_config *config, unsigned sched_ctx)
|
|
|
{
|
|
|
struct worker_collection *workers = starpu_get_worker_collection_of_sched_ctx(sched_ctx);
|
|
|
|
|
|
- int potential_workers = 0;
|
|
|
+ unsigned potential_workers = 0;
|
|
|
int worker;
|
|
|
|
|
|
if(workers->init_cursor)
|
|
@@ -167,7 +196,7 @@ static int _get_potential_nworkers(struct simple_policy_config *config, unsigned
|
|
|
while(workers->has_next(workers))
|
|
|
{
|
|
|
worker = workers->get_next(workers);
|
|
|
- if(!config->fixed_procs[worker])
|
|
|
+ if(!config->fixed_workers[worker])
|
|
|
potential_workers++;
|
|
|
}
|
|
|
if(workers->init_cursor)
|
|
@@ -176,59 +205,86 @@ static int _get_potential_nworkers(struct simple_policy_config *config, unsigned
|
|
|
return potential_workers;
|
|
|
}
|
|
|
|
|
|
-static unsigned simple_manage_idle_time(unsigned req_sched_ctx, int *sched_ctxs, int nsched_ctxs, int worker, double idle_time)
|
|
|
+static unsigned _get_nworkers_to_move(unsigned req_sched_ctx)
|
|
|
{
|
|
|
struct simple_policy_config *config = (struct simple_policy_config*)sched_ctx_hypervisor_get_config(req_sched_ctx);
|
|
|
-
|
|
|
- if(config != NULL && idle_time > config->max_idle[worker])
|
|
|
+ unsigned nworkers = starpu_get_nworkers_of_sched_ctx(req_sched_ctx);
|
|
|
+ unsigned nworkers_to_move = 0;
|
|
|
+
|
|
|
+ unsigned potential_moving_workers = _get_potential_nworkers(config, req_sched_ctx);
|
|
|
+ if(potential_moving_workers > 0)
|
|
|
{
|
|
|
- int ret = pthread_mutex_trylock(&act_hypervisor_mutex);
|
|
|
- if(ret != EBUSY)
|
|
|
- {
|
|
|
+ if(potential_moving_workers <= config->min_nworkers)
|
|
|
+
|
|
|
+
|
|
|
|
|
|
- unsigned nworkers = starpu_get_nworkers_of_sched_ctx(req_sched_ctx);
|
|
|
- unsigned nworkers_to_move = 0;
|
|
|
-
|
|
|
-
|
|
|
- int potential_moving_workers = _get_potential_nworkers(config, req_sched_ctx);
|
|
|
- if(potential_moving_workers > 0)
|
|
|
- {
|
|
|
- if(potential_moving_workers > config->granularity)
|
|
|
- {
|
|
|
- if((nworkers - config->granularity) > config->min_nprocs)
|
|
|
- nworkers_to_move = config->granularity;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- int nfixed_workers = nworkers - potential_moving_workers;
|
|
|
- if(nfixed_workers >= config->min_nprocs)
|
|
|
- nworkers_to_move = potential_moving_workers;
|
|
|
- else
|
|
|
- nworkers_to_move = potential_moving_workers - (config->min_nprocs - nfixed_workers);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(nworkers_to_move > 0)
|
|
|
- {
|
|
|
- unsigned prio_sched_ctx = _get_highest_priority_sched_ctx(req_sched_ctx, sched_ctxs, nsched_ctxs);
|
|
|
- if(prio_sched_ctx != STARPU_NMAX_SCHED_CTXS)
|
|
|
- {
|
|
|
- int *workers_to_move = _get_first_workers(req_sched_ctx, nworkers_to_move);
|
|
|
- sched_ctx_hypervisor_resize(req_sched_ctx, prio_sched_ctx, workers_to_move, nworkers_to_move);
|
|
|
-
|
|
|
- struct simple_policy_config *prio_config = (struct simple_policy_config*)sched_ctx_hypervisor_get_config(prio_sched_ctx);
|
|
|
- int i;
|
|
|
- for(i = 0; i < nworkers_to_move; i++)
|
|
|
- prio_config->max_idle[workers_to_move[i]] = prio_config->max_idle[workers_to_move[i]] !=MAX_IDLE_TIME ? prio_config->max_idle[workers_to_move[i]] : prio_config->new_workers_max_idle;
|
|
|
-
|
|
|
- free(workers_to_move);
|
|
|
- }
|
|
|
- }
|
|
|
- pthread_mutex_unlock(&act_hypervisor_mutex);
|
|
|
- return 0;
|
|
|
+ nworkers_to_move = potential_moving_workers;
|
|
|
+ else if(potential_moving_workers > config->max_nworkers)
|
|
|
+ {
|
|
|
+ if((potential_moving_workers - config->granularity) > config->max_nworkers)
|
|
|
+ nworkers_to_move = config->granularity;
|
|
|
+ else
|
|
|
+ nworkers_to_move = potential_moving_workers - config->max_nworkers;
|
|
|
+
|
|
|
+ }
|
|
|
+ else if(potential_moving_workers > config->granularity)
|
|
|
+ {
|
|
|
+ if((nworkers - config->granularity) > config->min_nworkers)
|
|
|
+ nworkers_to_move = config->granularity;
|
|
|
+ else
|
|
|
+ nworkers_to_move = potential_moving_workers - config->min_nworkers;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ int nfixed_workers = nworkers - potential_moving_workers;
|
|
|
+ if(nfixed_workers >= config->min_nworkers)
|
|
|
+ nworkers_to_move = potential_moving_workers;
|
|
|
+ else
|
|
|
+ nworkers_to_move = potential_moving_workers - (config->min_nworkers - nfixed_workers);
|
|
|
}
|
|
|
+ if((nworkers - nworkers_to_move) > config->max_nworkers)
|
|
|
+ nworkers_to_move = nworkers - config->max_nworkers;
|
|
|
}
|
|
|
- return 1;
|
|
|
+ return nworkers_to_move;
|
|
|
+}
|
|
|
+
|
|
|
+static unsigned simple_resize(unsigned req_sched_ctx, int *sched_ctxs, int nsched_ctxs)
|
|
|
+{
|
|
|
+ int ret = pthread_mutex_trylock(&act_hypervisor_mutex);
|
|
|
+ if(ret != EBUSY)
|
|
|
+ {
|
|
|
+ unsigned nworkers_to_move = _get_nworkers_to_move(req_sched_ctx);
|
|
|
+
|
|
|
+ if(nworkers_to_move > 0)
|
|
|
+ {
|
|
|
+ unsigned poor_sched_ctx = _find_poor_sched_ctx(req_sched_ctx, sched_ctxs, nsched_ctxs, nworkers_to_move);
|
|
|
+ if(poor_sched_ctx != STARPU_NMAX_SCHED_CTXS)
|
|
|
+ {
|
|
|
+ int *workers_to_move = _get_first_workers(req_sched_ctx, &nworkers_to_move);
|
|
|
+ sched_ctx_hypervisor_move_workers(req_sched_ctx, poor_sched_ctx, workers_to_move, nworkers_to_move);
|
|
|
+
|
|
|
+ struct simple_policy_config *new_config = (struct simple_policy_config*)sched_ctx_hypervisor_get_config(poor_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 void simple_manage_idle_time(unsigned req_sched_ctx, int *sched_ctxs, int nsched_ctxs, int worker, double idle_time)
|
|
|
+{
|
|
|
+ struct simple_policy_config *config = (struct simple_policy_config*)sched_ctx_hypervisor_get_config(req_sched_ctx);
|
|
|
+
|
|
|
+ if(config != NULL && idle_time > config->max_idle[worker])
|
|
|
+ simple_resize(req_sched_ctx, sched_ctxs, nsched_ctxs);
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
static void* simple_ioctl(unsigned sched_ctx, va_list varg_list, unsigned later)
|
|
@@ -261,6 +317,16 @@ static void* simple_ioctl(unsigned sched_ctx, va_list varg_list, unsigned later)
|
|
|
|
|
|
break;
|
|
|
|
|
|
+ case HYPERVISOR_EMPTY_CTX_MAX_IDLE:
|
|
|
+ workerids = va_arg(varg_list, int*);
|
|
|
+ nworkers = va_arg(varg_list, int);
|
|
|
+ double empty_ctx_max_idle = va_arg(varg_list, double);
|
|
|
+
|
|
|
+ for(i = 0; i < nworkers; i++)
|
|
|
+ config->empty_ctx_max_idle[workerids[i]] = empty_ctx_max_idle;
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
case HYPERVISOR_MIN_WORKING:
|
|
|
workerids = va_arg(varg_list, int*);
|
|
|
nworkers = va_arg(varg_list, int);
|
|
@@ -280,24 +346,24 @@ static void* simple_ioctl(unsigned sched_ctx, va_list varg_list, unsigned later)
|
|
|
config->priority[workerids[i]] = priority;
|
|
|
break;
|
|
|
|
|
|
- case HYPERVISOR_MIN_PROCS:
|
|
|
- config->min_nprocs = va_arg(varg_list, unsigned);
|
|
|
+ case HYPERVISOR_MIN_WORKERS:
|
|
|
+ config->min_nworkers = va_arg(varg_list, unsigned);
|
|
|
break;
|
|
|
|
|
|
- case HYPERVISOR_MAX_PROCS:
|
|
|
- config->max_nprocs = va_arg(varg_list, unsigned);
|
|
|
+ case HYPERVISOR_MAX_WORKERS:
|
|
|
+ config->max_nworkers = va_arg(varg_list, unsigned);
|
|
|
break;
|
|
|
|
|
|
case HYPERVISOR_GRANULARITY:
|
|
|
config->granularity = va_arg(varg_list, unsigned);
|
|
|
break;
|
|
|
|
|
|
- case HYPERVISOR_FIXED_PROCS:
|
|
|
+ case HYPERVISOR_FIXED_WORKERS:
|
|
|
workerids = va_arg(varg_list, int*);
|
|
|
nworkers = va_arg(varg_list, int);
|
|
|
|
|
|
for(i = 0; i < nworkers; i++)
|
|
|
- config->fixed_procs[workerids[i]] = 1;
|
|
|
+ config->fixed_workers[workerids[i]] = 1;
|
|
|
break;
|
|
|
|
|
|
case HYPERVISOR_NEW_WORKERS_MAX_IDLE:
|
|
@@ -326,18 +392,19 @@ static void simple_update_config(void *old_config, void* config)
|
|
|
struct simple_policy_config *old = (struct simple_policy_config*)old_config;
|
|
|
struct simple_policy_config *new = (struct simple_policy_config*)config;
|
|
|
|
|
|
- old->min_nprocs = new->min_nprocs != 0 ? new->min_nprocs : old->min_nprocs ;
|
|
|
- old->max_nprocs = new->max_nprocs != 0 ? new->max_nprocs : old->max_nprocs ;
|
|
|
- old->new_workers_max_idle = new->new_workers_max_idle != MAX_IDLE_TIME ? new->new_workers_max_idle : old->new_workers_max_idle;
|
|
|
- old->granularity = new->min_nprocs != 1 ? new->granularity : old->granularity;
|
|
|
+ old->min_nworkers = new->min_nworkers != -1 ? new->min_nworkers : old->min_nworkers ;
|
|
|
+ old->max_nworkers = new->max_nworkers != -1 ? new->max_nworkers : old->max_nworkers ;
|
|
|
+ old->new_workers_max_idle = new->new_workers_max_idle != -1.0 ? new->new_workers_max_idle : old->new_workers_max_idle;
|
|
|
+ old->granularity = new->granularity != -1 ? new->granularity : old->granularity;
|
|
|
|
|
|
int i;
|
|
|
for(i = 0; i < STARPU_NMAXWORKERS; i++)
|
|
|
{
|
|
|
- old->priority[i] = new->priority[i] != 0 ? new->priority[i] : old->priority[i];
|
|
|
- old->fixed_procs[i] = new->fixed_procs[i] != 0 ? new->fixed_procs[i] : old->fixed_procs[i];
|
|
|
- old->max_idle[i] = new->max_idle[i] != MAX_IDLE_TIME ? new->max_idle[i] : old->max_idle[i];;
|
|
|
- old->min_working[i] = new->min_working[i] != MIN_WORKING_TIME ? new->min_working[i] : old->min_working[i];
|
|
|
+ old->priority[i] = new->priority[i] != -1 ? new->priority[i] : old->priority[i];
|
|
|
+ old->fixed_workers[i] = new->fixed_workers[i] != -1 ? new->fixed_workers[i] : old->fixed_workers[i];
|
|
|
+ old->max_idle[i] = new->max_idle[i] != -1.0 ? new->max_idle[i] : old->max_idle[i];
|
|
|
+ old->empty_ctx_max_idle[i] = new->empty_ctx_max_idle[i] != -1.0 ? new->empty_ctx_max_idle[i] : old->empty_ctx_max_idle[i];
|
|
|
+ old->min_working[i] = new->min_working[i] != -1.0 ? new->min_working[i] : old->min_working[i];
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -353,5 +420,6 @@ struct hypervisor_policy simple_policy = {
|
|
|
.remove_sched_ctx = simple_remove_sched_ctx,
|
|
|
.ioctl = simple_ioctl,
|
|
|
.manage_idle_time = simple_manage_idle_time,
|
|
|
+ .resize = simple_resize,
|
|
|
.update_config = simple_update_config
|
|
|
};
|