Skip to content

Commit f78d5a1

Browse files
authored
Merge pull request #205 from kswiecicki/memspace-hwloc
Add predefined HOST ALL memspace
2 parents d1eca21 + a1b65bf commit f78d5a1

File tree

10 files changed

+241
-15
lines changed

10 files changed

+241
-15
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,19 @@ The `UMF_BUILD_LIBUMF_POOL_SCALABLE` option has to be turned `ON` to build this
161161
2) Required packages:
162162
- libtbb-dev (libraries: libtbbmalloc.so.2)
163163

164+
### Memspaces (Linux-only)
165+
166+
TODO: Add general information about memspaces.
167+
168+
#### Host all memspace
169+
170+
Memspace backed by all available NUMA nodes discovered on the platform. Can be retrieved
171+
using umfMemspaceHostAllGet.
172+
173+
##### Requirements
174+
175+
This feature relies on the OS memory provider.
176+
164177
## Contributions
165178

166179
All contributions to the UMF project are most welcome! Before submitting

include/umf/memspace.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ umfMemoryProviderCreateFromMemspace(umf_memspace_handle_t hMemspace,
4444
umf_memspace_policy_handle_t hPolicy,
4545
umf_memory_provider_handle_t *hProvider);
4646

47+
///
48+
/// \brief Retrieves predefined host all memspace.
49+
/// \return host all memspace handle on success or NULL on failure.
50+
///
51+
umf_memspace_handle_t umfMemspaceHostAllGet(void);
52+
4753
#ifdef __cplusplus
4854
}
4955
#endif

src/CMakeLists.txt

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,17 @@ set(UMF_SOURCES_MACOSX
5252
libumf_linux.c
5353
)
5454

55+
# Compile definitions for UMF library
56+
# TODO: Cleanup the compile definitions across all the Cmake files
57+
set(UMF_COMPILE_DEFINITIONS "")
58+
5559
if(UMF_BUILD_OS_MEMORY_PROVIDER)
5660
set(UMF_SOURCES_LINUX ${UMF_SOURCES_LINUX}
5761
provider/provider_os_memory.c
5862
provider/provider_os_memory_linux.c
5963
memory_targets/memory_target_numa.c
60-
memspaces/memspace_numa.c)
64+
memspaces/memspace_numa.c
65+
memspaces/memspace_host_all.c)
6166

6267
if(LINUX)
6368
if(PkgConfig_FOUND)
@@ -67,6 +72,8 @@ if(UMF_BUILD_OS_MEMORY_PROVIDER)
6772
find_package(LIBHWLOC REQUIRED hwloc)
6873
endif()
6974
set(UMF_LIBS ${UMF_LIBS} ${LIBHWLOC_LIBRARIES})
75+
# Currently, OS provider is only built for Linux
76+
set(UMF_COMPILE_DEFINITIONS ${UMF_COMPILE_DEFINITIONS} "UMF_BUILD_OS_MEMORY_PROVIDER=1")
7077
endif()
7178
endif()
7279

@@ -85,16 +92,18 @@ if(UMF_BUILD_SHARED_LIBRARY)
8592
LIBS ${UMF_LIBS}
8693
LINUX_MAP_FILE ${CMAKE_CURRENT_SOURCE_DIR}/libumf.map
8794
WINDOWS_DEF_FILE ${CMAKE_CURRENT_SOURCE_DIR}/libumf.def)
88-
target_compile_definitions(umf PUBLIC UMF_SHARED_LIBRARY)
95+
set(UMF_COMPILE_DEFINITIONS ${UMF_COMPILE_DEFINITIONS} "UMF_SHARED_LIBRARY")
8996
set_target_properties(umf PROPERTIES
9097
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_UMF_OUTPUT_DIRECTORY})
9198
else()
9299
add_umf_library(NAME umf
93-
TYPE STATIC
94-
SRCS ${UMF_SOURCES}
100+
TYPE STATIC
101+
SRCS ${UMF_SOURCES}
95102
LIBS ${UMF_LIBS})
96103
endif()
97104

105+
target_compile_definitions(umf PUBLIC ${UMF_COMPILE_DEFINITIONS})
106+
98107
if (UMF_ENABLE_POOL_TRACKING)
99108
target_sources(umf PRIVATE memory_pool_tracking.c)
100109
else()
@@ -103,10 +112,13 @@ endif()
103112

