// Compatibility function for accessing hwloc_obj_t object memory with different API versions of hwloc
std::size_t
-getHwLocObjectMemory(hwloc_obj_t obj)
+getHwLocObjectMemory(const hwloc_obj* obj)
{
#if GMX_HWLOC_API_VERSION_IS_2XX
return obj->total_memory;
* descendants of the provided object. If no objects of this type
* were found, the vector will be empty.
*/
-const std::vector<hwloc_obj_t>
-getHwLocDescendantsByType(hwloc_topology_t topo, hwloc_obj_t obj, const hwloc_obj_type_t type)
+const std::vector<const hwloc_obj*>
+getHwLocDescendantsByType(const hwloc_topology* topo, const hwloc_obj* obj, const hwloc_obj_type_t type)
{
GMX_RELEASE_ASSERT(obj, "NULL hwloc object provided to getHwLocDescendantsByType()");
- std::vector<hwloc_obj_t> v;
+ std::vector<const hwloc_obj*> v;
if (obj->type == type)
{
// Go through children; if this object has no children obj->arity is 0,
// and we'll return an empty vector.
hwloc_obj_t tempNode = nullptr;
- while ((tempNode = hwloc_get_next_child(topo, obj, tempNode)) != nullptr)
+ while ((tempNode = hwloc_get_next_child(const_cast<hwloc_topology_t>(topo),
+ const_cast<hwloc_obj_t>(obj),
+ tempNode)) != nullptr)
{
- std::vector<hwloc_obj_t> v2 = getHwLocDescendantsByType(topo, tempNode, type);
+ std::vector<const hwloc_obj*> v2 = getHwLocDescendantsByType(topo, tempNode, type);
v.insert(v.end(), v2.begin(), v2.end());
}
return v;
* \param machine Pointer to the machine structure in the HardwareTopology
* class, where the tree of sockets/cores/threads will be written.
*
- * \return If all the data is found the return value is 0, otherwise non-zero.
+ * \return If all the data is found
*/
-int
+bool
parseHwLocSocketsCoresThreads(hwloc_topology_t topo,
HardwareTopology::Machine * machine)
{
- hwloc_obj_t root = hwloc_get_root_obj(topo);
- std::vector<hwloc_obj_t> hwlocSockets = getHwLocDescendantsByType(topo, root, HWLOC_OBJ_PACKAGE);
+ const hwloc_obj* root = hwloc_get_root_obj(topo);
+ std::vector<const hwloc_obj*> hwlocSockets = getHwLocDescendantsByType(topo, root, HWLOC_OBJ_PACKAGE);
machine->logicalProcessorCount = hwloc_get_nbobjs_by_type(topo, HWLOC_OBJ_PU);
machine->logicalProcessors.resize(machine->logicalProcessorCount);
machine->sockets[i].id = hwlocSockets[i]->logical_index;
// Get children (cores)
- std::vector<hwloc_obj_t> hwlocCores = getHwLocDescendantsByType(topo, hwlocSockets[i], HWLOC_OBJ_CORE);
+ std::vector<const hwloc_obj*> hwlocCores = getHwLocDescendantsByType(topo, hwlocSockets[i], HWLOC_OBJ_CORE);
machine->sockets[i].cores.resize(hwlocCores.size());
topologyOk = topologyOk && !hwlocCores.empty(); // Fail if we have no cores in socket
machine->sockets[i].cores[j].numaNodeId = -1;
// Get children (hwthreads)
- std::vector<hwloc_obj_t> hwlocPUs = getHwLocDescendantsByType(topo, hwlocCores[j], HWLOC_OBJ_PU);
+ std::vector<const hwloc_obj*> hwlocPUs = getHwLocDescendantsByType(topo, hwlocCores[j], HWLOC_OBJ_PU);
machine->sockets[i].cores[j].hwThreads.resize(hwlocPUs.size());
topologyOk = topologyOk && !hwlocPUs.empty(); // Fail if we have no hwthreads in core
}
}
- if (topologyOk)
- {
- return 0;
- }
- else
+ if (!topologyOk)
{
machine->logicalProcessors.clear();
machine->sockets.clear();
- return -1;
}
+ return topologyOk;
}
-/*! \brief Fill \c machine with cache information from hwloc topology
+/*! \brief Read cache information from hwloc topology
*
* \param topo hwloc topology handle that has been initialized and loaded
* \param machine Pointer to the machine structure in the HardwareTopology
- * class, where cache data will be filled if found and valid.
+ * class, where cache data will be filled.
+ *
+ * \return If any cache data is found
*/
-void
+bool
parseHwLocCache(hwloc_topology_t topo,
HardwareTopology::Machine * machine)
{
hwloc_obj_t cache = hwloc_get_next_obj_by_depth(topo, depth, nullptr);
if (cache != nullptr)
{
- std::vector<hwloc_obj_t> hwThreads = getHwLocDescendantsByType(topo, cache, HWLOC_OBJ_PU);
+ std::vector<const hwloc_obj*> hwThreads = getHwLocDescendantsByType(topo, cache, HWLOC_OBJ_PU);
machine->caches.push_back( {
static_cast<int>(cache->attr->cache.depth),
}
}
}
+ return !machine->caches.empty();
}
-/*! \brief Fill \c machine with numa information from hwloc topology
+/*! \brief Read numa information from hwloc topology
*
* \param topo hwloc topology handle that has been initialized and loaded
* \param machine Pointer to the machine structure in the HardwareTopology
* completed successfully before calling this one. If this is not the case,
* you will get an error return code.
*
- * If the data found makes sense (either in the numa node or the
- * entire machine) the numa.nodes data structure in
- * HardwareTopology::Machine will be filled upon exit.
+ * \return If the data found makes sense (either in the numa node or the
+ * entire machine)
*/
-void
+bool
parseHwLocNuma(hwloc_topology_t topo,
HardwareTopology::Machine * machine)
{
- hwloc_obj_t root = hwloc_get_root_obj(topo);
- std::vector<hwloc_obj_t> hwlocNumaNodes = getHwLocDescendantsByType(topo, root, HWLOC_OBJ_NUMANODE);
- bool topologyOk = true;
+ const hwloc_obj* root = hwloc_get_root_obj(topo);
+ std::vector<const hwloc_obj*> hwlocNumaNodes = getHwLocDescendantsByType(topo, root, HWLOC_OBJ_NUMANODE);
+ bool topologyOk = true;
if (!hwlocNumaNodes.empty())
{
// Get list of PUs in this numa node. Get from numa node if v1.x.x, get from numa node's parent if 2.x.x
#if GMX_HWLOC_API_VERSION_IS_2XX
- std::vector<hwloc_obj_t> hwlocPUs = getHwLocDescendantsByType(topo, hwlocNumaNodes[i]->parent, HWLOC_OBJ_PU);
+ std::vector<const hwloc_obj*> hwlocPUs = getHwLocDescendantsByType(topo, hwlocNumaNodes[i]->parent, HWLOC_OBJ_PU);
#else
- std::vector<hwloc_obj_t> hwlocPUs = getHwLocDescendantsByType(topo, hwlocNumaNodes[i], HWLOC_OBJ_PU);
+ std::vector<const hwloc_obj*> hwlocPUs = getHwLocDescendantsByType(topo, hwlocNumaNodes[i], HWLOC_OBJ_PU);
#endif
for (auto &p : hwlocPUs)
{
}
else
{
- hwloc_distances_s** dist = new hwloc_distances_s*;
+ hwloc_distances_s* dist;
// Set the number of distance matrices to return (1 in our case, but hwloc 2.x.x allows
// for multiple distances types and therefore multiple distance matrices)
unsigned nr = 1;
- hwloc_distances_get(topo, &nr, dist, HWLOC_DISTANCES_KIND_MEANS_LATENCY, 0);
+ hwloc_distances_get(topo, &nr, &dist, HWLOC_DISTANCES_KIND_MEANS_LATENCY, 0);
// If no distances were found, nr will be 0, otherwise distances will be populated with 1
// hwloc_distances_s object
- if (nr > 0 && dist[0]->nbobjs == hwlocNumaNodes.size())
+ if (nr > 0 && dist->nbobjs == hwlocNumaNodes.size())
{
- machine->numa.relativeLatency.resize(dist[0]->nbobjs);
- for (std::size_t i = 0; i < dist[0]->nbobjs; i++)
+ machine->numa.relativeLatency.resize(dist->nbobjs);
+ for (std::size_t i = 0; i < dist->nbobjs; i++)
{
- machine->numa.relativeLatency[i].resize(dist[0]->nbobjs);
- for (std::size_t j = 0; j < dist[0]->nbobjs; j++)
+ machine->numa.relativeLatency[i].resize(dist->nbobjs);
+ for (std::size_t j = 0; j < dist->nbobjs; j++)
{
- machine->numa.relativeLatency[i][j] = dist[0]->values[i*dist[0]->nbobjs+j];
+ machine->numa.relativeLatency[i][j] = dist->values[i*dist->nbobjs+j];
}
}
}
{
topologyOk = false;
}
- hwloc_distances_release(topo, dist[0]);
+ hwloc_distances_release(topo, dist);
}
// hwloc-2.x provides latencies as integers, but to make things more similar to the case of a single
{
machine->numa.nodes.clear();
}
+ return topologyOk;
}
-/*! \brief Fill \c machine with PCI device information from hwloc topology
+/*! \brief Read PCI device information from hwloc topology
*
* \param topo hwloc topology handle that has been initialized and loaded
* \param machine Pointer to the machine structure in the HardwareTopology
- * class, where PCI device information will be filled if found
- * and valid.
+ * class, where PCI device information will be filled.
+ * *
+ * \return If any devices were found
*/
-void
+bool
parseHwLocDevices(hwloc_topology_t topo,
HardwareTopology::Machine * machine)
{
- hwloc_obj_t root = hwloc_get_root_obj(topo);
- std::vector<hwloc_obj_t> pcidevs = getHwLocDescendantsByType(topo, root, HWLOC_OBJ_PCI_DEVICE);
+ const hwloc_obj * root = hwloc_get_root_obj(topo);
+ std::vector<const hwloc_obj*> pcidevs = getHwLocDescendantsByType(topo, root, HWLOC_OBJ_PCI_DEVICE);
for (auto &p : pcidevs)
{
}
#else // GMX_HWLOC_API_VERSION_IS_2XX = false, api v 1.x.x
// numa nodes are normal part of tree, can use hwloc ancestor function
- const hwloc_obj * const ancestor = hwloc_get_ancestor_obj_by_type(topo, HWLOC_OBJ_NUMANODE, p);
+ const hwloc_obj * const ancestor = hwloc_get_ancestor_obj_by_type(topo, HWLOC_OBJ_NUMANODE,
+ const_cast<hwloc_obj_t>(p));
#endif // end if GMX_HWLOC_API_VERSION_IS_2XX
int numaId;
if (ancestor != nullptr)
numaId
} );
}
+ return !pcidevs.empty();
}
void
}
// If we get here, we can get a valid root object for the topology
- *isThisSystem = bool(hwloc_topology_is_thissystem(topo));
+ *isThisSystem = hwloc_topology_is_thissystem(topo) != 0;
// Parse basic information about sockets, cores, and hardware threads
- if (parseHwLocSocketsCoresThreads(topo, machine) == 0)
+ if (parseHwLocSocketsCoresThreads(topo, machine))
{
*supportLevel = HardwareTopology::SupportLevel::Basic;
}
}
// Get information about cache and numa nodes
- parseHwLocCache(topo, machine);
- parseHwLocNuma(topo, machine);
- if (!machine->caches.empty() && !machine->numa.nodes.empty())
+ if (parseHwLocCache(topo, machine) && parseHwLocNuma(topo, machine))
{
*supportLevel = HardwareTopology::SupportLevel::Full;
}
}
// PCI devices
- parseHwLocDevices(topo, machine);
- if (!machine->devices.empty())
+ if (parseHwLocDevices(topo, machine))
{
*supportLevel = HardwareTopology::SupportLevel::FullWithDevices;
}