Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
also display the kind of a task if known from SD_task_dump()
[simgrid.git] / src / simdag / sd_task.c
index 31bdac9..101c92c 100644 (file)
@@ -33,11 +33,8 @@ SD_task_t SD_task_create(const char *name, void *data, double amount)
 
   /* general information */
   task->data = data;            /* user data */
 
   /* general information */
   task->data = data;            /* user data */
-  if (name != NULL)
-    task->name = xbt_strdup(name);
-  else
-    task->name = NULL;
-
+  task->name = xbt_strdup(name);
+  task->kind = 0;
   task->state_hookup.prev = NULL;
   task->state_hookup.next = NULL;
   task->state_set = sd_global->not_scheduled_task_set;
   task->state_hookup.prev = NULL;
   task->state_hookup.next = NULL;
   task->state_set = sd_global->not_scheduled_task_set;
@@ -171,6 +168,77 @@ const char *SD_task_get_name(SD_task_t task)
   return task->name;
 }
 
   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
  *
 /**
  * \brief Returns the total amount of a task
  *
@@ -211,6 +279,18 @@ void SD_task_dump(SD_task_t task)
 
   INFO1("Displaying task %s",SD_task_get_name(task));
   INFO1("  - amount: %.0f",SD_task_get_amount(task));
 
   INFO1("Displaying task %s",SD_task_get_name(task));
   INFO1("  - amount: %.0f",SD_task_get_amount(task));
+  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);
+    }
+  }
   if (xbt_dynar_length(task->tasks_before)) {
     INFO0("  - pre-dependencies:");
     xbt_dynar_foreach(task->tasks_before,counter,dependency) {
   if (xbt_dynar_length(task->tasks_before)) {
     INFO0("  - pre-dependencies:");
     xbt_dynar_foreach(task->tasks_before,counter,dependency) {
@@ -1056,3 +1136,98 @@ void SD_task_destroy(SD_task_t task)
 
   DEBUG0("Task destroyed.");
 }
 
   DEBUG0("Task destroyed.");
 }
+
+
+/** @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
+ * allows to specify the task costs at creation, and decorelate them from the
+ * scheduling process where you just specify which resource should deliver the
+ * mandatory power.
+ *
+ * A end-to-end communication must be scheduled on 2 hosts, and the amount
+ * 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);
+  res->kind=SD_TASK_COMM_E2E;
+  return res;
+}
+/** @brief create a sequential computation task that can then be auto-scheduled
+ *
+ * Auto-scheduling mean that the task can be used with SD_task_schedulev(). This
+ * allows to specify the task costs at creation, and decorelate them from the
+ * scheduling process where you just specify which resource should deliver the
+ * mandatory power.
+ *
+ * A sequential computation must be scheduled on 1 host, and the 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);
+  res->kind=SD_TASK_COMP_SEQ;
+  return res;
+}
+
+/** @brief Auto-schedules a task.
+ *
+ * Auto-scheduling mean that the task can be used with SD_task_schedulev(). This
+ * allows to specify the task costs at creation, and decorelate them from the
+ * scheduling process where you just specify which resource should deliver the
+ * mandatory power.
+ *
+ * To be auto-schedulable, a task must be created with SD_task_create_comm_e2e() or
+ * SD_task_create_comp_seq(). Check their definitions for the exact semantic of each
+ * of them.
+ *
+ * @todo
+ * We should create tasks kind for the following categories:
+ *  - Point to point communication (done)
+ *  - Sequential computation       (done)
+ *  - group communication (redistribution, several kinds)
+ *  - parallel tasks with no internal communication (one kind per speedup model such as amdal)
+ *  - 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) {
+  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);
+    break;
+  default:
+    xbt_die(bprintf("Kind of task %s not supported by SD_task_schedulev()",
+          SD_task_get_name(task)));
+  }
+}
+/** @brief autoschedule a task on a list of workstations
+ *
+ * This function is very similar to SD_task_schedulev(),
+ * but takes the list of workstations to schedule onto as separate parameters.
+ * It builds a proper vector of workstations and then call SD_task_schedulev()
+ */
+void SD_task_schedulel(SD_task_t task, int count, ...) {
+  va_list ap;
+  SD_workstation_t *list=xbt_new(SD_workstation_t,count);
+  int i;
+  va_start(ap,count);
+  for (i=0;i<count;i++) {
+      list[i] = va_arg(ap,SD_workstation_t);
+  }
+  va_end(ap);
+  SD_task_schedulev(task,count,list);
+}