"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]);
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);
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);
SD_task_watch(taskC, SD_DONE);
SD_task_t *changed_tasks;
- int i;
changed_tasks = SD_simulate(0.001);
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;
}
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 ************************************/
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);
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;
}
*/
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);
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();
}
}
"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.
/* __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);
}
/**
__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) {
/**
* \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
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) {