diff --git a/src/libumf.c b/src/libumf.c index fb01eae573..9df7ee29cd 100644 --- a/src/libumf.c +++ b/src/libumf.c @@ -74,7 +74,11 @@ umf_result_t umfInit(void) { if (TRACKER) { LOG_DEBUG("UMF library initialized"); } - +#if !defined(UMF_NO_HWLOC) + // some benchmarks uses multiple forks, and topology initialization is very slow + // so if we initialize topology before the first fork, we can get significant performance gain. + umfGetTopologyReduced(); +#endif return UMF_RESULT_SUCCESS; } diff --git a/src/memspaces/memspace_host_all.c b/src/memspaces/memspace_host_all.c index efcfa7ef4b..06a07a6603 100644 --- a/src/memspaces/memspace_host_all.c +++ b/src/memspaces/memspace_host_all.c @@ -37,7 +37,7 @@ static umf_result_t umfMemspaceHostAllCreate(umf_memspace_handle_t *hMemspace) { umf_result_t umf_ret = UMF_RESULT_SUCCESS; - hwloc_topology_t topology = umfGetTopology(); + hwloc_topology_t topology = umfGetTopologyReduced(); if (!topology) { // TODO: What would be an approrpiate err? return UMF_RESULT_ERROR_UNKNOWN; diff --git a/src/memtargets/memtarget_numa.c b/src/memtargets/memtarget_numa.c index a0a1e592a0..d6431ef9ff 100644 --- a/src/memtargets/memtarget_numa.c +++ b/src/memtargets/memtarget_numa.c @@ -218,7 +218,7 @@ static umf_result_t numa_get_capacity(void *memTarget, size_t *capacity) { return UMF_RESULT_ERROR_INVALID_ARGUMENT; } - hwloc_topology_t topology = umfGetTopology(); + hwloc_topology_t topology = umfGetTopologyReduced(); if (!topology) { return UMF_RESULT_ERROR_NOT_SUPPORTED; } diff --git a/src/provider/provider_os_memory.c b/src/provider/provider_os_memory.c index 5c79b05829..e984d8ee83 100644 --- a/src/provider/provider_os_memory.c +++ b/src/provider/provider_os_memory.c @@ -98,6 +98,7 @@ umf_result_t umfOsMemoryProviderParamsSetPartitions( #include "critnib.h" #include "libumf.h" #include "provider_os_memory_internal.h" +#include "topology.h" #include "utils_common.h" #include "utils_concurrency.h" #include "utils_log.h" @@ -629,27 +630,19 @@ static umf_result_t os_initialize(const void *params, void **provider) { memset(os_provider, 0, sizeof(*os_provider)); - int r = hwloc_topology_init(&os_provider->topo); - if (r) { - LOG_ERR("HWLOC topology init failed"); - ret = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; - goto err_free_os_provider; - } - - r = hwloc_topology_load(os_provider->topo); - if (r) { + os_provider->topo = umfGetTopologyReduced(); + if (!os_provider->topo) { os_store_last_native_error(UMF_OS_RESULT_ERROR_TOPO_DISCOVERY_FAILED, 0); LOG_ERR("HWLOC topology discovery failed"); ret = UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC; - goto err_destroy_hwloc_topology; } os_provider->fd_offset_map = critnib_new(NULL, NULL); if (!os_provider->fd_offset_map) { LOG_ERR("creating file descriptor offset map failed"); ret = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; - goto err_destroy_hwloc_topology; + goto err_free_os_provider; } ret = translate_params(in_params, os_provider); @@ -692,8 +685,6 @@ static umf_result_t os_initialize(const void *params, void **provider) { free_bitmaps(os_provider); err_destroy_critnib: critnib_delete(os_provider->fd_offset_map); -err_destroy_hwloc_topology: - hwloc_topology_destroy(os_provider->topo); err_free_os_provider: umf_ba_global_free(os_provider); return ret; @@ -717,7 +708,7 @@ static umf_result_t os_finalize(void *provider) { if (os_provider->nodeset_str_buf) { umf_ba_global_free(os_provider->nodeset_str_buf); } - hwloc_topology_destroy(os_provider->topo); + umf_ba_global_free(os_provider); return UMF_RESULT_SUCCESS; } diff --git a/src/topology.c b/src/topology.c index eab7992ced..da7666f87c 100644 --- a/src/topology.c +++ b/src/topology.c @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2024 Intel Corporation + * Copyright (C) 2024-2025 Intel Corporation * * Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -13,7 +13,9 @@ #include "utils_log.h" static hwloc_topology_t topology = NULL; +static hwloc_topology_t topology_reduced = NULL; static UTIL_ONCE_FLAG topology_initialized = UTIL_ONCE_FLAG_INIT; +static UTIL_ONCE_FLAG topology_reduced_initialized = UTIL_ONCE_FLAG_INIT; void umfDestroyTopology(void) { if (topology) { @@ -24,22 +26,55 @@ void umfDestroyTopology(void) { memcpy(&topology_initialized, &is_initialized, sizeof(topology_initialized)); } + if (topology_reduced) { + hwloc_topology_destroy(topology_reduced); + + // portable version of "topology_initialized = UTIL_ONCE_FLAG_INIT;" + static UTIL_ONCE_FLAG is_initialized = UTIL_ONCE_FLAG_INIT; + memcpy(&topology_reduced_initialized, &is_initialized, + sizeof(topology_reduced_initialized)); + } } -static void umfCreateTopology(void) { - if (hwloc_topology_init(&topology)) { +static void umfCreateTopologyHelper(bool reduced, + hwloc_topology_t *topology_ptr) { + if (hwloc_topology_init(topology_ptr)) { LOG_ERR("Failed to initialize topology"); - topology = NULL; + *topology_ptr = NULL; return; } - if (hwloc_topology_load(topology)) { + if (reduced) { + // Set the topology to only include NUMA nodes and memory + // to improve performance of the topology load on large systems + if (hwloc_topology_set_all_types_filter(*topology_ptr, + HWLOC_TYPE_FILTER_KEEP_NONE)) { + LOG_ERR("Failed to set topology filter"); + hwloc_topology_destroy(*topology_ptr); + *topology_ptr = NULL; + return; + } + } + if (hwloc_topology_load(*topology_ptr)) { LOG_ERR("Failed to initialize topology"); - hwloc_topology_destroy(topology); - topology = NULL; + hwloc_topology_destroy(*topology_ptr); + *topology_ptr = NULL; } } +static void umfCreateTopology(void) { + umfCreateTopologyHelper(false, &topology); +} + +static void umfCreateTopologyReduced(void) { + umfCreateTopologyHelper(true, &topology_reduced); +} + +hwloc_topology_t umfGetTopologyReduced(void) { + utils_init_once(&topology_reduced_initialized, umfCreateTopologyReduced); + return topology_reduced; +} + hwloc_topology_t umfGetTopology(void) { utils_init_once(&topology_initialized, umfCreateTopology); return topology; diff --git a/src/topology.h b/src/topology.h index c20defda7a..5d5982a0ca 100644 --- a/src/topology.h +++ b/src/topology.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2024 Intel Corporation + * Copyright (C) 2024-2025 Intel Corporation * * Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -17,6 +17,7 @@ extern "C" { #endif hwloc_topology_t umfGetTopology(void); +hwloc_topology_t umfGetTopologyReduced(void); void umfDestroyTopology(void); #ifdef __cplusplus