/* * 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; }
/* This function is actually not used by biCPA */ double top_level_recursive_computation(SD_task_t task){ unsigned int i; double max_top_level = 0.0, my_top_level, current_parent_top_level = 0.0; SD_task_t parent, grand_parent=NULL; xbt_dynar_t parents, grand_parents; max_top_level = -1.0; if (!strcmp(SD_task_get_name(task),"root")){ XBT_DEBUG("root's top level is 0.0"); SD_task_mark(task); SD_task_set_top_level(task, 0.0); return 0.0; } 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); if (SD_task_is_marked(grand_parent)){ current_parent_top_level = SD_task_get_top_level(grand_parent) + SD_task_estimate_execution_time(grand_parent, SD_task_get_allocation_size(grand_parent)); } else { current_parent_top_level = top_level_recursive_computation(grand_parent) + SD_task_estimate_execution_time(grand_parent, SD_task_get_allocation_size(grand_parent)); } xbt_dynar_free_container(&grand_parents); } else { if (SD_task_is_marked(parent)){ current_parent_top_level = SD_task_get_top_level(parent) + SD_task_estimate_execution_time(parent, SD_task_get_allocation_size(parent)); } else { current_parent_top_level = top_level_recursive_computation(parent) + SD_task_estimate_execution_time(parent, SD_task_get_allocation_size(parent)); } } if (max_top_level < current_parent_top_level) max_top_level = current_parent_top_level; } my_top_level = max_top_level; SD_task_set_top_level(task, my_top_level); SD_task_mark(task); XBT_DEBUG("%s's top level is %f", SD_task_get_name(task), my_top_level); xbt_dynar_free_container(&parents); return my_top_level; }
/* This function is actually not used by biCPA */ int precedence_level_recursive_computation(SD_task_t task){ unsigned int i; int my_prec_level = -1, current_parent_prec_level = 0; SD_task_t parent, grand_parent=NULL; xbt_dynar_t parents, grand_parents; if (!strcmp(SD_task_get_name(task),"root")){ XBT_DEBUG("root's precedence level is 0.0"); SD_task_mark(task); SD_task_set_precedence_level(task, 0); return 0; } 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); if (SD_task_is_marked(grand_parent)){ current_parent_prec_level = SD_task_get_precedence_level(grand_parent) + 1; } else { current_parent_prec_level = precedence_level_recursive_computation(grand_parent) + 1; } xbt_dynar_free_container(&grand_parents); } else { if (SD_task_is_marked(parent)){ current_parent_prec_level = SD_task_get_precedence_level(parent) + 1; } else { current_parent_prec_level = precedence_level_recursive_computation(parent) + 1; } } if (my_prec_level < current_parent_prec_level) my_prec_level = current_parent_prec_level; } SD_task_set_precedence_level(task, my_prec_level); SD_task_mark(task); XBT_DEBUG("%s's precedence level is %d", SD_task_get_name(task), my_prec_level); xbt_dynar_free_container(&parents); return my_prec_level; }
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 {
/* * Return an estimation of the minimal time before which a task can start. This * time depends on the estimated finished time of the compute ancestors of the * task, as set when they have been scheduled. Two cases are considered, * depending on whether an ancestor is 'linked' to the task through a flow or * control dependency. Flow dependencies imply to look at the grand parents of * the task, while control dependencies look at the parent tasks directly. */ double SD_task_estimate_minimal_start_time(SD_task_t task){ unsigned int i; double min_start_time=0.0; xbt_dynar_t parents, grand_parents; SD_task_t parent, grand_parent; 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); if (SD_task_get_estimated_finish_time(grand_parent) > min_start_time) min_start_time = SD_task_get_estimated_finish_time(grand_parent); xbt_dynar_free_container(&grand_parents); } else{ if (SD_task_get_estimated_finish_time(parent) > min_start_time) min_start_time = SD_task_get_estimated_finish_time(parent); } } xbt_dynar_free_container(&parents); return min_start_time; }
/* Determine if a task is ready. The condition to meet is that all its compute predecessors have to be in one of the * following state: * - SD_RUNNABLE * - SD_RUNNING * - SD_DONE */ int SD_task_is_ready(SD_task_t task){ unsigned int i; int is_ready = 1; xbt_dynar_t parents, grand_parents; SD_task_t parent, grand_parent; parents = SD_task_get_parents(task); if (xbt_dynar_length(parents)) { xbt_dynar_foreach(parents, i, parent){ if (SD_task_get_kind(parent) == SD_TASK_COMM_E2E) { /* Data dependency case: a compute task is preceded by a data transfer. Its parent (in a scheduling sense) is * then the grand parent */ grand_parents = SD_task_get_parents(parent); xbt_dynar_get_cpy(grand_parents, 0, &grand_parent); if (SD_task_get_state(grand_parent) < SD_SCHEDULED) { is_ready =0; xbt_dynar_free_container(&grand_parents); /* avoid memory leaks */ break; } else { xbt_dynar_free_container(&grand_parents); /* avoid memory leaks */ } } else { /* Control dependency case: a compute task predecessor is another compute task. */ if (SD_task_get_state(parent) < SD_SCHEDULED) { is_ready =0; break; } } } } xbt_dynar_free_container(&parents); /* avoid memory leaks */ return is_ready; }