static void log_action(simgrid::xbt::ReplayAction& action, double date) { if (XBT_LOG_ISENABLED(replay_comm, xbt_log_priority_verbose)) { std::string s = boost::algorithm::join(action, " "); XBT_VERB("%s %f", s.c_str(), date); } }
static void log_timed_action (const char *const *action, double clock){ if (XBT_LOG_ISENABLED(smpi_replay, xbt_log_priority_verbose)){ char *name = xbt_str_join_array(action, " "); XBT_VERB("%s %f", name, smpi_process_simulated_elapsed()-clock); free(name); } }
static char* pointer_to_string(void* pointer) { if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose)) return bprintf("%p", pointer); return xbt_strdup("(verbose only)"); }
static void action_send(const char *const *action) { int to = atoi(action[2]); double size=parse_double(action[3]); double clock = smpi_process_simulated_elapsed(); #ifdef HAVE_TRACING int rank = smpi_comm_rank(MPI_COMM_WORLD); TRACE_smpi_computing_out(rank); int dst_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), to); TRACE_smpi_ptp_in(rank, rank, dst_traced, __FUNCTION__); TRACE_smpi_send(rank, rank, dst_traced); #endif smpi_mpi_send(NULL, size, MPI_BYTE, to , 0, MPI_COMM_WORLD); if (XBT_LOG_ISENABLED(smpi_replay, xbt_log_priority_verbose)){ char *name = xbt_str_join_array(action, " "); XBT_VERB("%s %f", name, smpi_process_simulated_elapsed()-clock); free(name); } #ifdef HAVE_TRACING TRACE_smpi_ptp_out(rank, rank, dst_traced, __FUNCTION__); TRACE_smpi_computing_in(rank); #endif }
static char* buff_size_to_string(size_t buff_size) { if (XBT_LOG_ISENABLED(mc_request, xbt_log_priority_verbose)) return bprintf("%zu", buff_size); return xbt_strdup("(verbose only)"); }
static void action_Irecv(const char *const *action) { int from = atoi(action[2]); double size=parse_double(action[3]); double clock = smpi_process_simulated_elapsed(); MPI_Request request; smpi_replay_globals_t globals = (smpi_replay_globals_t) smpi_process_get_user_data(); #ifdef HAVE_TRACING int rank = smpi_comm_rank(MPI_COMM_WORLD); int src_traced = smpi_group_rank(smpi_comm_group(MPI_COMM_WORLD), from); TRACE_smpi_ptp_in(rank, src_traced, rank, __FUNCTION__); #endif request = smpi_mpi_irecv(NULL, size, MPI_BYTE, from, 0, MPI_COMM_WORLD); #ifdef HAVE_TRACING TRACE_smpi_ptp_out(rank, src_traced, rank, __FUNCTION__); request->recv = 1; #endif xbt_dynar_push(globals->irecvs,&request); //TODO do the asynchronous cleanup if (XBT_LOG_ISENABLED(smpi_replay, xbt_log_priority_verbose)){ char *name = xbt_str_join_array(action, " "); XBT_VERB("%s %f", name, smpi_process_simulated_elapsed()-clock); free(name); } }
static void log_action(const char *const *action, double date) { if (XBT_LOG_ISENABLED(storage_actions, xbt_log_priority_verbose)) { char *name = xbt_str_join_array(action, " "); XBT_VERB("%s %f", name, date); xbt_free(name); } }
static void action_compute(const char *const *action) { double clock = smpi_process_simulated_elapsed(); smpi_execute_flops(parse_double(action[2])); if (XBT_LOG_ISENABLED(smpi_replay, xbt_log_priority_verbose)){ char *name = xbt_str_join_array(action, " "); XBT_VERB("%s %f", name, smpi_process_simulated_elapsed()-clock); free(name); } }
/** Displays the finger table of a node. */ void Node::printFingerTable() { if (XBT_LOG_ISENABLED(s4u_chord, xbt_log_priority_verbose)) { XBT_VERB("My finger table:"); XBT_VERB("Start | Succ"); for (int i = 0; i < nb_bits; i++) { XBT_VERB(" %3u | %3d", (id_ + (1U << i)) % nb_keys, fingers_[i]); } XBT_VERB("Predecessor: %d", pred_id_); } }
void SIMIX_simcall_answer(smx_simcall_t simcall) { if (simcall->issuer != simix_global->maestro_process){ XBT_DEBUG("Answer simcall %s (%d) issued by %s (%p)", SIMIX_simcall_name(simcall->call), (int)simcall->call, simcall->issuer->get_cname(), simcall->issuer); simcall->issuer->simcall.call = SIMCALL_NONE; xbt_assert(not XBT_LOG_ISENABLED(simix_popping, xbt_log_priority_debug) || std::find(begin(simix_global->actors_to_run), end(simix_global->actors_to_run), simcall->issuer) == end(simix_global->actors_to_run), "Actor %p should not exist in actors_to_run!", simcall->issuer); simix_global->actors_to_run.push_back(simcall->issuer); } }
static void buffer_debug(std::vector<simgrid::instr::PajeEvent*>* buf) { if (not XBT_LOG_ISENABLED(instr_paje_trace, xbt_log_priority_debug)) return; XBT_DEBUG(">>>>>> Dump the state of the buffer. %zu events", buf->size()); for (auto const& event : *buf) { event->print(); XBT_DEBUG("%p %s", event, event->stream_.str().c_str()); event->stream_.str(""); event->stream_.clear(); } XBT_DEBUG("<<<<<<"); }
/** * @brief Dumps the Lua stack if debug logs are enabled. * @param msg a message to print * @param L a Lua state */ void sglua_stack_dump(lua_State* L, const char* msg) { if (XBT_LOG_ISENABLED(lua_debug, xbt_log_priority_debug)) { char buff[2048]; char* p = buff; int top = lua_gettop(L); fflush(stdout); p[0] = '\0'; for (int i = 1; i <= top; i++) { /* repeat for each level */ p += snprintf(p, 2048-(p-buff), "%s ", sglua_tostring(L, i)); } XBT_DEBUG("%s%s", msg, buff); } }
static void action_barrier(const char *const *action){ double clock = smpi_process_simulated_elapsed(); #ifdef HAVE_TRACING int rank = smpi_comm_rank(MPI_COMM_WORLD); TRACE_smpi_computing_out(rank); TRACE_smpi_collective_in(rank, -1, __FUNCTION__); #endif smpi_mpi_barrier(MPI_COMM_WORLD); #ifdef HAVE_TRACING TRACE_smpi_collective_out(rank, -1, __FUNCTION__); TRACE_smpi_computing_in(rank); #endif if (XBT_LOG_ISENABLED(smpi_replay, xbt_log_priority_verbose)){ char *name = xbt_str_join_array(action, " "); XBT_VERB("%s %f", name, smpi_process_simulated_elapsed()-clock); free(name); } }
static void action_wait(const char *const *action){ double clock = smpi_process_simulated_elapsed(); MPI_Request request; MPI_Status status; smpi_replay_globals_t globals = (smpi_replay_globals_t) smpi_process_get_user_data(); xbt_assert(xbt_dynar_length(globals->irecvs), "action wait not preceded by any irecv: %s", xbt_str_join_array(action," ")); request = xbt_dynar_pop_as(globals->irecvs,MPI_Request); #ifdef HAVE_TRACING int rank = request && request->comm != MPI_COMM_NULL ? smpi_comm_rank(request->comm) : -1; TRACE_smpi_computing_out(rank); MPI_Group group = smpi_comm_group(request->comm); int src_traced = smpi_group_rank(group, request->src); int dst_traced = smpi_group_rank(group, request->dst); int is_wait_for_receive = request->recv; TRACE_smpi_ptp_in(rank, src_traced, dst_traced, __FUNCTION__); #endif smpi_mpi_wait(&request, &status); #ifdef HAVE_TRACING TRACE_smpi_ptp_out(rank, src_traced, dst_traced, __FUNCTION__); if (is_wait_for_receive) { TRACE_smpi_recv(rank, src_traced, dst_traced); } TRACE_smpi_computing_in(rank); #endif if (XBT_LOG_ISENABLED(smpi_replay, xbt_log_priority_verbose)){ char *name = xbt_str_join_array(action, " "); XBT_VERB("%s %f", name, smpi_process_simulated_elapsed()-clock); free(name); } }
static void action_allReduce(const char *const *action) { double comm_size = parse_double(action[2]); double comp_size = parse_double(action[3]); double clock = smpi_process_simulated_elapsed(); #ifdef HAVE_TRACING int rank = smpi_comm_rank(MPI_COMM_WORLD); TRACE_smpi_computing_out(rank); TRACE_smpi_collective_in(rank, -1, __FUNCTION__); #endif smpi_mpi_reduce(NULL, NULL, comm_size, MPI_BYTE, MPI_OP_NULL, 0, MPI_COMM_WORLD); smpi_execute_flops(comp_size); smpi_mpi_bcast(NULL, comm_size, MPI_BYTE, 0, MPI_COMM_WORLD); #ifdef HAVE_TRACING TRACE_smpi_collective_out(rank, -1, __FUNCTION__); TRACE_smpi_computing_in(rank); #endif if (XBT_LOG_ISENABLED(smpi_replay, xbt_log_priority_verbose)){ char *name = xbt_str_join_array(action, " "); XBT_VERB("%s %f", name, smpi_process_simulated_elapsed()-clock); free(name); } }
xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par, bool schedule){ xbt_assert(filename, "Unable to use a null file descriptor\n"); FILE *in_file = fopen(filename, "r"); xbt_assert(in_file != nullptr, "Failed to open file: %s", filename); unsigned int i; SD_task_t root; SD_task_t end; SD_task_t task; xbt_dict_t computers; xbt_dynar_t computer = nullptr; xbt_dict_cursor_t dict_cursor; bool schedule_success = true; xbt_dict_t jobs = xbt_dict_new_homogeneous(nullptr); xbt_dynar_t result = xbt_dynar_new(sizeof(SD_task_t), dot_task_p_free); Agraph_t * dag_dot = agread(in_file, NIL(Agdisc_t *)); if (schedule) computers = xbt_dict_new_homogeneous(nullptr); /* Create all the nodes */ Agnode_t *node = nullptr; for (node = agfstnode(dag_dot); node; node = agnxtnode(dag_dot, node)) { char *name = agnameof(node); double amount = atof(agget(node, (char*)"size")); task = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, name)); if (task == nullptr) { if (seq_or_par == sequential){ XBT_DEBUG("See <job id=%s amount =%.0f>", name, amount); task = SD_task_create_comp_seq(name, nullptr , amount); } else { double alpha = atof(agget(node, (char *) "alpha")); XBT_DEBUG("See <job id=%s amount =%.0f alpha = %.3f>", name, amount, alpha); task = SD_task_create_comp_par_amdahl(name, nullptr , amount, alpha); } xbt_dict_set(jobs, name, task, nullptr); if (strcmp(name,"root") && strcmp(name,"end")) xbt_dynar_push(result, &task); if((seq_or_par == sequential) && ((schedule && schedule_success) || XBT_LOG_ISENABLED(sd_dotparse, xbt_log_priority_verbose))){ /* try to take the information to schedule the task only if all is right*/ char *char_performer = agget(node, (char *) "performer"); char *char_order = agget(node, (char *) "order"); /* Tasks will execute on in a given "order" on a given set of "performer" hosts */ int performer = ((!char_performer || !strcmp(char_performer,"")) ? -1:atoi(char_performer)); int order = ((!char_order || !strcmp(char_order, ""))? -1:atoi(char_order)); if((performer != -1 && order != -1) && performer < (int) sg_host_count()){ /* required parameters are given and less performers than hosts are required */ XBT_DEBUG ("Task '%s' is scheduled on workstation '%d' in position '%d'", task->name, performer, order); if(!(computer = (xbt_dynar_t) xbt_dict_get_or_null(computers, char_performer))){ computer = xbt_dynar_new(sizeof(SD_task_t), nullptr); xbt_dict_set(computers, char_performer, computer, nullptr); } if((unsigned int)order < xbt_dynar_length(computer)){ SD_task_t *task_test = (SD_task_t *)xbt_dynar_get_ptr(computer,order); if(*task_test && *task_test != task){ /* the user gave the same order to several tasks */ schedule_success = false; XBT_VERB("Task '%s' wants to start on performer '%s' at the same position '%s' as task '%s'", (*task_test)->name, char_performer, char_order, task->name); continue; } } /* the parameter seems to be ok */ xbt_dynar_set_as(computer, order, SD_task_t, task); } else { /* one of required parameters is not given */ schedule_success = false; XBT_VERB("The schedule is ignored, task '%s' can not be scheduled on %d hosts", task->name, performer); } } } else { XBT_WARN("Task '%s' is defined more than once", name); } } /*Check if 'root' and 'end' nodes have been explicitly declared. If not, create them. */ if (!(root = (SD_task_t)xbt_dict_get_or_null(jobs, "root"))) root = (seq_or_par == sequential?SD_task_create_comp_seq("root", nullptr, 0): SD_task_create_comp_par_amdahl("root", nullptr, 0, 0)); SD_task_set_state(root, SD_SCHEDULABLE); /* by design the root task is always SCHEDULABLE */ xbt_dynar_insert_at(result, 0, &root); /* Put it at the beginning of the dynar */ if (!(end = (SD_task_t)xbt_dict_get_or_null(jobs, "end"))) end = (seq_or_par == sequential?SD_task_create_comp_seq("end", nullptr, 0): SD_task_create_comp_par_amdahl("end", nullptr, 0, 0)); /* Create edges */ xbt_dynar_t edges = xbt_dynar_new(sizeof(Agedge_t*), nullptr); for (node = agfstnode(dag_dot); node; node = agnxtnode(dag_dot, node)) { Agedge_t * edge; xbt_dynar_reset(edges); for (edge = agfstout(dag_dot, node); edge; edge = agnxtout(dag_dot, edge)) xbt_dynar_push_as(edges, Agedge_t *, edge); /* Be sure edges are sorted */ xbt_dynar_sort(edges, edge_compare); xbt_dynar_foreach(edges, i, edge) { char *src_name=agnameof(agtail(edge)), *dst_name=agnameof(aghead(edge)); double size = atof(agget(edge, (char *) "size")); SD_task_t src = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, src_name)); SD_task_t dst = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, dst_name)); if (size > 0) { char *name = bprintf("%s->%s", src_name, dst_name); XBT_DEBUG("See <transfer id=%s amount = %.0f>", name, size); task = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, name)); if (task == nullptr) { if (seq_or_par == sequential) task = SD_task_create_comm_e2e(name, nullptr , size); else task = SD_task_create_comm_par_mxn_1d_block(name, nullptr , size); SD_task_dependency_add(nullptr, nullptr, src, task); SD_task_dependency_add(nullptr, nullptr, task, dst); xbt_dict_set(jobs, name, task, nullptr); xbt_dynar_push(result, &task); } else { XBT_WARN("Task '%s' is defined more than once", name); } xbt_free(name); } else { SD_task_dependency_add(nullptr, nullptr, src, dst); } } }
/* * This gets called the first time a category is referenced and performs the * initialization. * Also resets threshold to inherited! */ int _xbt_log_cat_init(xbt_log_category_t category, e_xbt_log_priority_t priority) { #define _xbt_log_cat_init(a, b) (0) if (log_cat_init_mutex != NULL) { xbt_os_rmutex_acquire(log_cat_init_mutex); } if (category->initialized) { if (log_cat_init_mutex != NULL) { xbt_os_rmutex_release(log_cat_init_mutex); } return priority >= category->threshold; } unsigned int cursor; xbt_log_setting_t setting = NULL; int found = 0; XBT_DEBUG("Initializing category '%s' (firstChild=%s, nextSibling=%s)", category->name, (category->firstChild ? category->firstChild->name : "none"), (category->nextSibling ? category->nextSibling->name : "none")); if (category == &_XBT_LOGV(XBT_LOG_ROOT_CAT)) { category->threshold = xbt_log_priority_info; category->appender = xbt_log_default_appender; category->layout = xbt_log_default_layout; } else { if (!category->parent) category->parent = &_XBT_LOGV(XBT_LOG_ROOT_CAT); XBT_DEBUG("Set %s (%s) as father of %s ", category->parent->name, (category->parent->initialized ? xbt_log_priority_names[category->parent->threshold] : "uninited"), category->name); xbt_log_parent_set(category, category->parent); if (XBT_LOG_ISENABLED(log, xbt_log_priority_debug)) { char *buf, *res = NULL; xbt_log_category_t cpp = category->parent->firstChild; while (cpp) { if (res) { buf = bprintf("%s %s", res, cpp->name); free(res); res = buf; } else { res = xbt_strdup(cpp->name); } cpp = cpp->nextSibling; } XBT_DEBUG("Children of %s: %s; nextSibling: %s", category->parent->name, res, (category->parent->nextSibling ? category->parent->nextSibling->name : "none")); free(res); } } /* Apply the control */ if (xbt_log_settings) { xbt_assert(category, "NULL category"); xbt_assert(category->name); xbt_dynar_foreach(xbt_log_settings, cursor, setting) { xbt_assert(setting, "Damnit, NULL cat in the list"); xbt_assert(setting->catname, "NULL setting(=%p)->catname", (void *) setting); if (!strcmp(setting->catname, category->name)) { found = 1; _xbt_log_cat_apply_set(category, setting); xbt_dynar_cursor_rm(xbt_log_settings, &cursor); } } if (!found) XBT_DEBUG("Category '%s': inherited threshold = %s (=%d)", category->name, xbt_log_priority_names[category->threshold], category->threshold); }
xbt_dynar_t SD_dotload_generic(const char* filename, bool sequential, bool schedule) { xbt_assert(filename, "Unable to use a null file descriptor\n"); FILE *in_file = fopen(filename, "r"); xbt_assert(in_file != nullptr, "Failed to open file: %s", filename); SD_task_t root; SD_task_t end; SD_task_t task; std::vector<SD_task_t>* computer; std::unordered_map<std::string, std::vector<SD_task_t>*> computers; bool schedule_success = true; std::unordered_map<std::string, SD_task_t> jobs; xbt_dynar_t result = xbt_dynar_new(sizeof(SD_task_t), dot_task_p_free); Agraph_t * dag_dot = agread(in_file, NIL(Agdisc_t *)); /* Create all the nodes */ Agnode_t *node = nullptr; for (node = agfstnode(dag_dot); node; node = agnxtnode(dag_dot, node)) { char *name = agnameof(node); double amount = atof(agget(node, (char*)"size")); if (jobs.find(name) == jobs.end()) { if (sequential) { XBT_DEBUG("See <job id=%s amount =%.0f>", name, amount); task = SD_task_create_comp_seq(name, nullptr , amount); } else { double alpha = atof(agget(node, (char *) "alpha")); XBT_DEBUG("See <job id=%s amount =%.0f alpha = %.3f>", name, amount, alpha); task = SD_task_create_comp_par_amdahl(name, nullptr , amount, alpha); } jobs.insert({std::string(name), task}); if (strcmp(name,"root") && strcmp(name,"end")) xbt_dynar_push(result, &task); if ((sequential) && ((schedule && schedule_success) || XBT_LOG_ISENABLED(sd_dotparse, xbt_log_priority_verbose))) { /* try to take the information to schedule the task only if all is right*/ char *char_performer = agget(node, (char *) "performer"); char *char_order = agget(node, (char *) "order"); /* Tasks will execute on in a given "order" on a given set of "performer" hosts */ int performer = ((not char_performer || not strcmp(char_performer, "")) ? -1 : atoi(char_performer)); int order = ((not char_order || not strcmp(char_order, "")) ? -1 : atoi(char_order)); if ((performer != -1 && order != -1) && performer < static_cast<int>(sg_host_count())) { /* required parameters are given and less performers than hosts are required */ XBT_DEBUG ("Task '%s' is scheduled on workstation '%d' in position '%d'", task->name, performer, order); auto comp = computers.find(char_performer); if (comp != computers.end()) { computer = comp->second; } else { computer = new std::vector<SD_task_t>; computers.insert({char_performer, computer}); } if (static_cast<unsigned int>(order) < computer->size()) { SD_task_t task_test = computer->at(order); if (task_test && task_test != task) { /* the user gave the same order to several tasks */ schedule_success = false; XBT_VERB("Task '%s' wants to start on performer '%s' at the same position '%s' as task '%s'", task_test->name, char_performer, char_order, task->name); continue; } } else computer->resize(order); computer->insert(computer->begin() + order, task); } else { /* one of required parameters is not given */ schedule_success = false; XBT_VERB("The schedule is ignored, task '%s' can not be scheduled on %d hosts", task->name, performer); } } } else { XBT_WARN("Task '%s' is defined more than once", name); } } /*Check if 'root' and 'end' nodes have been explicitly declared. If not, create them. */ if (jobs.find("root") == jobs.end()) root = (sequential ? SD_task_create_comp_seq("root", nullptr, 0) : SD_task_create_comp_par_amdahl("root", nullptr, 0, 0)); else root = jobs.at("root"); SD_task_set_state(root, SD_SCHEDULABLE); /* by design the root task is always SCHEDULABLE */ xbt_dynar_insert_at(result, 0, &root); /* Put it at the beginning of the dynar */ if (jobs.find("end") == jobs.end()) end = (sequential ? SD_task_create_comp_seq("end", nullptr, 0) : SD_task_create_comp_par_amdahl("end", nullptr, 0, 0)); else end = jobs.at("end"); /* Create edges */ std::vector<Agedge_t*> edges; for (node = agfstnode(dag_dot); node; node = agnxtnode(dag_dot, node)) { edges.clear(); for (Agedge_t* edge = agfstout(dag_dot, node); edge; edge = agnxtout(dag_dot, edge)) edges.push_back(edge); /* Be sure edges are sorted */ std::sort(edges.begin(), edges.end(), [](const Agedge_t* a, const Agedge_t* b) { return AGSEQ(a) < AGSEQ(b); }); for (Agedge_t* edge : edges) { char *src_name=agnameof(agtail(edge)); char *dst_name=agnameof(aghead(edge)); double size = atof(agget(edge, (char *) "size")); SD_task_t src = jobs.at(src_name); SD_task_t dst = jobs.at(dst_name); if (size > 0) { std::string name = std::string(src_name) + "->" + dst_name; XBT_DEBUG("See <transfer id=%s amount = %.0f>", name.c_str(), size); if (jobs.find(name) == jobs.end()) { if (sequential) task = SD_task_create_comm_e2e(name.c_str(), nullptr, size); else task = SD_task_create_comm_par_mxn_1d_block(name.c_str(), nullptr, size); SD_task_dependency_add(src, task); SD_task_dependency_add(task, dst); jobs.insert({name, task}); xbt_dynar_push(result, &task); } else { XBT_WARN("Task '%s' is defined more than once", name.c_str()); } } else { SD_task_dependency_add(src, dst); } } } XBT_DEBUG("All tasks have been created, put %s at the end of the dynar", end->name); xbt_dynar_push(result, &end); /* Connect entry tasks to 'root', and exit tasks to 'end'*/ unsigned i; xbt_dynar_foreach (result, i, task){ if (task->predecessors->empty() && task->inputs->empty() && task != root) { XBT_DEBUG("Task '%s' has no source. Add dependency from 'root'", task->name); SD_task_dependency_add(root, task); } if (task->successors->empty() && task->outputs->empty() && task != end) { XBT_DEBUG("Task '%s' has no destination. Add dependency to 'end'", task->name); SD_task_dependency_add(task, end); } } agclose(dag_dot); fclose(in_file); if(schedule){ if (schedule_success) { std::vector<simgrid::s4u::Host*> hosts = simgrid::s4u::Engine::get_instance()->get_all_hosts(); for (auto const& elm : computers) { SD_task_t previous_task = nullptr; for (auto const& cur_task : *elm.second) { /* add dependency between the previous and the task to avoid parallel execution */ if (cur_task) { if (previous_task && not SD_task_dependency_exists(previous_task, cur_task)) SD_task_dependency_add(previous_task, cur_task); SD_task_schedulel(cur_task, 1, hosts[std::stod(elm.first)]); previous_task = cur_task; } } delete elm.second; } } else { XBT_WARN("The scheduling is ignored"); for (auto const& elm : computers) delete elm.second; xbt_dynar_free(&result); result = nullptr; } } if (result && not acyclic_graph_detail(result)) { std::string base = simgrid::xbt::Path(filename).get_base_name(); XBT_ERROR("The DOT described in %s is not a DAG. It contains a cycle.", base.c_str()); xbt_dynar_free(&result); result = nullptr; } return result; }
void simgrid::kernel::lmm::FairBottleneck::bottleneck_solve() { if (not modified_) return; XBT_DEBUG("Variable set : %zu", variable_set.size()); for (Variable& var : variable_set) { var.value = 0.0; XBT_DEBUG("Handling variable %p", &var); if (var.sharing_weight > 0.0 && std::find_if(begin(var.cnsts), end(var.cnsts), [](Element const& x) { return x.consumption_weight != 0.0; }) != end(var.cnsts)) { saturated_variable_set.push_back(var); } else { XBT_DEBUG("Err, finally, there is no need to take care of variable %p", &var); if (var.sharing_weight > 0.0) var.value = 1.0; } } XBT_DEBUG("Active constraints : %zu", active_constraint_set.size()); for (Constraint& cnst : active_constraint_set) { saturated_constraint_set.push_back(cnst); } for (Constraint& cnst : saturated_constraint_set) { cnst.remaining = cnst.bound; cnst.usage = 0.0; } XBT_DEBUG("Fair bottleneck Initialized"); /* * Compute Usage and store the variables that reach the maximum. */ auto& var_list = saturated_variable_set; auto& cnst_list = saturated_constraint_set; do { if (XBT_LOG_ISENABLED(surf_maxmin, xbt_log_priority_debug)) { XBT_DEBUG("Fair bottleneck done"); print(); } XBT_DEBUG("******* Constraints to process: %zu *******", cnst_list.size()); for (auto iter = std::begin(cnst_list); iter != std::end(cnst_list);) { Constraint& cnst = *iter; int nb = 0; XBT_DEBUG("Processing cnst %p ", &cnst); cnst.usage = 0.0; for (Element& elem : cnst.enabled_element_set) { xbt_assert(elem.variable->sharing_weight > 0); if (elem.consumption_weight > 0 && elem.variable->saturated_variable_set_hook.is_linked()) nb++; } XBT_DEBUG("\tThere are %d variables", nb); if (nb > 0 && cnst.sharing_policy == s4u::Link::SharingPolicy::FATPIPE) nb = 1; if (nb == 0) { cnst.remaining = 0.0; cnst.usage = 0.0; iter = cnst_list.erase(iter); } else { cnst.usage = cnst.remaining / nb; XBT_DEBUG("\tConstraint Usage %p : %f with %d variables", &cnst, cnst.usage, nb); iter++; } } for (auto iter = std::begin(var_list); iter != std::end(var_list);) { Variable& var = *iter; double min_inc = DBL_MAX; for (Element const& elm : var.cnsts) { if (elm.consumption_weight > 0) min_inc = std::min(min_inc, elm.constraint->usage / elm.consumption_weight); } if (var.bound > 0) min_inc = std::min(min_inc, var.bound - var.value); var.mu = min_inc; XBT_DEBUG("Updating variable %p maximum increment: %g", &var, var.mu); var.value += var.mu; if (var.value == var.bound) iter = var_list.erase(iter); else iter++; } for (auto iter = std::begin(cnst_list); iter != std::end(cnst_list);) { Constraint& cnst = *iter; XBT_DEBUG("Updating cnst %p ", &cnst); if (cnst.sharing_policy != s4u::Link::SharingPolicy::FATPIPE) { for (Element& elem : cnst.enabled_element_set) { xbt_assert(elem.variable->sharing_weight > 0); XBT_DEBUG("\tUpdate constraint %p (%g) with variable %p by %g", &cnst, cnst.remaining, elem.variable, elem.variable->mu); double_update(&cnst.remaining, elem.consumption_weight * elem.variable->mu, sg_maxmin_precision); } } else { for (Element& elem : cnst.enabled_element_set) { xbt_assert(elem.variable->sharing_weight > 0); XBT_DEBUG("\tNon-Shared variable. Update constraint usage of %p (%g) with variable %p by %g", &cnst, cnst.usage, elem.variable, elem.variable->mu); cnst.usage = std::min(cnst.usage, elem.consumption_weight * elem.variable->mu); } XBT_DEBUG("\tUpdate constraint %p (%g) by %g", &cnst, cnst.remaining, cnst.usage); double_update(&cnst.remaining, cnst.usage, sg_maxmin_precision); } XBT_DEBUG("\tRemaining for %p : %g", &cnst, cnst.remaining); if (cnst.remaining <= 0.0) { XBT_DEBUG("\tGet rid of constraint %p", &cnst); iter = cnst_list.erase(iter); for (Element& elem : cnst.enabled_element_set) { if (elem.variable->sharing_weight <= 0) break; if (elem.consumption_weight > 0 && elem.variable->saturated_variable_set_hook.is_linked()) { XBT_DEBUG("\t\tGet rid of variable %p", elem.variable); simgrid::xbt::intrusive_erase(var_list, *elem.variable); } } } else { iter++; } } } while (not var_list.empty()); cnst_list.clear(); modified_ = true; if (XBT_LOG_ISENABLED(surf_maxmin, xbt_log_priority_debug)) { XBT_DEBUG("Fair bottleneck done"); print(); } }