/home/runner/work/HiCR/HiCR/include/hicr/core/topology.hpp Source File

HiCR: /home/runner/work/HiCR/HiCR/include/hicr/core/topology.hpp Source File
HiCR
topology.hpp
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
23#pragma once
24
25#include <memory>
26#include <unordered_set>
27#include <nlohmann_json/json.hpp>
28#include <nlohmann_json/parser.hpp>
29#include <hicr/core/device.hpp>
30
31namespace HiCR
32{
33
41{
42 public:
43
47 using deviceList_t = std::vector<std::shared_ptr<Device>>;
48
49 Topology() = default;
50 ~Topology() = default;
51
57 Topology(const nlohmann::json &input) { deserialize(input); }
58
63 [[nodiscard]] __INLINE__ const deviceList_t &getDevices() const { return _deviceList; }
64
70 __INLINE__ void addDevice(const std::shared_ptr<HiCR::Device> &device) { _deviceList.push_back(device); }
71
77 __INLINE__ void merge(const Topology &source)
78 {
79 // Adding each device separately
80 for (const auto &d : source.getDevices()) addDevice(d);
81 }
82
88 [[nodiscard]] __INLINE__ nlohmann::json serialize() const
89 {
90 // Storage for newly created serialized output
91 nlohmann::json output;
92
93 // Adding serialized devices information into the array
94 std::string devicesKey = "Devices";
95 output[devicesKey] = std::vector<nlohmann::json>();
96 for (const auto &device : _deviceList) output[devicesKey] += device->serialize();
97
98 // Adding metadata, if defined
99 output["Metadata"] = _metadata;
100
101 // Returning topology
102 return output;
103 }
104
113 __INLINE__ void deserialize(const nlohmann::json &input)
114 {
115 if (input.contains("Devices"))
116 {
117 const auto &devicesJs = hicr::json::getArray<nlohmann::json>(input, "Devices");
118 for (const auto &deviceJs : devicesJs) addDevice(std::make_shared<Device>(deviceJs));
119 }
120
121 if (input.contains("Metadata")) _metadata = hicr::json::getObject(input, "Metadata");
122 };
123
129 __INLINE__ static void verify(const nlohmann::json &input)
130 {
131 // Sanity checks
132 if (input.contains("Devices") == false) HICR_THROW_LOGIC("Serialized topology manager information is invalid, as it lacks the 'Devices' entry");
133 if (input["Devices"].is_array() == false) HICR_THROW_LOGIC("Serialized topology manager 'Devices' entry is not an array.");
134
135 for (auto device : input["Devices"])
136 {
137 if (device.contains("Type") == false) HICR_THROW_LOGIC("Serialized device information is invalid, as it lacks the 'Type' entry");
138 if (device["Type"].is_string() == false) HICR_THROW_LOGIC("Serialized device information is invalid, as the 'Type' entry is not a string");
139 }
140 };
141
153 [[nodiscard]] __INLINE__ bool isSubset(const HiCR::Topology givenTopology)
154 {
155 // Making a copy of the current topology.
156 // Devices will be removed as we match them with the given device
157 auto currentDevices = getDevices();
158
160 const auto givenDevices = givenTopology.getDevices();
161
162 for (const auto &givenDevice : givenDevices)
163 {
164 const auto givenDeviceType = givenDevice->getType();
165 const auto givenDeviceMemorySpaces = givenDevice->getMemorySpaceList();
166 const auto givenDeviceComputeResources = givenDevice->getComputeResourceList();
167
168 // Iterating over all the current devices to see if one of them satisfies this given device
169 bool foundCompatibleDevice = false;
170 for (auto currentDeviceItr = currentDevices.begin(); currentDeviceItr != currentDevices.end() && foundCompatibleDevice == false; currentDeviceItr++)
171 {
172 // Getting current device object
173 const auto &currentDevice = currentDeviceItr.operator*();
174
175 // Checking type
176 const auto &currentDeviceType = currentDevice->getType();
177
178 // If this device is the same type as given, proceed to check compute resources and memory spaces
179 if (currentDeviceType == givenDeviceType)
180 {
181 // Flag to indicate this device is compatible with the request
182 bool deviceIsCompatible = true;
183
185 auto currentComputeResources = currentDevice->getComputeResourceList();
186
187 // Getting compute resources in this current device
188 for (const auto &givenComputeResource : givenDeviceComputeResources)
189 {
190 bool foundComputeResource = false;
191 for (auto currentComputeResourceItr = currentComputeResources.begin(); currentComputeResourceItr != currentComputeResources.end() && foundComputeResource == false;
192 currentComputeResourceItr++)
193 {
194 // Getting current device object
195 const auto &currentComputeResource = currentComputeResourceItr.operator*();
196
197 // If it's the same type as given
198 if (currentComputeResource->getType() == givenComputeResource->getType())
199 {
200 // Set compute resource as found
201 foundComputeResource = true;
202
203 // Erase this element from the list to not re-use it
204 currentComputeResources.erase(currentComputeResourceItr);
205 }
206 }
207
208 // If no compute resource was found, abandon search in this device
209 if (foundComputeResource == false)
210 {
211 deviceIsCompatible = false;
212 break;
213 }
214 }
215
216 // If no suitable device was found, advance with the next one
217 if (deviceIsCompatible == false) continue;
218
220 auto currentMemorySpaces = currentDevice->getMemorySpaceList();
221
222 // Getting compute resources in this current device
223 for (const auto &givenDeviceMemorySpace : givenDeviceMemorySpaces)
224 {
225 bool foundMemorySpace = false;
226 for (auto currentMemorySpaceItr = currentMemorySpaces.begin(); currentMemorySpaceItr != currentMemorySpaces.end() && foundMemorySpace == false; currentMemorySpaceItr++)
227 {
228 // Getting current device object
229 const auto &currentDeviceMemorySpace = currentMemorySpaceItr.operator*();
230
231 // If it's the same type as given
232 if (currentDeviceMemorySpace->getType() == givenDeviceMemorySpace->getType())
233 {
234 // Check whether the size is at least as big as given
235 if (currentDeviceMemorySpace->getSize() >= givenDeviceMemorySpace->getSize())
236 {
237 // Set compute resource as found
238 foundMemorySpace = true;
239
240 // Erase this element from the list to not re-use it
241 currentMemorySpaces.erase(currentMemorySpaceItr);
242 }
243 }
244 }
245
246 // If no compute resource was found, abandon search in this device
247 if (foundMemorySpace == false)
248 {
249 deviceIsCompatible = false;
250 break;
251 }
252 }
253
254 // If no suitable device was found, advance with the next one
255 if (deviceIsCompatible == false) continue;
256
257 // If we reached this point, we've found the device
258 foundCompatibleDevice = true;
259
260 // Deleting device to prevent it from being counted again
261 currentDevices.erase(currentDeviceItr);
262
263 // Stop checking
264 break;
265 }
266 }
267
268 // If no current devices could satisfy the given device, return false now
269 if (foundCompatibleDevice == false) return false;
270 }
271
272 // All requirements have been met, returning true
273 //printf("Requirements met\n");
274 return true;
275 }
276
282 nlohmann::json &getMetadata() { return _metadata; }
283
289 [[nodiscard]] const nlohmann::json &getMetadata() const { return _metadata; }
290
296 void setMetadata(const nlohmann::json &metadata) { _metadata = metadata; }
297
298 private:
299
305 nlohmann::json _metadata;
306
310 deviceList_t _deviceList;
311};
312
313} // namespace HiCR
Definition topology.hpp:41
__INLINE__ void deserialize(const nlohmann::json &input)
Definition topology.hpp:113
__INLINE__ bool isSubset(const HiCR::Topology givenTopology)
Definition topology.hpp:153
__INLINE__ void addDevice(const std::shared_ptr< HiCR::Device > &device)
Definition topology.hpp:70
__INLINE__ const deviceList_t & getDevices() const
Definition topology.hpp:63
void setMetadata(const nlohmann::json &metadata)
Definition topology.hpp:296
__INLINE__ nlohmann::json serialize() const
Definition topology.hpp:88
__INLINE__ void merge(const Topology &source)
Definition topology.hpp:77
static __INLINE__ void verify(const nlohmann::json &input)
Definition topology.hpp:129
Topology(const nlohmann::json &input)
Definition topology.hpp:57
const nlohmann::json & getMetadata() const
Definition topology.hpp:289
nlohmann::json & getMetadata()
Definition topology.hpp:282
std::vector< std::shared_ptr< Device > > deviceList_t
Definition topology.hpp:47
Provides a base definition for a HiCR Device class.
#define HICR_THROW_LOGIC(...)
Definition exceptions.hpp:67