X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/e9a3ff64a8ae1a5566286e3b68a5d669a1bf2949..a36a036c5edf09e563f1fe7b1df4aa791e3ea47e:/src/simdag/sd_dotloader.cpp diff --git a/src/simdag/sd_dotloader.cpp b/src/simdag/sd_dotloader.cpp index 5cc8bfc971..352125e392 100644 --- a/src/simdag/sd_dotloader.cpp +++ b/src/simdag/sd_dotloader.cpp @@ -6,11 +6,9 @@ #include "src/simdag/simdag_private.h" #include "simgrid/simdag.h" -#include "xbt/misc.h" #include "xbt/log.h" #include #include -#include XBT_LOG_NEW_DEFAULT_SUBCATEGORY(sd_dotparse, sd, "Parsing DOT files"); @@ -21,8 +19,6 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(sd_dotparse, sd, "Parsing DOT files"); #elif HAVE_AGRAPH_H #include #define agnxtnode(dot, node) agnxtnode(node) -#define agfstin(dot, node) agfstin(node) -#define agnxtin(dot, edge) agnxtin(edge) #define agfstout(dot, node) agfstout(node) #define agnxtout(dot, edge) agnxtout(edge) #endif @@ -32,109 +28,31 @@ typedef enum { parallel } seq_par_t; -xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par); +xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par, bool schedule); -static xbt_dynar_t result; -static xbt_dict_t jobs; -static xbt_dict_t computers; -static Agraph_t *dag_dot; -static bool schedule = true; static void dot_task_p_free(void *task) { - SD_task_t *t = task; - SD_task_destroy(*t); -} - -static void TRACE_sd_dotloader (SD_task_t task, const char *category) { - if (category && strlen (category)){ - if (task->category) - XBT_DEBUG("Change the category of %s from %s to %s", - task->name, task->category, category); - else - XBT_DEBUG("Set the category of %s to %s",task->name, category); - TRACE_category (category); - TRACE_sd_set_task_category(task, category); - } + SD_task_destroy(*(SD_task_t *)task); } /** @brief loads a DOT file describing a DAG * - * See http://www.graphviz.org/doc/info/lang.html - * for more details. - * To obtain information about transfers and tasks, two attributes are - * required : size on task (execution time in Flop) and size on edge - * (the amount of data transfer in bit). - * if they aren't here, there choose to be equal to zero. + * See http://www.graphviz.org/doc/info/lang.html for more details. + * The size attribute of a node describes: + * - for a compute task: the amount of flops to execute + * - for a communication task : the amount of bytes to transfer + * If this attribute is ommited, the default value is zero. */ xbt_dynar_t SD_dotload(const char *filename) { - computers = xbt_dict_new_homogeneous(NULL); - schedule = false; - SD_dotload_generic(filename, sequential); - xbt_dynar_t computer = NULL; - xbt_dict_cursor_t dict_cursor; - char *computer_name; - xbt_dict_foreach(computers,dict_cursor,computer_name,computer){ - xbt_dynar_free(&computer); - } - xbt_dict_free(&computers); - return result; + return SD_dotload_generic(filename, sequential, false); } -xbt_dynar_t SD_dotload_with_sched(const char *filename) { - computers = xbt_dict_new_homogeneous(NULL); - SD_dotload_generic(filename, sequential); - - if(schedule){ - xbt_dynar_t computer = NULL; - xbt_dict_cursor_t dict_cursor; - char *computer_name; - const SD_workstation_t *workstations = SD_workstation_get_list (); - xbt_dict_foreach(computers,dict_cursor,computer_name,computer){ - int count_computer = atoi(computer_name); - unsigned int count=0; - SD_task_t task; - SD_task_t task_previous = NULL; - xbt_dynar_foreach(computer,count,task){ - /* add dependency between the previous and the task to avoid - * parallel execution */ - if(task != NULL ){ - if(task_previous != NULL && - !SD_task_dependency_exists(task_previous, task)) - SD_task_dependency_add(NULL, NULL, task_previous, task); - SD_task_schedulel(task, 1, workstations[count_computer]); - task_previous = task; - } - } - xbt_dynar_free(&computer); - } - xbt_dict_free(&computers); - if(acyclic_graph_detail(result)) - return result; - else - XBT_WARN("There is at least one cycle in the provided task graph"); - }else{ - XBT_WARN("The scheduling is ignored"); - } - xbt_dynar_t computer = NULL; - xbt_dict_cursor_t dict_cursor; - char *computer_name; - xbt_dict_foreach(computers,dict_cursor,computer_name,computer){ - xbt_dynar_free(&computer); - } - xbt_dict_free(&computers); - xbt_dynar_free(&result); - return NULL; +xbt_dynar_t SD_PTG_dotload(const char * filename) { + return SD_dotload_generic(filename, parallel, false); } -xbt_dynar_t SD_PTG_dotload(const char * filename) { - xbt_dynar_t result = SD_dotload_generic(filename, parallel); - if (!acyclic_graph_detail(result)) { - XBT_ERROR("The DOT described in %s is not a DAG. It contains a cycle.", - basename((char*)filename)); - xbt_dynar_free(&result); - /* (result == NULL) here */ - } - return result; +xbt_dynar_t SD_dotload_with_sched(const char *filename) { + return SD_dotload_generic(filename, sequential, true); } #ifdef HAVE_CGRAPH_H @@ -146,56 +64,51 @@ static int edge_compare(const void *a, const void *b) } #endif -xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par){ +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"); unsigned int i; - result = xbt_dynar_new(sizeof(SD_task_t), dot_task_p_free); - jobs = xbt_dict_new_homogeneous(NULL); + SD_task_t root, end, task; + xbt_dict_t computers; + xbt_dynar_t computer = NULL; + char *computer_name; + xbt_dict_cursor_t dict_cursor; + bool schedule_success = true; + + xbt_dynar_t result = xbt_dynar_new(sizeof(SD_task_t), dot_task_p_free); + xbt_dict_t jobs = xbt_dict_new_homogeneous(NULL); + FILE *in_file = fopen(filename, "r"); if (in_file == NULL) xbt_die("Failed to open file: %s", filename); - dag_dot = agread(in_file, NIL(Agdisc_t *)); - SD_task_t root, end, task; - /* - * Create all the nodes - */ + + Agraph_t * dag_dot = agread(in_file, NIL(Agdisc_t *)); + + if (schedule) + computers = xbt_dict_new_homogeneous(NULL); + + /* Create all the nodes */ Agnode_t *node = NULL; for (node = agfstnode(dag_dot); node; node = agnxtnode(dag_dot, node)) { - char *name = agnameof(node); double amount = atof(agget(node, (char *) "size")); double alpha = 0.0; - if (seq_or_par == sequential){ - XBT_DEBUG("See ", name, amount); - } else { - if (!strcmp(agget(node, (char *) "alpha"), "")){ - alpha = atof(agget(node, (char *) "alpha")); - if (alpha == -1.){ - XBT_DEBUG("negative alpha value provided. Set to 0."); - alpha = 0.0 ; - } - } else { - XBT_DEBUG("no alpha value provided. Set to 0"); - alpha = 0.0 ; - } - - XBT_DEBUG("See ", - name, amount, alpha); - } - - if (!(task = xbt_dict_get_or_null(jobs, name))) { + if (!(task = (SD_task_t)xbt_dict_get_or_null(jobs, name))) { if (seq_or_par == sequential){ + XBT_DEBUG("See ", name, amount); task = SD_task_create_comp_seq(name, NULL , amount); } else { + alpha = atof(agget(node, (char *) "alpha")); + XBT_DEBUG("See ", name, amount, alpha); task = SD_task_create_comp_par_amdahl(name, NULL , amount, alpha); } - TRACE_sd_dotloader (task, agget (node, (char*)"category")); + xbt_dict_set(jobs, name, task, NULL); + if (!strcmp(name, "root")){ - /* by design the root task is always SCHEDULABLE */ - __SD_task_set_state(task, SD_SCHEDULABLE); - /* Put it at the beginning of the dynar */ + /* by design the root task is always SCHEDULABLE */ + SD_task_set_state(task, SD_SCHEDULABLE); + /* Put it at the beginning of the dynar */ xbt_dynar_insert_at(result, 0, &task); } else { if (!strcmp(name, "end")){ @@ -208,25 +121,21 @@ xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par){ } if((seq_or_par == sequential) && - (schedule || - XBT_LOG_ISENABLED(sd_dotparse, xbt_log_priority_verbose))){ - /* try to take the information to schedule the task only if all is - * right*/ + ((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*/ int performer, order; char *char_performer = agget(node, (char *) "performer"); char *char_order = agget(node, (char *) "order"); /* performer is the computer which execute the task */ - performer = - ((!char_performer || !strcmp(char_performer,"")) ? -1:atoi(char_performer)); + performer = ((!char_performer || !strcmp(char_performer,"")) ? -1:atoi(char_performer)); /* order is giving the task order on one computer */ order = ((!char_order || !strcmp(char_order, ""))? -1:atoi(char_order)); - XBT_DEBUG ("Task '%s' is scheduled on workstation '%d' in position '%d'", - task->name, performer, order); + XBT_DEBUG ("Task '%s' is scheduled on workstation '%d' in position '%d'", task->name, performer, order); xbt_dynar_t computer = NULL; if(performer != -1 && order != -1){ /* required parameters are given */ - computer = xbt_dict_get_or_null(computers, char_performer); + computer = (xbt_dynar_t)xbt_dict_get_or_null(computers, char_performer); if(computer == NULL){ computer = xbt_dynar_new(sizeof(SD_task_t), NULL); xbt_dict_set(computers, char_performer, computer, NULL); @@ -234,14 +143,13 @@ xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par){ if(performer < xbt_dict_length(host_list)){ /* the wanted computer is available */ SD_task_t *task_test = NULL; - if(order < computer->used) - task_test = xbt_dynar_get_ptr(computer,order); + if((unsigned int)order < computer->used) + task_test = (SD_task_t *)xbt_dynar_get_ptr(computer,order); if(task_test != NULL && *task_test != NULL && *task_test != task){ /* the user gives the same order to several tasks */ - schedule = false; + schedule_success = false; XBT_VERB("The task %s starts on the computer %s at the position : %s like the task %s", - (*task_test)->name, char_performer, char_order, - task->name); + (*task_test)->name, char_performer, char_order, task->name); }else{ /* the parameter seems to be ok */ xbt_dynar_set_as(computer, order, SD_task_t, task); @@ -249,15 +157,14 @@ xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par){ }else{ /* the platform has not enough processors to schedule the DAG like * the user wants*/ - schedule = false; + schedule_success = false; XBT_VERB("The schedule is ignored, there are not enough computers"); } } else { /* one of required parameters is not given */ - schedule = false; - XBT_VERB("The schedule is ignored, the task %s is not correctly scheduled", - task->name); + schedule_success = false; + XBT_VERB("The schedule is ignored, the task %s is not correctly scheduled", task->name); } } } else { @@ -265,32 +172,26 @@ xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par){ } } - /* - * Check if 'root' and 'end' nodes have been explicitly declared. - * If not, create them. - */ - if (!(root = xbt_dict_get_or_null(jobs, "root"))){ + /*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"))){ if (seq_or_par == sequential) root = SD_task_create_comp_seq("root", NULL, 0); else root = SD_task_create_comp_par_amdahl("root", NULL, 0, 0); /* by design the root task is always SCHEDULABLE */ - __SD_task_set_state(root, SD_SCHEDULABLE); + SD_task_set_state(root, SD_SCHEDULABLE); /* Put it at the beginning of the dynar */ - xbt_dynar_insert_at(result, 0, &root); + xbt_dynar_insert_at(result, 0, &root); } - if (!(end = xbt_dict_get_or_null(jobs, "end"))){ + if (!(end = (SD_task_t)xbt_dict_get_or_null(jobs, "end"))){ if (seq_or_par == sequential) end = SD_task_create_comp_seq("end", NULL, 0); else end = SD_task_create_comp_par_amdahl("end", NULL, 0, 0); - /* Should be inserted later in the dynar */ } - /* - * Create edges - */ + /* Create edges */ xbt_dynar_t edges = xbt_dynar_new(sizeof(Agedge_t*), NULL); for (node = agfstnode(dag_dot); node; node = agnxtnode(dag_dot, node)) { unsigned cursor; @@ -299,10 +200,9 @@ xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par){ for (edge = agfstout(dag_dot, node); edge; edge = agnxtout(dag_dot, edge)) xbt_dynar_push_as(edges, Agedge_t *, edge); #ifdef HAVE_CGRAPH_H - /* Hack: circumvent a bug in libcgraph, where the edges are not always given - * back in creation order. We sort them again, according to their sequence - * id. The problem appears to be solved (i.e.: I did not test it) in - * graphviz' mercurial repository by the following changeset: + /* Hack: circumvent a bug in libcgraph, where the edges are not always given back in creation order. We sort them + * again, according to their sequence id. The problem appears to be solved (i.e.: I did not test it) in graphviz' + * mercurial repository by the following changeset: * changeset: 8431:d5f1fb7e8103 * user: Emden Gansner * date: Tue Oct 11 12:38:58 2011 -0400 @@ -317,20 +217,18 @@ xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par){ char *dst_name=agnameof(aghead(edge)); double size = atof(agget(edge, (char *) "size")); - src = xbt_dict_get_or_null(jobs, src_name); - dst = xbt_dict_get_or_null(jobs, dst_name); + src = (SD_task_t)xbt_dict_get_or_null(jobs, src_name); + dst = (SD_task_t)xbt_dict_get_or_null(jobs, dst_name); if (size > 0) { - char *name = - xbt_malloc((strlen(src_name)+strlen(dst_name)+6)*sizeof(char)); + char *name = (char*)xbt_malloc((strlen(src_name)+strlen(dst_name)+6)*sizeof(char)); sprintf(name, "%s->%s", src_name, dst_name); XBT_DEBUG("See ", name, size); - if (!(task = xbt_dict_get_or_null(jobs, name))) { + if (!(task = (SD_task_t)xbt_dict_get_or_null(jobs, name))) { if (seq_or_par == sequential) task = SD_task_create_comm_e2e(name, NULL , size); else task = SD_task_create_comm_par_mxn_1d_block(name, NULL , size); - TRACE_sd_dotloader (task, agget (node, (char*)"category")); SD_task_dependency_add(NULL, NULL, src, task); SD_task_dependency_add(NULL, NULL, task, dst); xbt_dict_set(jobs, name, task, NULL); @@ -346,25 +244,21 @@ xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par){ } xbt_dynar_free(&edges); - /* all compute and transfer tasks have been created, put the "end" node at - * the end of dynar - */ - XBT_DEBUG("All tasks have been created, put %s at the end of the dynar", - end->name); + /* all compute and transfer tasks have been created, put the "end" node at the end of dynar */ + 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'*/ - xbt_dynar_foreach (result, i, task){ if (task == root || task == end) continue; if (xbt_dynar_is_empty(task->tasks_before)) { - XBT_DEBUG("file '%s' has no source. Add dependency from 'root'", - task->name); + XBT_DEBUG("file '%s' has no source. Add dependency from 'root'", task->name); SD_task_dependency_add(NULL, NULL, root, task); - } else if (xbt_dynar_is_empty(task->tasks_after)) { - XBT_DEBUG("file '%s' has no destination. Add dependency to 'end'", - task->name); + } + + if (xbt_dynar_is_empty(task->tasks_after)) { + XBT_DEBUG("file '%s' has no destination. Add dependency to 'end'", task->name); SD_task_dependency_add(NULL, NULL, task, end); } } @@ -373,11 +267,43 @@ xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par){ xbt_dict_free(&jobs); fclose(in_file); + if(schedule){ + if (schedule_success) { + const sg_host_t *workstations = sg_host_list (); + xbt_dict_foreach(computers,dict_cursor,computer_name,computer){ + int count_computer = atoi(computer_name); + unsigned int count=0; + SD_task_t task; + SD_task_t task_previous = NULL; + xbt_dynar_foreach(computer,count,task){ + /* add dependency between the previous and the task to avoid parallel execution */ + if(task != NULL ){ + if(task_previous != NULL && !SD_task_dependency_exists(task_previous, task)) + SD_task_dependency_add(NULL, NULL, task_previous, task); + + SD_task_schedulel(task, 1, workstations[count_computer]); + task_previous = task; + } + } + xbt_dynar_free(&computer); + } + xbt_dict_free(&computers); + } else { + XBT_WARN("The scheduling is ignored"); + xbt_dict_foreach(computers,dict_cursor,computer_name,computer){ + xbt_dynar_free(&computer); + } + + xbt_dict_free(&computers); + xbt_dynar_free(&result); + result = NULL; + } + } + if (!acyclic_graph_detail(result)) { - XBT_ERROR("The DOT described in %s is not a DAG. It contains a cycle.", - basename((char*)filename)); + XBT_ERROR("The DOT described in %s is not a DAG. It contains a cycle.", basename((char*)filename)); xbt_dynar_free(&result); - /* (result == NULL) here */ + result = NULL; } return result; }