SimGrid 【2】 s4u的使用 - mailbox 與 actor create

目錄

 

1. s4u概念與使用簡介

2. mailbox的概念與使用簡介

3. actor-create 例子

3.1 actor-create.cpp

3.2 small_platform.xml

3.3 deployment:li-s4u-actor-create_d.xml

3.4 運行結果

 

3.5 程序分析

參考文獻


1. s4u概念與使用簡介

s4u全稱爲 SimGrid for you,具體介紹如官網[1]中所寫:The S4U interface (SimGrid for you) mixes the full power of SimGrid with the full power of C++. This is the preferred interface to describe abstract algorithms in the domains of Cloud, P2P, HPC, IoT, and similar settings.

簡單而言就是,SimGrid推薦使用s4u來進行編寫C++程序,可以表示雲計算,P2P,HPC,IoT等抽象算法。

要使用s4u進行模擬,必須要自己寫一下幾部分的代碼。

(1)Actors:顯示的s4u描述Actors的Activities,包括, computation, communication, disk usage, and other Activities

(2)Platform:Platform files define the simulated platform on which the provided application will take place. In contains one or several Network Zone that contain both Host and Link Resources, as well as routing information.

(3)deployment:Deployment files specify the execution scenario: it lists the actors that should be started, along with their parameter.

2. mailbox的概念與使用簡介

mailbox這一概念出現在通信的時候,在SimGrid中communication不是直接一個Actor至另一個Actor,是通過mailbox進行中轉的(這裏沒能理解),可以是同步阻塞的也可以是異步的。官方文檔中的比喻是相當於電話號碼,caller可以通過其查找到receiver。Mailboxes are rendez-vous points for network communications, similar to URLs on which you could post and retrieve data. Actually, the mailboxes are not involved in the communication once it starts, but only to find the contact with which you want to communicate.

They are similar to many common things: The phone number, which allows the caller to find the receiver. The twitter hashtag, which help senders and receivers to find each others. In TCP, the pair {host name, host port} to which you can connect to find your peer. In HTTP, URLs through which the clients can connect to the servers. In ZeroMQ, the queues are used to match senders and receivers.

put()與get()是同步阻塞式的消息傳遞方式,The matching algorithm simple: first come, first serve. When a new send arrives, it matches the oldest enqueued receive. If no receive is currently enqueued, then the incoming send is enqueued. As you can see, the mailbox cannot contain both send and receive requests: all enqueued requests must be of the same sort.(沒懂,以後遇到代碼在進行理解......)

3. actor-create 例子

安裝SimGrid後,其example夾下自帶很多的例子,我學習與修改的是example/s4u/actor-create的例子。主要說明的是SimGrid代碼中3大元素的actor如何定義與啓動。

3.1 actor-create.cpp

/* Copyright (c) 2006-2020. The SimGrid Team. All rights reserved.          */

/* This program is free software; you can redistribute it and/or modify it
 * under the terms of the license (GNU LGPL) which comes with this package. */

/* This example shows how to declare and start your actors.
 *
 * The first step is to declare the code of your actors (what they do exactly does not matter to this example) and then
 * you ask SimGrid to start your actors. There is three ways of doing so:
 *  - Directly, by instantiating your actor as parameter to Actor::create()
 *  - By first registering your actors before instantiating it
 *  - Through the deployment file.
 *
 * This example shows all these solutions, even if you obviously should use only one of these solutions to start your
 * actors. The most advised solution is to use a deployment file, as it creates a clear separation between your
 * application and the settings to test it. This is a better scientific methodology. Actually, starting an actor with
 * Actor::create() is mostly useful to start an actor from another actor.
 */

#include <simgrid/s4u.hpp>
#include <string>

// This declares a logging channel so that XBT_INFO can be used later
XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_actor_create, "The logging channel used in this example");

/* Our first class of actors is simply implemented with a function, that takes a single string as parameter.
 *
 * Later, this actor class is instantiated within the simulation.
 */
static void receiver(const std::string& mailbox_name)
{
  simgrid::s4u::Mailbox* mailbox = simgrid::s4u::Mailbox::by_name(mailbox_name);

  XBT_INFO("I'm Receiver, I'm ready to get any message you'd want on %s", mailbox->get_cname());

  const std::string* msg1 = static_cast<std::string*>(mailbox->get());
  const std::string* msg2 = static_cast<std::string*>(mailbox->get());
  const std::string* msg3 = static_cast<std::string*>(mailbox->get());
  XBT_INFO("I received '%s', '%s' and '%s'", msg1->c_str(), msg2->c_str(), msg3->c_str());
  delete msg1;
  delete msg2;
  delete msg3;
  XBT_INFO("I'm done. See you.");
}

