X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/997eaf52ad0ae1eb34820b135c7ba884b2a17f3c..04d94544520a0cec2749347909d9500a81d0f670:/src/simdag/sd_task.c diff --git a/src/simdag/sd_task.c b/src/simdag/sd_task.c index 9109ff9a63..e7bd3091a7 100644 --- a/src/simdag/sd_task.c +++ b/src/simdag/sd_task.c @@ -91,12 +91,97 @@ SD_task_t SD_task_create(const char *name, void *data, double amount) sd_global->task_number++; #ifdef HAVE_TRACING - TRACE_sd_task_create(task); + task->category = NULL; #endif return task; } +static XBT_INLINE SD_task_t SD_task_create_sized(const char *name, + void *data, double amount, + int ws_count) +{ + SD_task_t task = SD_task_create(name, data, amount); + task->communication_amount = xbt_new0(double, ws_count * ws_count); + task->computation_amount = xbt_new0(double, ws_count); + task->workstation_nb = ws_count; + task->workstation_list = xbt_new0(SD_workstation_t, ws_count); + return task; +} + +/** @brief create a end-to-end communication task that can then be auto-scheduled + * + * Auto-scheduling mean that the task can be used with SD_task_schedulev(). This + * allows to specify the task costs at creation, and decouple them from the + * scheduling process where you just specify which resource should deliver the + * mandatory power. + * + * A end-to-end communication must be scheduled on 2 hosts, and the amount + * specified at creation is sent from hosts[0] to hosts[1]. + */ +SD_task_t SD_task_create_comm_e2e(const char *name, void *data, + double amount) +{ + SD_task_t res = SD_task_create_sized(name, data, amount, 2); + res->communication_amount[2] = amount; + res->kind = SD_TASK_COMM_E2E; + return res; +} + +/** @brief create a sequential computation task that can then be auto-scheduled + * + * Auto-scheduling mean that the task can be used with SD_task_schedulev(). This + * allows to specify the task costs at creation, and decouple them from the + * scheduling process where you just specify which resource should deliver the + * mandatory power. + * + * A sequential computation must be scheduled on 1 host, and the amount + * specified at creation to be run on hosts[0]. + * + * \param name the name of the task (can be \c NULL) + * \param data the user data you want to associate with the task (can be \c NULL) + * \param amount amount of compute work to be done by the task + * \return the new SD_TASK_COMP_SEQ typed task + */ +SD_task_t SD_task_create_comp_seq(const char *name, void *data, + double amount) +{ + SD_task_t res = SD_task_create_sized(name, data, amount, 1); + res->computation_amount[0] = amount; + res->kind = SD_TASK_COMP_SEQ; + return res; +} + +/** @brief create a parallel computation task that can then be auto-scheduled + * + * Auto-scheduling mean that the task can be used with SD_task_schedulev(). This + * allows to specify the task costs at creation, and decouple them from the + * scheduling process where you just specify which resource should deliver the + * mandatory power. + * + * A parallel computation can be scheduled on any number of host. + * The underlying speedup model is Amdahl's law. + * To be auto-scheduled, \see SD_task_distribute_comp_amdhal has to be called + * first. + * \param name the name of the task (can be \c NULL) + * \param data the user data you want to associate with the task (can be \c NULL) + * \param amount amount of compute work to be done by the task + * \param alpha purely serial fraction of the work to be done (in [0.;1.[) + * \return the new task + */ +SD_task_t SD_task_create_comp_par_amdahl(const char *name, void *data, + double amount, double alpha) +{ + xbt_assert(alpha < 1. && alpha >= 0., + "Invalid parameter: alpha must be in [0.;1.["); + + SD_task_t res = SD_task_create(name, data, amount); + res->alpha = alpha; + res->kind = SD_TASK_COMP_PAR_AMDAHL; + return res; +} + + /** * \brief Destroys a task. * @@ -131,7 +216,7 @@ void SD_task_destroy(SD_task_t task) sd_global->task_number--; #ifdef HAVE_TRACING - TRACE_sd_task_destroy(task); + if (task->category) xbt_free(task->category); #endif XBT_DEBUG("Task destroyed."); @@ -367,12 +452,15 @@ void SD_task_dump(SD_task_t task) case SD_TASK_COMP_SEQ: XBT_INFO(" - kind: sequential computation"); break; + case SD_TASK_COMP_PAR_AMDAHL: + XBT_INFO(" - kind: parallel computation following Amdahl's law"); + break; default: XBT_INFO(" - (unknown kind %d)", task->kind); } } XBT_INFO(" - amount: %.0f", SD_task_get_amount(task)); - XBT_INFO(" - Dependencies to satisfy: %d", task->unsatisfied_dependencies); + XBT_INFO(" - Dependencies to satisfy: %u", task->unsatisfied_dependencies); if (!xbt_dynar_is_empty(task->tasks_before)) { XBT_INFO(" - pre-dependencies:"); xbt_dynar_foreach(task->tasks_before, counter, dependency) { @@ -447,9 +535,10 @@ void SD_task_dependency_add(const char *name, void *data, SD_task_t src, SD_task_get_name(src)); if (!__SD_task_is_not_scheduled(src) && !__SD_task_is_schedulable(src) - && !__SD_task_is_scheduled_or_runnable(src)) + && !__SD_task_is_scheduled_or_runnable(src) && !__SD_task_is_running(src)) THROWF(arg_error, 0, - "Task '%s' must be SD_NOT_SCHEDULED, SD_SCHEDULABLE, SD_SCHEDULED or SD_RUNNABLE", + "Task '%s' must be SD_NOT_SCHEDULED, SD_SCHEDULABLE, SD_SCHEDULED or SD_RUNNABLE" + " or SD_RUNNING", SD_task_get_name(src)); if (!__SD_task_is_not_scheduled(dst) && !__SD_task_is_schedulable(dst) @@ -500,7 +589,7 @@ void SD_task_dependency_add(const char *name, void *data, SD_task_t src, } /** - * \brief Indacates whether there is a dependency between two tasks. + * \brief Indicates whether there is a dependency between two tasks. * * \param src a task * \param dst a task depending on \a src @@ -877,7 +966,7 @@ void __SD_task_really_run(SD_task_t task) xbt_assert(__SD_task_is_runnable_or_in_fifo(task), "Task '%s' is not runnable or in a fifo! Task state: %d", - SD_task_get_name(task), SD_task_get_state(task)); + SD_task_get_name(task), (int)SD_task_get_state(task)); xbt_assert(task->workstation_list != NULL, "Task '%s': workstation_list is NULL!", SD_task_get_name(task)); @@ -962,7 +1051,7 @@ void __SD_task_really_run(SD_task_t task) surf_workstations, computation_amount, communication_amount, - task->amount, task->rate); + task->rate); } else { xbt_free(surf_workstations); } @@ -979,7 +1068,7 @@ void __SD_task_really_run(SD_task_t task) __SD_task_destroy_scheduling_data(task); /* now the scheduling data are not useful anymore */ __SD_task_set_state(task, SD_RUNNING); xbt_assert(__SD_task_is_running(task), "Bad state of task '%s': %d", - SD_task_get_name(task), SD_task_get_state(task)); + SD_task_get_name(task), (int)SD_task_get_state(task)); } @@ -998,7 +1087,7 @@ int __SD_task_try_to_run(SD_task_t task) xbt_assert(__SD_task_is_runnable(task), "Task '%s' is not runnable! Task state: %d", - SD_task_get_name(task), SD_task_get_state(task)); + SD_task_get_name(task), (int)SD_task_get_state(task)); for (i = 0; i < task->workstation_nb; i++) { @@ -1020,7 +1109,7 @@ int __SD_task_try_to_run(SD_task_t task) } __SD_task_set_state(task, SD_IN_FIFO); xbt_assert(__SD_task_is_in_fifo(task), "Bad state of task '%s': %d", - SD_task_get_name(task), SD_task_get_state(task)); + SD_task_get_name(task), (int)SD_task_get_state(task)); XBT_DEBUG("Task '%s' state is now SD_IN_FIFO", SD_task_get_name(task)); } else { __SD_task_really_run(task); @@ -1046,7 +1135,7 @@ void __SD_task_just_done(SD_task_t task) xbt_assert(__SD_task_is_running(task), "The task must be running! Task state: %d", - SD_task_get_state(task)); + (int)SD_task_get_state(task)); xbt_assert(task->workstation_list != NULL, "Task '%s': workstation_list is NULL!", SD_task_get_name(task)); @@ -1065,7 +1154,7 @@ void __SD_task_just_done(SD_task_t task) for (i = 0; i < task->workstation_nb; i++) { workstation = task->workstation_list[i]; XBT_DEBUG("Workstation '%s': access_mode = %d", - SD_workstation_get_name(workstation), workstation->access_mode); + SD_workstation_get_name(workstation), (int)workstation->access_mode); if (workstation->access_mode == SD_WORKSTATION_SEQUENTIAL_ACCESS) { xbt_assert(workstation->task_fifo != NULL, "Workstation '%s' has sequential access but no fifo!", @@ -1088,7 +1177,7 @@ void __SD_task_just_done(SD_task_t task) xbt_assert(__SD_task_is_in_fifo(candidate), "Bad state of candidate '%s': %d", SD_task_get_name(candidate), - SD_task_get_state(candidate)); + (int)SD_task_get_state(candidate)); } XBT_DEBUG("Candidate in fifo: %p", candidate); @@ -1127,7 +1216,7 @@ void __SD_task_just_done(SD_task_t task) xbt_assert(__SD_task_is_in_fifo(candidate), "Bad state of candidate '%s': %d", - SD_task_get_name(candidate), SD_task_get_state(candidate)); + SD_task_get_name(candidate), (int)SD_task_get_state(candidate)); for (j = 0; j < candidate->workstation_nb && can_start; j++) { workstation = candidate->workstation_list[j]; @@ -1161,7 +1250,7 @@ void __SD_task_just_done(SD_task_t task) /* finally execute the task */ XBT_DEBUG("Task '%s' state: %d", SD_task_get_name(candidate), - SD_task_get_state(candidate)); + (int)SD_task_get_state(candidate)); __SD_task_really_run(candidate); XBT_DEBUG @@ -1171,7 +1260,7 @@ void __SD_task_just_done(SD_task_t task) xbt_assert(__SD_task_is_running(candidate), "Bad state of task '%s': %d", SD_task_get_name(candidate), - SD_task_get_state(candidate)); + (int)SD_task_get_state(candidate)); XBT_DEBUG("Okay, the task is running."); } /* can start */ @@ -1235,56 +1324,27 @@ double SD_task_get_finish_time(SD_task_t task) else return task->finish_time; } - -static XBT_INLINE SD_task_t SD_task_create_sized(const char *name, - void *data, double amount, - int ws_count) +/** @brief Blah + * + */ +void SD_task_distribute_comp_amdhal(SD_task_t task, int ws_count) { - SD_task_t task = SD_task_create(name, data, amount); - task->communication_amount = xbt_new0(double, ws_count * ws_count); + int i; + xbt_assert(task->kind == SD_TASK_COMP_PAR_AMDAHL, + "Task %s is not a SD_TASK_COMP_PAR_AMDAHL typed task." + "Cannot use this function.", + SD_task_get_name(task)); + task->computation_amount = xbt_new0(double, ws_count); + task->communication_amount = xbt_new0(double, ws_count * ws_count); task->workstation_nb = ws_count; task->workstation_list = xbt_new0(SD_workstation_t, ws_count); - return task; -} - -/** @brief create a end-to-end communication task that can then be auto-scheduled - * - * Auto-scheduling mean that the task can be used with SD_task_schedulev(). This - * allows to specify the task costs at creation, and decorelate them from the - * scheduling process where you just specify which resource should deliver the - * mandatory power. - * - * A end-to-end communication must be scheduled on 2 hosts, and the amount - * specified at creation is sent from hosts[0] to hosts[1]. - */ -SD_task_t SD_task_create_comm_e2e(const char *name, void *data, - double amount) -{ - SD_task_t res = SD_task_create_sized(name, data, amount, 2); - res->communication_amount[2] = amount; - res->kind = SD_TASK_COMM_E2E; - return res; -} - -/** @brief create a sequential computation task that can then be auto-scheduled - * - * Auto-scheduling mean that the task can be used with SD_task_schedulev(). This - * allows to specify the task costs at creation, and decorelate them from the - * scheduling process where you just specify which resource should deliver the - * mandatory power. - * - * A sequential computation must be scheduled on 1 host, and the amount - * specified at creation to be run on hosts[0]. - */ -SD_task_t SD_task_create_comp_seq(const char *name, void *data, - double amount) -{ - SD_task_t res = SD_task_create_sized(name, data, amount, 1); - res->computation_amount[0] = amount; - res->kind = SD_TASK_COMP_SEQ; - return res; -} + + for(i=0;icomputation_amount[i] = + (task->alpha + (1 - task->alpha)/ws_count) * task->amount; + } +} /** @brief Auto-schedules a task. * @@ -1316,6 +1376,8 @@ void SD_task_schedulev(SD_task_t task, int count, SD_task_get_name(task)); switch (task->kind) { case SD_TASK_COMM_E2E: + case SD_TASK_COMP_PAR_AMDAHL: + xbt_assert(task->computation_amount, "SD_task_distribute_comp_amdhal should be called first."); case SD_TASK_COMP_SEQ: xbt_assert(task->workstation_nb == count,"Got %d locations, but were expecting %d locations",count,task->workstation_nb); for (i = 0; i < count; i++) @@ -1334,6 +1396,13 @@ void SD_task_schedulev(SD_task_t task, int count, task->communication_amount[2]); } + if (task->kind == SD_TASK_COMP_PAR_AMDAHL) { + XBT_VERB("Schedule computation task %s on %d hosts. It costs %.f flops on each host", + SD_task_get_name(task), + task->workstation_nb, + task->computation_amount[0]); + } + /* Iterate over all childs and parent being COMM_E2E to say where I am located (and start them if runnable) */ if (task->kind == SD_TASK_COMP_SEQ) { XBT_VERB("Schedule computation task %s on %s. It costs %.f flops", @@ -1400,3 +1469,50 @@ void SD_task_schedulel(SD_task_t task, int count, ...) SD_task_schedulev(task, count, list); free(list); } + +/** + * \brief Sets the tracing category of a task. + * + * This function should be called after the creation of a + * SimDAG task, to define the category of that task. The first + * parameter must contain a task that was created with the + * function #SD_task_create. The second parameter must contain + * a category that was previously declared with the function + * #TRACE_category. + * + * \param task The task to be considered + * \param category the name of the category to be associated to the task + * + * \see SD_task_get_category, TRACE_category, TRACE_category_with_color + */ +void SD_task_set_category (SD_task_t task, const char *category) +{ +#ifdef HAVE_TRACING + if (!TRACE_is_enabled()) return; + if (task == NULL) return; + if (category == NULL){ + if (task->category) xbt_free (task->category); + task->category = NULL; + }else{ + task->category = xbt_strdup (category); + } +#endif +} + +/** + * \brief Gets the current tracing category of a task. + * + * \param task The task to be considered + * + * \see SD_task_set_category + * + * \return Returns the name of the tracing category of the given task, NULL otherwise + */ +const char *SD_task_get_category (SD_task_t task) +{ +#ifdef HAVE_TRACING + return task->category; +#else + return NULL; +#endif +}