From: thiery Date: Tue, 4 Jul 2006 16:42:25 +0000 (+0000) Subject: Add functions SD_workstation_get_computation_time, SD_workstation_route_get_communica... X-Git-Tag: v3.3~2879 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/0cf55eb21f1c33798b700bc0608d25ed45f52e7b Add functions SD_workstation_get_computation_time, SD_workstation_route_get_communication_time, SD_workstation_route_get_latency, SD_workstation_route_get_bandwidth and SD_task_get_execution_time git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@2479 48e7efb5-ca39-0410-a469-dd3cf9ba447f --- diff --git a/examples/simdag/sd_test.c b/examples/simdag/sd_test.c index b2c435ae9f..e5f6f156cb 100644 --- a/examples/simdag/sd_test.c +++ b/examples/simdag/sd_test.c @@ -8,12 +8,14 @@ XBT_LOG_NEW_DEFAULT_CATEGORY(sd_test, "Logging specific to this SimDag example"); int main(int argc, char **argv) { + int i; /* initialisation of SD */ SD_init(&argc, argv); - /* xbt_log_control_set("sd.thres=debug");*/ - +/* xbt_log_control_set("sd_test.thres=debug"); */ +/* xbt_log_control_set("sd.thres=debug"); */ + if (argc < 2) { INFO1("Usage: %s platform_file", argv[0]); INFO1("example: %s sd_platform.xml", argv[0]); @@ -24,6 +26,34 @@ int main(int argc, char **argv) { char * platform_file = argv[1]; SD_create_environment(platform_file); + /* test the estimation functions (use small_platform.xml) */ + SD_workstation_t w1 = SD_workstation_get_by_name("Jupiter"); + SD_workstation_t w2 = SD_workstation_get_by_name("Ginette"); + const char *name1 = SD_workstation_get_name(w1); + const char *name2 = SD_workstation_get_name(w2); + const double computation_amount1 = 2000000; + const double computation_amount2 = 1000000; + const double communication_amount12 = 2000000; + const double communication_amount21 = 3000000; + INFO3("Computation time for %f flops on %s: %f", computation_amount1, name1, + SD_workstation_get_computation_time(w1, computation_amount1)); + INFO3("Computation time for %f flops on %s: %f", computation_amount2, name2, + SD_workstation_get_computation_time(w2, computation_amount2)); + + INFO2("Route between %s and %s:", name1, name2); + SD_link_t *route = SD_workstation_route_get_list(w1, w2); + int route_size = SD_workstation_route_get_size(w1, w2); + for (i = 0; i < route_size; i++) { + INFO3("\tLink %s: latency = %f, bandwidth = %f", SD_link_get_name(route[i]), + SD_link_get_current_latency(route[i]), SD_link_get_current_bandwidth(route[i])); + } + INFO2("Route latency = %f, route bandwidth = %f", SD_workstation_route_get_latency(w1, w2), + SD_workstation_route_get_bandwidth(w1, w2)); + INFO4("Communication time for %f bytes between %s and %s: %f", communication_amount12, name1, name2, + SD_workstation_route_get_communication_time(w1, w2, communication_amount12)); + INFO4("Communication time for %f bytes between %s and %s: %f", communication_amount21, name2, name1, + SD_workstation_route_get_communication_time(w2, w1, communication_amount21)); + /* creation of the tasks and their dependencies */ SD_task_t taskA = SD_task_create("Task A", NULL, 10.0); SD_task_t taskB = SD_task_create("Task B", NULL, 40.0); @@ -34,19 +64,28 @@ int main(int argc, char **argv) { SD_task_dependency_add(NULL, NULL, taskC, taskA); SD_task_dependency_add(NULL, NULL, taskD, taskB); SD_task_dependency_add(NULL, NULL, taskD, taskC); - /* SD_task_dependency_add(NULL, NULL, taskA, taskD); /\* deadlock */ + /* SD_task_dependency_add(NULL, NULL, taskA, taskD); /\* deadlock *\/ */ - /* let's launch the simulation! */ + /* scheduling parameters */ - int workstation_number = 2; - const SD_workstation_t *workstation_list = SD_workstation_get_list(); - double computation_amount[] = {100, 200}; + const int workstation_number = 2; + /* const SD_workstation_t *workstation_list = SD_workstation_get_list();*/ + const SD_workstation_t workstation_list[] = {w1, w2}; + double computation_amount[] = {computation_amount1, computation_amount2}; double communication_amount[] = { - 0, 30, - 20, 0 + 0, communication_amount12, + communication_amount21, 0 }; - double rate = 1; + double rate = -1.0; + + /* estimated time */ + SD_task_t task = taskD; + INFO2("Estimated time for '%s': %f", SD_task_get_name(task), + SD_task_get_execution_time(task, workstation_number, workstation_list, + computation_amount, communication_amount, rate)); + + /* let's launch the simulation! */ SD_task_schedule(taskA, workstation_number, workstation_list, computation_amount, communication_amount, rate); @@ -60,7 +99,6 @@ int main(int argc, char **argv) { SD_task_watch(taskC, SD_DONE); SD_task_t *changed_tasks; - int i; changed_tasks = SD_simulate(0.001); @@ -96,10 +134,15 @@ int main(int argc, char **argv) { free(changed_tasks); + DEBUG0("Destroying tasks..."); + SD_task_destroy(taskA); SD_task_destroy(taskB); SD_task_destroy(taskC); SD_task_destroy(taskD); + + DEBUG0("Tasks destroyed. Exiting SimDag..."); + SD_exit(); return 0; } diff --git a/include/simdag/simdag.h b/include/simdag/simdag.h index 1c2f004151..5affb36365 100644 --- a/include/simdag/simdag.h +++ b/include/simdag/simdag.h @@ -55,6 +55,13 @@ SD_link_t* SD_workstation_route_get_list(SD_workstation_t src, SD_w int SD_workstation_route_get_size(SD_workstation_t src, SD_workstation_t dst); double SD_workstation_get_power(SD_workstation_t workstation); double SD_workstation_get_available_power(SD_workstation_t workstation); + +double SD_workstation_get_computation_time(SD_workstation_t workstation, double computation_amount); +double SD_workstation_route_get_latency(SD_workstation_t src, SD_workstation_t dst); +double SD_workstation_route_get_bandwidth(SD_workstation_t src, SD_workstation_t dst); +double SD_workstation_route_get_communication_time(SD_workstation_t src, SD_workstation_t dst, + double communication_amount); + /** @} */ /************************** Task handling ************************************/ @@ -78,10 +85,14 @@ void* SD_task_get_data(SD_task_t task); void SD_task_set_data(SD_task_t task, void *data); e_SD_task_state_t SD_task_get_state(SD_task_t task); const char* SD_task_get_name(SD_task_t task); -double SD_task_get_amount(SD_task_t task); -double SD_task_get_remaining_amount(SD_task_t task); void SD_task_watch(SD_task_t task, e_SD_task_state_t state); void SD_task_unwatch(SD_task_t task, e_SD_task_state_t state); +double SD_task_get_amount(SD_task_t task); +double SD_task_get_remaining_amount(SD_task_t task); +double SD_task_get_execution_time(SD_task_t task, int workstation_nb, + const SD_workstation_t *workstation_list, + const double *computation_amount, const double *communication_amount, + double rate); void SD_task_schedule(SD_task_t task, int workstation_nb, const SD_workstation_t *workstation_list, const double *computation_amount, const double *communication_amount, double rate); diff --git a/src/simdag/sd_global.c b/src/simdag/sd_global.c index 741805e302..7462f685e8 100644 --- a/src/simdag/sd_global.c +++ b/src/simdag/sd_global.c @@ -214,6 +214,7 @@ SD_task_t* SD_simulate(double how_long) INFO0("Simulation finished"); DEBUG3("elapsed_time = %f, total_time = %f, watch_point_reached = %d", elapsed_time, total_time, sd_global->watch_point_reached); + DEBUG1("current time = %f", surf_get_clock()); return changed_tasks; } @@ -228,17 +229,18 @@ SD_task_t* SD_simulate(double how_long) */ void SD_exit(void) { if (sd_global != NULL) { + DEBUG0("Destroying workstation and link dictionaries..."); xbt_dict_free(&sd_global->workstations); xbt_dict_free(&sd_global->links); + DEBUG0("Destroying workstation and link arrays if necessary..."); if (sd_global->workstation_list != NULL) xbt_free(sd_global->workstation_list); if (sd_global->link_list != NULL) xbt_free(sd_global->link_list); - xbt_free(sd_global); - + DEBUG0("Destroying the swags..."); xbt_swag_free(sd_global->not_scheduled_task_set); xbt_swag_free(sd_global->scheduled_task_set); xbt_swag_free(sd_global->ready_task_set); @@ -246,6 +248,9 @@ void SD_exit(void) { xbt_swag_free(sd_global->done_task_set); xbt_swag_free(sd_global->failed_task_set); + xbt_free(sd_global); + + DEBUG0("Exiting Surf..."); surf_exit(); } } diff --git a/src/simdag/sd_task.c b/src/simdag/sd_task.c index a40dd23854..dc05a2244e 100644 --- a/src/simdag/sd_task.c +++ b/src/simdag/sd_task.c @@ -7,6 +7,7 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(sd_task,sd, "Logging specific to SimDag (task)"); static void __SD_task_remove_dependencies(SD_task_t task); +static void __SD_task_destroy_scheduling_data(SD_task_t task); /** * \brief Creates a new task. @@ -393,15 +394,42 @@ void SD_task_unwatch(SD_task_t task, e_SD_task_state_t state) { /* __SD_print_watch_points(task);*/ } -/* Destroys the data memorised by SD_task_schedule. Task state must be SD_SCHEDULED or SD_READY. +/** + * \brief Returns an approximative estimation of the execution time of a task. + * + * The estimation is very approximative because the value returned is the time + * the task would take if it was executed now and if it was the only task. + * + * \param task the task to evaluate + * \param workstation_nb number of workstations on which the task would be executed + * \param workstation_list the workstations on which the task would be executed + * \param computation_amount computation amount for each workstation + * \param communication_amount communication amount between each pair of workstations + * \param rate task execution speed rate + * \see SD_schedule() */ -static void __SD_task_destroy_scheduling_data(SD_task_t task) { - SD_CHECK_INIT_DONE(); - xbt_assert1(__SD_task_is_scheduled_or_ready(task), - "Task '%s' must be SD_SCHEDULED or SD_READY", SD_task_get_name(task)); - xbt_free(task->workstation_list); - xbt_free(task->computation_amount); - xbt_free(task->communication_amount); +double SD_task_get_execution_time(SD_task_t task, + int workstation_nb, + const SD_workstation_t *workstation_list, + const double *computation_amount, + const double *communication_amount, + double rate) { + /* the task execution time is the maximum execution time of the parallel tasks */ + double time, max_time = 0.0; + int i, j; + for (i = 0; i < workstation_nb; i++) { + time = SD_workstation_get_computation_time(workstation_list[i], computation_amount[i]); + + for (j = 0; j < workstation_nb; j++) { + time += SD_workstation_route_get_communication_time(workstation_list[i], workstation_list[j], + communication_amount[i * workstation_nb + j]); + } + + if (time > max_time) { + max_time = time; + } + } + return max_time * SD_task_get_amount(task); } /** @@ -480,7 +508,18 @@ void SD_task_unschedule(SD_task_t task) { __SD_task_set_state(task, SD_NOT_SCHEDULED); } -/* Runs a task. This function is called by SD_simulate when a scheduled task can start +/* Destroys the data memorised by SD_task_schedule. Task state must be SD_SCHEDULED or SD_READY. + */ +static void __SD_task_destroy_scheduling_data(SD_task_t task) { + SD_CHECK_INIT_DONE(); + xbt_assert1(__SD_task_is_scheduled_or_ready(task), + "Task '%s' must be SD_SCHEDULED or SD_READY", SD_task_get_name(task)); + xbt_free(task->workstation_list); + xbt_free(task->computation_amount); + xbt_free(task->communication_amount); +} + +/* Runs a task. This function is called by SD_simulate() when a scheduled task can start * (ie when its dependencies are satisfied). */ surf_action_t __SD_task_run(SD_task_t task) { diff --git a/src/simdag/sd_workstation.c b/src/simdag/sd_workstation.c index f2337be66e..c2939600a2 100644 --- a/src/simdag/sd_workstation.c +++ b/src/simdag/sd_workstation.c @@ -121,7 +121,7 @@ const char* SD_workstation_get_name(SD_workstation_t workstation) { /** * \brief Returns the route between two workstations * - * Use SD_workstation_route_get_size() to know the array size. + * Use SD_workstation_route_get_size() to know the array size. Don't forget to free the array after use. * * \param src a workstation * \param dst another workstation @@ -188,6 +188,112 @@ double SD_workstation_get_available_power(SD_workstation_t workstation) { return surf_workstation_resource->extension_public->get_available_speed(workstation->surf_workstation); } +/** + * \brief Returns an approximative estimated time for the given computation amount on a workstation + * + * \param workstation a workstation + * \param computation_amount the computation amount you want to evaluate (in flops) + * \return an approximative astimated computation time for the given computation amount on this workstation (in seconds) + */ +double SD_workstation_get_computation_time(SD_workstation_t workstation, double computation_amount) { + SD_CHECK_INIT_DONE(); + xbt_assert0(workstation != NULL, "Invalid parameter"); + xbt_assert0(computation_amount >= 0, "computation_amount must be greater than or equal to zero"); + return computation_amount / SD_workstation_get_power(workstation); +} + +/** + * \brief Returns the latency of the route between two workstations, i.e. the sum of all link latencies + * between the workstations. + * + * \param src the first workstation + * \param dst the second workstation + * \return the latency of the route between the two workstations (in seconds) + */ +double SD_workstation_route_get_latency(SD_workstation_t src, SD_workstation_t dst) { + SD_CHECK_INIT_DONE(); + xbt_assert0(src != NULL && dst != NULL, "Invalid parameter"); + SD_link_t *links = SD_workstation_route_get_list(src, dst); + int nb_links = SD_workstation_route_get_size(src, dst); + double latency = 0.0; + int i; + + for (i = 0; i < nb_links; i++) { + latency += SD_link_get_current_latency(links[i]); + } + + free(links); + return latency; +} + +/** + * \brief Returns the bandwidth of the route between two workstations, i.e. the minimum link bandwidth of all + * between the workstations. + * + * \param src the first workstation + * \param dst the second workstation + * \return the bandwidth of the route between the two workstations (in bytes/second) + */ +double SD_workstation_route_get_bandwidth(SD_workstation_t src, SD_workstation_t dst) { + SD_CHECK_INIT_DONE(); + xbt_assert0(src != NULL && dst != NULL, "Invalid parameter"); + SD_link_t *links = SD_workstation_route_get_list(src, dst); + int nb_links = SD_workstation_route_get_size(src, dst); + double bandwidth, min_bandwidth = -1.0; + int i; + + for (i = 0; i < nb_links; i++) { + bandwidth = SD_link_get_current_bandwidth(links[i]); + if (bandwidth < min_bandwidth || min_bandwidth == -1.0) + min_bandwidth = bandwidth; + } + + free(links); + return min_bandwidth; +} + +/** + * \brief Returns an approximative estimated time for the given + * communication amount between two workstations + * + * \param src the first workstation + * \param dst the second workstation + * \param communication_amount the communication amount you want to evaluate (in bytes) + * \return an approximative astimated computation time for the given communication amount + * between the workstations (in seconds) + */ +double SD_workstation_route_get_communication_time(SD_workstation_t src, SD_workstation_t dst, + double communication_amount) { + /* total time = latency + transmission time of the slowest link + transmission time of a link = communication amount / link bandwidth */ + SD_CHECK_INIT_DONE(); + xbt_assert0(src != NULL && dst != NULL, "Invalid parameter"); + xbt_assert0(communication_amount >= 0, "communication_amount must be greater than or equal to zero"); + + SD_link_t *links; + int nb_links; + double bandwidth, min_bandwidth; + double latency; + int i; + + if (communication_amount == 0.0) + return 0.0; + + links = SD_workstation_route_get_list(src, dst); + nb_links = SD_workstation_route_get_size(src, dst); + min_bandwidth = -1.0; + latency = 0; + + for (i = 0; i < nb_links; i++) { + latency += SD_link_get_current_latency(links[i]); + bandwidth = SD_link_get_current_bandwidth(links[i]); + if (bandwidth < min_bandwidth || min_bandwidth == -1.0) + min_bandwidth = bandwidth; + } + + return latency + (communication_amount / min_bandwidth); +} + /* Destroys a workstation. */ void __SD_workstation_destroy(void *workstation) {