Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
bugfixes to make the dax loader and typed task scheduler work
[simgrid.git] / src / simdag / sd_task.c
index 901e8f0..64870f9 100644 (file)
@@ -168,6 +168,77 @@ const char *SD_task_get_name(SD_task_t task)
   return task->name;
 }
 
+/** @brief Returns the dynar of the parents of a task
+ *
+ * \param task a task
+ * \return a newly allocated dynar comprising the parents of this task
+ */
+
+xbt_dynar_t SD_task_get_parents(SD_task_t task)
+{
+  unsigned int i;
+  xbt_dynar_t parents;
+  SD_dependency_t dep;
+  SD_CHECK_INIT_DONE();
+  xbt_assert0(task != NULL, "Invalid parameter");
+
+  parents = xbt_dynar_new(sizeof(SD_task_t), NULL);
+  xbt_dynar_foreach(task->tasks_before, i, dep){
+    xbt_dynar_push(parents, &(dep->src));
+  }
+  return parents;
+}
+
+/** @brief Returns the dynar of the parents of a task
+ *
+ * \param task a task
+ * \return a newly allocated dynar comprising the parents of this task
+ */
+xbt_dynar_t SD_task_get_children(SD_task_t task)
+{
+  unsigned int i;
+  xbt_dynar_t children;
+  SD_dependency_t dep;
+  SD_CHECK_INIT_DONE();
+  xbt_assert0(task != NULL, "Invalid parameter");
+
+  children = xbt_dynar_new(sizeof(SD_task_t), NULL);
+  xbt_dynar_foreach(task->tasks_after, i, dep){
+    xbt_dynar_push(children, &(dep->dst));
+  }
+  return children;
+}
+
+/**
+ * \brief Returns the amount of workstations involved in a task
+ *
+ * Only call this on already scheduled tasks!
+ * \param task a task
+ */
+int SD_task_get_workstation_count(SD_task_t task)
+{
+  SD_CHECK_INIT_DONE();
+  xbt_assert0(task != NULL, "Invalid parameter");
+  //  xbt_assert1( task->state_set != sd_global->scheduled_task_set, 
+  //          "Unscheduled task %s", task->name);
+  return task->workstation_nb;
+}
+
+/**
+ * \brief Returns the list of workstations involved in a task
+ *
+ * Only call this on already scheduled tasks!
+ * \param task a task
+ */
+SD_workstation_t* SD_task_get_workstation_list(SD_task_t task)
+{
+  SD_CHECK_INIT_DONE();
+  xbt_assert0(task != NULL, "Invalid parameter");
+  //xbt_assert1( task->state_set != sd_global->scheduled_task_set, 
+  //          "Unscheduled task %s", task->name);
+  return task->workstation_list;
+}
+
 /**
  * \brief Returns the total amount of a task
  *
@@ -200,13 +271,41 @@ double SD_task_get_remaining_amount(SD_task_t task)
     return task->remains;
 }
 
-/* temporary function for debbuging */
+int SD_task_get_kind(SD_task_t task) {
+  return task->kind;
+}
+
+/** @brief Displays debugging informations about a task */
 void SD_task_dump(SD_task_t task)
 {
   unsigned int counter;
   SD_dependency_t dependency;
+  char *statename;
 
   INFO1("Displaying task %s",SD_task_get_name(task));
+  statename=bprintf("%s %s %s %s %s %s %s",
+      (task->state&SD_NOT_SCHEDULED?"not scheduled":""),
+      (task->state&SD_SCHEDULED?"scheduled":""),
+      (task->state&SD_READY?"ready":"not ready"),
+      (task->state&SD_IN_FIFO?"in fifo":""),
+      (task->state&SD_RUNNING?"running":""),
+      (task->state&SD_DONE?"done":""),
+      (task->state&SD_FAILED?"failed":""));
+  INFO1("  - state: %s",statename);
+  free(statename);
+
+  if (task->kind!=0) {
+    switch(task->kind){
+    case SD_TASK_COMM_E2E:
+      INFO0("  - kind: end-to-end communication");
+      break;
+    case SD_TASK_COMP_SEQ:
+      INFO0("  - kind: sequential computation");
+      break;
+    default:
+      INFO1("  - (unknown kind %d)",task->kind);
+    }
+  }
   INFO1("  - amount: %.0f",SD_task_get_amount(task));
   if (xbt_dynar_length(task->tasks_before)) {
     INFO0("  - pre-dependencies:");
@@ -221,6 +320,24 @@ void SD_task_dump(SD_task_t task)
     }
   }
 }
