From 28576ce34587a14772cd232febbc64902cf1ef19 Mon Sep 17 00:00:00 2001 From: Martin Quinson Date: Sun, 12 Feb 2023 00:11:57 +0100 Subject: [PATCH] move the flatifier functions to the s4u::Engine, for public consumption --- ChangeLog | 2 + docs/source/app_s4u.rst | 1 + include/simgrid/s4u/Engine.hpp | 23 +++++ src/s4u/s4u_Engine.cpp | 150 +++++++++++++++++++++++++++--- teshsuite/platforms/flatifier.cpp | 144 +--------------------------- 5 files changed, 165 insertions(+), 155 deletions(-) diff --git a/ChangeLog b/ChangeLog index d523cdec43..048fed7a0b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,8 @@ General: S4U: - Activity::set_remaining() is not public anymore. Use for example Comm::set_payload_size() to change the size of the simulated data. + - New function: Engine::flatify_platform(), to get a fully detailed vision of the + configured platform. Kernel: - optimize an internal datastructure, leading to a potentially big diff --git a/docs/source/app_s4u.rst b/docs/source/app_s4u.rst index 44f14272ba..7d3d6b0767 100644 --- a/docs/source/app_s4u.rst +++ b/docs/source/app_s4u.rst @@ -825,6 +825,7 @@ Simulation setup .. doxygenfunction:: simgrid::s4u::Engine::load_deployment .. doxygenfunction:: simgrid::s4u::Engine::load_platform + .. doxygenfunction:: simgrid::s4u::Engine::flatify_platform .. doxygenfunction:: simgrid::s4u::Engine::register_actor(const std::string &name) .. doxygenfunction:: simgrid::s4u::Engine::register_actor(const std::string &name, F code) .. doxygenfunction:: simgrid::s4u::Engine::register_default(const std::function< void(int, char **)> &code) diff --git a/include/simgrid/s4u/Engine.hpp b/include/simgrid/s4u/Engine.hpp index f2a3203660..94b0202dfc 100644 --- a/include/simgrid/s4u/Engine.hpp +++ b/include/simgrid/s4u/Engine.hpp @@ -57,8 +57,31 @@ public: static s4u::Engine* get_instance(int* argc, char** argv); static bool has_instance() { return instance_ != nullptr; } + /** + * Creates a new platform, including hosts, links, and the routing table. + * + * @beginrst + * See also: :ref:`platform`. + * @endrst + */ void load_platform(const std::string& platf) const; + /** + * @brief Seals the platform, finishing the creation of its resources. + * + * This method is optional. The seal() is done automatically when you call Engine::run. + */ void seal_platform() const; + /** @brief Get a debug output of the platform. + * + * It looks like a XML platform file, but it may be very different from the input platform file: All netzones are + * flatified into a unique zone. This representation is mostly useful to debug your platform configuration and ensure + * that your assumptions over your configuration hold. This enables you to verify the exact list of links traversed + * between any two hosts, and the characteristics of every host and link. But you should not use the resulting file as + * an input platform file: it is very verbose, and thus much less efficient (in parsing time and runtime performance) + * than a regular platform file with the sufficient amount of intermediary netzones. Even if you use one zone only, + * specialized zones (such as clusters) are more efficient than the one with fully explicit routing used here. + */ + std::string flatify_platform() const; /** @verbatim embed:rst:inline Bind an actor name that could be found in :ref:`pf_tag_actor` tag to a function taking classical argc/argv parameters. See the :ref:`example `. @endverbatim */ void register_function(const std::string& name, const std::function& code); diff --git a/src/s4u/s4u_Engine.cpp b/src/s4u/s4u_Engine.cpp index e808263551..d994ec074c 100644 --- a/src/s4u/s4u_Engine.cpp +++ b/src/s4u/s4u_Engine.cpp @@ -107,28 +107,154 @@ const std::vector& Engine::get_all_models() c return pimpl->get_all_models(); } -/** - * Creates a new platform, including hosts, links, and the routing table. - * - * @beginrst - * See also: :ref:`platform`. - * @endrst - */ void Engine::load_platform(const std::string& platf) const { pimpl->load_platform(platf); } -/** - * @brief Seals the platform, finishing the creation of its resources. - * - * This method is optional. The seal() is done automatically when you call Engine::run. - */ void Engine::seal_platform() const { pimpl->seal_platform(); } +static void flatify_hosts(Engine const& engine, std::stringstream& ss) +{ + // Regular hosts + std::vector hosts = engine.get_all_hosts(); + + for (auto const* h : hosts) { + ss << " get_name() << "\" speed=\"" << h->get_speed() << "\""; + const std::unordered_map* props = h->get_properties(); + if (h->get_core_count() > 1) + ss << " core=\"" << h->get_core_count() << "\""; + + // Sort the properties before displaying them, so that the tests are perfectly reproducible + std::vector keys; + for (auto const& [key, _] : *props) + keys.push_back(key); + if (not keys.empty()) { + ss << ">\n"; + std::sort(keys.begin(), keys.end()); + for (const std::string& key : keys) + ss << " at(key) << "\"/>\n"; + ss << " \n"; + } else { + ss << "/>\n"; + } + } + + // Routers + std::vector netpoints = engine.get_all_netpoints(); + std::sort(netpoints.begin(), netpoints.end(), + [](const simgrid::kernel::routing::NetPoint* a, const simgrid::kernel::routing::NetPoint* b) { + return a->get_name() < b->get_name(); + }); + + for (auto const& src : netpoints) + if (src->is_router()) + ss << " get_name() << "\"/>\n"; +} + +static void flatify_links(Engine const& engine, std::stringstream& ss) +{ + std::vector links = engine.get_all_links(); + + std::sort(links.begin(), links.end(), [](const Link* a, const Link* b) { return a->get_name() < b->get_name(); }); + + for (auto const* link : links) { + ss << " get_name() << "\""; + ss << " bandwidth=\"" << link->get_bandwidth() << "\""; + ss << " latency=\"" << link->get_latency() << "\""; + if (link->get_concurrency_limit() != -1) + ss << " concurrency=\"" << link->get_concurrency_limit() << "\""; + if (link->is_shared()) { + ss << "/>\n"; + } else { + ss << " sharing_policy=\"FATPIPE\"/>\n"; + } + } +} + +static void flatify_routes(Engine const& engine, std::stringstream& ss) +{ + auto hosts = engine.get_all_hosts(); + auto netpoints = engine.get_all_netpoints(); + std::sort(netpoints.begin(), netpoints.end(), + [](const simgrid::kernel::routing::NetPoint* a, const simgrid::kernel::routing::NetPoint* b) { + return a->get_name() < b->get_name(); + }); + + for (auto const* src_host : hosts) { // Routes from host + const simgrid::kernel::routing::NetPoint* src = src_host->get_netpoint(); + for (auto const* dst_host : hosts) { // Routes to host + std::vector route; + const simgrid::kernel::routing::NetPoint* dst = dst_host->get_netpoint(); + simgrid::kernel::routing::NetZoneImpl::get_global_route(src, dst, route, nullptr); + if (route.empty()) + continue; + ss << " get_name() << "\" dst=\"" << dst_host->get_name() << "\">\n "; + for (auto const& link : route) + ss << "get_name() << "\"/>"; + ss << "\n \n"; + } + + for (auto const& dst : netpoints) { // to router + if (not dst->is_router()) + continue; + ss << " get_name() << "\" dst=\"" << dst->get_name() << "\">\n "; + std::vector route; + simgrid::kernel::routing::NetZoneImpl::get_global_route(src, dst, route, nullptr); + for (auto const& link : route) + ss << "get_name() << "\"/>"; + ss << "\n \n"; + } + } + + for (auto const& value1 : netpoints) { // Routes from router + if (not value1->is_router()) + continue; + for (auto const& value2 : netpoints) { // to router + if (not value2->is_router()) + continue; + std::vector route; + simgrid::kernel::routing::NetZoneImpl::get_global_route(value1, value2, route, nullptr); + if (route.empty()) + continue; + ss << " get_name() << "\" dst=\"" << value2->get_name() << "\">\n "; + for (auto const& link : route) + ss << "get_name() << "\"/>"; + ss << "\n \n"; + } + for (auto const* dst_host : hosts) { // Routes to host + ss << " get_name() << "\" dst=\"" << dst_host->get_name() << "\">\n "; + std::vector route; + const simgrid::kernel::routing::NetPoint* netcardDst = dst_host->get_netpoint(); + simgrid::kernel::routing::NetZoneImpl::get_global_route(value1, netcardDst, route, nullptr); + for (auto const& link : route) + ss << "get_name() << "\"/>"; + ss << "\n \n"; + } + } +} +std::string Engine::flatify_platform() const +{ + std::string version = "4.1"; + std::stringstream ss; + + ss << "\n"; + ss << "\n"; + ss << "\n"; + ss << "get_name() << "\" routing=\"Full\">\n"; + + flatify_hosts(*this, ss); + flatify_links(*this, ss); + flatify_routes(*this, ss); + + ss << "\n"; + ss << "\n"; + return ss.str(); +} + /** Registers the main function of an actor that will be launched from the deployment file */ void Engine::register_function(const std::string& name, const std::function& code) { diff --git a/teshsuite/platforms/flatifier.cpp b/teshsuite/platforms/flatifier.cpp index 728ddfbdfe..bce6303dff 100644 --- a/teshsuite/platforms/flatifier.cpp +++ b/teshsuite/platforms/flatifier.cpp @@ -37,148 +37,6 @@ static bool parse_cmdline(bool* timings, char** platformFile, int argc, char** a return parse_ok && platformFile != nullptr; } -static void dump_hosts(sg4::Engine& engine, std::stringstream& ss) -{ - std::vector hosts = engine.get_all_hosts(); - - for (auto const* h : hosts) { - ss << " get_name() << "\" speed=\"" << h->get_speed() << "\""; - const std::unordered_map* props = h->get_properties(); - if (h->get_core_count() > 1) - ss << " core=\"" << h->get_core_count() << "\""; - - // Sort the properties before displaying them, so that the tests are perfectly reproducible - std::vector keys; - for (auto const& [key, _] : *props) - keys.push_back(key); - if (not keys.empty()) { - ss << ">\n"; - std::sort(keys.begin(), keys.end()); - for (const std::string& key : keys) - ss << " at(key) << "\"/>\n"; - ss << " \n"; - } else { - ss << "/>\n"; - } - } -} - -static void dump_links(sg4::Engine& engine, std::stringstream& ss) -{ - std::vector links = engine.get_all_links(); - - std::sort(links.begin(), links.end(), - [](const sg4::Link* a, const sg4::Link* b) { return a->get_name() < b->get_name(); }); - - for (auto const* link : links) { - ss << " get_name() << "\""; - ss << " bandwidth=\"" << link->get_bandwidth() << "\""; - ss << " latency=\"" << link->get_latency() << "\""; - if (link->get_concurrency_limit() != -1) - ss << " concurrency=\"" << link->get_concurrency_limit() << "\""; - if (link->is_shared()) { - ss << "/>\n"; - } else { - ss << " sharing_policy=\"FATPIPE\"/>\n"; - } - } -} - -static void dump_routers(sg4::Engine& engine, std::stringstream& ss) -{ - std::vector netpoints = engine.get_all_netpoints(); - std::sort(netpoints.begin(), netpoints.end(), - [](const simgrid::kernel::routing::NetPoint* a, const simgrid::kernel::routing::NetPoint* b) { - return a->get_name() < b->get_name(); - }); - - for (auto const& src : netpoints) - if (src->is_router()) - ss << " get_name() << "\"/>\n"; -} - -static void dump_routes(sg4::Engine& engine, std::stringstream& ss) -{ - auto hosts = engine.get_all_hosts(); - auto netpoints = engine.get_all_netpoints(); - std::sort(netpoints.begin(), netpoints.end(), - [](const simgrid::kernel::routing::NetPoint* a, const simgrid::kernel::routing::NetPoint* b) { - return a->get_name() < b->get_name(); - }); - - for (auto const* src_host : hosts) { // Routes from host - const simgrid::kernel::routing::NetPoint* src = src_host->get_netpoint(); - for (auto const* dst_host : hosts) { // Routes to host - std::vector route; - const simgrid::kernel::routing::NetPoint* dst = dst_host->get_netpoint(); - simgrid::kernel::routing::NetZoneImpl::get_global_route(src, dst, route, nullptr); - if (route.empty()) - continue; - ss << " get_name() << "\" dst=\"" << dst_host->get_name() << "\">\n "; - for (auto const& link : route) - ss << "get_name() << "\"/>"; - ss << "\n \n"; - } - - for (auto const& dst : netpoints) { // to router - if (not dst->is_router()) - continue; - ss << " get_name() << "\" dst=\"" << dst->get_name() << "\">\n "; - std::vector route; - simgrid::kernel::routing::NetZoneImpl::get_global_route(src, dst, route, nullptr); - for (auto const& link : route) - ss << "get_name() << "\"/>"; - ss << "\n \n"; - } - } - - for (auto const& value1 : netpoints) { // Routes from router - if (not value1->is_router()) - continue; - for (auto const& value2 : netpoints) { // to router - if (not value2->is_router()) - continue; - std::vector route; - simgrid::kernel::routing::NetZoneImpl::get_global_route(value1, value2, route, nullptr); - if (route.empty()) - continue; - ss << " get_name() << "\" dst=\"" << value2->get_name() << "\">\n "; - for (auto const& link : route) - ss << "get_name() << "\"/>"; - ss << "\n \n"; - } - for (auto const* dst_host : hosts) { // Routes to host - ss << " get_name() << "\" dst=\"" << dst_host->get_name() << "\">\n "; - std::vector route; - const simgrid::kernel::routing::NetPoint* netcardDst = dst_host->get_netpoint(); - simgrid::kernel::routing::NetZoneImpl::get_global_route(value1, netcardDst, route, nullptr); - for (auto const& link : route) - ss << "get_name() << "\"/>"; - ss << "\n \n"; - } - } -} - -static std::string dump_platform(sg4::Engine& engine) -{ - std::string version = "4.1"; - std::stringstream ss; - - ss << "\n"; - ss << "\n"; - ss << "\n"; - ss << "get_name() << "\" routing=\"Full\">\n"; - - dump_hosts(engine, ss); - dump_routers(engine, ss); - dump_links(engine, ss); - dump_routes(engine, ss); - - ss << "\n"; - ss << "\n"; - return ss.str(); -} - int main(int argc, char** argv) { char* platformFile = nullptr; @@ -200,7 +58,7 @@ int main(int argc, char** argv) XBT_INFO("Parsing time: %fs (%zu hosts, %zu links)", xbt_os_timer_elapsed(parse_time), e.get_host_count(), e.get_link_count()); } else { - std::printf("%s", dump_platform(e).c_str()); + std::printf("%s", e.flatify_platform().c_str()); } xbt_os_timer_free(parse_time); -- 2.20.1