SimGrid  3.7
Scalable simulation of distributed systems
Basic Master/Slaves
MSG Examples

Simulation of a master-slave application using a realistic platform and an external description of the deployment.

Table of contents:


Code of the application

Preliminary declarations

#include <stdio.h>
#include "msg/msg.h"            /* Yeah! If you want to use msg, you need to include msg/msg.h */
#include "xbt/sysdep.h"         /* calloc, printf */

/* Create a log channel to have nice outputs. */
#include "xbt/log.h"
#include "xbt/asserts.h"
XBT_LOG_NEW_DEFAULT_CATEGORY(msg_test,
                             "Messages specific for this msg example");

int master(int argc, char *argv[]);
int slave(int argc, char *argv[]);
int forwarder(int argc, char *argv[]);
MSG_error_t test_all(const char *platform_file,
                     const char *application_file);

#define FINALIZE ((void*)221297)        /* a magic number to tell people to stop working */

int master(int argc, char *argv[])
{
  int slaves_count = 0;
  m_host_t *slaves = NULL;
  m_task_t *todo = NULL;
  int number_of_tasks = 0;
  double task_comp_size = 0;
  double task_comm_size = 0;

  int i;

  _XBT_GNUC_UNUSED int res = sscanf(argv[1], "%d", &number_of_tasks);
  xbt_assert(res,"Invalid argument %s\n", argv[1]);
  res = sscanf(argv[2], "%lg", &task_comp_size);
  xbt_assert(res, "Invalid argument %s\n", argv[2]);
  res = sscanf(argv[3], "%lg", &task_comm_size);
  xbt_assert(res, "Invalid argument %s\n", argv[3]);

  {                             /*  Task creation */
    char sprintf_buffer[64];

    todo = xbt_new0(m_task_t, number_of_tasks);

    for (i = 0; i < number_of_tasks; i++) {
      sprintf(sprintf_buffer, "Task_%d", i);
      todo[i] =
          MSG_task_create(sprintf_buffer, task_comp_size, task_comm_size,
                          NULL);
    }

Master code

This function has to be assigned to a m_process_t that will behave as the master. It should not be called directly but either given as a parameter to MSG_process_create() or registered as a public function through MSG_function_register() and then automatically assigned to a process through MSG_launch_application().

C style arguments (argc/argv) are interpreted as:

Tasks are dumbly sent in a round-robin style.

  }

  {                             /* Process organisation */
    slaves_count = argc - 4;
    slaves = xbt_new0(m_host_t, slaves_count);

    for (i = 4; i < argc; i++) {
      slaves[i - 4] = MSG_get_host_by_name(argv[i]);
      xbt_assert(slaves[i - 4] != NULL, "Unknown host %s. Stopping Now! ",
                  argv[i]);
    }
  }

  XBT_INFO("Got %d slaves and %d tasks to process", slaves_count,
        number_of_tasks);
  for (i = 0; i < slaves_count; i++)
    XBT_DEBUG("%s", MSG_host_get_name(slaves[i]));

  for (i = 0; i < number_of_tasks; i++) {
    XBT_INFO("Sending \"%s\" to \"%s\"",
          todo[i]->name, MSG_host_get_name(slaves[i % slaves_count]));
    if (MSG_host_self() == slaves[i % slaves_count]) {
      XBT_INFO("Hey ! It's me ! :)");
    }

    MSG_task_send(todo[i], MSG_host_get_name(slaves[i % slaves_count]));
    XBT_INFO("Sent");
  }

  XBT_INFO
      ("All tasks have been dispatched. Let's tell everybody the computation is over.");
  for (i = 0; i < slaves_count; i++) {
    m_task_t finalize = MSG_task_create("finalize", 0, 0, FINALIZE);
    MSG_task_send(finalize, MSG_host_get_name(slaves[i]));
  }

  XBT_INFO("Goodbye now!");
  free(slaves);
  free(todo);
  return 0;
}                               /* end_of_master */

Slave code

This function has to be assigned to a m_process_t that has to behave as a slave. Just like the master fuction (described in Master code), it should not be called directly.

This function keeps waiting for tasks and executes them as it receives them.

int slave(int argc, char *argv[])
{
  m_task_t task = NULL;
  _XBT_GNUC_UNUSED int res;
  while (1) {
    res = MSG_task_receive(&(task),MSG_host_get_name(MSG_host_self()));
    xbt_assert(res == MSG_OK, "MSG_task_get failed");

    XBT_INFO("Received \"%s\"", MSG_task_get_name(task));
    if (!strcmp(MSG_task_get_name(task), "finalize")) {
      MSG_task_destroy(task);
      break;
    }

    XBT_INFO("Processing \"%s\"", MSG_task_get_name(task));
    MSG_task_execute(task);
    XBT_INFO("\"%s\" done", MSG_task_get_name(task));
    MSG_task_destroy(task);
    task = NULL;
  }
  XBT_INFO("I'm done. See you!");
  return 0;
}                               /* end_of_slave */

