Skip to content

Commit 00bc05b

Browse files
committed
add mempolicy for split mode
Signed-off-by: Łukasz Plewa <[email protected]>
1 parent 33a82d0 commit 00bc05b

File tree

8 files changed

+143
-8
lines changed

8 files changed

+143
-8
lines changed

include/umf/mempolicy.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,22 @@ typedef enum umf_mempolicy_membind_t {
2525
/// Bind memory to namespace
2626
UMF_MEMPOLICY_BIND,
2727
/// Prefer memory from namespace but fallback to other memory if not available
28-
UMF_MEMPOLICY_PREFERRED
28+
UMF_MEMPOLICY_PREFERRED,
29+
/// Allocation will be split evenly across nodes specified in nodemask.
30+
/// umf_mempolicy_split_partition_t can be used to specify different distribution
31+
/// to specify other distribution.
32+
UMF_MEMPOLICY_SPLIT
2933
} umf_mempolicy_membind_t;
3034

35+
/// user defined partition for UMF_MEMPOLICY_SPLIT mode
36+
typedef struct umf_mempolicy_split_partition_t {
37+
/// The weight of the partition, representing the proportion of
38+
/// the allocation that should be assigned to this NUMA node.
39+
unsigned weight;
40+
/// The NUMA node where the pages assigned to this partition will be bound.
41+
unsigned target;
42+
} umf_mempolicy_split_partition_t;
43+
3144
///
3245
/// @brief Creates a new memory policy
3346
/// @param bind memory binding policy
@@ -52,6 +65,18 @@ umf_result_t umfMempolicyDestroy(umf_mempolicy_handle_t hPolicy);
5265
///
5366
umf_result_t umfMempolicySetInterleavePartSize(umf_mempolicy_handle_t hPolicy,
5467
size_t partSize);
68+
69+
///
70+
/// @brief Sets custom split partitions
71+
/// @param hPolicy handle to memory policy
72+
/// @param partList ordered array of partitions
73+
/// @param partListLen length of the partList array
74+
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
75+
///
76+
umf_result_t
77+
umfMempolicySetCustomSplitPartitions(umf_mempolicy_handle_t hPolicy,
78+
umf_mempolicy_split_partition_t *partList,
79+
size_t partListLen);
5580
#ifdef __cplusplus
5681
}
5782
#endif

src/libumf.def.in

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,10 @@ EXPORTS
3636
umfMemoryProviderPurgeForce
3737
umfMemoryProviderPurgeLazy
3838
umfMemoryProviderPutIPCHandle
39-
umfMempolicyCreate;
40-
umfMempolicyDestroy;
41-
umfMempolicySetInterleavePartSize;
39+
umfMempolicyCreate
40+
umfMempolicyDestroy
41+
umfMempolicySetCustomSplitPartitions
42+
umfMempolicySetInterleavePartSize
4243
umfMemspaceDestroy
4344
umfOpenIPCHandle
4445
umfOsMemoryProviderOps

