fi
fi
-target=tests
+target=examples
ncores=$(grep -c processor /proc/cpuinfo)
install_path=$(sed -n 's/^CMAKE_INSTALL_PREFIX:PATH=//p' CMakeCache.txt)
add_dependencies(tests tests-mc)
add_custom_target(tests-ns3 COMMENT "Recompiling the ns3 tests and tools.")
add_dependencies(tests tests-ns3)
+add_custom_target(examples COMMENT "Recompiling all examples")
+add_dependencies(examples tests)
### Build some Maintainer files
include(${CMAKE_HOME_DIRECTORY}/tools/cmake/MaintainerMode.cmake)
S4U:
- New class ActivitySet to ease wait_any()/test_any()/wait_all()
+ - New function NetZone::add_route(host1, host2, links) when you don't need gateways
+ Also add a variant with s4u::Link, when you don't want to specify the directions
+ on symmetric routes.
+
+SMPI:
+ - New SMPI_app_instance_join(): wait for the completion of a started MPI instance
+ - MPI_UNIVERSE_SIZE now initialized to the total amount of hosts in the platform
Python:
- Make the host_load plugin available from Python. See examples/python/plugin-host-load
if some do not work for you.
- **make**: Build the core of SimGrid that gets installed, but not any example.
-- **make tests**: Build the tests and examples.
+- **make examples**: Build the examples, which are needed by the tests.
- **make simgrid**: Build only the SimGrid library. Not any example nor the helper tools.
- **make s4u-comm-pingpong**: Build only this example (works for any example)
- **make python-bindings**: Build the Python bindings
communications are not slowed down, because there is no contention yet).
As an alternative to the above LMM-based models, it is possible to use the :ref:`ns-3 simulator as a network model <models_ns3>`. ns-3 performs
-a mushc more detailed, packet-level simulation
+a much more detailed, packet-level simulation
than the above models. As a result is is much slower but will produce more accurate results.
Both simulators have time complexity that is linear in the size of their input, but ns-3 has a much larger input in case of large communications
because it considers individual network packets.
=======
This routing model is particularly well adapted to Peer-to-Peer and Clouds platforms: each component is connected to the
-cloud through a private link of which the upload and download rate may be asymmetric.
+cloud through a private link whose upload and download rates may be asymmetric.
-The network core (between the private links) is assumed to be over-sized so only the latency is taken into account.
-Instead of a matrix of latencies that would become too large when the amount of peers grows, Vivaldi netzones give a
-coordinate to each peer and compute the latency between host A=(xA,yA,zA) and host B=(xB,yB,zB) as follows:
+The network core (between the private links) is assumed to be over-provisioned so that only the latency has to be
+taken into account. Instead of a matrix of latencies that would become too large when the amount of peers grows,
+Vivaldi netzones give a coordinate to each peer and compute the latency between host A=(xA,yA,zA) and host B=(xB,yB,zB)
+as follows:
latency = sqrt( (xA-xB)² + (yA-yB)² ) + zA + zB
sg4::Mailbox* prev = nullptr;
sg4::Mailbox* next = nullptr;
sg4::Mailbox* me = nullptr;
- std::vector<sg4::CommPtr> pending_recvs;
- std::vector<sg4::CommPtr> pending_sends;
+ sg4::ActivitySet pending_recvs;
+ sg4::ActivitySet pending_sends;
unsigned long long received_bytes = 0;
unsigned int received_pieces = 0;
while (not done) {
sg4::CommPtr comm = me->get_async<FilePiece>(&received);
- pending_recvs.push_back(comm);
+ pending_recvs.push(comm);
- ssize_t idx = sg4::Comm::wait_any(pending_recvs);
- if (idx != -1) {
- comm = pending_recvs.at(idx);
+ auto completed_one = pending_recvs.wait_any();
+ if (completed_one != nullptr) {
+ comm = boost::dynamic_pointer_cast<sg4::Comm>(completed_one);
XBT_DEBUG("Peer %s got a 'SEND_DATA' message", me->get_cname());
- pending_recvs.erase(pending_recvs.begin() + idx);
if (next != nullptr) {
XBT_DEBUG("Sending (asynchronously) from %s to %s", me->get_cname(), next->get_cname());
sg4::CommPtr send = next->put_async(received, MESSAGE_SEND_DATA_HEADER_SIZE + PIECE_SIZE);
- pending_sends.push_back(send);
+ pending_sends.push(send);
} else
delete received;
void sendFile()
{
- std::vector<sg4::CommPtr> pending_sends;
+ sg4::ActivitySet pending_sends;
for (unsigned int current_piece = 0; current_piece < piece_count; current_piece++) {
XBT_DEBUG("Sending (send) piece %u from %s into mailbox %s", current_piece, sg4::Host::current()->get_cname(),
first->get_cname());
sg4::CommPtr comm = first->put_async(new FilePiece(), MESSAGE_SEND_DATA_HEADER_SIZE + PIECE_SIZE);
- pending_sends.push_back(comm);
+ pending_sends.push(comm);
}
- sg4::Comm::wait_all(pending_sends);
+ pending_sends.wait_all();
}
Broadcaster(int hostcount, unsigned int piece_count) : piece_count(piece_count)
p.joinChain();
p.forwardFile();
- sg4::Comm::wait_all(p.pending_sends);
+ p.pending_sends.wait_all();
double end_time = sg4::Engine::get_clock();
XBT_INFO("### %f %llu bytes (Avg %f MB/s); copy finished (simulated).", end_time - start_time, p.received_bytes,
auto* host1 = zone->create_host("Host1", "1f");
auto* host2 = zone->create_host("Host2", "1f");
auto* host3 = zone->create_host("Host3", "1f");
+ auto* link2 = zone->create_link("linkto2", "1bps")->seal();
+ auto* link3 = zone->create_link("linkto3", "1bps")->seal();
- sg4::LinkInRoute linkto2{zone->create_link("linkto2", "1bps")->seal()};
- sg4::LinkInRoute linkto3{zone->create_link("linkto3", "1bps")->seal()};
-
- zone->add_route(host1->get_netpoint(), host2->get_netpoint(), nullptr, nullptr, {linkto2}, false);
- zone->add_route(host1->get_netpoint(), host3->get_netpoint(), nullptr, nullptr, {linkto3}, false);
+ zone->add_route(host1, host2, {link2});
+ zone->add_route(host1, host3, {link3});
zone->seal();
sg4::Actor::create("Sender", host1, Sender("mailbox2", "mailbox3"));
sg4::Actor::create("Receiver", host2, Receiver("mailbox2"));
sg4::Actor::create("Receiver", host3, Receiver("mailbox3"));
-
+
sg4::Actor::create("LinkKiller", host1, [](){
sg4::this_actor::sleep_for(10.0);
XBT_INFO("Turning off link 'linkto2'");
> [ 10.000000] (1:Sender@Host1) Comm to mailbox3 has state: STARTED
> [ 10.000000] (1:Sender@Host1) Waiting on a FAILED comm raises an exception: 'Cannot wait for a failed communication'
> [ 10.000000] (1:Sender@Host1) Wait for remaining comm, just to be nice
-> [ 16.494845] (3:Receiver@Host3) Receiver has received successfully!
+> [ 17.319588] (3:Receiver@Host3) Receiver has received successfully!
// Define an amount of work that should take 1 second to execute.
double computation_amount = sg4::this_actor::get_host()->get_speed();
- std::vector<sg4::ExecPtr> pending_execs;
// Create a small DAG
// + Two parents and a child
// + First parent ends after 1 second and the Second parent after 2 seconds.
sg4::ExecPtr first_parent = sg4::this_actor::exec_init(computation_amount);
- pending_execs.push_back(first_parent);
sg4::ExecPtr second_parent = sg4::this_actor::exec_init(2 * computation_amount);
- pending_execs.push_back(second_parent);
sg4::ExecPtr child = sg4::Exec::init()->set_flops_amount(computation_amount);
- pending_execs.push_back(child);
+
+ sg4::ActivitySet pending_execs ({first_parent, second_parent, child});
// Name the activities (for logging purposes only)
first_parent->set_name("parent 1");
// wait for the completion of all activities
while (not pending_execs.empty()) {
- ssize_t changed_pos = sg4::Exec::wait_any_for(pending_execs, -1);
- XBT_INFO("Exec '%s' is complete", pending_execs[changed_pos]->get_cname());
- pending_execs.erase(pending_execs.begin() + changed_pos);
+ auto completed_one = pending_execs.wait_any();
+ if (completed_one != nullptr)
+ XBT_INFO("Exec '%s' is complete", completed_one->get_cname());
}
}
static void test()
{
- std::vector<sg4::ActivityPtr> pending_activities;
-
sg4::ExecPtr bob_compute = sg4::this_actor::exec_init(1e9);
- pending_activities.push_back(boost::dynamic_pointer_cast<sg4::Activity>(bob_compute));
sg4::IoPtr bob_write = sg4::Host::current()->get_disks().front()->io_init(4000000, sg4::Io::OpType::WRITE);
- pending_activities.push_back(boost::dynamic_pointer_cast<sg4::Activity>(bob_write));
sg4::IoPtr carl_read = sg4::Host::by_name("carl")->get_disks().front()->io_init(4000000, sg4::Io::OpType::READ);
- pending_activities.push_back(boost::dynamic_pointer_cast<sg4::Activity>(carl_read));
sg4::ExecPtr carl_compute = sg4::Host::by_name("carl")->exec_init(1e9);
- pending_activities.push_back(boost::dynamic_pointer_cast<sg4::Activity>(carl_compute));
+
+ sg4::ActivitySet pending_activities ({boost::dynamic_pointer_cast<sg4::Activity>(bob_compute),
+ boost::dynamic_pointer_cast<sg4::Activity>(bob_write),
+ boost::dynamic_pointer_cast<sg4::Activity>(carl_read),
+ boost::dynamic_pointer_cast<sg4::Activity>(carl_compute)});
// Name the activities (for logging purposes only)
bob_compute->set_name("bob compute");
// wait for the completion of all activities
while (not pending_activities.empty()) {
- ssize_t changed_pos = sg4::Activity::wait_any(pending_activities);
- XBT_INFO("Activity '%s' is complete", pending_activities[changed_pos]->get_cname());
- pending_activities.erase(pending_activities.begin() + changed_pos);
+ auto completed_one = pending_activities.wait_any();
+ if (completed_one != nullptr)
+ XBT_INFO("Activity '%s' is complete", completed_one->get_cname());
}
}
/* add link UP/DOWN for communications from the host */
root->add_route(host->get_netpoint(), nullptr, nullptr, nullptr, {{l, sg4::LinkInRoute::Direction::UP}}, true);
- const sg4::Link* loopback = root->create_link(hostname + "_loopback", BW_LOCAL)->set_latency(LATENCY)->seal();
- root->add_route(host->get_netpoint(), host->get_netpoint(), nullptr, nullptr, {sg4::LinkInRoute(loopback)});
+ sg4::Link* loopback = root->create_link(hostname + "_loopback", BW_LOCAL)->set_latency(LATENCY)->seal();
+ root->add_route(host, host, {loopback});
}
root->seal();
*/
#include <simgrid/s4u.hpp>
+#include <string>
namespace sg4 = simgrid::s4u;
void operator()() const
{
// sphinx-doc: init-begin (this line helps the doc to build; ignore it)
- /* Vector in which we store all ongoing communications */
- std::vector<sg4::CommPtr> pending_comms;
+ /* ActivitySet in which we store all ongoing communications */
+ sg4::ActivitySet pending_comms;
- /* Make a vector of the mailboxes to use */
+ /* Mailbox to use */
sg4::Mailbox* mbox = sg4::Mailbox::by_name("receiver");
// sphinx-doc: init-end
/* Create a communication representing the ongoing communication, and store it in pending_comms */
sg4::CommPtr comm = mbox->put_async(payload, size);
- pending_comms.push_back(comm);
+ pending_comms.push(comm);
}
XBT_INFO("Done dispatching all messages");
/* Now that all message exchanges were initiated, wait for their completion in one single call */
- sg4::Comm::wait_all(pending_comms);
+ pending_comms.wait_all();
// sphinx-doc: put-end
XBT_INFO("Goodbye now!");
explicit Receiver(int count) : messages_count(count) { mbox = sg4::Mailbox::by_name("receiver"); }
void operator()()
{
- /* Vector in which we store all incoming msgs */
- std::vector<std::unique_ptr<std::string*>> pending_msgs;
- std::vector<sg4::CommPtr> pending_comms;
+ /* Where we store all incoming msgs */
+ std::unordered_map<sg4::CommPtr, std::shared_ptr<std::string*>> pending_msgs;
+ sg4::ActivitySet pending_comms;
XBT_INFO("Wait for %d messages asynchronously", messages_count);
for (int i = 0; i < messages_count; i++) {
- pending_msgs.push_back(std::make_unique<std::string*>());
- pending_comms.emplace_back(mbox->get_async<std::string>(pending_msgs[i].get()));
+ std::shared_ptr<std::string*> msg =std::make_shared<std::string*>();
+ auto comm = mbox->get_async<std::string>(msg.get());
+ pending_comms.push(comm);
+ pending_msgs.insert({comm, msg});
}
+
while (not pending_comms.empty()) {
- ssize_t index = sg4::Comm::wait_any(pending_comms);
- std::string* msg = *pending_msgs[index];
- XBT_INFO("I got '%s'.", msg->c_str());
- /* cleanup memory and remove from vectors */
- delete msg;
- pending_comms.erase(pending_comms.begin() + index);
- pending_msgs.erase(pending_msgs.begin() + index);
+ auto completed_one = pending_comms.wait_any();
+ if (completed_one != nullptr){
+ auto comm = boost::dynamic_pointer_cast<sg4::Comm>(completed_one);
+ auto msg = *pending_msgs[comm];
+ XBT_INFO("I got '%s'.", msg->c_str());
+ /* cleanup memory and remove from map */
+ delete msg;
+ pending_msgs.erase(comm);
+ }
}
}
};
link->set_latency(10e-6)->seal();
/* create routes between nodes */
- zone->add_route(sender->get_netpoint(), receiver->get_netpoint(), nullptr, nullptr,
- {{link, sg4::LinkInRoute::Direction::UP}}, true);
+ zone->add_route(sender, receiver, {link});
zone->seal();
/* create actors Sender/Receiver */
*
* This example is very similar to the other asynchronous communication examples, but messages get serialized by the platform.
* Without this call to Link::set_concurrency_limit(2) in main, all messages would be received at the exact same timestamp since
- * they are initiated at the same instant and are of the same size. But with this extra configuration to the link, at most 2
+ * they are initiated at the same instant and are of the same size. But with this extra configuration to the link, at most 2
* messages can travel through the link at the same time.
*/
void operator()() const
{
// sphinx-doc: init-begin (this line helps the doc to build; ignore it)
- /* Vector in which we store all ongoing communications */
- std::vector<sg4::CommPtr> pending_comms;
+ /* ActivitySet in which we store all ongoing communications */
+ sg4::ActivitySet pending_comms;
- /* Make a vector of the mailboxes to use */
+ /* Mailbox to use */
sg4::Mailbox* mbox = sg4::Mailbox::by_name("receiver");
// sphinx-doc: init-end
/* Create a communication representing the ongoing communication, and store it in pending_comms */
sg4::CommPtr comm = mbox->put_async(payload, msg_size);
- pending_comms.push_back(comm);
+ pending_comms.push(comm);
}
XBT_INFO("Done dispatching all messages");
/* Now that all message exchanges were initiated, wait for their completion in one single call */
- sg4::Comm::wait_all(pending_comms);
+ pending_comms.wait_all();
// sphinx-doc: put-end
XBT_INFO("Goodbye now!");
explicit Receiver(int count) : messages_count(count) { mbox = sg4::Mailbox::by_name("receiver"); }
void operator()()
{
- /* Vector in which we store all incoming msgs */
- std::vector<std::unique_ptr<std::string*>> pending_msgs;
- std::vector<sg4::CommPtr> pending_comms;
+ /* Where we store all incoming msgs */
+ std::unordered_map<sg4::CommPtr, std::shared_ptr<std::string*>> pending_msgs;
+ sg4::ActivitySet pending_comms;
XBT_INFO("Wait for %d messages asynchronously", messages_count);
for (int i = 0; i < messages_count; i++) {
- pending_msgs.push_back(std::make_unique<std::string*>());
- pending_comms.emplace_back(mbox->get_async<std::string>(pending_msgs[i].get()));
+ std::shared_ptr<std::string*> msg =std::make_shared<std::string*>();
+ auto comm = mbox->get_async<std::string>(msg.get());
+ pending_comms.push(comm);
+ pending_msgs.insert({comm, msg});
}
+
while (not pending_comms.empty()) {
- ssize_t index = sg4::Comm::wait_any(pending_comms);
- std::string* msg = *pending_msgs[index];
- XBT_INFO("I got '%s'.", msg->c_str());
- /* cleanup memory and remove from vectors */
- delete msg;
- pending_comms.erase(pending_comms.begin() + index);
- pending_msgs.erase(pending_msgs.begin() + index);
+ auto completed_one = pending_comms.wait_any();
+ if (completed_one != nullptr){
+ auto comm = boost::dynamic_pointer_cast<sg4::Comm>(completed_one);
+ auto msg = *pending_msgs[comm];
+ XBT_INFO("I got '%s'.", msg->c_str());
+ /* cleanup memory and remove from map */
+ delete msg;
+ pending_msgs.erase(comm);
+ }
}
}
};
zone->create_split_duplex_link("link1", 10e9)->set_latency(10e-6)->set_concurrency_limit(2)->seal();
/* create routes between nodes */
- zone->add_route(sender->get_netpoint(), receiver->get_netpoint(), nullptr, nullptr,
- {{link, sg4::LinkInRoute::Direction::UP}}, true);
+ zone->add_route(sender, receiver, {link});
zone->seal();
/* create actors Sender/Receiver */
// Add a new host programatically, and attach a state profile to it
auto* root = e.get_netzone_root();
auto* lilibeth = root->create_host("Lilibeth", 1e15);
- auto link = sg4::LinkInRoute(e.link_by_name("10"));
- root->add_route(e.host_by_name("Tremblay")->get_netpoint(), lilibeth->get_netpoint(), nullptr, nullptr, {link}, true);
+ auto link = e.link_by_name("10");
+ root->add_route(e.host_by_name("Tremblay"), lilibeth, {link});
lilibeth->set_state_profile(simgrid::kernel::profile::ProfileBuilder::from_string("lilibeth_profile", R"(
4 0
5 1
}
auto* router = cluster->create_router("cluster_router");
- cluster->add_route(router, nullptr, nullptr, nullptr, {});
+ std::vector<sg4::LinkInRoute> links; // empty
+ cluster->add_route(router, nullptr, nullptr, nullptr, links);
simgrid::plugin::ProducerConsumerPtr<int> pc = simgrid::plugin::ProducerConsumer<int>::create(2);
host2 = zone.create_host("Host2", "1f")
host3 = zone.create_host("Host3", "1f")
- link_to_2 = LinkInRoute(zone.create_link("link_to_2", "1bps").seal())
- link_to_3 = LinkInRoute(zone.create_link("link_to_3", "1bps").seal())
+ link_to_2 = zone.create_link("link_to_2", "1bps").seal()
+ link_to_3 = zone.create_link("link_to_3", "1bps").seal()
- zone.add_route(host1.netpoint, host2.netpoint, None, None, [link_to_2], False)
- zone.add_route(host1.netpoint, host3.netpoint, None, None, [link_to_3], False)
+ zone.add_route(host1, host2, [link_to_2])
+ zone.add_route(host1, host3, [link_to_3])
zone.seal()
Actor.create("Sender", host1, sender, "mailbox2", "mailbox3")
> [ 10.000000] (1:Sender@Host1) Comm to mailbox3 has state: STARTED
> [ 10.000000] (1:Sender@Host1) Waiting on a FAILED comm raises an exception: 'Cannot wait for a failed communication'
> [ 10.000000] (1:Sender@Host1) Wait for remaining comm, just to be nice
-> [ 16.494845] (3:Receiver-2@Host3) Receiver has received successfully (mailbox3)!
+> [ 17.319588] (3:Receiver-2@Host3) Receiver has received successfully (mailbox3)!
link.set_latency(10e-6).seal()
# create routes between nodes
- zone.add_route(sender.netpoint, receiver.netpoint, None, None,
- [LinkInRoute(link, LinkInRoute.Direction.UP)], True)
+ zone.add_route(sender, receiver, [link])
zone.seal()
# create actors Sender/Receiver
link = zone.create_split_duplex_link("link1", 10e9).set_latency(10e-6).set_concurrency_limit(2).seal()
# create routes between nodes
- zone.add_route(
- sender_host.netpoint,
- receiver_host.netpoint,
- None,
- None,
- [LinkInRoute(link, LinkInRoute.UP)],
- True
- )
+ zone.add_route(sender_host, receiver_host, [link])
zone.seal()
# create actors Sender/Receiver
this_actor.info(f'Run an activity of {100E6:.0E} flops')
this_actor.execute(100E6)
this_actor.info(f'Done working on my activity; this took {Engine.clock - start}s; current peak speed: {host.speed:.0E} flop/s; number of flops computed so far: {host.computed_flops:.0E}')
- Engine
+
start = Engine.clock
this_actor.info("========= Requesting a reset of the computation and load counters")
host.reset_load()
const sg4::Link* link9 = root->create_split_duplex_link("9", "7.20975MBps")->set_latency("1.461517ms")->seal();
- root->add_route(tremblay->get_netpoint(), jupiter->get_netpoint(), nullptr, nullptr,
- {{link9, sg4::LinkInRoute::Direction::UP}}, true);
+ root->add_route(tremblay, jupiter, {link9});
root->seal();
/* set cost callback for MPI_Send and MPI_Recv */
SMPI_app_instance_start("alltoall_mpi", alltoall_mpi,
{e.host_by_name_or_null("Ginette"), e.host_by_name_or_null("Bourassa"),
e.host_by_name_or_null("Jupiter"), e.host_by_name_or_null("Fafard")});
+ SMPI_app_instance_join("alltoall_mpi");
+ XBT_INFO("This other alltoall_mpi instance terminated.");
});
+
e.run();
XBT_INFO("Simulation time %g", simgrid::s4u::Engine::get_clock());
> [Ginette:alltoall_mpi#0:(11) 10.036773] [smpi_masterworkers/INFO] after alltoall 0
> [Bourassa:alltoall_mpi#1:(12) 10.046578] [smpi_masterworkers/INFO] after alltoall 1
> [Fafard:alltoall_mpi#3:(14) 10.046865] [smpi_masterworkers/INFO] after alltoall 3
-> [Jupiter:alltoall_mpi#2:(13) 10.046865] [smpi_masterworkers/INFO] after alltoall 2
\ No newline at end of file
+> [Jupiter:alltoall_mpi#2:(13) 10.046865] [smpi_masterworkers/INFO] after alltoall 2
+> [Ginette:launcher:(10) 10.046865] [smpi_masterworkers/INFO] This other alltoall_mpi instance terminated.
\ No newline at end of file
#include <vector>
-namespace simgrid::s4u {
+namespace simgrid {
+
+extern template class XBT_PUBLIC xbt::Extendable<s4u::ActivitySet>;
+
+namespace s4u {
/** @brief ActivitiesSet
*
* This class is a container of activities, allowing to wait for the completion of any or all activities in the set.
bool has_failed_activities() { return not failed_activities_.empty(); }
};
-}; // namespace simgrid::s4u
+} // namespace s4u
+} // namespace simgrid
#endif
*/
void add_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst, kernel::routing::NetPoint* gw_src,
kernel::routing::NetPoint* gw_dst, const std::vector<LinkInRoute>& link_list, bool symmetrical = true);
+ /**
+ * @brief Add a route between 2 netpoints, and same in other direction
+ *
+ * Create a route:
+ * - route between 2 hosts/routers in same netzone, no gateway is needed
+ * - route between 2 netzones, connecting 2 gateways.
+ *
+ * @param src Source netzone's netpoint
+ * @param dst Destination netzone' netpoint
+ * @param gw_src Netpoint of the gateway in the source netzone
+ * @param gw_dst Netpoint of the gateway in the destination netzone
+ * @param link_list List of links
+ */
+ void add_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst, kernel::routing::NetPoint* gw_src,
+ kernel::routing::NetPoint* gw_dst, const std::vector<const Link*>& links);
+
+ /**
+ * @brief Add a route between 2 hosts
+ *
+ * @param src Source host
+ * @param dst Destination host
+ * @param link_list List of links and their direction used in this communication
+ * @param symmetrical Bi-directional communication
+ */
+ void add_route(const Host* src, const Host* dst, const std::vector<LinkInRoute>& link_list, bool symmetrical = true);
+ /**
+ * @brief Add a route between 2 hosts
+ *
+ * @param src Source host
+ * @param dst Destination host
+ * @param link_list List of links. The UP direction will be used on src->dst and DOWN direction on dst->src
+ */
+ void add_route(const Host* src, const Host* dst, const std::vector<const Link*>& links);
void add_bypass_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst,
kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst,
#ifdef __cplusplus
XBT_PUBLIC void SMPI_app_instance_start(const char* name, std::function<void()> const& code,
std::vector<simgrid::s4u::Host*> const& hosts);
+XBT_PUBLIC void SMPI_app_instance_join(const std::string& instance_id);
/* This version without parameter is nice to use with SMPI_app_instance_start() */
XBT_PUBLIC void MPI_Init();
simgrid::kernel::routing::NetPoint*, simgrid::kernel::routing::NetPoint*,
const std::vector<simgrid::s4u::LinkInRoute>&, bool>(&simgrid::s4u::NetZone::add_route),
"Add a route between 2 netpoints")
+ .def("add_route",
+ py::overload_cast<const simgrid::s4u::Host*, const simgrid::s4u::Host*,
+ const std::vector<simgrid::s4u::LinkInRoute>&, bool>(&simgrid::s4u::NetZone::add_route),
+ "Add a route between 2 netpoints")
+ .def("add_route",
+ py::overload_cast<const simgrid::s4u::Host*, const simgrid::s4u::Host*,
+ const std::vector<const simgrid::s4u::Link*>&>(&simgrid::s4u::NetZone::add_route),
+ "Add a route between 2 netpoints")
.def("create_host", py::overload_cast<const std::string&, double>(&simgrid::s4u::NetZone::create_host),
"Creates a host")
.def("create_host",
const std::function<void(void*)>& clean_fun, // used to free the synchro in case of problem after a detached send
const std::function<void(activity::CommImpl*, void*, size_t)>&
copy_data_fun, // used to copy data if not default one
- void* payload, bool detached, std::string fun_call)
+ void* payload, bool detached, std::string_view fun_call)
: SimcallObserver(actor)
, mbox_(mbox)
, payload_size_(payload_size)
CommIrecvSimcall(ActorImpl* actor, activity::MailboxImpl* mbox, unsigned char* dst_buff, size_t* dst_buff_size,
const std::function<bool(void*, void*, activity::CommImpl*)>& match_fun,
const std::function<void(activity::CommImpl*, void*, size_t)>& copy_data_fun, void* payload,
- double rate, std::string fun_call)
+ double rate, std::string_view fun_call)
: SimcallObserver(actor)
, mbox_(mbox)
, dst_buff_(dst_buff)
if (cluster->router_id.empty())
cluster->router_id = cluster->prefix + cluster->id + "_router" + cluster->suffix;
auto* router = zone->create_router(cluster->router_id);
- zone->add_route(router, nullptr, nullptr, nullptr, {});
+ std::vector<simgrid::s4u::LinkInRoute> links;
+ zone->add_route(router, nullptr, nullptr, nullptr, links);
simgrid::kernel::routing::on_cluster_creation(*cluster);
}
chosen = xbt::random::uniform_int(0, possibilities-1);
for (auto const& [aid, actor] : actors_to_run_) {
- if (((not actor.is_todo()) && must_be_todo) || actor.is_done() || (not actor.is_enabled()))
+ if (((not actor.is_todo()) && must_be_todo) || actor.is_done() || (not actor.is_enabled()))
continue;
if (chosen == 0) {
return std::make_pair(aid, valuation.at(aid));
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(s4u_activityset, s4u_activity, "S4U set of activities");
-namespace simgrid::s4u {
+namespace simgrid {
+
+template class xbt::Extendable<s4u::ActivitySet>;
+
+namespace s4u {
void ActivitySet::erase(ActivityPtr a)
{
return ret;
}
-}; // namespace simgrid::s4u
\ No newline at end of file
+} // namespace s4u
+} // namespace simgrid
xbt_assert(src_buff_ == nullptr && dst_buff_ == nullptr,
"Direct host-to-host communications cannot carry any data.");
XBT_DEBUG("host-to-host Comm. Pimpl already created and set, just start it.");
- fire_on_start();
- fire_on_this_start();
kernel::actor::simcall_answered([this] {
pimpl_->set_state(kernel::activity::State::READY);
boost::static_pointer_cast<kernel::activity::CommImpl>(pimpl_)->start();
});
+ fire_on_start();
+ fire_on_this_start();
} else if (src_buff_ != nullptr) { // Sender side
on_send(*this);
on_this_send(*this);
{
pimpl_->add_route(src, dst, gw_src, gw_dst, link_list, symmetrical);
}
+void NetZone::add_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst,
+ kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst,
+ const std::vector<const Link*>& links)
+{
+ std::vector<LinkInRoute> links_direct;
+ std::vector<LinkInRoute> links_reverse;
+ for (auto* l : links) {
+ links_direct.emplace_back(LinkInRoute(l, LinkInRoute::Direction::UP));
+ links_reverse.emplace_back(LinkInRoute(l, LinkInRoute::Direction::DOWN));
+ }
+ pimpl_->add_route(src, dst, gw_src, gw_dst, links_direct, false);
+ pimpl_->add_route(dst, src, gw_dst, gw_src, links_reverse, false);
+}
+
+void NetZone::add_route(const Host* src, const Host* dst, const std::vector<LinkInRoute>& link_list, bool symmetrical)
+{
+ pimpl_->add_route(src->get_netpoint(), dst->get_netpoint(), nullptr, nullptr, link_list, symmetrical);
+}
+void NetZone::add_route(const Host* src, const Host* dst, const std::vector<const Link*>& links)
+{
+ std::vector<LinkInRoute> links_direct;
+ std::vector<LinkInRoute> links_reverse;
+ for (auto* l : links) {
+ links_direct.emplace_back(LinkInRoute(l, LinkInRoute::Direction::UP));
+ links_reverse.emplace_back(LinkInRoute(l, LinkInRoute::Direction::DOWN));
+ }
+ pimpl_->add_route(src->get_netpoint(), dst->get_netpoint(), nullptr, nullptr, links_direct, false);
+ pimpl_->add_route(dst->get_netpoint(), src->get_netpoint(), nullptr, nullptr, links_reverse, false);
+}
void NetZone::add_bypass_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst,
kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst,
#include <climits>
#include "private.hpp"
+#include "simgrid/s4u/Engine.hpp"
#include "smpi_comm.hpp"
-#include "smpi_info.hpp"
#include "smpi_errhandler.hpp"
+#include "smpi_info.hpp"
#include "src/smpi/include/smpi_actor.hpp"
XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(smpi_pmpi);
return MPI_SUCCESS;
case MPI_UNIVERSE_SIZE:
*flag = 1;
- universe_size = smpi_get_universe_size();
+ universe_size = simgrid::s4u::Engine::get_instance()->get_host_count();
*static_cast<int**>(attr_value) = &universe_size;
return MPI_SUCCESS;
case MPI_LASTUSEDCODE:
XBT_PRIVATE simgrid::smpi::ActorExt* smpi_process();
XBT_PRIVATE simgrid::smpi::ActorExt* smpi_process_remote(simgrid::s4u::ActorPtr actor);
-XBT_PRIVATE int smpi_get_universe_size();
XBT_PRIVATE void smpi_deployment_register_process(const std::string& instance_id, int rank,
const simgrid::s4u::Actor* actor);
void ActorExt::init()
{
- xbt_assert(smpi_get_universe_size() != 0, "SimGrid was not initialized properly before entering MPI_Init. "
- "Aborting, please check compilation process and use smpirun.");
-
ActorExt* ext = smpi_process();
// if we are in MPI_Init and argc handling has already been done.
if (ext->initialized())
namespace simgrid::smpi::app {
-static int universe_size = 0;
-
class Instance {
public:
explicit Instance(int max_no_processes) : size_(max_no_processes)
{
auto* group = new simgrid::smpi::Group(size_);
comm_world_ = new simgrid::smpi::Comm(group, nullptr, false, -1);
- universe_size += max_no_processes;
bar_ = s4u::Barrier::create(size_);
}
s4u::BarrierPtr bar_;
rank++;
}
}
+void SMPI_app_instance_join(const std::string& instance_id)
+{
+ std::vector<simgrid::s4u::ActorPtr> actors =
+ simgrid::s4u::Engine::get_instance()->get_filtered_actors([instance_id](simgrid::s4u::ActorPtr act) {
+ auto* actor_instance = act->get_property("instance_id");
+ return actor_instance != nullptr && strcmp(actor_instance, instance_id.c_str()) == 0;
+ });
+
+ for (auto& act : actors)
+ act->join();
+}
void smpi_deployment_register_process(const std::string& instance_id, int rank, const simgrid::s4u::Actor* actor)
{
smpi_instances.clear();
}
-int smpi_get_universe_size()
-{
- return simgrid::smpi::app::universe_size;
-}
-
/** @brief Auxiliary method to get list of hosts to deploy app */
static std::vector<simgrid::s4u::Host*> smpi_get_hosts(const simgrid::s4u::Engine* e, const std::string& hostfile)
{
links[name] = zone->create_link(name, 1e9)->set_latency(1e-9)->seal();
}
links["L0"] = zone->create_link("L0", 1e3)->seal();
- zone->add_route(hosts["S1"]->get_netpoint(), hosts["C1"]->get_netpoint(), nullptr, nullptr,
- {sg4::LinkInRoute(links["L1"]), sg4::LinkInRoute(links["L0"]), sg4::LinkInRoute(links["L2"])});
- zone->add_route(hosts["S2"]->get_netpoint(), hosts["C2"]->get_netpoint(), nullptr, nullptr,
- {sg4::LinkInRoute(links["L3"]), sg4::LinkInRoute(links["L0"]), sg4::LinkInRoute(links["L4"])});
-
+ zone->add_route(hosts["S1"], hosts["C1"], {links["L1"], links["L0"], links["L2"]});
+ zone->add_route(hosts["S2"], hosts["C2"], {links["L3"], links["L0"], links["L4"]});
zone->seal();
sg4::Actor::create("", hosts["S1"], sender, "C1", nullptr);
auto const* host1 = zone->create_host("host1", 1e6)->seal();
auto const* host2 = zone->create_host("host2", 1e6)->seal();
auto* testlink = zone->create_link("L1", 1e10)->seal();
- zone->add_route(host1->get_netpoint(), host2->get_netpoint(), nullptr, nullptr, {sg4::LinkInRoute(testlink)});
+ zone->add_route(host1, host2, {testlink});
simgrid::s4u::Actor::create("dispatcher", engine.host_by_name("host1"), main_dispatcher, testlink);
engine.run();
->set_bandwidth_profile(linkSaBandwidthProfile)
->seal();
- world->add_route(hostGl01->get_netpoint(), hostSa01->get_netpoint(), nullptr, nullptr,
- {{linkSa, sg4::LinkInRoute::Direction::NONE}}, true);
+ world->add_route(hostGl01, hostSa01, {{linkSa, sg4::LinkInRoute::Direction::NONE}}, true);
world->seal();
sg4::Mailbox* mb1 = e.mailbox_by_name_or_create("Mailbox 1");
auto* rootzone = sg4::create_full_zone("root");
auto* hostA = rootzone->create_host("hostA", 1e9);
auto* hostB = rootzone->create_host("hostB", 1e9);
- sg4::LinkInRoute link(rootzone->create_link("backbone", "1")->set_latency("1s")->seal());
- rootzone->add_route(hostA->get_netpoint(), hostB->get_netpoint(), nullptr, nullptr, {link}, true);
+ auto* backb = rootzone->create_link("backbone", "1")->set_latency("1s")->seal();
+ rootzone->add_route(hostA, hostB, {backb});
rootzone->seal();
sg4::Actor::create("ptask", hostA, ptask, hostA, hostB);
hosts.append(host2)
link1 = dijkstra.create_link("link1_up", [1e9]).set_latency(1e-3).set_concurrency_limit(10).seal()
link2 = dijkstra.create_link("link1_down", ["1GBps"]).set_latency("1ms").seal()
- dijkstra.add_route(host1.netpoint, host2.netpoint, None, None, [LinkInRoute(link1)], False)
- dijkstra.add_route(host2.netpoint, host1.netpoint, None, None, [LinkInRoute(link2)], False)
+ dijkstra.add_route(host1, host2, [LinkInRoute(link1)], False)
+ dijkstra.add_route(host2, host1, [LinkInRoute(link2)], False)
dijkstra.seal()
# vivaldi
pr::Profile* profile_link = pr::ProfileBuilder::from_string("link_profile", ctx.link_profile.str(), 0);
sg4::Link const* link =
zone->create_link("link", LinkBandwidth)->set_latency(LinkLatency)->set_state_profile(profile_link)->seal();
- zone->add_route(sender_host->get_netpoint(), receiver_host->get_netpoint(), nullptr, nullptr,
- {sg4::LinkInRoute{link}}, false);
+ zone->add_route(sender_host, receiver_host, {link});
zone->seal();
sg4::Host::on_onoff_cb([mbox](sg4::Host const& host) {
for (int i = 1; i < cfg_host_count; i++) {
auto hostname = "lilibeth " + std::to_string(i);
auto* host = rootzone->create_host(hostname, 1e9);
- sg4::LinkInRoute link(rootzone->create_link(hostname, "1MBps")->set_latency("24us")->seal());
- rootzone->add_route(master_host->get_netpoint(), host->get_netpoint(), nullptr, nullptr, {link}, true);
+ auto* link = rootzone->create_link(hostname, "1MBps")->set_latency("24us")->seal();
+ rootzone->add_route(master_host, host, {link});
worker_hosts.push_back(host);
}
rootzone->seal();
for i in range(1, host_count):
link = rootzone.create_split_duplex_link(f"link {i}", "1MBps").set_latency("24us")
host = rootzone.create_host(f"lilibeth {i}", 1e9)
- rootzone.add_route(main.netpoint, host.netpoint, None, None, [LinkInRoute(link, LinkInRoute.Direction.UP)], True)
+ rootzone.add_route(main, host, [link])
Actor.create("worker", host, worker, i).set_auto_restart(True)
e.netzone_root.seal()
auto* rootzone = sg4::create_full_zone("root");
auto* paul = rootzone->create_host("Paul", 1e9);
auto* carol = rootzone->create_host("Carol", 1e9);
- sg4::LinkInRoute link(rootzone->create_link("link", "1MBps")->set_latency("24us")->seal());
- rootzone->add_route(paul->get_netpoint(), carol->get_netpoint(), nullptr, nullptr, {link}, true);
+ auto* link = rootzone->create_link("link", "1MBps")->set_latency("24us")->seal();
+ rootzone->add_route(paul, carol, {link});
SharedBuffer buffer;
sg4::Actor::create("producer", paul, producer, std::ref(buffer))->set_auto_restart();
auto* host = zone->create_host(hostname, 1e9);
host->create_disk("disk-" + hostname, 1e9, 1e6);
const auto* link = zone->create_link("link-" + hostname, 1e9);
- zone->add_route(host->get_netpoint(), router, nullptr, nullptr, {sg4::LinkInRoute(link)});
+ zone->add_route(host->get_netpoint(), router, nullptr, nullptr, {link});
}
return zone;
}
# This script is used by various build projects on Jenkins
+case "$JENKINS_HOME" in
+*-qualif)
+ echo "Build skipped on $JENKINS_HOME."
+ exit 0
+ ;;
+esac
+
# See https://ci.inria.fr/simgrid/job/SimGrid/configure
# See https://ci.inria.fr/simgrid/job/Simgrid-Windows/configure