104113
add_library(${PROJECT_NAME}::umf ALIAS umf)
105114

106-
target_include_directories(umf PUBLIC
115+
target_include_directories(umf PUBLIC
107116
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
117+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
108118
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/critnib>
109119
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/provider>
120+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/memspaces>
121+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/memory_targets>
110122
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
111123
)
112124

src/libumf.def

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ EXPORTS
1616
umfMemoryProviderAllocationMerge
1717
umfMemoryProviderAllocationSplit
1818
umfMemoryProviderCreate
19+
umfMemoryProviderCreateFromMemspace
1920
umfMemoryProviderDestroy
2021
umfMemoryProviderFree
2122
umfMemoryProviderGetLastNativeError
@@ -24,18 +25,17 @@ EXPORTS
2425
umfMemoryProviderGetRecommendedPageSize
2526
umfMemoryProviderPurgeForce
2627
umfMemoryProviderPurgeLazy
28+
umfMemspaceDestroy
2729
umfPoolAlignedMalloc
2830
umfPoolByPtr
2931
umfPoolCalloc
3032
umfPoolCreate
33+
umfPoolCreateFromMemspace
3134
umfPoolDestroy
3235
umfPoolFree
3336
umfPoolGetLastAllocationError
3437
umfPoolGetMemoryProvider
3538
umfPoolMalloc
3639
umfPoolMallocUsableSize
3740
umfPoolRealloc
38-
umfPoolCreateFromMemspace
39-
umfMemoryProviderCreateFromMemspace
40-
umfMemspaceDestroy
4141
umfProxyPoolOps

src/libumf.map

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ UMF_1.0 {
1010
umfMemoryProviderAllocationMerge;
1111
umfMemoryProviderAllocationSplit;
1212
umfMemoryProviderCreate;
13+
umfMemoryProviderCreateFromMemspace;
1314
umfMemoryProviderDestroy;
1415
umfMemoryProviderFree;
1516
umfMemoryProviderGetLastNativeError;
@@ -18,23 +19,23 @@ UMF_1.0 {
1819
umfMemoryProviderGetRecommendedPageSize;
1920
umfMemoryProviderPurgeForce;
2021
umfMemoryProviderPurgeLazy;
22+
umfMemspaceCreateFromNumaArray;
23+
umfMemspaceDestroy;
24+
umfMemspaceHostAllGet;
25+
umfOsMemoryProviderOps;
2126
umfPoolAlignedMalloc;
2227
umfPoolByPtr;
2328
umfPoolCalloc;
2429
umfPoolCreate;
30+
umfPoolCreateFromMemspace;
2531
umfPoolDestroy;
2632
umfPoolFree;
2733
umfPoolGetLastAllocationError;
2834
umfPoolGetMemoryProvider;
2935
umfPoolMalloc;
3036
umfPoolMallocUsableSize;
3137
umfPoolRealloc;
32-
umfOsMemoryProviderOps;
3338
umfProxyPoolOps;
34-
umfPoolCreateFromMemspace;
35-
umfMemoryProviderCreateFromMemspace;
36-
umfMemspaceCreateFromNumaArray;
37-
umfMemspaceDestroy;
3839
local:
3940
*;
4041
};

src/libumf_linux.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <stddef.h>
1111

1212
#include "base_alloc_global.h"
13+
#include "memspace_host_all_internal.h"
1314
#include "provider_tracking.h"
1415

1516
umf_memory_tracker_handle_t TRACKER = NULL;
@@ -23,6 +24,10 @@ void __attribute__((destructor)) umfDestroy(void) {
2324
// make sure TRACKER is not used after being destroyed
2425
TRACKER = NULL;
2526
umfMemoryTrackerDestroy(t);
27+
28+
#if defined(UMF_BUILD_OS_MEMORY_PROVIDER)
29+
umfMemspaceHostAllDestroy();
30+
#endif
2631
}
2732

2833
void libumfInit(void) {

src/memspaces/memspace_host_all.c

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
*
3+
* Copyright (C) 2024 Intel Corporation
4+
*
5+
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
6+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
*
8+
*/
9+
10+
#include <assert.h>
11+
#include <hwloc.h>
12+
#include <stdlib.h>
13+
14+
#include "base_alloc_global.h"
15+
#include "memory_target_numa.h"
16+
#include "memspace_host_all_internal.h"
17+
#include "memspace_internal.h"
18+
#include "memspace_numa.h"
19+
#include "utils_concurrency.h"
20+
21+
static umf_result_t umfMemspaceHostAllCreate(umf_memspace_handle_t *hMemspace) {
22+
if (!hMemspace) {
23+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
24+
}
25+
26+
umf_result_t umf_ret = UMF_RESULT_SUCCESS;
27+
28+
hwloc_topology_t topology;
29+
if (hwloc_topology_init(&topology)) {
30+
// TODO: What would be an approrpiate err?
31+
return UMF_RESULT_ERROR_UNKNOWN;
32+
}
33+
34+
if (hwloc_topology_load(topology)) {
35+
umf_ret = UMF_RESULT_ERROR_UNKNOWN;
36+
goto err_topology_destroy;
37+
}
38+
39+
// Shouldn't return -1, as 'HWLOC_OBJ_NUMANODE' doesn't appear to be an
40+
// object that can be present on multiple levels.
41+
// Source: https://www.open-mpi.org/projects/hwloc/doc/hwloc-v2.10.0-letter.pdf
42+
int nNodes = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_NUMANODE);
43+
assert(nNodes != -1);
44+
45+
size_t *nodeIds = umf_ba_global_alloc(nNodes * sizeof(size_t));
46+
if (!nodeIds) {
47+
umf_ret = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
48+
goto err_topology_destroy;
49+
}
50+
51+
// Collect all available NUMA node ids on the platform
52+
int nodeIdx = 0;
53+
hwloc_obj_t numaNodeObj = NULL;
54+
while ((numaNodeObj = hwloc_get_next_obj_by_type(
55+
topology, HWLOC_OBJ_NUMANODE, numaNodeObj)) != NULL) {
56+
// Shouldn't be possible to iterate over more 'HWLOC_OBJ_NUMANODE' objects
57+
// than the number returned by hwloc_get_nbobjs_by_type.
58+
assert(nodeIdx < nNodes);
59+
nodeIds[nodeIdx++] = numaNodeObj->os_index;
60+
}
61+
62+
umf_ret =
63+
umfMemspaceCreateFromNumaArray(nodeIds, (size_t)nNodes, hMemspace);
64+
65+
umf_ba_global_free(nodeIds, nNodes * sizeof(size_t));
66+
67+
err_topology_destroy:
68+
hwloc_topology_destroy(topology);
69+
return umf_ret;
70+
}
71+
72+
static umf_memspace_handle_t UMF_MEMSPACE_HOST_ALL = NULL;
73+
static UTIL_ONCE_FLAG UMF_MEMSPACE_HOST_ALL_INITIALIZED = UTIL_ONCE_FLAG_INIT;
74+
75+
void umfMemspaceHostAllDestroy(void) {
76+
if (UMF_MEMSPACE_HOST_ALL) {
77+
umfMemspaceDestroy(UMF_MEMSPACE_HOST_ALL);
78+
UMF_MEMSPACE_HOST_ALL = NULL;
79+
}
80+
}
81+
82+
static void umfMemspaceHostAllInit(void) {
83+
umf_result_t ret = umfMemspaceHostAllCreate(&UMF_MEMSPACE_HOST_ALL);
84+
assert(ret == UMF_RESULT_SUCCESS);
85+
(void)ret;
86+
87+
// TODO: Setup appropriate cleanup when 'HOST ALL' memspace becomes available
88+
// on Windows. 'HOST ALL' memspace depends on OS provider, which currently
89+
// doesn't support Windows.
90+
}
91+
92+
umf_memspace_handle_t umfMemspaceHostAllGet(void) {
93+
util_init_once(&UMF_MEMSPACE_HOST_ALL_INITIALIZED, umfMemspaceHostAllInit);
94+
return UMF_MEMSPACE_HOST_ALL;
95+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
*
3+
* Copyright (C) 2024 Intel Corporation
4+
*
5+
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
6+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
*
8+
*/
9+
10+
#ifndef UMF_MEMSPACE_HOST_ALL_INTERNAL_H
11+
#define UMF_MEMSPACE_HOST_ALL_INTERNAL_H 1
12+
13+
#ifdef __cplusplus
14+
extern "C" {
15+
#endif
16+
17+
///
18+
/// \brief Destroys the predefined host all memspace.
19+
///
20+
void umfMemspaceHostAllDestroy(void);
21+
22+
#ifdef __cplusplus
23+
}
24+
#endif
25+
26+
#endif /* UMF_MEMSPACE_HOST_ALL_INTERNAL_H */

test/CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ function(add_umf_test)
5050
set_tests_properties(${TEST_NAME} PROPERTIES LABELS "umf")
5151

5252
if(WIN32)
53-
set_property(TEST ${TEST_NAME} PROPERTY ENVIRONMENT_MODIFICATION
53+
set_property(TEST ${TEST_NAME} PROPERTY ENVIRONMENT_MODIFICATION
5454
"PATH=path_list_append:../bin/$<CONFIG>")
5555
endif()
5656

@@ -61,7 +61,7 @@ endfunction()
6161

6262
add_subdirectory(common)
6363

64-
add_umf_test(NAME base
64+
add_umf_test(NAME base
6565
SRCS base.cpp)
6666
add_umf_test(NAME memoryPool
6767
SRCS memoryPoolAPI.cpp malloc_compliance_tests.cpp)
@@ -129,6 +129,9 @@ if(UMF_BUILD_OS_MEMORY_PROVIDER AND LINUX) # OS-specific functions are implement
129129
add_umf_test(NAME provider_os_memory_config
130130
SRCS provider_os_memory_config.cpp
131131
LIBS umf_utils ${LIBNUMA_LIBRARIES})
132+
add_umf_test(NAME memspace_host_all
133+
SRCS memspace_host_all.cpp
134+
LIBS ${LIBNUMA_LIBRARIES})
132135
endif()
133136

134137
if(UMF_BUILD_SHARED_LIBRARY)

test/memspace_host_all.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright (C) 2024 Intel Corporation
2+
// Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
3+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
5+
#include "base.hpp"
6+
#include "test_helpers.h"
7+
8+
#include <umf/memspace.h>
9+
10+
using umf_test::test;
11+
12+
#define SIZE_4K (4096)
13+
14+
struct predefinedMemspaceTest : test {
15+
16+
void SetUp() override {
17+
::test::SetUp();
18+
19+
hMemspace = umfMemspaceHostAllGet();
20+
UT_ASSERTne(hMemspace, nullptr);
21+
}
22+
23+
umf_memspace_handle_t hMemspace;
24+
};
25+
26+
struct predefinedMemspaceProviderTest : predefinedMemspaceTest {
27+
28+
void SetUp() override {
29+
::predefinedMemspaceTest::SetUp();
30+
31+
enum umf_result_t ret =
32+
umfMemoryProviderCreateFromMemspace(hMemspace, nullptr, &provider);
33+
UT_ASSERTeq(ret, UMF_RESULT_SUCCESS);
34+
UT_ASSERTne(provider, nullptr);
35+
}
36+
37+
void TearDown() override {
38+
::predefinedMemspaceTest::TearDown();
39+
40+
umfMemoryProviderDestroy(provider);
41+
}
42+
43+
umf_memory_provider_handle_t provider = nullptr;
44+
};
45+
46+
TEST_F(test, memspaceGet) {
47+
umf_memspace_handle_t hMemspace = umfMemspaceHostAllGet();
48+
UT_ASSERTne(hMemspace, nullptr);
49+
}
50+
51+
TEST_F(predefinedMemspaceProviderTest, allocFree) {
52+
void *ptr = nullptr;
53+
size_t size = SIZE_4K;
54+
size_t alignment = 0;
55+
56+
enum umf_result_t ret =
57+
umfMemoryProviderAlloc(provider, size, alignment, &ptr);
58+
UT_ASSERTeq(ret, UMF_RESULT_SUCCESS);
59+
UT_ASSERTne(ptr, nullptr);
60+
61+
memset(ptr, 0xFF, size);
62+
63+
ret = umfMemoryProviderFree(provider, ptr, size);
64+
UT_ASSERTeq(ret, UMF_RESULT_SUCCESS);
65+
}

0 commit comments

Comments
 (0)