src/libumf.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ UMF_1.0 {
3333
umfMemoryProviderPutIPCHandle;
3434
umfMempolicyCreate;
3535
umfMempolicyDestroy;
36+
umfMempolicySetCustomSplitPartitions;
3637
umfMempolicySetInterleavePartSize;
3738
umfMemspaceCreateFromNumaArray;
3839
umfMemspaceDestroy;

src/memory_targets/memory_target_numa.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "memory_target_numa.h"
2121
#include "mempolicy_internal.h"
2222
#include "topology.h"
23+
#include "utils_assert.h"
2324
#include "utils_log.h"
2425

2526
struct numa_memory_target_t {
@@ -75,14 +76,33 @@ static umf_result_t numa_memory_provider_create_from_memspace(
7576
switch (policy->type) {
7677
case UMF_MEMPOLICY_INTERLEAVE:
7778
params.numa_mode = UMF_NUMA_MODE_INTERLEAVE;
78-
params.part_size = policy->ops.part_size;
79+
params.part_size = policy->ops.interleave.part_size;
7980
break;
8081
case UMF_MEMPOLICY_BIND:
8182
params.numa_mode = UMF_NUMA_MODE_BIND;
8283
break;
8384
case UMF_MEMPOLICY_PREFERRED:
8485
params.numa_mode = UMF_NUMA_MODE_PREFERRED;
8586
break;
87+
case UMF_MEMPOLICY_SPLIT:
88+
params.numa_mode = UMF_NUMA_MODE_SPLIT;
89+
90+
// compile time check to ensure we can just cast
91+
// umf_mempolicy_split_partition_t to
92+
// umf_numa_split_partition_t
93+
COMPILE_ERROR_ON(sizeof(umf_mempolicy_split_partition_t) !=
94+
sizeof(umf_numa_split_partition_t));
95+
COMPILE_ERROR_ON(
96+
offsetof(umf_mempolicy_split_partition_t, weight) !=
97+
offsetof(umf_numa_split_partition_t, weight));
98+
COMPILE_ERROR_ON(
99+
offsetof(umf_mempolicy_split_partition_t, target) !=
100+
offsetof(umf_numa_split_partition_t, target));
101+
102+
params.partitions =
103+
(umf_numa_split_partition_t *)policy->ops.split.part;
104+
params.partitions_len = policy->ops.split.part_len;
105+
break;
86106
default:
87107
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
88108
}

src/mempolicy.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ umf_result_t umfMempolicyCreate(umf_mempolicy_membind_t bind,
2525

2626
(*policy)->type = bind;
2727
if (bind == UMF_MEMPOLICY_INTERLEAVE) {
28-
(*policy)->ops.part_size = 0;
28+
(*policy)->ops.interleave.part_size = 0;
29+
} else if (bind == UMF_MEMPOLICY_SPLIT) {
30+
(*policy)->ops.split.part_len = 0;
2931
}
32+
3033
return UMF_RESULT_SUCCESS;
3134
}
3235

@@ -45,6 +48,22 @@ umf_result_t umfMempolicySetInterleavePartSize(umf_mempolicy_handle_t policy,
4548
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
4649
}
4750

48-
policy->ops.part_size = partSize;
51+
policy->ops.interleave.part_size = partSize;
52+
return UMF_RESULT_SUCCESS;
53+
}
54+
55+
umf_result_t
56+
umfMempolicySetCustomSplitPartitions(umf_mempolicy_handle_t policy,
57+
umf_mempolicy_split_partition_t *partList,
58+
size_t partListLen) {
59+
if (policy == NULL) {
60+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
61+
}
62+
if (policy->type != UMF_MEMPOLICY_SPLIT) {
63+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
64+
}
65+
66+
policy->ops.split.part = partList;
67+
policy->ops.split.part_len = partListLen;
4968
return UMF_RESULT_SUCCESS;
5069
}

src/mempolicy_internal.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@ extern "C" {
1919
typedef struct umf_mempolicy_t {
2020
umf_mempolicy_membind_t type;
2121
union {
22-
size_t part_size;
22+
struct {
23+
size_t part_size;
24+
} interleave;
25+
struct {
26+
umf_mempolicy_split_partition_t *part;
27+
size_t part_len;
28+
} split;
2329
} ops;
2430
} umf_mempolicy_t;
2531

src/utils/utils_assert.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ extern "C" {
5656
} \
5757
} while (0)
5858

59+
#define COMPILE_ERROR_ON(cond) ((void)sizeof(char[(cond) ? -1 : 1]))
60+
5961
#ifdef __cplusplus
6062
}
6163
#endif

test/memspaces/mempolicy.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ TEST_F(test, mempolicyDefaultPreferred) {
3636
ASSERT_NE(ProviderInternal, nullptr);
3737
EXPECT_EQ(ProviderInternal->numa_policy, HWLOC_MEMBIND_BIND);
3838
EXPECT_EQ(ProviderInternal->numa_flags, HWLOC_MEMBIND_BYNODESET);
39+
EXPECT_EQ(ProviderInternal->mode, UMF_NUMA_MODE_PREFERRED);
3940
umfMemoryProviderDestroy(hProvider);
4041
}
4142

@@ -59,6 +60,7 @@ TEST_F(test, mempolicyDefaultBind) {
5960
EXPECT_EQ(ProviderInternal->numa_policy, HWLOC_MEMBIND_BIND);
6061
EXPECT_EQ(ProviderInternal->numa_flags,
6162
HWLOC_MEMBIND_BYNODESET | HWLOC_MEMBIND_STRICT);
63+
EXPECT_EQ(ProviderInternal->mode, UMF_NUMA_MODE_BIND);
6264
umfMemoryProviderDestroy(hProvider);
6365
}
6466

@@ -82,6 +84,7 @@ TEST_F(test, mempolicyDefaultInterleave) {
8284
EXPECT_EQ(ProviderInternal->numa_policy, HWLOC_MEMBIND_INTERLEAVE);
8385
EXPECT_EQ(ProviderInternal->numa_flags, HWLOC_MEMBIND_BYNODESET);
8486
EXPECT_EQ(ProviderInternal->part_size, 0);
87+
EXPECT_EQ(ProviderInternal->mode, UMF_NUMA_MODE_INTERLEAVE);
8588
umfMemoryProviderDestroy(hProvider);
8689
}
8790

@@ -109,5 +112,63 @@ TEST_F(test, mempolicyInterleavePartSize) {
109112
EXPECT_EQ(ProviderInternal->numa_flags,
110113
HWLOC_MEMBIND_BYNODESET | HWLOC_MEMBIND_STRICT);
111114
EXPECT_EQ(ProviderInternal->part_size, part_size);
115+
EXPECT_EQ(ProviderInternal->mode, UMF_NUMA_MODE_INTERLEAVE);
116+
umfMemoryProviderDestroy(hProvider);
117+
}
118+
119+
TEST_F(test, mempolicyDefaultSplit) {
120+
umf_memory_provider_handle_t hProvider = nullptr;
121+
umf_mempolicy_handle_t hPolicy = nullptr;
122+
123+
umf_result_t ret = umfMempolicyCreate(UMF_MEMPOLICY_SPLIT, &hPolicy);
124+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
125+
126+
ret = umfMemoryProviderCreateFromMemspace(umfMemspaceHostAllGet(), hPolicy,
127+
&hProvider);
128+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
129+
ASSERT_NE(hProvider, nullptr);
130+
ret = umfMempolicyDestroy(hPolicy);
131+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
132+
133+
os_memory_provider_t *ProviderInternal =
134+
(os_memory_provider_t *)providerGetPriv(hProvider);
135+
ASSERT_NE(ProviderInternal, nullptr);
136+
EXPECT_EQ(ProviderInternal->numa_policy, HWLOC_MEMBIND_BIND);
137+
EXPECT_EQ(ProviderInternal->numa_flags,
138+
HWLOC_MEMBIND_BYNODESET | HWLOC_MEMBIND_STRICT);
139+
EXPECT_EQ(ProviderInternal->partitions_len, ProviderInternal->nodeset_len);
140+
EXPECT_EQ(ProviderInternal->mode, UMF_NUMA_MODE_SPLIT);
141+
umfMemoryProviderDestroy(hProvider);
142+
}
143+
144+
TEST_F(test, mempolicyCustomSplit) {
145+
umf_memory_provider_handle_t hProvider = nullptr;
146+
umf_mempolicy_handle_t hPolicy = nullptr;
147+
148+
umf_result_t ret = umfMempolicyCreate(UMF_MEMPOLICY_SPLIT, &hPolicy);
149+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
150+
umf_mempolicy_split_partition_t part[] = {{1, 0}, {1, 0}};
151+
152+
ret = umfMempolicySetCustomSplitPartitions(hPolicy, part, 2);
153+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
154+
155+
ret = umfMemoryProviderCreateFromMemspace(umfMemspaceHostAllGet(), hPolicy,
156+
&hProvider);
157+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
158+
ASSERT_NE(hProvider, nullptr);
159+
ret = umfMempolicyDestroy(hPolicy);
160+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
161+
162+
os_memory_provider_t *ProviderInternal =
163+
(os_memory_provider_t *)providerGetPriv(hProvider);
164+
ASSERT_NE(ProviderInternal, nullptr);
165+
EXPECT_EQ(ProviderInternal->numa_policy, HWLOC_MEMBIND_BIND);
166+
EXPECT_EQ(ProviderInternal->numa_flags,
167+
HWLOC_MEMBIND_BYNODESET | HWLOC_MEMBIND_STRICT);
168+
EXPECT_EQ(ProviderInternal->partitions_len, 2);
169+
EXPECT_EQ(ProviderInternal->mode, UMF_NUMA_MODE_SPLIT);
170+
EXPECT_EQ(ProviderInternal->partitions_weight_sum, 2);
171+
EXPECT_EQ(ProviderInternal->partitions[0].target,
172+
ProviderInternal->partitions[1].target);
112173
umfMemoryProviderDestroy(hProvider);
113174
}

0 commit comments

Comments
 (0)