Skip to content

Commit f3006bf

Browse files
authored
Merge pull request #331 from igchor/high_capacity_memspace
High capacity memspace
2 parents 492d1f4 + 8a527ad commit f3006bf

17 files changed

+422
-30
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,10 @@ TODO: Add general information about memspaces.
192192
Memspace backed by all available NUMA nodes discovered on the platform. Can be retrieved
193193
using umfMemspaceHostAllGet.
194194

195-
##### Requirements
195+
#### Highest capacity memspace
196196

197-
This feature relies on the OS memory provider.
197+
Memspace backed by all available NUMA nodes discovered on the platform sorted by capacity.
198+
Can be retrieved using umfMemspaceHighestCapacityGet.
198199

199200
## Contributions
200201

include/umf/memspace.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ umfMemoryProviderCreateFromMemspace(umf_memspace_handle_t hMemspace,
5050
///
5151
umf_memspace_handle_t umfMemspaceHostAllGet(void);
5252

53+
///
54+
/// \brief Retrieves predefined highest capacity memspace.
55+
/// \return highest capacity memspace handle on success or NULL on failure.
56+
///
57+
umf_memspace_handle_t umfMemspaceHighestCapacityGet(void);
58+
5359
#ifdef __cplusplus
5460
}
5561
#endif

src/CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ set(UMF_SOURCES
6060
memspace.c
6161
provider/provider_tracking.c
6262
critnib/critnib.c
63-
pool/pool_proxy.c)
63+
pool/pool_proxy.c
64+
topology.c)
6465

6566
set(UMF_SOURCES_LINUX libumf_linux.c)
6667

@@ -77,7 +78,8 @@ set(UMF_SOURCES_LINUX
7778
provider/provider_os_memory_linux.c
7879
memory_targets/memory_target_numa.c
7980
memspaces/memspace_numa.c
80-
memspaces/memspace_host_all.c)
81+
memspaces/memspace_host_all.c
82+
memspaces/memspace_highest_capacity.c)
8183

8284
set(UMF_SOURCES_WINDOWS ${UMF_SOURCES_WINDOWS} provider/provider_os_memory.c
8385
provider/provider_os_memory_windows.c)