/* Our second class of actors is also a function */
static int forwarder(int argc, char** argv)
{
  xbt_assert(argc >= 3, "Actor forwarder requires 2 parameters, but got only %d", argc - 1);
  simgrid::s4u::Mailbox* in    = simgrid::s4u::Mailbox::by_name(argv[1]);
  simgrid::s4u::Mailbox* out   = simgrid::s4u::Mailbox::by_name(argv[2]);
  std::string* msg             = static_cast<std::string*>(in->get());
  XBT_INFO("Forward '%s'.", msg->c_str());
  out->put(msg, msg->size());
  return 0;
}

/* Declares a third class of actors which sends a message to the mailbox 'li'.
 * The sent message is what was passed as parameter on creation (or 'GaBuZoMeu' by default)
 *
 * Later, this actor class is instantiated twice in the simulation.
 */
class Sender {
public:
  std::string mbox  = "li";
  std::string msg = "linweieran-default";
  explicit Sender() = default; /* Sending the default message */
  explicit Sender(const std::string& arg) : msg(arg) { /* Sending the specified message */}
  explicit Sender(std::vector<std::string> args)
  {
    /* This constructor is used when we start the actor from the deployment file */
    /* args[0] is the actor's name, so the first parameter is args[1] */

    xbt_assert(args.size() >= 3, "The sender is expecting 2 parameters from the deployment file but got %zu",
               args.size() - 1);
    msg  = args[1];
    mbox = args[2];
  }
  void operator()() /* This is the main code of the actor */
  {
    XBT_INFO("Hello s4u, I have something to send");
    simgrid::s4u::Mailbox* mailbox = simgrid::s4u::Mailbox::by_name(mbox);

    mailbox->put(new std::string(msg), msg.size());
    XBT_INFO("I'm done. See you.");
  }
};

/* Here comes the main function of your program */
int main(int argc, char** argv)
{
  /* When your program starts, you have to first start a new simulation engine, as follows */
  simgrid::s4u::Engine e(&argc, argv);

  /* Then you should load a platform file, describing your simulated platform */
  e.load_platform("../../platforms/small_platform.xml");

  /* And now you have to ask SimGrid to actually start your actors.
   *
   * The easiest way to do so is to implement the behavior of your actor in a single function,
   * as we do here for the receiver actors. This function can take any kind of parameters, as
   * long as the last parameters of Actor::create() match what your function expects.
   */
  simgrid::s4u::Actor::create("receiver", simgrid::s4u::Host::by_name("Fafard"), &receiver, "li");
  XBT_INFO("Start actor receiver done.");
  /* If your actor is getting more complex, you probably want to implement it as a class instead,
   * as we do here for the sender actors. The main behavior goes into operator()() of the class.
   *
   * You can then directly start your actor, as follows: */
  simgrid::s4u::Actor::create("sender1", simgrid::s4u::Host::by_name("Tremblay"), Sender());
  XBT_INFO("Start actor Sender1 done.");

  /* If you want to pass parameters to your class, that's very easy: just use your constructors */
  simgrid::s4u::Actor::create("sender2", simgrid::s4u::Host::by_name("Jupiter"), Sender("XJTU-input"));
  XBT_INFO("Start actor Sender2 done.");

  /* But starting actors directly is considered as a bad experimental habit, since it ties the code
   * you want to test with the experimental scenario. Starting your actors from an external deployment
   * file in XML ensures that you can test your code in several scenarios without changing the code itself.
   *
   * For that, you first need to register your function or your actor as follows.
   * Actor classes must have a (std::vector<std::string>) constructor,
   * and actor functions must be of type int(*)(int argc, char**argv). */
  e.register_actor<Sender>("sender"); // The sender class is passed as a template parameter here
  XBT_INFO("Register_actor<Sender> done.");
  e.register_function("forwarder", &forwarder);
  /* Once actors and functions are registered, just load the deployment file */
  e.load_deployment("li-s4u-actor-create_d.xml");

  /* Once every actors are started in the engine, the simulation can start */
  e.run();
  XBT_INFO("The program is ended");
  /* Once the simulation is done, the program is ended */
  return 0;
}

