Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add functions SD_workstation_get_computation_time, SD_workstation_route_get_communica...
authorthiery <thiery@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Tue, 4 Jul 2006 16:42:25 +0000 (16:42 +0000)
committerthiery <thiery@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Tue, 4 Jul 2006 16:42:25 +0000 (16:42 +0000)
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@2479 48e7efb5-ca39-0410-a469-dd3cf9ba447f

examples/simdag/sd_test.c
include/simdag/simdag.h
src/simdag/sd_global.c
src/simdag/sd_task.c
src/simdag/sd_workstation.c

index b2c435a..e5f6f15 100644 (file)
@@ -8,12 +8,14 @@ XBT_LOG_NEW_DEFAULT_CATEGORY(sd_test,
                             "Logging specific to this SimDag example");
 
 int main(int argc, char **argv) {
+  int i;
   
   /* initialisation of SD */
   SD_init(&argc, argv);
 
-  /*  xbt_log_control_set("sd.thres=debug");*/
-
+/*   xbt_log_control_set("sd_test.thres=debug"); */
+/*   xbt_log_control_set("sd.thres=debug"); */
+  
   if (argc < 2) {
      INFO1("Usage: %s platform_file", argv[0]);
      INFO1("example: %s sd_platform.xml", argv[0]);
@@ -24,6 +26,34 @@ int main(int argc, char **argv) {
   char * platform_file = argv[1];
   SD_create_environment(platform_file);
 
+  /* test the estimation functions (use small_platform.xml) */
+  SD_workstation_t w1 = SD_workstation_get_by_name("Jupiter");
+  SD_workstation_t w2 = SD_workstation_get_by_name("Ginette");
+  const char *name1 = SD_workstation_get_name(w1);
+  const char *name2 = SD_workstation_get_name(w2);
+  const double computation_amount1 = 2000000;
+  const double computation_amount2 = 1000000;
+  const double communication_amount12 = 2000000;
+  const double communication_amount21 = 3000000;
+  INFO3("Computation time for %f flops on %s: %f", computation_amount1, name1,
+       SD_workstation_get_computation_time(w1, computation_amount1));
+  INFO3("Computation time for %f flops on %s: %f", computation_amount2, name2,
+       SD_workstation_get_computation_time(w2, computation_amount2));
+
+  INFO2("Route between %s and %s:", name1, name2);
+  SD_link_t *route = SD_workstation_route_get_list(w1, w2);
+  int route_size = SD_workstation_route_get_size(w1, w2);
+  for (i = 0; i < route_size; i++) {
+    INFO3("\tLink %s: latency = %f, bandwidth = %f", SD_link_get_name(route[i]),
+         SD_link_get_current_latency(route[i]), SD_link_get_current_bandwidth(route[i]));
+  }
+  INFO2("Route latency = %f, route bandwidth = %f", SD_workstation_route_get_latency(w1, w2),
+       SD_workstation_route_get_bandwidth(w1, w2));
+  INFO4("Communication time for %f bytes between %s and %s: %f", communication_amount12, name1, name2,
+       SD_workstation_route_get_communication_time(w1, w2, communication_amount12));
+  INFO4("Communication time for %f bytes between %s and %s: %f", communication_amount21, name2, name1,
+       SD_workstation_route_get_communication_time(w2, w1, communication_amount21));
+
   /* creation of the tasks and their dependencies */
   SD_task_t taskA = SD_task_create("Task A", NULL, 10.0);
   SD_task_t taskB = SD_task_create("Task B", NULL, 40.0);
@@ -34,19 +64,28 @@ int main(int argc, char **argv) {
   SD_task_dependency_add(NULL, NULL, taskC, taskA);
   SD_task_dependency_add(NULL, NULL, taskD, taskB);
   SD_task_dependency_add(NULL, NULL, taskD, taskC);
-  /*  SD_task_dependency_add(NULL, NULL, taskA, taskD); /\* deadlock */
+  /*  SD_task_dependency_add(NULL, NULL, taskA, taskD); /\* deadlock *\/ */
 
-  /* let's launch the simulation! */
+  /* scheduling parameters */
 
-  int workstation_number = 2;
-  const SD_workstation_t *workstation_list = SD_workstation_get_list();
-  double computation_amount[] = {100, 200};
+  const int workstation_number = 2;
+  /*  const SD_workstation_t *workstation_list = SD_workstation_get_list();*/
+  const SD_workstation_t workstation_list[] = {w1, w2};
+  double computation_amount[] = {computation_amount1, computation_amount2};
   double communication_amount[] =
     {
-      0, 30,
-      20, 0
+      0, communication_amount12,
+      communication_amount21, 0
     };
-  double rate = 1;
+  double rate = -1.0;
+
+  /* estimated time */
+  SD_task_t task = taskD;
+  INFO2("Estimated time for '%s': %f", SD_task_get_name(task),
+       SD_task_get_execution_time(task, workstation_number, workstation_list,
+                                  computation_amount, communication_amount, rate));
+
+  /* let's launch the simulation! */
 
   SD_task_schedule(taskA, workstation_number, workstation_list,
                   computation_amount, communication_amount, rate);
@@ -60,7 +99,6 @@ int main(int argc, char **argv) {
   SD_task_watch(taskC, SD_DONE);
 
   SD_task_t *changed_tasks;
-  int i;
 
   changed_tasks = SD_simulate(0.001);
   
@@ -96,10 +134,15 @@ int main(int argc, char **argv) {
 
   free(changed_tasks);
 
+  DEBUG0("Destroying tasks...");
+
   SD_task_destroy(taskA);
   SD_task_destroy(taskB);
   SD_task_destroy(taskC);
   SD_task_destroy(taskD);
+
+  DEBUG0("Tasks destroyed. Exiting SimDag...");
+
   SD_exit();
   return 0;
 }
index 1c2f004..5affb36 100644 (file)
@@ -55,6 +55,13 @@ SD_link_t*              SD_workstation_route_get_list(SD_workstation_t src, SD_w
 int                     SD_workstation_route_get_size(SD_workstation_t src, SD_workstation_t dst);
 double                  SD_workstation_get_power(SD_workstation_t workstation);
 double                  SD_workstation_get_available_power(SD_workstation_t workstation);
+
+double    SD_workstation_get_computation_time(SD_workstation_t workstation, double computation_amount);
+double    SD_workstation_route_get_latency(SD_workstation_t src, SD_workstation_t dst);
+double    SD_workstation_route_get_bandwidth(SD_workstation_t src, SD_workstation_t dst);
+double    SD_workstation_route_get_communication_time(SD_workstation_t src, SD_workstation_t dst,
+                                                     double communication_amount);
+
 /** @} */
 
 /************************** Task handling ************************************/
@@ -78,10 +85,14 @@ void*             SD_task_get_data(SD_task_t task);
 void              SD_task_set_data(SD_task_t task, void *data);
 e_SD_task_state_t SD_task_get_state(SD_task_t task);
 const char*       SD_task_get_name(SD_task_t task);
-double            SD_task_get_amount(SD_task_t task);
-double            SD_task_get_remaining_amount(SD_task_t task);
 void              SD_task_watch(SD_task_t task, e_SD_task_state_t state);
 void              SD_task_unwatch(SD_task_t task, e_SD_task_state_t state);
+double            SD_task_get_amount(SD_task_t task);
+double            SD_task_get_remaining_amount(SD_task_t task);
+double            SD_task_get_execution_time(SD_task_t task, int workstation_nb,
+                                            const SD_workstation_t *workstation_list,
+                                            const double *computation_amount, const double *communication_amount,
+                                            double rate);
 void              SD_task_schedule(SD_task_t task, int workstation_nb,
                                   const SD_workstation_t *workstation_list, const double *computation_amount,
                                   const double *communication_amount, double rate);
index 741805e..7462f68 100644 (file)
@@ -214,6 +214,7 @@ SD_task_t* SD_simulate(double how_long)
 
   INFO0("Simulation finished");
   DEBUG3("elapsed_time = %f, total_time = %f, watch_point_reached = %d", elapsed_time, total_time, sd_global->watch_point_reached);
+  DEBUG1("current time = %f", surf_get_clock());
 
   return changed_tasks;
 }
@@ -228,17 +229,18 @@ SD_task_t* SD_simulate(double how_long)
  */
 void SD_exit(void) {
   if (sd_global != NULL) {
+    DEBUG0("Destroying workstation and link dictionaries...");
     xbt_dict_free(&sd_global->workstations);
     xbt_dict_free(&sd_global->links);
 
+    DEBUG0("Destroying workstation and link arrays if necessary...");
     if (sd_global->workstation_list != NULL)
       xbt_free(sd_global->workstation_list);
 
     if (sd_global->link_list != NULL)
       xbt_free(sd_global->link_list);
 
-    xbt_free(sd_global);
-
+    DEBUG0("Destroying the swags...");
     xbt_swag_free(sd_global->not_scheduled_task_set);
     xbt_swag_free(sd_global->scheduled_task_set);
     xbt_swag_free(sd_global->ready_task_set);
@@ -246,6 +248,9 @@ void SD_exit(void) {
     xbt_swag_free(sd_global->done_task_set);
     xbt_swag_free(sd_global->failed_task_set);
 
+    xbt_free(sd_global);
+
+    DEBUG0("Exiting Surf...");
     surf_exit();
   }
 }
index a40dd23..dc05a22 100644 (file)
@@ -7,6 +7,7 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(sd_task,sd,
                                "Logging specific to SimDag (task)");
 
 static void __SD_task_remove_dependencies(SD_task_t task);
+static void __SD_task_destroy_scheduling_data(SD_task_t task);
 
 /**
  * \brief Creates a new task.
@@ -393,15 +394,42 @@ void SD_task_unwatch(SD_task_t task, e_SD_task_state_t state) {
   /*  __SD_print_watch_points(task);*/
 }
 
-/* Destroys the data memorised by SD_task_schedule. Task state must be SD_SCHEDULED or SD_READY.
+/**
+ * \brief Returns an approximative estimation of the execution time of a task.
+ * 
+ * The estimation is very approximative because the value returned is the time
+ * the task would take if it was executed now and if it was the only task.
+ * 
+ * \param task the task to evaluate
+ * \param workstation_nb number of workstations on which the task would be executed
+ * \param workstation_list the workstations on which the task would be executed
+ * \param computation_amount computation amount for each workstation
+ * \param communication_amount communication amount between each pair of workstations
+ * \param rate task execution speed rate
+ * \see SD_schedule()
  */
-static void __SD_task_destroy_scheduling_data(SD_task_t task) {
-  SD_CHECK_INIT_DONE();
-  xbt_assert1(__SD_task_is_scheduled_or_ready(task),
-             "Task '%s' must be SD_SCHEDULED or SD_READY", SD_task_get_name(task));
-  xbt_free(task->workstation_list);
-  xbt_free(task->computation_amount);
-  xbt_free(task->communication_amount);
+double SD_task_get_execution_time(SD_task_t task,
+                                 int workstation_nb,
+                                 const SD_workstation_t *workstation_list,
+                                 const double *computation_amount,
+                                 const double *communication_amount,
+                                 double rate) {
+  /* the task execution time is the maximum execution time of the parallel tasks */
+  double time, max_time = 0.0;
+  int i, j;
+  for (i = 0; i < workstation_nb; i++) {
+    time = SD_workstation_get_computation_time(workstation_list[i], computation_amount[i]);
+    
+    for (j = 0; j < workstation_nb; j++) {
+      time += SD_workstation_route_get_communication_time(workstation_list[i], workstation_list[j],
+                                                         communication_amount[i * workstation_nb + j]);
+    }
+
+    if (time > max_time) {
+      max_time = time;
+    }
+  }
+  return max_time * SD_task_get_amount(task);
 }
 
 /**
@@ -480,7 +508,18 @@ void SD_task_unschedule(SD_task_t task) {
     __SD_task_set_state(task, SD_NOT_SCHEDULED);
 }
 
-/* Runs a task. This function is called by SD_simulate when a scheduled task can start
+/* Destroys the data memorised by SD_task_schedule. Task state must be SD_SCHEDULED or SD_READY.
+ */
+static void __SD_task_destroy_scheduling_data(SD_task_t task) {
+  SD_CHECK_INIT_DONE();
+  xbt_assert1(__SD_task_is_scheduled_or_ready(task),
+             "Task '%s' must be SD_SCHEDULED or SD_READY", SD_task_get_name(task));
+  xbt_free(task->workstation_list);
+  xbt_free(task->computation_amount);
+  xbt_free(task->communication_amount);
+}
+
+/* Runs a task. This function is called by SD_simulate() when a scheduled task can start
  * (ie when its dependencies are satisfied).
  */
 surf_action_t __SD_task_run(SD_task_t task) {
index f2337be..c293960 100644 (file)
@@ -121,7 +121,7 @@ const char* SD_workstation_get_name(SD_workstation_t workstation) {
 /**
  * \brief Returns the route between two workstations
  *
- * Use SD_workstation_route_get_size() to know the array size.
+ * Use SD_workstation_route_get_size() to know the array size. Don't forget to free the array after use.
  *
  * \param src a workstation
  * \param dst another workstation
@@ -188,6 +188,112 @@ double SD_workstation_get_available_power(SD_workstation_t workstation) {
   return surf_workstation_resource->extension_public->get_available_speed(workstation->surf_workstation);
 }
 
+/**
+ * \brief Returns an approximative estimated time for the given computation amount on a workstation
+ *
+ * \param workstation a workstation
+ * \param computation_amount the computation amount you want to evaluate (in flops)
+ * \return an approximative astimated computation time for the given computation amount on this workstation (in seconds)
+ */
+double SD_workstation_get_computation_time(SD_workstation_t workstation, double computation_amount) {
+  SD_CHECK_INIT_DONE();
+  xbt_assert0(workstation != NULL, "Invalid parameter");
+  xbt_assert0(computation_amount >= 0, "computation_amount must be greater than or equal to zero");
+  return computation_amount / SD_workstation_get_power(workstation);
+}
+
+/**
+ * \brief Returns the latency of the route between two workstations, i.e. the sum of all link latencies
+ * between the workstations.
+ *
+ * \param src the first workstation
+ * \param dst the second workstation
+ * \return the latency of the route between the two workstations (in seconds)
+ */
+double SD_workstation_route_get_latency(SD_workstation_t src, SD_workstation_t dst) {
+  SD_CHECK_INIT_DONE();
+  xbt_assert0(src != NULL && dst != NULL, "Invalid parameter");
+  SD_link_t *links = SD_workstation_route_get_list(src, dst);
+  int nb_links = SD_workstation_route_get_size(src, dst);
+  double latency = 0.0;
+  int i;
+  
+  for (i = 0; i < nb_links; i++) {
+    latency += SD_link_get_current_latency(links[i]);
+  }
+
+  free(links);
+  return latency;
+}
+
+/**
+ * \brief Returns the bandwidth of the route between two workstations, i.e. the minimum link bandwidth of all
+ * between the workstations.
+ *
+ * \param src the first workstation
+ * \param dst the second workstation
+ * \return the bandwidth of the route between the two workstations (in bytes/second)
+ */
+double SD_workstation_route_get_bandwidth(SD_workstation_t src, SD_workstation_t dst) {
+  SD_CHECK_INIT_DONE();
+  xbt_assert0(src != NULL && dst != NULL, "Invalid parameter");
+  SD_link_t *links = SD_workstation_route_get_list(src, dst);
+  int nb_links = SD_workstation_route_get_size(src, dst);
+  double bandwidth, min_bandwidth = -1.0;
+  int i;
+  
+  for (i = 0; i < nb_links; i++) {
+    bandwidth = SD_link_get_current_bandwidth(links[i]);
+    if (bandwidth < min_bandwidth || min_bandwidth == -1.0)
+      min_bandwidth = bandwidth;
+  }
+
+  free(links);
+  return min_bandwidth;
+}
+
+/**
+ * \brief Returns an approximative estimated time for the given
+ * communication amount between two workstations
+ *
+ * \param src the first workstation
+ * \param dst the second workstation
+ * \param communication_amount the communication amount you want to evaluate (in bytes)
+ * \return an approximative astimated computation time for the given communication amount
+ * between the workstations (in seconds)
+ */
+double SD_workstation_route_get_communication_time(SD_workstation_t src, SD_workstation_t dst,
+                                                  double communication_amount) {
+  /* total time = latency + transmission time of the slowest link
+     transmission time of a link = communication amount / link bandwidth */
+  SD_CHECK_INIT_DONE();
+  xbt_assert0(src != NULL && dst != NULL, "Invalid parameter");
+  xbt_assert0(communication_amount >= 0, "communication_amount must be greater than or equal to zero");
+
+  SD_link_t *links;
+  int nb_links;
+  double bandwidth, min_bandwidth;
+  double latency;
+  int i;
+  
+  if (communication_amount == 0.0)
+    return 0.0;
+
+  links = SD_workstation_route_get_list(src, dst);
+  nb_links = SD_workstation_route_get_size(src, dst);
+  min_bandwidth = -1.0;
+  latency = 0;
+
+  for (i = 0; i < nb_links; i++) {
+    latency += SD_link_get_current_latency(links[i]);
+    bandwidth = SD_link_get_current_bandwidth(links[i]);
+    if (bandwidth < min_bandwidth || min_bandwidth == -1.0)
+      min_bandwidth = bandwidth;
+  }
+
+  return latency + (communication_amount / min_bandwidth);
+}
+
 /* Destroys a workstation.
  */
 void __SD_workstation_destroy(void *workstation) {