+/** @brief Dumps the task in dotty formalism into the FILE* passed as second argument */
+void SD_task_dotty(SD_task_t task,void* out) {
+  unsigned int counter;
+  SD_dependency_t dependency;
+  fprintf(out, "  T%d [label=\"%.20s\"",(unsigned int)task,task->name);
+  switch(task->kind){
+    case SD_TASK_COMM_E2E:
+      fprintf(out,", shape=box");
+      break;
+    case SD_TASK_COMP_SEQ:
+      fprintf(out,", shape=circle");
+      break;
+  }
+  fprintf(out,"];\n");
+  xbt_dynar_foreach(task->tasks_before,counter,dependency) {
+    fprintf(out," T%d -> T%d;\n",(unsigned int)dependency->src,(unsigned int)dependency->dst);
+  }
+}
 
 /* Destroys a dependency between two tasks.
  */
@@ -553,6 +670,19 @@ double SD_task_get_execution_time(SD_task_t task,
   }
   return max_time * SD_task_get_amount(task);
 }
+static inline void SD_task_do_schedule(SD_task_t task) {
+  SD_CHECK_INIT_DONE();
+
+   if (!__SD_task_is_not_scheduled(task))
+     THROW1(arg_error, 0, "Task '%s' has already been scheduled",
+            SD_task_get_name(task));
+
+ /* update the task state */
+  if (xbt_dynar_length(task->tasks_before) == 0)
+    __SD_task_set_state(task, SD_READY);
+  else
+    __SD_task_set_state(task, SD_SCHEDULED);
+}
 
 /**
  * \brief Schedules a task
@@ -569,45 +699,33 @@ double SD_task_get_execution_time(SD_task_t task,
  * \param rate task execution speed rate
  * \see SD_task_unschedule()
  */
-void SD_task_schedule(SD_task_t task, int workstation_nb,
+void SD_task_schedule(SD_task_t task, int workstation_count,
                       const SD_workstation_t * workstation_list,
                       const double *computation_amount,
                       const double *communication_amount, double rate)
 {
+  xbt_assert0(workstation_count > 0, "workstation_nb must be positive");
 
   int communication_nb;
 
-  SD_CHECK_INIT_DONE();
-  xbt_assert0(task != NULL, "Invalid parameter");
-  xbt_assert0(workstation_nb > 0, "workstation_nb must be positive");
-
-  if (!__SD_task_is_not_scheduled(task))
-    THROW1(arg_error, 0, "Task '%s' has already been scheduled",
-           SD_task_get_name(task));
-
-  task->workstation_nb = workstation_nb;
+  task->workstation_nb = workstation_count;
   task->rate = rate;
 
-  task->computation_amount = xbt_new(double, workstation_nb);
+  task->computation_amount = xbt_new(double, workstation_count);
   memcpy(task->computation_amount, computation_amount,
-         sizeof(double) * workstation_nb);
+         sizeof(double) * workstation_count);
 
-  communication_nb = workstation_nb * workstation_nb;
+  communication_nb = workstation_count * workstation_count;
   task->communication_amount = xbt_new(double, communication_nb);
   memcpy(task->communication_amount, communication_amount,
          sizeof(double) * communication_nb);
 
-  task->workstation_list = xbt_new(SD_workstation_t, workstation_nb);
+  task->workstation_list = xbt_new(SD_workstation_t, workstation_count);
   memcpy(task->workstation_list, workstation_list,
-         sizeof(SD_workstation_t) * workstation_nb);
+         sizeof(SD_workstation_t) * workstation_count);
 
-  /* update the task state */
-  if (xbt_dynar_length(task->tasks_before) == 0)
-    __SD_task_set_state(task, SD_READY);
-  else
-    __SD_task_set_state(task, SD_SCHEDULED);
+  SD_task_do_schedule(task);
 }
-
 /**
  * \brief Unschedules a task
  *
@@ -1031,10 +1149,10 @@ void SD_task_destroy(SD_task_t task)
   DEBUG1("Destroying task %s...", SD_task_get_name(task));
 
   __SD_task_remove_dependencies(task);
-
   /* if the task was scheduled or ready we have to free the scheduling parameters */
   if (__SD_task_is_scheduled_or_ready(task))
     __SD_task_destroy_scheduling_data(task);
+  xbt_swag_remove(task,task->state_set);
 
   if (task->name != NULL)
     xbt_free(task->name);
@@ -1055,6 +1173,14 @@ void SD_task_destroy(SD_task_t task)
 }
 
 
+static inline SD_task_t SD_task_create_sized(const char*name,void*data,double amount,int ws_count) {
+  SD_task_t task = SD_task_create(name,data,amount);
+  task->communication_amount = xbt_new0(double,ws_count*ws_count);
+  task->computation_amount = xbt_new0(double,ws_count);
+  task->workstation_nb = ws_count;
+  task->workstation_list = xbt_new0(SD_workstation_t,ws_count);
+  return task;
+}
 /** @brief create a end-to-end communication task that can then be auto-scheduled
  *
  * Auto-scheduling mean that the task can be used with SD_task_schedulev(). This
@@ -1066,7 +1192,8 @@ void SD_task_destroy(SD_task_t task)
  * specified at creation is sent from hosts[0] to hosts[1].
  */
 SD_task_t SD_task_create_comm_e2e(const char*name, void *data, double amount) {
-  SD_task_t res = SD_task_create(name,data,amount);
+  SD_task_t res = SD_task_create_sized(name,data,amount,2);
+  res->communication_amount[2] = amount;
   res->kind=SD_TASK_COMM_E2E;
   return res;
 }