3.2 small_platform.xml

<?xml version='1.0'?>
<!DOCTYPE platform SYSTEM "https://simgrid.org/simgrid.dtd">
<platform version="4.1">
  <zone id="zone0" routing="Full">
    <host id="Tremblay" speed="98.095Mf"/>
    <host id="Jupiter" speed="76.296Mf"/>
    <host id="Fafard" speed="76.296Mf"/>
    <host id="Ginette" speed="48.492Mf"/>
    <host id="Bourassa" speed="48.492Mf"/>
    <host id="Jacquelin" speed="137.333Mf"/>
    <host id="Boivin" speed="98.095Mf"/>

    <link id="6" bandwidth="41.279125MBps" latency="59.904us"/>
    <link id="3" bandwidth="34.285625MBps" latency="514.433us"/>
    <link id="7" bandwidth="11.618875MBps" latency="189.98us"/>
    <link id="9" bandwidth="7.20975MBps" latency="1.461517ms"/>
    <link id="2" bandwidth="118.6825MBps" latency="136.931us"/>
    <link id="8" bandwidth="8.158MBps" latency="270.544us"/>
    <link id="1" bandwidth="34.285625MBps" latency="514.433us"/>
    <link id="4" bandwidth="10.099625MBps" latency="479.78us"/>
    <link id="0" bandwidth="41.279125MBps" latency="59.904us"/>
    <link id="5" bandwidth="27.94625MBps" latency="278.066us"/>
    <link id="145" bandwidth="2.583375MBps" latency="410.463us"/>
    <link id="10" bandwidth="34.285625MBps" latency="514.433us"/>
    <link id="11" bandwidth="118.6825MBps" latency="136.931us"/>
    <link id="16" bandwidth="34.285625MBps" latency="514.433us"/>
    <link id="17" bandwidth="118.6825MBps" latency="136.931us"/>
    <link id="44" bandwidth="10.314625MBps" latency="6.932556ms"/>
    <link id="47" bandwidth="10.314625MBps" latency="6.932556ms"/>
    <link id="54" bandwidth="15.376875MBps" latency="35.083019ms"/>
    <link id="56" bandwidth="21.41475MBps" latency="29.5890617ms"/>
    <link id="59" bandwidth="11.845375MBps" latency="370.788us"/>
    <link id="78" bandwidth="27.94625MBps" latency="278.066us"/>
    <link id="79" bandwidth="8.42725MBps" latency="156.056us"/>
    <link id="80" bandwidth="15.376875MBps" latency="35.083019ms"/>
    <link id="loopback" bandwidth="498MBps" latency="15us" 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="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="Jupiter" dst="Ginette">
      <link_ctn id="9"/>
      <link_ctn id="4"/>
      <link_ctn id="3"/>
      <link_ctn id="5"/>
    </route>  
    <route src="Jacquelin" dst="Tremblay">
      <link_ctn id="145"/>
      <link_ctn id="59"/>
      <link_ctn id="56"/>
      <link_ctn id="54"/>
      <link_ctn id="2"/>
      <link_ctn id="3"/>
    </route>    
  </zone>
</platform>

3.3 deployment:li-s4u-actor-create_d.xml

<?xml version='1.0'?>
<!DOCTYPE platform SYSTEM "https://simgrid.org/simgrid.dtd">
<platform version="4.1">

  <!-- This a weird deployment file: we only start one actor from here and the others from the main().
    -
    -  This is only for the example, but don't do that at home.
    -  Instead, you want to start all your actors from the deployment file.
    -->
   
  <actor host="Fafard" function="sender">
    <argument value="linweieran-deploy!"/> <!-- msg as argv[1] -->
    <argument value="other mb"/> <!-- mbox as argv[2] -->
  </actor>
  <actor host="Ginette" function="forwarder">
    <argument value="other mb"/>
    <argument value="li"/>
  </actor>
</platform>

3.4 運行結果

3.5 程序分析

從輸出可以看到SimGrid的整體運行爲,先開啓/註冊,在e.run();之後再運行actor的具體函數。但是不明白是的爲什麼最後註冊的這個首先執行完,不是First come,Frist serve嗎?。。。

 

參考文獻

[1] s4u的簡介:https://simgrid.org/doc/latest/app_s4u.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章