Forwarder code

This function has to be assigned to a m_process_t that has to behave as a forwarder. Just like the master function (described in Master code), it should not be called directly.

C style arguments (argc/argv) are interpreted as a list of host that will accept those tasks.

This function keeps waiting for tasks and dispathes them to its slaves.

int forwarder(int argc, char *argv[])
{
  int i;
  int slaves_count;
  m_host_t *slaves;

  {                             /* Process organisation */
    slaves_count = argc - 1;
    slaves = xbt_new0(m_host_t, slaves_count);

    for (i = 1; i < argc; i++) {
      slaves[i - 1] = MSG_get_host_by_name(argv[i]);
      if (slaves[i - 1] == NULL) {
        XBT_INFO("Unknown host %s. Stopping Now! ", argv[i]);
        abort();
      }
    }
  }

  i = 0;
  while (1) {
    m_task_t task = NULL;
    int a;
    a = MSG_task_receive(&(task),MSG_host_get_name(MSG_host_self()));
    if (a == MSG_OK) {
      XBT_INFO("Received \"%s\"", MSG_task_get_name(task));
      if (MSG_task_get_data(task) == FINALIZE) {
        XBT_INFO
            ("All tasks have been dispatched. Let's tell everybody the computation is over.");
        for (i = 0; i < slaves_count; i++)
          MSG_task_send(MSG_task_create("finalize", 0, 0, FINALIZE),
                          MSG_host_get_name(slaves[i]));
        MSG_task_destroy(task);
        break;
      }
      XBT_INFO("Sending \"%s\" to \"%s\"",
            MSG_task_get_name(task), MSG_host_get_name(slaves[i % slaves_count]));
      MSG_task_send(task, MSG_host_get_name(slaves[i % slaves_count]));
      i++;
    } else {
      XBT_INFO("Hey ?! What's up ? ");
      xbt_die("Unexpected behavior");
    }
  }
  xbt_free(slaves);

  XBT_INFO("I'm done. See you!");
  return 0;
}                               /* end_of_forwarder */

Simulation core

This function is the core of the simulation and is divided only into 3 parts thanks to MSG_create_environment() and MSG_launch_application().

  1. Simulation settings : MSG_create_environment() creates a realistic environment
  2. Application deployment : create the processes on the right locations with MSG_launch_application()
  3. The simulation is run with MSG_main()

Its arguments are:

MSG_error_t test_all(const char *platform_file,
                     const char *application_file)
{
  MSG_error_t res = MSG_OK;

  /* MSG_config("workstation/model","KCCFLN05"); */
  {                             /*  Simulation setting */
    MSG_create_environment(platform_file);
  }
  {                             /*   Application deployment */
    MSG_function_register("master", master);
    MSG_function_register("slave", slave);
    MSG_function_register("forwarder", forwarder);
    MSG_launch_application(application_file);
  }
  res = MSG_main();

  XBT_INFO("Simulation time %g", MSG_get_clock());
  return res;
}                               /* end_of_test_all */

Main() function

This initializes MSG, runs a simulation, and free all data-structures created by MSG.


int main(int argc, char *argv[])
{
  MSG_error_t res = MSG_OK;

  MSG_global_init(&argc, argv);
  if (argc < 3) {
    printf("Usage: %s platform_file deployment_file\n", argv[0]);
    printf("example: %s msg_platform.xml msg_deployment.xml\n", argv[0]);
    exit(1);
  }
  res = test_all(argv[1], argv[2]);
  MSG_clean();

  if (res == MSG_OK)
    return 0;
  else
    return 1;
}                               /* end_of_main */

Helping files

Example of application file

<?xml version='1.0'?>
<!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid.dtd">
<platform version="3">
  <!-- The master process (with some arguments) -->
  <process host="Tremblay" function="master">
     <argument value="20"/>       <!-- Number of tasks -->
     <argument value="50000000"/>  <!-- Computation size of tasks -->
     <argument value="1000000"/>   <!-- Communication size of tasks -->
     <argument value="Jupiter"/>  <!-- First slave -->
     <argument value="Fafard"/>   <!-- Second slave -->
     <argument value="Ginette"/>  <!-- Third slave -->
     <argument value="Bourassa"/> <!-- Last slave -->
     <argument value="Tremblay"/> <!-- Me! I can work too! -->
  </process>
  <!-- The slave process (with no argument) -->
  <process host="Tremblay" function="slave"/>
  <process host="Jupiter" function="slave"/>
  <process host="Fafard" function="slave"/>
  <process host="Ginette" function="slave"/>
  <process host="Bourassa" function="slave"/>