@@ -1081,7 +1208,8 @@ SD_task_t SD_task_create_comm_e2e(const char*name, void *data, double amount) {
  * specified at creation to be run on hosts[0].
  */
 SD_task_t SD_task_create_comp_seq(const char*name, void *data, double amount) {
-  SD_task_t res = SD_task_create(name,data,amount);
+  SD_task_t res = SD_task_create_sized(name,data,amount,1);
+  res->computation_amount[0]=amount;
   res->kind=SD_TASK_COMP_SEQ;
   return res;
 }
@@ -1106,30 +1234,62 @@ SD_task_t SD_task_create_comp_seq(const char*name, void *data, double amount) {
  *  - idem+ internal communication. Task type not enough since we cannot store comm cost alongside to comp one)
  */
 void SD_task_schedulev(SD_task_t task, int count, const SD_workstation_t*list) {
+  int i;
   xbt_assert1(task->kind != 0,"Task %s is not typed. Cannot automatically schedule it.",SD_task_get_name(task));
-  double *comp,*comms;
   switch(task->kind) {
   case SD_TASK_COMM_E2E:
-    xbt_assert2(count == 2,
-          "Task %s is end to end communication, but scheduled with %d hosts",
-          SD_task_get_name(task),count);
-    comms=xbt_new(double,count);
-    comms[0]=0;
-    comms[1]=SD_task_get_amount(task);
-    SD_task_schedule(task,count,list,NULL,comms,1);
-    break;
   case SD_TASK_COMP_SEQ:
-    xbt_assert2(count==1,
-        "Task %s is sequential computation, but scheduled with %d hosts",
-        SD_task_get_name(task),count);
-    comp=xbt_new(double,count);
-    comp[0]=SD_task_get_amount(task);
-    SD_task_schedule(task,count,list,comp,NULL,1);
+    xbt_assert(task->workstation_nb==count);
+    for (i=0;i<count;i++)
+      task->workstation_list[i]=list[i];
+    SD_task_do_schedule(task);
     break;
   default:
     xbt_die(bprintf("Kind of task %s not supported by SD_task_schedulev()",
           SD_task_get_name(task)));
   }
+  if (task->kind == SD_TASK_COMM_E2E) {
+    VERB4("Schedule comm task %s between %s -> %s. It costs %.f bytes",
+        SD_task_get_name(task),
+        SD_workstation_get_name(task->workstation_list[0]),SD_workstation_get_name(task->workstation_list[1]),
+        task->communication_amount[2]);
+
+  }
+  /* Iterate over all childs and parent being COMM_E2E to say where I am located (and start them if ready) */
+  if (task->kind == SD_TASK_COMP_SEQ) {
+    VERB3("Schedule computation task %s on %s. It costs %.f flops",
+        SD_task_get_name(task),SD_workstation_get_name(task->workstation_list[0]),
+        task->computation_amount[0]);
+    SD_dependency_t dep;
+    unsigned int cpt;
+    xbt_dynar_foreach(task->tasks_before,cpt,dep) {
+      SD_task_t before = dep->src;
+      if (before->kind == SD_TASK_COMM_E2E) {
+        before->workstation_list[1] = task->workstation_list[0];
+        if (before->workstation_list[0] && __SD_task_is_not_scheduled(before)) {
+          SD_task_do_schedule(before);
+          VERB4("Auto-Schedule comm task %s between %s -> %s. It costs %.f bytes",
+              SD_task_get_name(before),
+              SD_workstation_get_name(before->workstation_list[0]),SD_workstation_get_name(before->workstation_list[1]),
+              before->communication_amount[2]);
+        }
+      }
+    }
+    xbt_dynar_foreach(task->tasks_after,cpt,dep) {
+      SD_task_t after = dep->dst;
+      if (after->kind == SD_TASK_COMM_E2E) {
+        after->workstation_list[0] = task->workstation_list[0];
+        if (after->workstation_list[1] && __SD_task_is_not_scheduled(after)) {
+          SD_task_do_schedule(after);
+          VERB4("Auto-Schedule comm task %s between %s -> %s. It costs %.f bytes",
+              SD_task_get_name(after),
+              SD_workstation_get_name(after->workstation_list[0]),SD_workstation_get_name(after->workstation_list[1]),
+              after->communication_amount[2]);
+
+        }
+      }
+    }
+  }
 }
 /** @brief autoschedule a task on a list of workstations
  *
@@ -1147,4 +1307,5 @@ void SD_task_schedulel(SD_task_t task, int count, ...) {
   }
   va_end(ap);
   SD_task_schedulev(task,count,list);
+  free(list);
 }