/* StarPU --- Runtime system for heterogeneous multicore architectures. * * Copyright (C) 2013-2014, 2016 Université de Bordeaux * Copyright (C) 2013 INRIA * Copyright (C) 2013 Simon Archipoff * * StarPU is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at * your option) any later version. * * StarPU is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU Lesser General Public License in COPYING.LGPL for more details. */ #include #include "helper_mct.h" /* Alpha, Beta and Gamma are MCT-specific values, which allows the * user to set more precisely the weight of each computing value. * Beta, for example, controls the weight of communications between * memories for the computation of the best component to choose. */ #define _STARPU_SCHED_ALPHA_DEFAULT 1.0 #define _STARPU_SCHED_BETA_DEFAULT 1.0 #define _STARPU_SCHED_GAMMA_DEFAULT 1000.0 #ifdef STARPU_USE_TOP static void param_modified(struct starpu_top_param* d) { /* Just to show parameter modification. */ fprintf(stderr, "%s has been modified : %f\n", d->name, *(double*) d->value); } #endif /* !STARPU_USE_TOP */ #ifdef STARPU_USE_TOP static const float alpha_minimum=0; static const float alpha_maximum=10.0; static const float beta_minimum=0; static const float beta_maximum=10.0; static const float gamma_minimum=0; static const float gamma_maximum=10000.0; static const float idle_power_minimum=0; static const float idle_power_maximum=10000.0; #endif /* !STARPU_USE_TOP */ struct _starpu_mct_data *starpu_mct_init_parameters(struct starpu_sched_component_mct_data *params) { struct _starpu_mct_data * data = malloc(sizeof(*data)); if (params) { data->alpha = params->alpha; data->beta = params->beta; data->_gamma = params->_gamma; data->idle_power = params->idle_power; } else { data->alpha = starpu_get_env_float_default("STARPU_SCHED_ALPHA", _STARPU_SCHED_ALPHA_DEFAULT); data->beta = starpu_get_env_float_default("STARPU_SCHED_BETA", _STARPU_SCHED_BETA_DEFAULT); data->_gamma = starpu_get_env_float_default("STARPU_SCHED_GAMMA", _STARPU_SCHED_GAMMA_DEFAULT); data->idle_power = starpu_get_env_float_default("STARPU_IDLE_POWER", 0.0); } #ifdef STARPU_USE_TOP starpu_top_register_parameter_float("MCT_ALPHA", &data->alpha, alpha_minimum, alpha_maximum, param_modified); starpu_top_register_parameter_float("MCT_BETA", &data->beta, beta_minimum, beta_maximum, param_modified); starpu_top_register_parameter_float("MCT_GAMMA", &data->_gamma, gamma_minimum, gamma_maximum, param_modified); starpu_top_register_parameter_float("MCT_IDLE_POWER", &data->idle_power, idle_power_minimum, idle_power_maximum, param_modified); #endif /* !STARPU_USE_TOP */ return data; } /* compute predicted_end by taking into account the case of the predicted transfer and the predicted_end overlap */ static double compute_expected_time(double now, double predicted_end, double predicted_length, double predicted_transfer) { STARPU_ASSERT(!isnan(now + predicted_end + predicted_length + predicted_transfer)); STARPU_ASSERT(now >= 0.0 && predicted_end >= 0.0 && predicted_length >= 0.0 && predicted_transfer >= 0.0); /* TODO: actually schedule transfers */ if (now + predicted_transfer < predicted_end) { /* We may hope that the transfer will be finished by * the start of the task. */ predicted_transfer = 0; } else { /* The transfer will not be finished by then, take the * remainder into account */ predicted_transfer -= (predicted_end - now); } predicted_end += predicted_transfer; predicted_end += predicted_length; return predicted_end; } double starpu_mct_compute_fitness(struct _starpu_mct_data * d, double exp_end, double min_exp_end, double max_exp_end, double transfer_len, double local_energy) { /* Note: the expected end includes the data transfer duration, which we want to be able to tune separately */ return d->alpha * (exp_end - min_exp_end) + d->beta * transfer_len + d->_gamma * local_energy + d->_gamma * d->idle_power * (exp_end - max_exp_end); } int starpu_mct_compute_expected_times(struct starpu_sched_component *component, struct starpu_task *task, double *estimated_lengths, double *estimated_transfer_length, double *estimated_ends_with_task, double *min_exp_end_with_task, double *max_exp_end_with_task, int *suitable_components) { int nsuitable_components = 0; int i; for(i = 0; i < component->nchildren; i++) { struct starpu_sched_component * c = component->children[i]; if(starpu_sched_component_execute_preds(c, task, estimated_lengths + i)) { if(isnan(estimated_lengths[i])) /* The perfmodel had been purged since the task was pushed * onto the mct component. */ continue; /* Estimated availability of worker */ double estimated_end = c->estimated_end(c); double now = starpu_timing_now(); if (estimated_end < now) estimated_end = now; estimated_transfer_length[i] = starpu_sched_component_transfer_length(c, task); estimated_ends_with_task[i] = compute_expected_time(now, estimated_end, estimated_lengths[i], estimated_transfer_length[i]); if(estimated_ends_with_task[i] < *min_exp_end_with_task) *min_exp_end_with_task = estimated_ends_with_task[i]; if(estimated_ends_with_task[i] > *max_exp_end_with_task) *max_exp_end_with_task = estimated_ends_with_task[i]; suitable_components[nsuitable_components++] = i; } } return nsuitable_components; }