From: Bruno Donassolo Date: Mon, 26 Apr 2021 15:12:13 +0000 (+0200) Subject: New: s4u::create_fatTree_zone X-Git-Tag: v3.28~404 X-Git-Url: http://bilbo.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/6e835f0ea3cd49e0c025a416ab3af54375f91401 New: s4u::create_fatTree_zone Implements the builder method for Fat Tree zones. Similar signature and behavior of create_torus_zone. --- diff --git a/MANIFEST.in b/MANIFEST.in index bee77ffeeb..ecad1680e8 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2203,6 +2203,7 @@ include src/kernel/routing/DijkstraZone.cpp include src/kernel/routing/DragonflyZone.cpp include src/kernel/routing/EmptyZone.cpp include src/kernel/routing/FatTreeZone.cpp +include src/kernel/routing/FatTreeZone_test.cpp include src/kernel/routing/FloydZone.cpp include src/kernel/routing/FullZone.cpp include src/kernel/routing/NetPoint.cpp diff --git a/include/simgrid/kernel/routing/ClusterZone.hpp b/include/simgrid/kernel/routing/ClusterZone.hpp index 87d5d8c034..3ead7da3d3 100644 --- a/include/simgrid/kernel/routing/ClusterZone.hpp +++ b/include/simgrid/kernel/routing/ClusterZone.hpp @@ -117,6 +117,12 @@ public: { return node_pos_with_loopback(id) + (has_limiter_ ? 1 : 0); } + /** Fill the leaf retriving netpoint from a user's callback */ + void fill_leaf_from_cb(unsigned int position, const std::vector& dimensions, + const std::function& set_netpoint_cb, + const std::function& set_loopback_cb, + const std::function& set_limiter_cb, NetPoint** node_netpoint, + s4u::Link** lb_link, s4u::Link** limiter_link); }; } // namespace routing } // namespace kernel diff --git a/include/simgrid/kernel/routing/FatTreeZone.hpp b/include/simgrid/kernel/routing/FatTreeZone.hpp index 8853322f02..71e2de72a8 100644 --- a/include/simgrid/kernel/routing/FatTreeZone.hpp +++ b/include/simgrid/kernel/routing/FatTreeZone.hpp @@ -120,7 +120,9 @@ class XBT_PRIVATE FatTreeZone : public ClusterZone { std::vector links_; std::vector nodes_by_level_; - ClusterCreationArgs* cluster_ = nullptr; + s4u::Link::SharingPolicy link_sharing_policy_; //!< fat tree links: sharing policy + double link_bw_; //!< fat tree links: bandwidth + double link_lat_; //!< fat tree links: latency void add_link(FatTreeNode* parent, unsigned int parent_port, FatTreeNode* child, unsigned int child_port); int get_level_position(const unsigned int level); @@ -139,11 +141,16 @@ public: ~FatTreeZone() override; void get_local_route(NetPoint* src, NetPoint* dst, RouteCreationArgs* into, double* latency) override; - /** @brief Read the parameters in topo_parameters field. - * - * It will also store the cluster for future use. - */ + /** @brief Read the parameters in topo_parameters field. */ void parse_specific_arguments(ClusterCreationArgs* cluster) override; + /** @brief Checks topology parameters */ + static void check_topology(unsigned int n_levels, const std::vector& down_links, + const std::vector& up_links, const std::vector& link_count); + /** @brief Set FatTree topology */ + void set_topology(unsigned int n_levels, const std::vector& down_links, + const std::vector& up_links, const std::vector& link_count); + /** @brief Set the characteristics of links inside the Fat Tree zone */ + void set_link_characteristics(double bw, double lat, s4u::Link::SharingPolicy sharing_policy); void add_processing_node(int id, resource::LinkImpl* limiter, resource::LinkImpl* loopback); void generate_dot_file(const std::string& filename = "fat_tree.dot") const; }; diff --git a/include/simgrid/s4u/NetZone.hpp b/include/simgrid/s4u/NetZone.hpp index 0ed4bfcf26..179b087c5a 100644 --- a/include/simgrid/s4u/NetZone.hpp +++ b/include/simgrid/s4u/NetZone.hpp @@ -149,32 +149,32 @@ XBT_PUBLIC NetZone* create_full_zone(const std::string& name); XBT_PUBLIC NetZone* create_cluster_zone(const std::string& name); XBT_PUBLIC NetZone* create_star_zone(const std::string& name); XBT_PUBLIC NetZone* create_dijkstra_zone(const std::string& name, bool cache); -XBT_PUBLIC NetZone* create_dragonfly_zone(const std::string& name); XBT_PUBLIC NetZone* create_empty_zone(const std::string& name); -XBT_PUBLIC NetZone* create_fatTree_zone(const std::string& name); XBT_PUBLIC NetZone* create_floyd_zone(const std::string& name); +XBT_PUBLIC NetZone* create_vivaldi_zone(const std::string& name); +XBT_PUBLIC NetZone* create_wifi_zone(const std::string& name); /** - * @brief Callback used to set the netpoint and gateway located at some leaf of the torus + * @brief Callback used to set the netpoint and gateway located at some leaf of clusters (Torus, FatTree, etc) * * The netpoint can be either a host, router or another netzone. * Gateway must be non-null if netpoint is a netzone * - * @param zone: The newly create Torus zone, needed for creating new resources (hosts, links) - * @param coord: the coordinates of the element in the torus, eg. 0,1,1 + * @param zone: The newly create zone, needed for creating new resources (hosts, links) + * @param coord: the coordinates of the element * @param id: Internal identifier of the element * @return pair: returns a pair of netpoint and gateway. */ -using TorusNetPointCb = std::pair( +using ClusterNetPointCb = std::pair( NetZone* zone, const std::vector& coord, int id); /** - * @brief Callback used to set the links for some leaf of the torus + * @brief Callback used to set the links for some leaf of the cluster (Torus, FatTree, etc) * - * @param zone: The newly create Torus zone, needed for creating new resources (hosts, links) - * @param coord: the coordinates of the element in the torus, eg. 0,1,1 + * @param zone: The newly create zone, needed for creating new resources (hosts, links) + * @param coord: the coordinates of the element * @param id: Internal identifier of the element * @return Pointer to the Link */ -using TorusLinkCb = Link*(NetZone* zone, const std::vector& coord, int id); +using ClusterLinkCb = Link*(NetZone* zone, const std::vector& coord, int id); /** * @brief Create a torus zone * @@ -200,13 +200,31 @@ using TorusLinkCb = Link*(NetZone* zone, const std::vector& coord, * @param set_limiter Callback to set the limiter * @return Pointer to new netzone */ -NetZone* create_torus_zone(const std::string& name, const NetZone* parent, const std::vector& dimensions, - double bandwidth, double latency, Link::SharingPolicy sharing_policy, - const std::function& set_netpoint, - const std::function& set_loopback = {}, - const std::function& set_limiter = {}); -XBT_PUBLIC NetZone* create_vivaldi_zone(const std::string& name); -XBT_PUBLIC NetZone* create_wifi_zone(const std::string& name); +XBT_PUBLIC NetZone* create_torus_zone(const std::string& name, const NetZone* parent, + const std::vector& dimensions, double bandwidth, double latency, + Link::SharingPolicy sharing_policy, + const std::function& set_netpoint, + const std::function& set_loopback = {}, + const std::function& set_limiter = {}); +struct FatTreeParams { + unsigned int levels; + std::vector down; + std::vector up; + std::vector number; + FatTreeParams(unsigned int n_levels, const std::vector& down_links, + const std::vector& up_links, const std::vector& links_number) + : levels(n_levels), down(down_links), up(up_links), number(links_number) + { /* nothing to do */ + } +}; + +XBT_PUBLIC NetZone* create_fatTree_zone(const std::string& name, const NetZone* parent, const FatTreeParams& parameters, + double bandwidth, double latency, Link::SharingPolicy sharing_policy, + const std::function& set_netpoint, + const std::function& set_loopback = {}, + const std::function& set_limiter = {}); + +XBT_PUBLIC NetZone* create_dragonfly_zone(const std::string& name); } // namespace s4u } // namespace simgrid diff --git a/src/kernel/routing/ClusterZone.cpp b/src/kernel/routing/ClusterZone.cpp index d7e42550a2..cb0f886e8b 100644 --- a/src/kernel/routing/ClusterZone.cpp +++ b/src/kernel/routing/ClusterZone.cpp @@ -174,6 +174,65 @@ NetPoint* ClusterZone::get_gateway(unsigned int position) return res; } +void ClusterZone::fill_leaf_from_cb(unsigned int position, const std::vector& dimensions, + const std::function& set_netpoint_cb, + const std::function& set_loopback_cb, + const std::function& set_limiter_cb, NetPoint** node_netpoint, + s4u::Link** lb_link, s4u::Link** limiter_link) +{ + xbt_assert(node_netpoint, "Invalid node_netpoint parameter"); + xbt_assert(lb_link, "Invalid lb_link parameter"); + xbt_assert(limiter_link, "Invalid limiter_link paramater"); + *lb_link = nullptr; + *limiter_link = nullptr; + + // auxiliary function to get dims from index + auto index_to_dims = [&dimensions](int index) { + std::vector dims_array(dimensions.size()); + for (unsigned long i = dimensions.size() - 1; i != 0; --i) { + if (index <= 0) { + break; + } + unsigned int value = index % dimensions[i]; + dims_array[i] = value; + index = (index / dimensions[i]); + } + return dims_array; + }; + + kernel::routing::NetPoint* netpoint = nullptr; + kernel::routing::NetPoint* gw = nullptr; + auto dims = index_to_dims(position); + std::tie(netpoint, gw) = set_netpoint_cb(get_iface(), dims, position); + xbt_assert(netpoint, "set_netpoint(elem=%u): Invalid netpoint (nullptr)", position); + if (netpoint->is_netzone()) { + xbt_assert(gw && not gw->is_netzone(), + "set_netpoint(elem=%u): Netpoint (%s) is a netzone, but gateway (%s) is invalid", position, + netpoint->get_cname(), gw ? gw->get_cname() : "nullptr"); + } else { + xbt_assert(not gw, "set_netpoint: Netpoint (%s) isn't netzone, gateway must be nullptr", netpoint->get_cname()); + } + // setting gateway + set_gateway(position, gw); + + if (set_loopback_cb) { + s4u::Link* loopback = set_loopback_cb(get_iface(), dims, position); + xbt_assert(loopback, "set_loopback: Invalid loopback link (nullptr) for element %u", position); + set_loopback(); + add_private_link_at(node_pos(netpoint->id()), {loopback->get_impl(), loopback->get_impl()}); + *lb_link = loopback; + } + + if (set_limiter_cb) { + s4u::Link* limiter = set_limiter_cb(get_iface(), dims, position); + xbt_assert(limiter, "set_limiter: Invalid limiter link (nullptr) for element %u", position); + set_limiter(); + add_private_link_at(node_pos_with_loopback(netpoint->id()), {limiter->get_impl(), limiter->get_impl()}); + *limiter_link = limiter; + } + *node_netpoint = netpoint; +} + } // namespace routing } // namespace kernel diff --git a/src/kernel/routing/FatTreeZone.cpp b/src/kernel/routing/FatTreeZone.cpp index e68caae8b5..faa06f6fcc 100644 --- a/src/kernel/routing/FatTreeZone.cpp +++ b/src/kernel/routing/FatTreeZone.cpp @@ -4,6 +4,7 @@ * under the terms of the license (GNU LGPL) which comes with this package. */ #include +#include #include #include @@ -116,6 +117,9 @@ void FatTreeZone::get_local_route(NetPoint* src, NetPoint* dst, RouteCreationArg } } } + // set gateways (if any) + into->gw_src = get_gateway(src->id()); + into->gw_dst = get_gateway(dst->id()); } /* This function makes the assumption that parse_specific_arguments() and @@ -342,11 +346,11 @@ void FatTreeZone::add_link(FatTreeNode* parent, unsigned int parentPort, FatTree std::string id = "link_from_" + std::to_string(child->id) + "_" + std::to_string(parent->id) + "_" + std::to_string(uniqueId); - if (cluster_->sharing_policy == s4u::Link::SharingPolicy::SPLITDUPLEX) { - linkup = create_link(id + "_UP", std::vector{cluster_->bw})->set_latency(cluster_->lat)->seal(); - linkdown = create_link(id + "_DOWN", std::vector{cluster_->bw})->set_latency(cluster_->lat)->seal(); + if (link_sharing_policy_ == s4u::Link::SharingPolicy::SPLITDUPLEX) { + linkup = create_link(id + "_UP", std::vector{link_bw_})->set_latency(link_lat_)->seal(); + linkdown = create_link(id + "_DOWN", std::vector{link_bw_})->set_latency(link_lat_)->seal(); } else { - linkup = create_link(id, std::vector{cluster_->bw})->set_latency(cluster_->lat)->seal(); + linkup = create_link(id, std::vector{link_bw_})->set_latency(link_lat_)->seal(); linkdown = linkup; } uniqueId++; @@ -360,33 +364,76 @@ void FatTreeZone::add_link(FatTreeNode* parent, unsigned int parentPort, FatTree this->links_.push_back(newLink); } +void FatTreeZone::check_topology(unsigned int n_levels, const std::vector& down_links, + const std::vector& up_links, const std::vector& link_count) + +{ + /* check number of levels */ + if (n_levels <= 0) + throw std::invalid_argument("FatTreeZone: invalid number of levels, must be > 0"); + + auto check_vector = [&n_levels](const std::vector& vector, const std::string& var_name) { + if (vector.size() != n_levels) + throw std::invalid_argument("FatTreeZone: invalid " + var_name + " parameter, vector has " + + std::to_string(vector.size()) + " elements, must have " + std::to_string(n_levels)); + + auto check_zero = [](unsigned int i) { return i == 0; }; + if (std::any_of(vector.begin(), vector.end(), check_zero)) + throw std::invalid_argument("FatTreeZone: invalid " + var_name + " parameter, all values must be greater than 0"); + }; + + /* check remaining vectors */ + check_vector(down_links, "down links"); + check_vector(up_links, "up links"); + check_vector(link_count, "link count"); +} + +void FatTreeZone::set_link_characteristics(double bw, double lat, s4u::Link::SharingPolicy sharing_policy) +{ + link_sharing_policy_ = sharing_policy; + link_bw_ = bw; + link_lat_ = lat; +} + +void FatTreeZone::set_topology(unsigned int n_levels, const std::vector& down_links, + const std::vector& up_links, const std::vector& link_count) +{ + levels_ = n_levels; + num_children_per_node_ = down_links; + num_parents_per_node_ = up_links; + num_port_lower_level_ = link_count; +} + void FatTreeZone::parse_specific_arguments(ClusterCreationArgs* cluster) { std::vector parameters; std::vector tmp; + unsigned int n_lev = 0; + std::vector down; + std::vector up; + std::vector count; boost::split(parameters, cluster->topo_parameters, boost::is_any_of(";")); - // TODO : we have to check for zeros and negative numbers, or it might crash surf_parse_assert( parameters.size() == 4, "Fat trees are defined by the levels number and 3 vectors, see the documentation for more information."); // The first parts of topo_parameters should be the levels number try { - this->levels_ = std::stoi(parameters[0]); + n_lev = std::stoi(parameters[0]); } catch (const std::invalid_argument&) { surf_parse_error(std::string("First parameter is not the amount of levels: ") + parameters[0]); } // Then, a l-sized vector standing for the children number by level boost::split(tmp, parameters[1], boost::is_any_of(",")); - surf_parse_assert(tmp.size() == this->levels_, std::string("You specified ") + std::to_string(this->levels_) + - " levels but the child count vector (the first one) contains " + - std::to_string(tmp.size()) + " levels."); + surf_parse_assert(tmp.size() == n_lev, std::string("You specified ") + std::to_string(n_lev) + + " levels but the child count vector (the first one) contains " + + std::to_string(tmp.size()) + " levels."); for (std::string const& level : tmp) { try { - this->num_children_per_node_.push_back(std::stoi(level)); + down.push_back(std::stoi(level)); } catch (const std::invalid_argument&) { surf_parse_error(std::string("Invalid child count: ") + level); } @@ -394,12 +441,12 @@ void FatTreeZone::parse_specific_arguments(ClusterCreationArgs* cluster) // Then, a l-sized vector standing for the parents number by level boost::split(tmp, parameters[2], boost::is_any_of(",")); - surf_parse_assert(tmp.size() == this->levels_, std::string("You specified ") + std::to_string(this->levels_) + - " levels but the parent count vector (the second one) contains " + - std::to_string(tmp.size()) + " levels."); + surf_parse_assert(tmp.size() == n_lev, std::string("You specified ") + std::to_string(n_lev) + + " levels but the parent count vector (the second one) contains " + + std::to_string(tmp.size()) + " levels."); for (std::string const& parent : tmp) { try { - this->num_parents_per_node_.push_back(std::stoi(parent)); + up.push_back(std::stoi(parent)); } catch (const std::invalid_argument&) { surf_parse_error(std::string("Invalid parent count: ") + parent); } @@ -407,17 +454,22 @@ void FatTreeZone::parse_specific_arguments(ClusterCreationArgs* cluster) // Finally, a l-sized vector standing for the ports number with the lower level boost::split(tmp, parameters[3], boost::is_any_of(",")); - surf_parse_assert(tmp.size() == this->levels_, std::string("You specified ") + std::to_string(this->levels_) + - " levels but the port count vector (the third one) contains " + - std::to_string(tmp.size()) + " levels."); + surf_parse_assert(tmp.size() == n_lev, std::string("You specified ") + std::to_string(n_lev) + + " levels but the port count vector (the third one) contains " + + std::to_string(tmp.size()) + " levels."); for (std::string const& port : tmp) { try { - this->num_port_lower_level_.push_back(std::stoi(port)); + count.push_back(std::stoi(port)); } catch (const std::invalid_argument&) { throw std::invalid_argument(std::string("Invalid lower level port number:") + port); } } - this->cluster_ = cluster; + + /* set topology */ + FatTreeZone::check_topology(n_lev, down, up, count); + set_topology(n_lev, down, up, count); + /* saving internal links properties */ + set_link_characteristics(cluster->bw, cluster->lat, cluster->sharing_policy); } void FatTreeZone::generate_dot_file(const std::string& filename) const @@ -445,9 +497,39 @@ void FatTreeZone::generate_dot_file(const std::string& filename) const } // namespace kernel namespace s4u { -NetZone* create_fatTree_zone(const std::string& name) +NetZone* create_fatTree_zone(const std::string& name, const NetZone* parent, const FatTreeParams& params, + double bandwidth, double latency, Link::SharingPolicy sharing_policy, + const std::function& set_netpoint, + const std::function& set_loopback, + const std::function& set_limiter) { - return (new kernel::routing::FatTreeZone(name))->get_iface(); + /* initial checks */ + if (bandwidth <= 0) + throw std::invalid_argument("FatTreeZone: incorrect bandwidth for internode communication, bw=" + + std::to_string(bandwidth)); + if (latency < 0) + throw std::invalid_argument("FatTreeZone: incorrect latency for internode communication, lat=" + + std::to_string(latency)); + kernel::routing::FatTreeZone::check_topology(params.levels, params.down, params.up, params.number); + + /* creating zone */ + auto* zone = new kernel::routing::FatTreeZone(name); + zone->set_topology(params.levels, params.down, params.up, params.number); + if (parent) + zone->set_parent(parent->get_impl()); + zone->set_link_characteristics(bandwidth, latency, sharing_policy); + + /* populating it */ + int tot_elements = std::accumulate(params.down.begin(), params.down.end(), 1, std::multiplies<>()); + for (int i = 0; i < tot_elements; i++) { + kernel::routing::NetPoint* netpoint; + Link* limiter; + Link* loopback; + zone->fill_leaf_from_cb(i, params.down, set_netpoint, set_loopback, set_limiter, &netpoint, &loopback, &limiter); + zone->add_processing_node(i, limiter ? limiter->get_impl() : nullptr, loopback ? loopback->get_impl() : nullptr); + } + + return zone->get_iface(); } } // namespace s4u diff --git a/src/kernel/routing/FatTreeZone_test.cpp b/src/kernel/routing/FatTreeZone_test.cpp new file mode 100644 index 0000000000..bd6eafce2f --- /dev/null +++ b/src/kernel/routing/FatTreeZone_test.cpp @@ -0,0 +1,106 @@ +/* Copyright (c) 2017-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. */ + +#include "catch.hpp" + +#include "simgrid/kernel/routing/FatTreeZone.hpp" +#include "simgrid/kernel/routing/NetPoint.hpp" +#include "simgrid/s4u/Engine.hpp" +#include "simgrid/s4u/Host.hpp" +#include "simgrid/s4u/NetZone.hpp" + +namespace { +class EngineWrapper { +public: + explicit EngineWrapper(std::string name) : argv(&name[0]), e(&argc, &argv) {} + int argc = 1; + char* argv; + simgrid::s4u::Engine e; +}; + +std::pair +create_host(simgrid::s4u::NetZone* zone, const std::vector& coord, int id) +{ + const simgrid::s4u::Host* host = zone->create_host(std::to_string(id), 1e9)->seal(); + return std::make_pair(host->get_netpoint(), nullptr); +} +} // namespace + +TEST_CASE("kernel::routing::FatTreeZone: Creating Zone", "") +{ + using namespace simgrid::s4u; + EngineWrapper e("test"); + REQUIRE(create_fatTree_zone("test", e.e.get_netzone_root(), {2, {4, 4}, {1, 2}, {1, 2}}, 1e9, 10, + simgrid::s4u::Link::SharingPolicy::SHARED, create_host)); +} + +TEST_CASE("kernel::routing::FatTreeZone: Invalid params", "") +{ + using namespace simgrid::s4u; + EngineWrapper e("test"); + + SECTION("0 levels") + { + REQUIRE_THROWS_AS(create_fatTree_zone("test", e.e.get_netzone_root(), {0, {4, 4}, {1, 2}, {1, 2}}, 1e9, 10, + simgrid::s4u::Link::SharingPolicy::SHARED, create_host), + std::invalid_argument); + } + + SECTION("Invalid down links") + { + REQUIRE_THROWS_AS(create_fatTree_zone("test", e.e.get_netzone_root(), {2, {4}, {1, 2}, {1, 2}}, 1e9, 10, + simgrid::s4u::Link::SharingPolicy::SHARED, create_host), + std::invalid_argument); + } + + SECTION("Invalid up links") + { + REQUIRE_THROWS_AS(create_fatTree_zone("test", e.e.get_netzone_root(), {2, {4, 4}, {1}, {1, 2}}, 1e9, 10, + simgrid::s4u::Link::SharingPolicy::SHARED, create_host), + std::invalid_argument); + } + + SECTION("Invalid link count") + { + REQUIRE_THROWS_AS(create_fatTree_zone("test", e.e.get_netzone_root(), {2, {4, 4}, {1, 2}, {1}}, 1e9, 10, + simgrid::s4u::Link::SharingPolicy::SHARED, create_host), + std::invalid_argument); + } + + SECTION("Down links with zeroes") + { + REQUIRE_THROWS_AS(create_fatTree_zone("test", e.e.get_netzone_root(), {2, {4, 0}, {1, 2}, {1, 2}}, 1e9, 10, + simgrid::s4u::Link::SharingPolicy::SHARED, create_host), + std::invalid_argument); + } + + SECTION("Up links with zeroes") + { + REQUIRE_THROWS_AS(create_fatTree_zone("test", e.e.get_netzone_root(), {2, {4, 4}, {0, 2}, {1, 2}}, 1e9, 10, + simgrid::s4u::Link::SharingPolicy::SHARED, create_host), + std::invalid_argument); + } + + SECTION("Link count with zeroes") + { + REQUIRE_THROWS_AS(create_fatTree_zone("test", e.e.get_netzone_root(), {2, {4, 4}, {1, 2}, {1, 0}}, 1e9, 10, + simgrid::s4u::Link::SharingPolicy::SHARED, create_host), + std::invalid_argument); + } + + SECTION("0 bandwidth") + { + REQUIRE_THROWS_AS(create_fatTree_zone("test", e.e.get_netzone_root(), {2, {4, 4}, {1, 2}, {1, 2}}, 0, 10, + simgrid::s4u::Link::SharingPolicy::SHARED, create_host), + std::invalid_argument); + } + + SECTION("Negative latency") + { + REQUIRE_THROWS_AS(create_fatTree_zone("test", e.e.get_netzone_root(), {2, {4, 4}, {1, 2}, {1, 2}}, 1e9, -10, + simgrid::s4u::Link::SharingPolicy::SHARED, create_host), + std::invalid_argument); + } +} \ No newline at end of file diff --git a/src/kernel/routing/TorusZone.cpp b/src/kernel/routing/TorusZone.cpp index f11a739dbe..a3f8c82cdb 100644 --- a/src/kernel/routing/TorusZone.cpp +++ b/src/kernel/routing/TorusZone.cpp @@ -234,8 +234,8 @@ s4u::NetZone* create_torus_zone_with_hosts(const kernel::routing::ClusterCreatio { using namespace std::placeholders; auto set_host = std::bind(create_torus_host, cluster, _1, _2, _3); - std::function set_loopback{}; - std::function set_limiter{}; + std::function set_loopback{}; + std::function set_limiter{}; if (cluster->loopback_bw > 0 || cluster->loopback_lat > 0) { set_loopback = std::bind(create_torus_loopback, cluster, _1, _2, _3); @@ -257,9 +257,9 @@ namespace s4u { NetZone* create_torus_zone(const std::string& name, const NetZone* parent, const std::vector& dimensions, double bandwidth, double latency, Link::SharingPolicy sharing_policy, - const std::function& set_netpoint, - const std::function& set_loopback, - const std::function& set_limiter) + const std::function& set_netpoint, + const std::function& set_loopback, + const std::function& set_limiter) { int tot_elements = std::accumulate(dimensions.begin(), dimensions.end(), 1, std::multiplies<>()); if (dimensions.empty() || tot_elements <= 0) @@ -271,55 +271,16 @@ NetZone* create_torus_zone(const std::string& name, const NetZone* parent, const throw std::invalid_argument("TorusZone: incorrect latency for internode communication, lat=" + std::to_string(latency)); - // auxiliary function to get dims from index - auto index_to_dims = [&dimensions](int index) { - std::vector dims_array(dimensions.size()); - for (unsigned long i = dimensions.size() - 1; i != 0; --i) { - if (index <= 0) { - break; - } - unsigned int value = index % dimensions[i]; - dims_array[i] = value; - index = (index / dimensions[i]); - } - return dims_array; - }; - auto* zone = new kernel::routing::TorusZone(name); zone->set_topology(dimensions); if (parent) zone->set_parent(parent->get_impl()); for (int i = 0; i < tot_elements; i++) { - kernel::routing::NetPoint* netpoint = nullptr; - kernel::routing::NetPoint* gw = nullptr; - auto dims = index_to_dims(i); - std::tie(netpoint, gw) = set_netpoint(zone->get_iface(), dims, i); - xbt_assert(netpoint, "TorusZone::set_netpoint(elem=%d): Invalid netpoint (nullptr)", i); - if (netpoint->is_netzone()) { - xbt_assert(gw && not gw->is_netzone(), - "TorusZone::set_netpoint(elem=%d): Netpoint (%s) is a netzone, but gateway (%s) is invalid", i, - netpoint->get_cname(), gw ? gw->get_cname() : "nullptr"); - } else { - xbt_assert(not gw, "TorusZone: Netpoint (%s) isn't netzone, gateway must be nullptr", netpoint->get_cname()); - } - // setting gateway - zone->set_gateway(i, gw); - - if (set_loopback) { - const Link* loopback = set_loopback(zone->get_iface(), dims, i); - xbt_assert(loopback, "TorusZone::set_loopback: Invalid loopback link (nullptr) for element %d", i); - zone->set_loopback(); - zone->add_private_link_at(zone->node_pos(netpoint->id()), {loopback->get_impl(), loopback->get_impl()}); - } - - if (set_limiter) { - const Link* limiter = set_limiter(zone->get_iface(), dims, i); - xbt_assert(limiter, "TorusZone::set_limiter: Invalid limiter link (nullptr) for element %d", i); - zone->set_limiter(); - zone->add_private_link_at(zone->node_pos_with_loopback(netpoint->id()), - {limiter->get_impl(), limiter->get_impl()}); - } + kernel::routing::NetPoint* netpoint; + Link* limiter; + Link* loopback; + zone->fill_leaf_from_cb(i, dimensions, set_netpoint, set_loopback, set_limiter, &netpoint, &loopback, &limiter); kernel::routing::ClusterCreationArgs params; params.id = name; diff --git a/tools/cmake/Tests.cmake b/tools/cmake/Tests.cmake index 7a9af11cfc..fca894cb26 100644 --- a/tools/cmake/Tests.cmake +++ b/tools/cmake/Tests.cmake @@ -124,6 +124,7 @@ ENDIF() # New tests should use the Catch Framework set(UNIT_TESTS src/xbt/unit-tests_main.cpp src/kernel/resource/profile/Profile_test.cpp + src/kernel/routing/FatTreeZone_test.cpp src/kernel/routing/StarZone_test.cpp src/kernel/routing/TorusZone_test.cpp src/xbt/config_test.cpp