</platform>

Example of platform file

<?xml version='1.0'?>
 <!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid.dtd">
 <platform version="3">
 <AS  id="AS0"  routing="Full">
   <!-- ljlkj -->
   <host id="Tremblay" power="98095000"/>
   <host id="Jupiter" power="76296000"/>
   <host id="Fafard" power="76296000"/>
   <host id="Ginette" power="48492000"/>
   <host id="Bourassa" power="48492000"/>
   <link id="6" bandwidth="41279125" latency="5.9904e-05"/>
   <link id="11" bandwidth="252750" latency="0.00570455"/>
   <link id="3" bandwidth="34285625" latency="0.000514433"/>
   <link id="7" bandwidth="11618875" latency="0.00018998"/>
   <link id="9" bandwidth="7209750" latency="0.001461517"/>
   <link id="12" bandwidth="1792625" latency="0.007877863"/>
   <link id="2" bandwidth="118682500" latency="0.000136931"/>
   <link id="8" bandwidth="8158000" latency="0.000270544"/>
   <link id="1" bandwidth="34285625" latency="0.000514433"/>
   <link id="4" bandwidth="10099625" latency="0.00047978"/>
   <link id="0" bandwidth="41279125" latency="5.9904e-05"/>
   <link id="10" bandwidth="4679750" latency="0.000848712"/>
   <link id="5" bandwidth="27946250" latency="0.000278066"/>
   <link id="loopback" bandwidth="498000000" latency="0.000015" sharing_policy="FATPIPE"/>
   <route src="Tremblay" dst="Tremblay"><link_ctn id="loopback"/></route>
   <route src="Jupiter" dst="Jupiter"><link_ctn id="loopback"/></route>
   <route src="Fafard" dst="Fafard"><link_ctn id="loopback"/></route>
   <route src="Ginette" dst="Ginette"><link_ctn id="loopback"/></route>
   <route src="Bourassa" dst="Bourassa"><link_ctn id="loopback"/></route>
   <route src="Tremblay" dst="Jupiter">
     <link_ctn id="9"/>
   </route>
   <route src="Tremblay" dst="Fafard">
     <link_ctn id="4"/><link_ctn id="3"/><link_ctn id="2"/><link_ctn id="0"/><link_ctn id="1"/><link_ctn id="8"/>
   </route>
   <route src="Tremblay" dst="Ginette">
     <link_ctn id="4"/><link_ctn id="3"/><link_ctn id="5"/>
   </route>
   <route src="Tremblay" dst="Bourassa">
     <link_ctn id="4"/><link_ctn id="3"/><link_ctn id="2"/><link_ctn id="0"/><link_ctn id="1"/><link_ctn id="6"/><link_ctn id="7"/>
   </route>
   <route src="Jupiter" dst="Fafard">
     <link_ctn id="9"/><link_ctn id="4"/><link_ctn id="3"/><link_ctn id="2"/><link_ctn id="0"/><link_ctn id="1"/><link_ctn id="8"/>
   </route>
   <route src="Jupiter" dst="Ginette">
     <link_ctn id="9"/><link_ctn id="4"/><link_ctn id="3"/><link_ctn id="5"/>
   </route>
   <route src="Jupiter" dst="Bourassa">
     <link_ctn id="9"/><link_ctn id="4"/><link_ctn id="3"/><link_ctn id="2"/><link_ctn id="0"/><link_ctn id="1"/><link_ctn id="6"/><link_ctn id="7"/>
   </route>
   <route src="Fafard" dst="Ginette">
     <link_ctn id="8"/><link_ctn id="1"/><link_ctn id="0"/><link_ctn id="2"/><link_ctn id="5"/>
   </route>
   <route src="Fafard" dst="Bourassa">
     <link_ctn id="8"/><link_ctn id="6"/><link_ctn id="7"/>
   </route>
   <route src="Ginette" dst="Bourassa">
     <link_ctn id="5"/><link_ctn id="2"/><link_ctn id="0"/><link_ctn id="1"/><link_ctn id="6"/><link_ctn id="7"/>
   </route>
 </AS>
 </platform>


Back to the main Simgrid Documentation page The version of SimGrid documented here is v3.7.
Documentation of other versions can be found in their respective archive files (directory doc/html).
Generated by doxygen