xbt_dynar_foreach(dax, cursor, task) { int kind = SD_task_get_kind(task); SD_workstation_t *wsl = SD_task_get_workstation_list(task); switch (kind) { case SD_TASK_COMP_SEQ: fprintf(out, "[%f] %s compute %f # %s\n", SD_task_get_start_time(task), SD_workstation_get_name(wsl[0]), SD_task_get_amount(task), SD_task_get_name(task)); break; case SD_TASK_COMM_E2E: fprintf(out, "[%f] %s send %s %f # %s\n", SD_task_get_start_time(task), SD_workstation_get_name(wsl[0]), SD_workstation_get_name(wsl[1]), SD_task_get_amount(task), SD_task_get_name(task)); fprintf(out, "[%f] %s recv %s %f # %s\n", SD_task_get_finish_time(task), SD_workstation_get_name(wsl[1]), SD_workstation_get_name(wsl[0]), SD_task_get_amount(task), SD_task_get_name(task)); break; default: xbt_die("Task %s is of unknown kind %d", SD_task_get_name(task), SD_task_get_kind(task)); } SD_task_destroy(task); }
static double finish_on_at(SD_task_t task, sg_host_t host) { double result; unsigned int i; double data_available = 0.; double redist_time = 0; double last_data_available; xbt_dynar_t parents = SD_task_get_parents(task); if (!xbt_dynar_is_empty(parents)) { /* compute last_data_available */ SD_task_t parent; last_data_available = -1.0; xbt_dynar_foreach(parents, i, parent) { /* normal case */ if (SD_task_get_kind(parent) == SD_TASK_COMM_E2E) { xbt_dynar_t grand_parents = SD_task_get_parents(parent); SD_task_t grand_parent; xbt_assert(xbt_dynar_length(grand_parents) <2, "Error: transfer %s has 2 parents", SD_task_get_name(parent)); xbt_dynar_get_cpy(grand_parents, 0, &grand_parent); sg_host_t * grand_parent_host_list = SD_task_get_workstation_list(grand_parent); /* Estimate the redistribution time from this parent */ if (SD_task_get_amount(parent) <= 1e-6){ redist_time= 0; } else { redist_time = SD_route_get_latency(grand_parent_host_list[0], host) + SD_task_get_amount(parent) / SD_route_get_bandwidth(grand_parent_host_list[0], host); } data_available = SD_task_get_finish_time(grand_parent) + redist_time; xbt_dynar_free_container(&grand_parents); } /* no transfer, control dependency */ if (SD_task_get_kind(parent) == SD_TASK_COMP_SEQ) { data_available = SD_task_get_finish_time(parent); } if (last_data_available < data_available) last_data_available = data_available; } xbt_dynar_free_container(&parents); result = MAX(sg_host_get_available_at(host), last_data_available) + SD_task_get_amount(task)/sg_host_speed(host); } else {
/* * Estimate the time at which all the input data of a task are available (i.e., * have been transfered to) on its current allocation. This estimation * corresponds to the maximum value among the compute parents of the task of * the sum of the estimated finish time of the parent and estimated transfer * time of the data sent by this parent. For control dependencies, the second * part is obviously discarded. */ double SD_task_estimate_last_data_arrival_time (SD_task_t task){ unsigned int i; double last_data_arrival = -1., data_availability, estimated_transfer_time; SD_task_t parent, grand_parent; xbt_dynar_t parents, grand_parents; parents = SD_task_get_parents(task); xbt_dynar_foreach(parents, i, parent){ if (SD_task_get_kind(parent) == SD_TASK_COMM_PAR_MXN_1D_BLOCK) { grand_parents = SD_task_get_parents(parent); xbt_dynar_get_cpy(grand_parents, 0, &grand_parent); estimated_transfer_time = SD_task_estimate_transfer_time_from(grand_parent, task, SD_task_get_amount(parent)); data_availability = SD_task_get_estimated_finish_time(grand_parent)+ estimated_transfer_time; xbt_dynar_free_container(&grand_parents); } else { data_availability = SD_task_get_estimated_finish_time(parent); } if (last_data_arrival < data_availability) last_data_arrival = data_availability; } xbt_dynar_free_container(&parents); return last_data_arrival; }
xbt_dynar_foreach(dot, cursor, task) { int kind = SD_task_get_kind(task); sg_host_t *wsl = SD_task_get_workstation_list(task); switch (kind) { case SD_TASK_COMP_SEQ: fprintf(out, "[%f->%f] %s compute %f flops # %s\n", SD_task_get_start_time(task), SD_task_get_finish_time(task), sg_host_get_name(wsl[0]), SD_task_get_amount(task), SD_task_get_name(task)); break; case SD_TASK_COMM_E2E: fprintf(out, "[%f -> %f] %s -> %s transfer of %.0f bytes # %s\n", SD_task_get_start_time(task), SD_task_get_finish_time(task), sg_host_get_name(wsl[0]), sg_host_get_name(wsl[1]), SD_task_get_amount(task), SD_task_get_name(task)); break; default: xbt_die("Task %s is of unknown kind %d", SD_task_get_name(task), SD_task_get_kind(task)); } SD_task_destroy(task); }
/** @brief Displays debugging information about a task */ void SD_task_dump(SD_task_t task) { XBT_INFO("Displaying task %s", SD_task_get_name(task)); char *statename = bprintf("%s%s%s%s%s%s%s", (task->state == SD_NOT_SCHEDULED ? " not scheduled" : ""), (task->state == SD_SCHEDULABLE ? " schedulable" : ""), (task->state == SD_SCHEDULED ? " scheduled" : ""), (task->state == SD_RUNNABLE ? " runnable" : " not runnable"), (task->state == SD_RUNNING ? " running" : ""), (task->state == SD_DONE ? " done" : ""), (task->state == SD_FAILED ? " failed" : "")); XBT_INFO(" - state:%s", statename); free(statename); if (task->kind != 0) { switch (task->kind) { case SD_TASK_COMM_E2E: XBT_INFO(" - kind: end-to-end communication"); break; 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; case SD_TASK_COMM_PAR_MXN_1D_BLOCK: XBT_INFO(" - kind: MxN data redistribution assuming 1D block distribution"); break; default: XBT_INFO(" - (unknown kind %d)", task->kind); } } XBT_INFO(" - amount: %.0f", SD_task_get_amount(task)); if (task->kind == SD_TASK_COMP_PAR_AMDAHL) XBT_INFO(" - alpha: %.2f", task->alpha); XBT_INFO(" - Dependencies to satisfy: %zu", task->inputs->size()+ task->predecessors->size()); if ((task->inputs->size()+ task->predecessors->size()) > 0) { XBT_INFO(" - pre-dependencies:"); for (std::set<SD_task_t>::iterator it=task->predecessors->begin(); it!=task->predecessors->end(); ++it) XBT_INFO(" %s", SD_task_get_name(*it)); for (std::set<SD_task_t>::iterator it=task->inputs->begin(); it!=task->inputs->end(); ++it) XBT_INFO(" %s", SD_task_get_name(*it)); } if ((task->outputs->size() + task->successors->size()) > 0) { XBT_INFO(" - post-dependencies:"); for (std::set<SD_task_t>::iterator it=task->successors->begin(); it!=task->successors->end(); ++it) XBT_INFO(" %s", SD_task_get_name(*it)); for (std::set<SD_task_t>::iterator it=task->outputs->begin(); it!=task->outputs->end(); ++it) XBT_INFO(" %s", SD_task_get_name(*it)); } }
/* * Return a rough estimation of what would be the execution time of task given * as input on a given number of workstations. The task has to be of kind * SD_TASK_COMP_PAR_AMDAHL, as Amdahl's law is applied to get this estimation. * It also assumes a fully homogeneous set of workstations as no distinction is * made within the whole set. */ double SD_task_estimate_execution_time(SD_task_t task, int nworkstations){ const SD_workstation_t *workstations = SD_workstation_get_list(); double amount, alpha, power, estimate; amount = SD_task_get_amount(task); alpha = SD_task_get_alpha(task); power = SD_workstation_get_power(workstations[0]); estimate = (alpha + (1 - alpha)/nworkstations) * (amount/power); XBT_DEBUG("Estimation for task %s is: %f seconds", SD_task_get_name(task), estimate); return estimate; }
int main(int argc, char **argv) { int i; const char *platform_file; const SD_workstation_t *workstations; int kind; SD_task_t task, taskA, taskB, taskC; xbt_dynar_t changed_tasks; SD_workstation_t workstation_list[2]; double computation_amount[2]; double communication_amount[4] = { 0 }; double rate = -1.0; SD_workstation_t w1, w2; /* SD initialization */ SD_init(&argc, argv); /* xbt_log_control_set("sd.thres=debug"); */ if (argc < 2) { XBT_INFO("Usage: %s platform_file", argv[0]); XBT_INFO("example: %s sd_platform.xml", argv[0]); exit(1); } /* creation of the environment */ platform_file = argv[1]; SD_create_environment(platform_file); /* Change the access mode of the workstations */ workstations = SD_workstation_get_list(); w1 = workstations[0]; w2 = workstations[1]; for (i = 0; i < 2; i++) { SD_workstation_set_access_mode(workstations[i], SD_WORKSTATION_SEQUENTIAL_ACCESS); XBT_INFO("Access mode of %s is %s", SD_workstation_get_name(workstations[i]), (SD_workstation_get_access_mode(workstations[i]) == SD_WORKSTATION_SEQUENTIAL_ACCESS) ? "sequential" : "shared"); } /* creation of the tasks and their dependencies */ taskA = SD_task_create_comp_seq("Task A", NULL, 2e9); taskB = SD_task_create_comm_e2e("Task B", NULL, 2e9); taskC = SD_task_create_comp_seq("Task C", NULL, 1e9); TRACE_category ("taskA"); TRACE_category ("taskB"); TRACE_category ("taskC"); TRACE_sd_set_task_category (taskA, "taskA"); TRACE_sd_set_task_category (taskB, "taskB"); TRACE_sd_set_task_category (taskC, "taskC"); /* if everything is ok, no exception is forwarded or rethrown by main() */ /* watch points */ SD_task_watch(taskA, SD_RUNNING); SD_task_watch(taskB, SD_RUNNING); SD_task_watch(taskC, SD_RUNNING); SD_task_watch(taskC, SD_DONE); /* scheduling parameters */ workstation_list[0] = w1; workstation_list[1] = w2; computation_amount[0] = SD_task_get_amount(taskA); computation_amount[1] = SD_task_get_amount(taskB); communication_amount[1] = SD_task_get_amount(taskC); communication_amount[2] = 0.0; SD_task_schedule(taskA, 1, &w1, &(computation_amount[0]), SD_SCHED_NO_COST, rate); SD_task_schedule(taskB, 2, workstation_list, SD_SCHED_NO_COST, communication_amount, rate); SD_task_schedule(taskC, 1, &w1, &(computation_amount[1]), SD_SCHED_NO_COST, rate); /* let's launch the simulation! */ while (!xbt_dynar_is_empty(changed_tasks = SD_simulate(-1.0))) { for (i = 0; i < 2; i++) { task = SD_workstation_get_current_task(workstations[i]); if (task) kind = SD_task_get_kind(task); else { XBT_INFO("There is no task running on %s", SD_workstation_get_name(workstations[i])); continue; } switch (kind) { case SD_TASK_COMP_SEQ: XBT_INFO("%s is currently running on %s (SD_TASK_COMP_SEQ)", SD_task_get_name(task), SD_workstation_get_name(workstations[i])); break; case SD_TASK_COMM_E2E: XBT_INFO("%s is currently running on %s (SD_TASK_COMM_E2E)", SD_task_get_name(task), SD_workstation_get_name(workstations[i])); break; case SD_TASK_NOT_TYPED: XBT_INFO("Task running on %s has no type", SD_workstation_get_name(workstations[i])); break; default: XBT_ERROR("Shouldn't be here"); } } xbt_dynar_free_container(&changed_tasks); } xbt_dynar_free_container(&changed_tasks); XBT_DEBUG("Destroying tasks..."); SD_task_destroy(taskA); SD_task_destroy(taskB); SD_task_destroy(taskC); XBT_DEBUG("Tasks destroyed. Exiting SimDag..."); SD_exit(); return 0; }