From c35095c612c457532413b5ee35f0c716ed358d12 Mon Sep 17 00:00:00 2001 From: Bruno Donassolo Date: Fri, 13 Aug 2021 19:05:21 +0200 Subject: [PATCH] Potpourri of python bindings (disk, host, netzone) Add several methods to python bindings. Add a test mixing them. --- MANIFEST.in | 2 + src/bindings/python/simgrid_python.cpp | 44 ++++++- teshsuite/python/CMakeLists.txt | 10 +- teshsuite/python/platform-mix/platform-mix.py | 124 ++++++++++++++++++ .../python/platform-mix/platform-mix.tesh | 26 ++++ 5 files changed, 202 insertions(+), 4 deletions(-) create mode 100644 teshsuite/python/platform-mix/platform-mix.py create mode 100644 teshsuite/python/platform-mix/platform-mix.tesh diff --git a/MANIFEST.in b/MANIFEST.in index 8b4bf08a5f..f392e2705b 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -707,6 +707,8 @@ include teshsuite/python/borken-context/borken-context_d.xml include teshsuite/python/corrupt-stack/corrupt-stack.py include teshsuite/python/corrupt-stack/corrupt-stack.tesh include teshsuite/python/corrupt-stack/corrupt-stack_d.xml +include teshsuite/python/platform-mix/platform-mix.py +include teshsuite/python/platform-mix/platform-mix.tesh include teshsuite/s4u/activity-lifecycle/activity-lifecycle.cpp include teshsuite/s4u/activity-lifecycle/activity-lifecycle.hpp include teshsuite/s4u/activity-lifecycle/activity-lifecycle.tesh diff --git a/src/bindings/python/simgrid_python.cpp b/src/bindings/python/simgrid_python.cpp index 09c0e4ef58..6d4d372974 100644 --- a/src/bindings/python/simgrid_python.cpp +++ b/src/bindings/python/simgrid_python.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -229,6 +230,11 @@ PYBIND11_MODULE(simgrid, m) .def_static("create_fatTree_zone", &simgrid::s4u::create_fatTree_zone, "Creates a cluster of type Fat-Tree") .def_static("create_dragonfly_zone", &simgrid::s4u::create_dragonfly_zone, "Creates a cluster of type Dragonfly") .def_static("create_star_zone", &simgrid::s4u::create_star_zone, "Creates a zone of type Star") + .def_static("create_floyd_zone", &simgrid::s4u::create_floyd_zone, "Creates a zone of type Floyd") + .def_static("create_dijkstra_zone", &simgrid::s4u::create_floyd_zone, "Creates a zone of type Dijkstra") + .def_static("create_vivaldi_zone", &simgrid::s4u::create_vivaldi_zone, "Creates a zone of type Vivaldi") + .def_static("create_empty_zone", &simgrid::s4u::create_empty_zone, "Creates a zone of type Empty") + .def_static("create_wifi_zone", &simgrid::s4u::create_wifi_zone, "Creates a zone of type Wi-Fi") .def("add_route", py::overload_cast(&simgrid::s4u::NetZone::create_host), "Creates a host") + .def("create_host", + py::overload_cast&>(&simgrid::s4u::NetZone::create_host), + "Creates a host") + .def("create_host", + py::overload_cast&>(&simgrid::s4u::NetZone::create_host), + "Creates a host") + .def("create_link", py::overload_cast(&simgrid::s4u::NetZone::create_link), + "Creates a network link") + .def("create_link", + py::overload_cast(&simgrid::s4u::NetZone::create_link), + "Creates a network link") .def("create_link", py::overload_cast&>(&simgrid::s4u::NetZone::create_link), "Creates a network link") + .def("create_link", + py::overload_cast&>(&simgrid::s4u::NetZone::create_link), + "Creates a network link") .def("create_split_duplex_link", py::overload_cast(&simgrid::s4u::NetZone::create_split_duplex_link), "Creates a split-duplex link") .def("create_split_duplex_link", py::overload_cast(&simgrid::s4u::NetZone::create_split_duplex_link), "Creates a split-duplex link") + .def("create_router", &simgrid::s4u::NetZone::create_router, "Create a router") .def("set_parent", &simgrid::s4u::NetZone::set_parent, "Set the parent of this zone") + .def("set_property", &simgrid::s4u::NetZone::set_property, "Add a property to this zone") .def("get_netpoint", &simgrid::s4u::NetZone::get_netpoint, "Retrieve the netpoint associated to this zone") - .def("seal", &simgrid::s4u::NetZone::seal, "Seal this NetZone"); + .def("seal", &simgrid::s4u::NetZone::seal, "Seal this NetZone") + .def_property_readonly( + "name", [](const simgrid::s4u::NetZone* self) { return self->get_name(); }, "The name of this network zone"); /* Class ClusterCallbacks */ py::class_(m, "ClusterCallbacks", "Callbacks used to create cluster zones") @@ -274,6 +298,13 @@ PYBIND11_MODULE(simgrid, m) .def("get_pstate_count", &Host::get_pstate_count, "Retrieve the count of defined pstate levels") .def("get_pstate_speed", &Host::get_pstate_speed, "Retrieve the maximal speed at the given pstate") .def("get_netpoint", &Host::get_netpoint, "Retrieve the netpoint associated to this host") + .def("get_disks", &Host::get_disks, "Retrieve the list of disks in this host") + .def("set_core_count", &Host::set_core_count, "Set the number of cores in the CPU") + .def("set_coordinates", &Host::set_coordinates, "Set the coordinates of this host") + .def("create_disk", py::overload_cast(&Host::create_disk), "Create a disk") + .def("create_disk", + py::overload_cast(&Host::create_disk), + "Create a disk") .def("seal", &Host::seal, "Seal this host") .def_property( "pstate", &Host::get_pstate, @@ -298,6 +329,14 @@ PYBIND11_MODULE(simgrid, m) "The peak computing speed in flops/s at the current pstate, taking the external load into account. " "This is the max potential speed."); + /* Class Disk */ + py::class_>(m, "Disk", "Simulated disk") + .def("read", &simgrid::s4u::Disk::read, py::call_guard(), "Read data from disk") + .def("write", &simgrid::s4u::Disk::write, py::call_guard(), "Write data in disk") + .def("seal", &simgrid::s4u::Disk::seal, "Seal this disk") + .def_property_readonly( + "name", [](const simgrid::s4u::Disk* self) { return self->get_name(); }, "The name of this disk"); + /* Class NetPoint */ py::class_>( m, "NetPoint", "NetPoint object"); @@ -307,6 +346,9 @@ PYBIND11_MODULE(simgrid, m) link.def("set_latency", py::overload_cast(&simgrid::s4u::Link::set_latency), "Set the latency"); link.def("set_latency", py::overload_cast(&simgrid::s4u::Link::set_latency), "Set the latency"); link.def("set_sharing_policy", &simgrid::s4u::Link::set_sharing_policy, "Set sharing policy for this link"); + link.def("set_concurrency_limit", &simgrid::s4u::Link::set_concurrency_limit, "Set concurrency limit for this link"); + link.def("set_host_wifi_rate", &simgrid::s4u::Link::set_host_wifi_rate, + "Set level of communication speed of given host on this Wi-Fi link"); link.def("seal", &simgrid::s4u::Link::seal, "Seal this link"); link.def_property_readonly( "name", diff --git a/teshsuite/python/CMakeLists.txt b/teshsuite/python/CMakeLists.txt index 8d5aeb0a85..314d09c86b 100644 --- a/teshsuite/python/CMakeLists.txt +++ b/teshsuite/python/CMakeLists.txt @@ -1,6 +1,5 @@ -foreach(example borken-context corrupt-stack) - set(tesh_files ${tesh_files} ${CMAKE_CURRENT_SOURCE_DIR}/${example}/${example}.tesh - ${CMAKE_CURRENT_SOURCE_DIR}/${example}/${example}_d.xml) +foreach(example borken-context corrupt-stack platform-mix) + set(tesh_files ${tesh_files} ${CMAKE_CURRENT_SOURCE_DIR}/${example}/${example}.tesh) set(examples_src ${examples_src} ${CMAKE_CURRENT_SOURCE_DIR}/${example}/${example}.py) if(enable_python) @@ -15,5 +14,10 @@ foreach(example borken-context corrupt-stack) endif() endforeach() +foreach(example borken-context corrupt-stack) + set(xml_files ${xml_files} ${CMAKE_CURRENT_SOURCE_DIR}/${example}/${example}_d.xml) +endforeach() + set(tesh_files ${tesh_files} PARENT_SCOPE) +set(xml_files ${xml_files} PARENT_SCOPE) set(examples_src ${examples_src} PARENT_SCOPE) diff --git a/teshsuite/python/platform-mix/platform-mix.py b/teshsuite/python/platform-mix/platform-mix.py new file mode 100644 index 0000000000..b138dfb955 --- /dev/null +++ b/teshsuite/python/platform-mix/platform-mix.py @@ -0,0 +1,124 @@ +# Copyright (c) 2006-2021. 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. + +from simgrid import Actor, Engine, Comm, Host, Mailbox, NetZone, Link, LinkInRoute, this_actor +import sys +import functools + +class Sender: + """ + Send 1 message for each host + """ + def __init__(self, hosts): + self.hosts = hosts + + # Actors that are created as object will execute their __call__ method. + # So, the following constitutes the main function of the Sender actor. + def __call__(self): + + for host in self.hosts: + mbox = Mailbox.by_name(host.name) + msg = "Hello. I'm " + str(this_actor.get_host().name) + size = int(1e6) + this_actor.info("Sending msg to " + host.name) + mbox.put(msg, size) + + this_actor.info("Done dispatching all messages. Goodbye!") + +class Receiver: + """ + Receiver actor: wait for 1 messages and do operations + """ + + def __call__(self): + this_actor.execute(1e9) + for disk in Host.current().get_disks(): + this_actor.info("Using disk " + disk.name) + disk.read(10000) + disk.write(10000) + mbox = Mailbox.by_name(this_actor.get_host().name) + msg = mbox.get() + this_actor.info("I got '%s'." % msg) + this_actor.info("Finished executing. Goodbye!") + +def load_platform(): + """ Creates a mixed platform, using many methods available in the API + """ + + root = NetZone.create_floyd_zone("root") + hosts = [] + # dijkstra + dijkstra = NetZone.create_dijkstra_zone("dijkstra") + this_actor.info("Creating zone: " + dijkstra.name) + dijkstra.set_parent(root) + host1 = dijkstra.create_host("host1", [1e9, 1e8]).set_core_count(2) + hosts.append(host1) + host1.create_disk("disk1", 1e5, 1e4).seal() + host1.create_disk("disk2", "1MBps", "1Mbps").seal() + host1.seal() + host2 = dijkstra.create_host("host2", ["1Gf", "1Mf"]).seal() + 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.get_netpoint(), host2.get_netpoint(), None, None, [LinkInRoute(link1)], False) + dijkstra.add_route(host2.get_netpoint(), host1.get_netpoint(), None, None, [LinkInRoute(link2)], False) + dijkstra.seal() + + # vivaldi + vivaldi = NetZone.create_vivaldi_zone("vivaldi") + this_actor.info("Creating zone: " + vivaldi.name) + vivaldi.set_parent(root) + host3 = vivaldi.create_host("host3", 1e9).set_coordinates("1 1 1").seal() + host4 = vivaldi.create_host("host4", "1Gf").set_coordinates("2 2 2").seal() + hosts.append(host3) + hosts.append(host4) + + # empty + empty = NetZone.create_empty_zone("empty") + this_actor.info("Creating zone: " + empty.name) + empty.set_parent(root) + host5 = empty.create_host("host5", 1e9) + hosts.append(host5) + empty.seal() + + # wifi + wifi = NetZone.create_wifi_zone("wifi") + this_actor.info("Creating zone: " + wifi.name) + wifi.set_parent(root) + router = wifi.create_router("wifi_router") + wifi.set_property("access_point", "wifi_router") + host6 = wifi.create_host( + "host6", ["100.0Mf", "50.0Mf", "20.0Mf"]).seal() + hosts.append(host6) + wifi_link = wifi.create_link("AP1", ["54Mbps", "36Mbps", "24Mbps"]).seal() + wifi_link.set_host_wifi_rate(host6, 1) + wifi.seal() + + # create routes between netzones + linkA = vivaldi.create_link("linkA", 1e9).seal() + linkB = vivaldi.create_link("linkB", "1GBps").seal() + linkC = vivaldi.create_link("linkC", "1GBps").seal() + root.add_route(dijkstra.get_netpoint(), vivaldi.get_netpoint( + ), host1.get_netpoint(), host3.get_netpoint(), [LinkInRoute(linkA)], True) + root.add_route(vivaldi.get_netpoint(), empty.get_netpoint( + ), host3.get_netpoint(), host5.get_netpoint(), [LinkInRoute(linkB)], True) + root.add_route(empty.get_netpoint(), wifi.get_netpoint( + ), host5.get_netpoint(), router, [LinkInRoute(linkC)], True) + + # create actors Sender/Receiver + Actor.create("sender", hosts[0], Sender(hosts)) + for host in hosts: + Actor.create("receiver", host, Receiver()) + +################################################################################################### + +if __name__ == '__main__': + e = Engine(sys.argv) + + # create platform + load_platform() + + # runs the simulation + e.run() diff --git a/teshsuite/python/platform-mix/platform-mix.tesh b/teshsuite/python/platform-mix/platform-mix.tesh new file mode 100644 index 0000000000..64297cd43e --- /dev/null +++ b/teshsuite/python/platform-mix/platform-mix.tesh @@ -0,0 +1,26 @@ +$ ${pythoncmd:=python3} ${PYTHON_TOOL_OPTIONS:=} ${srcdir:=.}/platform-mix.py "--log=root.fmt:[%10.6r]%e(%i:%a@%h)%e%m%n" +> [ 0.000000] (0:maestro@) Creating zone: dijkstra +> [ 0.000000] (0:maestro@) Creating zone: vivaldi +> [ 0.000000] (0:maestro@) Creating zone: empty +> [ 0.000000] (0:maestro@) Creating zone: wifi +> [ 0.000000] (1:sender@host1) Sending msg to host1 +> [ 1.000000] (2:receiver@host1) Using disk disk1 +> [ 2.100000] (2:receiver@host1) Using disk disk2 +> [ 2.190103] (2:receiver@host1) I got 'Hello. I'm host1'. +> [ 2.190103] (2:receiver@host1) Finished executing. Goodbye! +> [ 2.190103] (1:sender@host1) Sending msg to host2 +> [ 2.204144] (3:receiver@host2) I got 'Hello. I'm host1'. +> [ 2.204144] (3:receiver@host2) Finished executing. Goodbye! +> [ 2.204144] (1:sender@host1) Sending msg to host3 +> [ 2.205226] (4:receiver@host3) I got 'Hello. I'm host1'. +> [ 2.205226] (4:receiver@host3) Finished executing. Goodbye! +> [ 2.205226] (1:sender@host1) Sending msg to host4 +> [ 2.264825] (5:receiver@host4) I got 'Hello. I'm host1'. +> [ 2.264825] (5:receiver@host4) Finished executing. Goodbye! +> [ 2.264825] (1:sender@host1) Sending msg to host5 +> [ 2.265908] (6:receiver@host5) I got 'Hello. I'm host1'. +> [ 2.265908] (6:receiver@host5) Finished executing. Goodbye! +> [ 2.265908] (1:sender@host1) Sending msg to host6 +> [ 10.240550] (1:sender@host1) Done dispatching all messages. Goodbye! +> [ 10.240550] (7:receiver@host6) I got 'Hello. I'm host1'. +> [ 10.240550] (7:receiver@host6) Finished executing. Goodbye! -- 2.20.1