/home/runner/work/HiCR/HiCR/include/hicr/backends/hwloc/topologyManager.hpp Source File

HiCR: /home/runner/work/HiCR/HiCR/include/hicr/backends/hwloc/topologyManager.hpp Source File
HiCR
topologyManager.hpp
Go to the documentation of this file.
1/*
2 * Copyright 2025 Huawei Technologies Co., Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
24#pragma once
25
26#include "hwloc.h"
30#include <hicr/core/topology.hpp>
32
33namespace HiCR::backend::hwloc
34{
35
39constexpr size_t _HWLOC_MAX_MEMSPACE_SIZE = 1024;
40
45{
46 public:
47
53 TopologyManager(hwloc_topology_t *topology)
54 : HiCR::TopologyManager(),
55 _topology(topology)
56 {}
57
61 ~TopologyManager() override = default;
62
63 __INLINE__ HiCR::Topology queryTopology() override
64 {
65 // Disable filters in order to detect instr. caches
66 hwloc_topology_set_icache_types_filter(*_topology, HWLOC_TYPE_FILTER_KEEP_ALL);
67
68 // Loading HWLoc topology object
69 hwloc_topology_load(*_topology);
70
71 // Storage for the new HICR topology
73
74 // Ask hwloc about number of NUMA nodes and add as many devices as NUMA domains
75 auto n = hwloc_get_nbobjs_by_type(*_topology, HWLOC_OBJ_NUMANODE);
76 for (int i = 0; i < n; i++)
77 {
78 // Creating new device for the current NUMA domain
79 auto d = std::make_shared<hwloc::Device>(i, queryComputeResources(i), queryMemorySpaces(i));
80
81 // Inserting new device into the list
82 t.addDevice(d);
83 }
84
85 // Returning the created topology
86 return t;
87 }
88
94 __INLINE__ static HiCR::Topology deserializeTopology(const nlohmann::json &topology)
95 {
96 // Verifying input's syntax
97 HiCR::Topology::verify(topology);
98
99 // New topology to create
101
102 // Iterating over the device list entries in the serialized input
103 for (const auto &device : topology["Devices"])
104 {
105 // Getting device type
106 const auto type = device["Type"].get<std::string>();
107
108 // If the device type is recognized, add it to the new topology
109 if (type == "NUMA Domain") t.addDevice(std::make_shared<hwloc::Device>(device));
110 }
111
112 // Returning new topology
113 return t;
114 }
115
116 [[nodiscard]] __INLINE__ HiCR::Topology _deserializeTopology(const nlohmann::json &topology) const override { return deserializeTopology(topology); }
117
123 __INLINE__ static std::unique_ptr<HiCR::TopologyManager> createDefault()
124 {
125 // Creating HWloc topology object
126 auto topology = new hwloc_topology_t;
127
128 // Reserving memory for hwloc
129 hwloc_topology_init(topology);
130
131 // Initializing HWLoc-based topology manager
132 return std::make_unique<HiCR::backend::hwloc::TopologyManager>(topology);
133 }
134
135 private:
136
140 __INLINE__ HiCR::Device::computeResourceList_t queryComputeResources(const hwloc::Device::NUMADomainID_t numaDomainId)
141 {
142 // New compute resource list to return
143 HiCR::Device::computeResourceList_t computeResourceList;
144
145 // Creating compute resource list, based on the processing units (hyperthreads) observed by HWLoc
146 std::vector<HiCR::backend::hwloc::ComputeResource::logicalProcessorId_t> logicalProcessorIds;
147 HiCR::backend::hwloc::ComputeResource::detectThreadPUs(*_topology, hwloc_get_root_obj(*_topology), 0, logicalProcessorIds);
148
149 // Adding detected PUs as long they belong to this numa domain
150 for (const auto id : logicalProcessorIds)
151 if (ComputeResource::getCpuNumaAffinity(*_topology, id) == numaDomainId)
152 {
153 // Creating new compute resource class (of CPU core/processor type)
154 auto processor = std::make_shared<HiCR::backend::hwloc::ComputeResource>(*_topology, id);
155
156 // Adding new resource to the list
157 computeResourceList.push_back(processor);
158 }
159
160 // Returning new compute resource list
161 return computeResourceList;
162 }
163
167 __INLINE__ HiCR::Device::memorySpaceList_t queryMemorySpaces(const hwloc::Device::NUMADomainID_t numaDomainId)
168 {
169 // New memory space list to return
170 HiCR::Device::memorySpaceList_t memorySpaceList;
171
172 // Getting HWLoc object related to this NUMA domain
173 auto hwlocObj = hwloc_get_obj_by_type(*_topology, HWLOC_OBJ_NUMANODE, numaDomainId);
174
175 // Checking whther bound memory allocation and freeing is supported
177 size_t size = _HWLOC_MAX_MEMSPACE_SIZE;
178 auto ptr = hwloc_alloc_membind(*_topology, size, hwlocObj->nodeset, HWLOC_MEMBIND_DEFAULT, HWLOC_MEMBIND_BYNODESET | HWLOC_MEMBIND_STRICT);
179 if (ptr != nullptr)
180 {
181 // Attempting to free with hwloc
182 auto status = hwloc_free(*_topology, ptr, size);
183
184 // Freeing was successful, then strict binding is supported
185 if (status == 0) bindingSupport = LocalMemorySlot::binding_type::strict_binding;
186 }
187
188 // Getting memory space size
189 auto memSpaceSize = hwlocObj->attr->cache.size;
190
191 // Creating new memory space object
192 auto memorySpace = std::make_shared<hwloc::MemorySpace>(memSpaceSize, hwlocObj, bindingSupport);
193
194 // Storing new memory space
195 memorySpaceList.push_back(memorySpace);
196
197 // Returning new memory space list
198 return memorySpaceList;
199 }
200
204 hwloc_topology_t *const _topology;
205};
206
207} // namespace HiCR::backend::hwloc
This file implements the compute resource class for the HWLoc-based backend.
This file implements the Device class for the hwloc backend.
This file implements the memory space class for the HWLoc-based backend.
constexpr size_t _HWLOC_MAX_MEMSPACE_SIZE
Definition topologyManager.hpp:39
std::vector< std::shared_ptr< ComputeResource > > computeResourceList_t
Definition device.hpp:59
std::vector< std::shared_ptr< MemorySpace > > memorySpaceList_t
Definition device.hpp:64
Definition topologyManager.hpp:50
Definition topology.hpp:40
__INLINE__ void addDevice(const std::shared_ptr< HiCR::Device > &device)
Definition topology.hpp:62
static __INLINE__ void verify(const nlohmann::json &input)
Definition topology.hpp:102
Definition computeResource.hpp:41
static __INLINE__ void detectThreadPUs(hwloc_topology_t topology, hwloc_obj_t obj, int depth, std::vector< logicalProcessorId_t > &threadPUs)
Definition computeResource.hpp:129
unsigned int NUMADomainID_t
Definition device.hpp:44
@ strict_binding
Definition localMemorySlot.hpp:48
@ strict_non_binding
Definition localMemorySlot.hpp:53
Definition topologyManager.hpp:45
static __INLINE__ std::unique_ptr< HiCR::TopologyManager > createDefault()
Definition topologyManager.hpp:123
static __INLINE__ HiCR::Topology deserializeTopology(const nlohmann::json &topology)
Definition topologyManager.hpp:94
TopologyManager(hwloc_topology_t *topology)
Definition topologyManager.hpp:53
__INLINE__ HiCR::Topology _deserializeTopology(const nlohmann::json &topology) const override
Definition topologyManager.hpp:116
__INLINE__ HiCR::Topology queryTopology() override
Definition topologyManager.hpp:63
Provides a definition for the abstract device manager class.