From 9bccd25fab4a34c0dbb11c032ed7be082e705837 Mon Sep 17 00:00:00 2001 From: Ernst Bablick Date: Wed, 6 Nov 2024 11:41:53 +0100 Subject: [PATCH 1/2] added module test that allows to test possible enhancement for the core and memory binding --- source/libs/sgeobj/CMakeLists.txt | 1 + source/libs/sgeobj/ocs_HostTopology.cc | 135 +++++++++++++++++++ source/libs/sgeobj/ocs_HostTopology.h | 56 ++++++++ test/libs/sgeobj/CMakeLists.txt | 6 + test/libs/sgeobj/test_sgeobj_HostTopology.cc | 33 +++++ 5 files changed, 231 insertions(+) create mode 100644 source/libs/sgeobj/ocs_HostTopology.cc create mode 100644 source/libs/sgeobj/ocs_HostTopology.h create mode 100644 test/libs/sgeobj/test_sgeobj_HostTopology.cc diff --git a/source/libs/sgeobj/CMakeLists.txt b/source/libs/sgeobj/CMakeLists.txt index 183757de1..20540a606 100644 --- a/source/libs/sgeobj/CMakeLists.txt +++ b/source/libs/sgeobj/CMakeLists.txt @@ -25,6 +25,7 @@ set(LIBRARY_SOURCES cull_parse_util.cc ocs_binding_io.cc ocs_DataStore.cc + ocs_HostTopology.cc ocs_Session.cc parse.cc sge_ack.cc diff --git a/source/libs/sgeobj/ocs_HostTopology.cc b/source/libs/sgeobj/ocs_HostTopology.cc new file mode 100644 index 000000000..d1b919e91 --- /dev/null +++ b/source/libs/sgeobj/ocs_HostTopology.cc @@ -0,0 +1,135 @@ +/*___INFO__MARK_BEGIN_NEW__*/ +/*************************************************************************** + * + * Copyright 2024 HPC-Gridware GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************/ +/*___INFO__MARK_END_NEW__*/ + +#include +#include + +#include "ocs_HostTopology.h" + +ocs::HostTopology::HostTopology(std::string &topo_mask) : topo_mask(topo_mask) { + parseTopoMask(topo_mask); + numberTopoNodes(sockets); + sortNodes(sockets); +} + +/** @brief Parses the topology mask and builds the topology tree. + * + * EBNF format of a well-formed topology mask: + * topo_mask := socket_mask+ + * socket_mask := socket_char core_mask+ + * core_mask := core_char thread_mask+ + * thread_mask := thread_char + * socket_char := 'S' | 's' + * core_char := 'C' | 'c' | 'E' | 'e' + * thread_char := 'T' | 't' + * + * @param topo_mask + */ +void +ocs::HostTopology::parseTopoMask(std::string &topo_mask){ + std::vector cores; + std::vector threads; + + // We reverse the topo_mask to simplify the parsing! + for (char &it : std::ranges::reverse_view(topo_mask)) { + if (it == 'S' || it == 's') { + // put collected cores into a socket + std::reverse(cores.begin(), cores.end()); + Node socket(it, std::move(cores)); + cores = std::vector(); + + // collect all sockets + this->sockets.push_back(std::move(socket)); + } else if (it == 'C' || it == 'c' || it == 'E' || it == 'e') { + // put collected threads into a core + std::reverse(threads.begin(), threads.end()); + Node core(it, std::move(threads)); + threads = std::vector(); + + // collect all cores + cores.push_back(std::move(core)); + } else if (it == 'T' || it == 't') { + Node thread(it); + + // collect all threads + threads.push_back(std::move(thread)); + } + } + std::reverse(sockets.begin(), sockets.end()); + + // We did not strictly parse the EBNF syntax of the topology mask. But need to ensure that it is really well-formed. + // Therefor, we compare the parsed topology mask with the original one. + if (topo_mask != getTopoMask()) { + throw std::runtime_error("Invalid topology mask"); + } +} + +void +ocs::HostTopology::buildTopoMask(const Node& node, std::ostringstream& oss) const { + oss << node.c; + for (const auto& child : node.nodes) { + buildTopoMask(child, oss); + } +} + +void +ocs::HostTopology::buildFullTopoMask(const Node& node, std::ostringstream& oss) const { + oss << node.c << node.id; + for (const auto& child : node.nodes) { + buildFullTopoMask(child, oss); + } +} + +std::string +ocs::HostTopology::getTopoMask() const { + std::ostringstream oss; + for (const auto& socket : sockets) { + buildTopoMask(socket, oss); + } + return oss.str(); +} + +std::string +ocs::HostTopology::getFullTopoMask() const { + std::ostringstream oss; + for (const auto& socket : sockets) { + buildFullTopoMask(socket, oss); + } + return oss.str(); +} + +void +ocs::HostTopology::numberTopoNodes(std::vector &nodes) { + size_t id = 0; + for (auto &node : nodes) { + node.id = id++; + numberTopoNodes(node.nodes); + } +} + +void +ocs::HostTopology::sortNodes(std::vector& nodes) { + std::sort(nodes.begin(), nodes.end(), [](const Node& a, const Node& b) { + return a.c < b.c; + }); + for (auto& node : nodes) { + sortNodes(node.nodes); + } +} diff --git a/source/libs/sgeobj/ocs_HostTopology.h b/source/libs/sgeobj/ocs_HostTopology.h new file mode 100644 index 000000000..22223dff8 --- /dev/null +++ b/source/libs/sgeobj/ocs_HostTopology.h @@ -0,0 +1,56 @@ +#pragma once + +/*___INFO__MARK_BEGIN_NEW__*/ +/*************************************************************************** + * + * Copyright 2024 HPC-Gridware GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************/ +/*___INFO__MARK_END_NEW__*/ + +#include +#include +#include +#include + +namespace ocs { + class HostTopology { + class Node { + public: + char c; + size_t id; + std::vector nodes; + + explicit Node(char c, std::vector nodes) : c(c), id(0), nodes(std::move(nodes)) {} + explicit Node(char c) : c(c), id(0), nodes() {} + ~Node() = default; + }; + + std::string topo_mask; + std::vector sockets; + + void parseTopoMask(std::string &topo_mask); + void buildTopoMask(const Node& node, std::ostringstream& oss) const; + void buildFullTopoMask(const Node& node, std::ostringstream& oss) const; + void numberTopoNodes(std::vector &nodes); + void sortNodes(std::vector& nodes); + + public: + HostTopology(std::string &topo_mask); + + std::string getTopoMask() const; + std::string getFullTopoMask() const; + }; +}; \ No newline at end of file diff --git a/test/libs/sgeobj/CMakeLists.txt b/test/libs/sgeobj/CMakeLists.txt index ea1754261..c66cbc501 100644 --- a/test/libs/sgeobj/CMakeLists.txt +++ b/test/libs/sgeobj/CMakeLists.txt @@ -40,6 +40,11 @@ target_include_directories(test_sgeobj_fgl PRIVATE "./") target_link_libraries(test_sgeobj_fgl PRIVATE sgeobj cull commlists uti ${SGE_LIBS}) add_test(NAME test_sgeobj_fgl COMMAND test_sgeobj_fgl) +add_executable(test_sgeobj_HostTopology test_sgeobj_HostTopology.cc) +target_include_directories(test_sgeobj_HostTopology PRIVATE "./") +target_link_libraries(test_sgeobj_HostTopology PRIVATE sched gdi sgeobj gdi cull comm uti commlists ${SGE_LIBS}) +add_test(NAME test_sgeobj_HostTopology COMMAND test_sgeobj_HostTopology) + add_executable(test_sgeobj_object test_sgeobj_object.cc) target_include_directories(test_sgeobj_object PRIVATE "./") target_link_libraries(test_sgeobj_object PRIVATE sgeobj cull comm uti commlists ${SGE_LIBS}) @@ -75,6 +80,7 @@ if (INSTALL_SGE_TEST) install(TARGETS test_sgeobj_performance DESTINATION testbin/${SGE_ARCH}) install(TARGETS test_sgeobj_attr DESTINATION testbin/${SGE_ARCH}) install(TARGETS test_sgeobj_fgl DESTINATION testbin/${SGE_ARCH}) + install(TARGETS test_sgeobj_HostTopology DESTINATION testbin/${SGE_ARCH}) install(TARGETS test_sgeobj_object DESTINATION testbin/${SGE_ARCH}) install(TARGETS test_sgeobj_range DESTINATION testbin/${SGE_ARCH}) install(TARGETS test_sgeobj_resource_quota DESTINATION testbin/${SGE_ARCH}) diff --git a/test/libs/sgeobj/test_sgeobj_HostTopology.cc b/test/libs/sgeobj/test_sgeobj_HostTopology.cc new file mode 100644 index 000000000..4730d90e9 --- /dev/null +++ b/test/libs/sgeobj/test_sgeobj_HostTopology.cc @@ -0,0 +1,33 @@ +/*___INFO__MARK_BEGIN_NEW__*/ +/*************************************************************************** + * + * Copyright 2024 HPC-Gridware GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************/ +/*___INFO__MARK_END_NEW__*/ + +#include + +#include "sgeobj/ocs_HostTopology.h" + +int main (int argc, char *argv[]) { + std::string topo_mask = "ScTTCtTsctTtt"; + ocs::HostTopology ht = ocs::HostTopology(topo_mask); + + std::cout << topo_mask << std::endl; + std::cout << ht.getTopoMask() << std::endl; + std::cout << ht.getFullTopoMask() << std::endl; + return 0; +} \ No newline at end of file From cc6a13a1a023e93395ad3bfb0ccd0dca9554ca17 Mon Sep 17 00:00:00 2001 From: Ernst Bablick Date: Fri, 8 Nov 2024 18:25:42 +0000 Subject: [PATCH 2/2] BF: fixed broken build --- source/libs/sgeobj/ocs_HostTopology.cc | 14 ++++++++------ source/libs/sgeobj/ocs_HostTopology.h | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/source/libs/sgeobj/ocs_HostTopology.cc b/source/libs/sgeobj/ocs_HostTopology.cc index d1b919e91..373d997aa 100644 --- a/source/libs/sgeobj/ocs_HostTopology.cc +++ b/source/libs/sgeobj/ocs_HostTopology.cc @@ -51,7 +51,8 @@ ocs::HostTopology::parseTopoMask(std::string &topo_mask){ for (char &it : std::ranges::reverse_view(topo_mask)) { if (it == 'S' || it == 's') { // put collected cores into a socket - std::reverse(cores.begin(), cores.end()); +// std::reverse is not available at su0-0-lx-riscv64. Why? + //std::reverse(cores.begin(), cores.end()); Node socket(it, std::move(cores)); cores = std::vector(); @@ -59,7 +60,7 @@ ocs::HostTopology::parseTopoMask(std::string &topo_mask){ this->sockets.push_back(std::move(socket)); } else if (it == 'C' || it == 'c' || it == 'E' || it == 'e') { // put collected threads into a core - std::reverse(threads.begin(), threads.end()); + //std::reverse(threads.begin(), threads.end()); Node core(it, std::move(threads)); threads = std::vector(); @@ -72,7 +73,7 @@ ocs::HostTopology::parseTopoMask(std::string &topo_mask){ threads.push_back(std::move(thread)); } } - std::reverse(sockets.begin(), sockets.end()); + //std::reverse(sockets.begin(), sockets.end()); // We did not strictly parse the EBNF syntax of the topology mask. But need to ensure that it is really well-formed. // Therefor, we compare the parsed topology mask with the original one. @@ -126,9 +127,10 @@ ocs::HostTopology::numberTopoNodes(std::vector &nodes) { void ocs::HostTopology::sortNodes(std::vector& nodes) { - std::sort(nodes.begin(), nodes.end(), [](const Node& a, const Node& b) { - return a.c < b.c; - }); + // also not available on su0-0-lx-riscv64 ? + //std::sort(nodes.begin(), nodes.end(), [](const Node& a, const Node& b) { + // return a.c < b.c; + //}); for (auto& node : nodes) { sortNodes(node.nodes); } diff --git a/source/libs/sgeobj/ocs_HostTopology.h b/source/libs/sgeobj/ocs_HostTopology.h index 22223dff8..dbcdee8a1 100644 --- a/source/libs/sgeobj/ocs_HostTopology.h +++ b/source/libs/sgeobj/ocs_HostTopology.h @@ -53,4 +53,4 @@ namespace ocs { std::string getTopoMask() const; std::string getFullTopoMask() const; }; -}; \ No newline at end of file +}