src/libumf.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ UMF_1.0 {
2222
umfMemoryProviderPurgeLazy;
2323
umfMemspaceCreateFromNumaArray;
2424
umfMemspaceDestroy;
25+
umfMemspaceHighestCapacityGet;
2526
umfMemspaceHostAllGet;
2627
umfOsMemoryProviderOps;
2728
umfPoolAlignedMalloc;

src/libumf_linux.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010
#include <stddef.h>
1111

1212
#include "base_alloc_global.h"
13-
#include "memspace_host_all_internal.h"
13+
#include "memspace_internal.h"
1414
#include "provider_tracking.h"
15+
#include "topology.h"
1516
#include "utils_log.h"
1617

1718
umf_memory_tracker_handle_t TRACKER = NULL;
@@ -27,6 +28,8 @@ void __attribute__((destructor)) umfDestroy(void) {
2728
TRACKER = NULL;
2829
umfMemoryTrackerDestroy(t);
2930
umfMemspaceHostAllDestroy();
31+
umfMemspaceHighestCapacityDestroy();
32+
umfDestroyTopology();
3033
}
3134

3235
void libumfInit(void) {

src/memory_target.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright (C) 2023 Intel Corporation
3+
* Copyright (C) 2023-2024 Intel Corporation
44
*
55
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
66
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -53,3 +53,34 @@ void umfMemoryTargetDestroy(umf_memory_target_handle_t memoryTarget) {
5353
memoryTarget->ops->finalize(memoryTarget->priv);
5454
umf_ba_global_free(memoryTarget);
5555
}
56+
57+
umf_result_t umfMemoryTargetClone(umf_memory_target_handle_t memoryTarget,
58+
umf_memory_target_handle_t *outHandle) {
59+
assert(memoryTarget);
60+
assert(outHandle);
61+
62+
*outHandle =
63+
(umf_memory_target_t *)umf_ba_global_alloc(sizeof(umf_memory_target_t));
64+
if (!*outHandle) {
65+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
66+
}
67+
68+
void *outPriv;
69+
umf_result_t ret = memoryTarget->ops->clone(memoryTarget->priv, &outPriv);
70+
if (ret != UMF_RESULT_SUCCESS) {
71+
umf_ba_global_free(*outHandle);
72+
return ret;
73+
}
74+
75+
(*outHandle)->ops = memoryTarget->ops;
76+
(*outHandle)->priv = outPriv;
77+
78+
return UMF_RESULT_SUCCESS;
79+
}
80+
81+
umf_result_t umfMemoryTargetGetCapacity(umf_memory_target_handle_t memoryTarget,
82+
size_t *capacity) {
83+
assert(memoryTarget);
84+
assert(capacity);
85+
return memoryTarget->ops->get_capacity(memoryTarget->priv, capacity);
86+
}

src/memory_target.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright (C) 2023 Intel Corporation
3+
* Copyright (C) 2023-2024 Intel Corporation
44
*
55
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
66
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -31,9 +31,13 @@ typedef umf_memory_target_t *umf_memory_target_handle_t;
3131
umf_result_t umfMemoryTargetCreate(const umf_memory_target_ops_t *ops,
3232
void *params,
3333
umf_memory_target_handle_t *memoryTarget);
34-
3534
void umfMemoryTargetDestroy(umf_memory_target_handle_t memoryTarget);
3635

36+
umf_result_t umfMemoryTargetClone(umf_memory_target_handle_t memoryTarget,
37+
umf_memory_target_handle_t *outHandle);
38+
umf_result_t umfMemoryTargetGetCapacity(umf_memory_target_handle_t memoryTarget,
39+
size_t *capacity);
40+
3741
#ifdef __cplusplus
3842
}
3943
#endif

src/memory_target_ops.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ typedef struct umf_memory_target_ops_t {
2929
umf_result_t (*initialize)(void *params, void **memoryTarget);
3030
void (*finalize)(void *memoryTarget);
3131

32+
umf_result_t (*clone)(void *memoryTarget, void **outMemoryTarget);
33+
3234
umf_result_t (*pool_create_from_memspace)(
3335
umf_memspace_handle_t memspace, void **memoryTargets, size_t numTargets,
3436
umf_memspace_policy_handle_t policy, umf_memory_pool_handle_t *pool);
@@ -37,6 +39,8 @@ typedef struct umf_memory_target_ops_t {
3739
umf_memspace_handle_t memspace, void **memoryTargets, size_t numTargets,
3840
umf_memspace_policy_handle_t policy,
3941
umf_memory_provider_handle_t *provider);
42+
43+
umf_result_t (*get_capacity)(void *memoryTarget, size_t *capacity);
4044
} umf_memory_target_ops_t;
4145

4246
#ifdef __cplusplus

src/memory_targets/memory_target_numa.c

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright (C) 2023 Intel Corporation
3+
* Copyright (C) 2023-2024 Intel Corporation
44
*
55
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
66
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -18,6 +18,7 @@
1818
#include "base_alloc.h"
1919
#include "base_alloc_global.h"
2020
#include "memory_target_numa.h"
21+
#include "topology.h"
2122

2223
struct numa_memory_target_t {
2324
size_t id;
@@ -150,10 +151,47 @@ static umf_result_t numa_pool_create_from_memspace(
150151
return UMF_RESULT_ERROR_NOT_SUPPORTED;
151152
}
152153

154+
static umf_result_t numa_clone(void *memTarget, void **outMemTarget) {
155+
struct numa_memory_target_t *numaTarget =
156+
(struct numa_memory_target_t *)memTarget;
157+
struct numa_memory_target_t *newNumaTarget =
158+
umf_ba_global_alloc(sizeof(struct numa_memory_target_t));
159+
if (!newNumaTarget) {
160+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
161+
}
162+
163+
newNumaTarget->id = numaTarget->id;
164+
*outMemTarget = newNumaTarget;
165+
return UMF_RESULT_SUCCESS;
166+
}
167+
168+
static umf_result_t numa_get_capacity(void *memTarget, size_t *capacity) {
169+
hwloc_topology_t topology = umfGetTopology();
170+
if (!topology) {
171+
return UMF_RESULT_ERROR_NOT_SUPPORTED;
172+
}
173+
174+
hwloc_obj_t numaNode =
175+
hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE,
176+
((struct numa_memory_target_t *)memTarget)->id);
177+
if (!numaNode) {
178+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
179+
}
180+
181+
if (!numaNode->attr) {
182+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
183+
}
184+
185+
*capacity = numaNode->attr->numanode.local_memory;
186+
return UMF_RESULT_SUCCESS;
187+
}
188+
153189
struct umf_memory_target_ops_t UMF_MEMORY_TARGET_NUMA_OPS = {
154190
.version = UMF_VERSION_CURRENT,
155191
.initialize = numa_initialize,
156192
.finalize = numa_finalize,
157193
.pool_create_from_memspace = numa_pool_create_from_memspace,
194+
.clone = numa_clone,
195+
.get_capacity = numa_get_capacity,
158196
.memory_provider_create_from_memspace =
159197
numa_memory_provider_create_from_memspace};

src/memspace.c

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright (C) 2023 Intel Corporation
3+
* Copyright (C) 2023-2024 Intel Corporation
44
*
55
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
66
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -109,3 +109,102 @@ void umfMemspaceDestroy(umf_memspace_handle_t memspace) {
109109
umf_ba_global_free(memspace->nodes);
110110
umf_ba_global_free(memspace);
111111
}
112+
113+
enum umf_result_t umfMemspaceClone(umf_memspace_handle_t hMemspace,
114+
umf_memspace_handle_t *outHandle) {
115+
if (!hMemspace || !outHandle) {
116+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
117+
}
118+
119+
umf_memspace_handle_t clone =
120+
umf_ba_global_alloc(sizeof(struct umf_memspace_t));
121+
if (!clone) {
122+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
123+
}
124+
125+
clone->size = hMemspace->size;
126+
clone->nodes =
127+
umf_ba_global_alloc(sizeof(umf_memory_target_handle_t) * clone->size);
128+
if (!clone->nodes) {
129+
umf_ba_global_free(clone);
130+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
131+
}
132+
133+
size_t i;
134+
umf_result_t ret;
135+
136+
for (i = 0; i < clone->size; i++) {
137+
ret = umfMemoryTargetClone(hMemspace->nodes[i], &clone->nodes[i]);
138+
if (ret != UMF_RESULT_SUCCESS) {
139+
goto err;
140+
}
141+
}
142+
143+
*outHandle = clone;
144+
145+
return UMF_RESULT_SUCCESS;
146+
err:
147+
while (i != 0) {
148+
i--;
149+
umfMemoryTargetDestroy(clone->nodes[i]);
150+
}
151+
umf_ba_global_free(clone->nodes);
152+
umf_ba_global_free(clone);
153+
return ret;
154+
}
155+
156+
struct memory_target_sort_entry {
157+
uint64_t property;
158+
umf_memory_target_handle_t node;
159+
};
160+
161+
static int propertyCmp(const void *a, const void *b) {
162+
const struct memory_target_sort_entry *entryA = a;
163+
const struct memory_target_sort_entry *entryB = b;
164+
165+
if (entryA->property < entryB->property) {
166+
return 1;
167+
} else if (entryA->property > entryB->property) {
168+
return -1;
169+
} else {
170+
return 0;
171+
}
172+
}
173+
174+
enum umf_result_t
175+
umfMemspaceSortDesc(umf_memspace_handle_t hMemspace,
176+
umf_result_t (*getProperty)(umf_memory_target_handle_t node,
177+
uint64_t *property)) {
178+
if (!hMemspace || !getProperty) {
179+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
180+
}
181+
182+
struct memory_target_sort_entry *entries = umf_ba_global_alloc(
183+
sizeof(struct memory_target_sort_entry) * hMemspace->size);
184+
if (!entries) {
185+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
186+
}
187+
188+
// create temporary array that contains desired property values for sorting
189+
for (size_t i = 0; i < hMemspace->size; i++) {
190+
entries[i].node = hMemspace->nodes[i];
191+
umf_result_t ret =
192+
getProperty(hMemspace->nodes[i], &entries[i].property);
193+
if (ret != UMF_RESULT_SUCCESS) {
194+
umf_ba_global_free(entries);
195+
return ret;
196+
}
197+
}
198+
199+
qsort(entries, hMemspace->size, sizeof(struct memory_target_sort_entry),
200+
propertyCmp);
201+
202+
// apply the order to the original array
203+
for (size_t i = 0; i < hMemspace->size; i++) {
204+
hMemspace->nodes[i] = entries[i].node;
205+
}
206+
207+
umf_ba_global_free(entries);
208+
209+
return UMF_RESULT_SUCCESS;
210+
}

src/memspace_internal.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright (C) 2023 Intel Corporation
3+
* Copyright (C) 2023-2024 Intel Corporation
44
*
55
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
66
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -24,12 +24,30 @@ struct umf_memspace_t {
2424
umf_memory_target_handle_t *nodes;
2525
};
2626

27+
///
28+
/// \brief Clones memspace
29+
///
30+
enum umf_result_t umfMemspaceClone(umf_memspace_handle_t hMemspace,
31+
umf_memspace_handle_t *outHandle);
32+
33+
typedef umf_result_t (*umfGetPropertyFn)(umf_memory_target_handle_t,
34+
uint64_t *);
35+
36+
///
37+
/// \brief Sorts memspace by getProperty() in descending order
38+
///
39+
enum umf_result_t umfMemspaceSortDesc(umf_memspace_handle_t hMemspace,
40+
umfGetPropertyFn getProperty);
41+
2742
///
2843
/// \brief Destroys memspace
2944
/// \param hMemspace handle to memspace
3045
///
3146
void umfMemspaceDestroy(umf_memspace_handle_t hMemspace);
3247

48+
void umfMemspaceHostAllDestroy(void);
49+
void umfMemspaceHighestCapacityDestroy(void);
50+
3351
#ifdef __cplusplus
3452
}
3553
#endif

0 commit comments

Comments
 (0)