Skip to content

Commit 9a4675b

Browse files
Merge pull request #390 from igchor/memspace_highest_capacity_alloc
Fix highest capacity memspace with OS provider integration.
2 parents 837f205 + 8fb3275 commit 9a4675b

File tree

8 files changed

+74
-36
lines changed

8 files changed

+74
-36
lines changed

.github/workflows/qemu.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ jobs:
7373
-machine q35,usb=off,hmat=on \
7474
-enable-kvm \
7575
-net nic -net user,hostfwd=tcp::2222-:22 \
76-
-m 3G \
76+
-m 3500M \
7777
-smp 4 \
78-
-object memory-backend-ram,size=1G,id=ram0 \
79-
-object memory-backend-ram,size=1G,id=ram1 \
80-
-object memory-backend-ram,size=1G,id=ram2 \
78+
-object memory-backend-ram,size=1100M,id=ram0 \
79+
-object memory-backend-ram,size=1200M,id=ram1 \
80+
-object memory-backend-ram,size=1200M,id=ram2 \
8181
-numa node,nodeid=0,memdev=ram0,cpus=0-1 \
8282
-numa node,nodeid=1,memdev=ram1,cpus=2-3 \
8383
-numa node,nodeid=2,memdev=ram2,initiator=0 \

scripts/qemu/run-build.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,6 @@ make -j $(nproc)
3636

3737
ctest --output-on-failure
3838

39+
# run tests bound to a numa node
40+
numactl -N 0 ctest --output-on-failure
41+
numactl -N 1 ctest --output-on-failure

src/memory_targets/memory_target_numa.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#include "topology.h"
2222

2323
struct numa_memory_target_t {
24-
size_t id;
24+
size_t physical_id;
2525
};
2626

2727
static umf_result_t numa_initialize(void *params, void **memTarget) {
@@ -38,7 +38,7 @@ static umf_result_t numa_initialize(void *params, void **memTarget) {
3838
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
3939
}
4040

41-
numaTarget->id = config->id;
41+
numaTarget->physical_id = config->physical_id;
4242
*memTarget = numaTarget;
4343
return UMF_RESULT_SUCCESS;
4444
}
@@ -60,7 +60,7 @@ numa_targets_create_nodemask(struct numa_memory_target_t **targets,
6060
}
6161

6262
for (size_t i = 0; i < numTargets; i++) {
63-
if (hwloc_bitmap_set(bitmap, targets[i]->id)) {
63+
if (hwloc_bitmap_set(bitmap, targets[i]->physical_id)) {
6464
hwloc_bitmap_free(bitmap);
6565
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
6666
}
@@ -106,6 +106,7 @@ static enum umf_result_t numa_memory_provider_create_from_memspace(
106106
umf_memspace_policy_handle_t policy,
107107
umf_memory_provider_handle_t *provider) {
108108
(void)memspace;
109+
(void)numTargets;
109110
// TODO: apply policy
110111
(void)policy;
111112

@@ -115,9 +116,18 @@ static enum umf_result_t numa_memory_provider_create_from_memspace(
115116
unsigned long *nodemask;
116117
unsigned maxnode;
117118
size_t nodemask_size;
119+
size_t numNodesProvider;
120+
121+
if (memspace == umfMemspaceHighestCapacityGet()) {
122+
// Pass only a single node to provider for now.
123+
// TODO: change this once we implement memspace policies
124+
numNodesProvider = 1;
125+
} else {
126+
numNodesProvider = numTargets;
127+
}
118128

119129
umf_result_t ret = numa_targets_create_nodemask(
120-
numaTargets, numTargets, &nodemask, &maxnode, &nodemask_size);
130+
numaTargets, numNodesProvider, &nodemask, &maxnode, &nodemask_size);
121131
if (ret != UMF_RESULT_SUCCESS) {
122132
return ret;
123133
}
@@ -160,7 +170,7 @@ static umf_result_t numa_clone(void *memTarget, void **outMemTarget) {
160170
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
161171
}
162172

163-
newNumaTarget->id = numaTarget->id;
173+
newNumaTarget->physical_id = numaTarget->physical_id;
164174
*outMemTarget = newNumaTarget;
165175
return UMF_RESULT_SUCCESS;
166176
}
@@ -171,9 +181,8 @@ static umf_result_t numa_get_capacity(void *memTarget, size_t *capacity) {
171181
return UMF_RESULT_ERROR_NOT_SUPPORTED;
172182
}
173183

174-
hwloc_obj_t numaNode =
175-
hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE,
176-
((struct numa_memory_target_t *)memTarget)->id);
184+
hwloc_obj_t numaNode = hwloc_get_numanode_obj_by_os_index(
185+
topology, ((struct numa_memory_target_t *)memTarget)->physical_id);
177186
if (!numaNode) {
178187
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
179188
}

src/memory_targets/memory_target_numa.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ extern "C" {
2121
#endif
2222

2323
struct umf_numa_memory_target_config_t {
24-
size_t id;
24+
size_t physical_id;
2525
};
2626

2727
extern struct umf_memory_target_ops_t UMF_MEMORY_TARGET_NUMA_OPS;

test/common/numa_helpers.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
#ifndef UMF_NUMA_HELPERS_H
6+
#define UMF_NUMA_HELPERS_H 1
7+
8+
#include <numa.h>
9+
#include <numaif.h>
10+
#include <stdint.h>
11+
#include <stdio.h>
12+
13+
#include "test_helpers.h"
14+
15+
#ifdef __cplusplus
16+
extern "C" {
17+
#endif
18+
19+
// returns the node where page starting at 'ptr' resides
20+
int getNumaNodeByPtr(void *ptr) {
21+
int nodeId;
22+
int retm =
23+
get_mempolicy(&nodeId, nullptr, 0, ptr, MPOL_F_ADDR | MPOL_F_NODE);
24+
UT_ASSERTeq(retm, 0);
25+
return nodeId;
26+
}
27+
28+
#ifdef __cplusplus
29+
}
30+
#endif
31+
32+
#endif /* UMF_NUMA_HELPERS_H */

test/memspaces/memspace_highest_capacity.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "memory_target_numa.h"
66
#include "memspace_helpers.hpp"
77
#include "memspace_internal.h"
8+
#include "numa_helpers.h"
89
#include "test_helpers.h"
910

1011
#include <numa.h>
@@ -39,28 +40,29 @@ TEST_F(memspaceHighestCapacityProviderTest, highestCapacityVerify) {
3940
static constexpr size_t alloc_size = 1024;
4041

4142
long long maxCapacity = 0;
42-
int maxCapacityNode = -1;
43+
std::vector<int> maxCapacityNodes{};
4344
for (auto nodeId : nodeIds) {
4445
if (numa_node_size64(nodeId, nullptr) > maxCapacity) {
45-
maxCapacityNode = nodeId;
4646
maxCapacity = numa_node_size64(nodeId, nullptr);
4747
}
4848
}
4949

50+
for (auto nodeId : nodeIds) {
51+
if (numa_node_size64(nodeId, nullptr) == maxCapacity) {
52+
maxCapacityNodes.push_back(nodeId);
53+
}
54+
}
55+
5056
// Confirm that the HighestCapacity memspace indeed has highest capacity
5157
void *ptr;
5258
auto ret = umfMemoryProviderAlloc(hProvider, alloc_size, 0, &ptr);
59+
memset(ptr, 0, alloc_size);
5360
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
5461

55-
struct bitmask *nodemask = numa_allocate_nodemask();
56-
UT_ASSERTne(nodemask, nullptr);
57-
int retm = get_mempolicy(nullptr, nodemask->maskp, nodemask->size, ptr,
58-
MPOL_F_ADDR);
59-
UT_ASSERTeq(retm, 0);
60-
UT_ASSERT(numa_bitmask_isbitset(nodemask, maxCapacityNode));
62+
auto nodeId = getNumaNodeByPtr(ptr);
63+
ASSERT_TRUE(std::any_of(maxCapacityNodes.begin(), maxCapacityNodes.end(),
64+
[nodeId](int node) { return nodeId == node; }));
6165

6266
ret = umfMemoryProviderFree(hProvider, ptr, alloc_size);
6367
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
64-
65-
numa_bitmask_free(nodemask);
6668
}

test/memspaces/memspace_host_all.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "memory_target_numa.h"
66
#include "memspace_helpers.hpp"
77
#include "memspace_internal.h"
8+
#include "numa_helpers.h"
89
#include "test_helpers.h"
910
#include "utils_sanitizers.h"
1011

@@ -27,7 +28,7 @@ TEST_F(numaNodesTest, memspaceGet) {
2728
struct umf_numa_memory_target_config_t *numaTargetCfg =
2829
(struct umf_numa_memory_target_config_t *)hMemspace->nodes[i]->priv;
2930
UT_ASSERT(std::find(nodeIds.begin(), nodeIds.end(),
30-
numaTargetCfg->id) != nodeIds.end());
31+
numaTargetCfg->physical_id) != nodeIds.end());
3132
}
3233
}
3334

@@ -91,9 +92,7 @@ static void getAllocationPolicy(void *ptr, unsigned long maxNodeId, int &mode,
9192
}
9293

9394
// Get the node that allocated the memory at 'ptr'.
94-
int nodeId = -1;
95-
ret = get_mempolicy(&nodeId, nullptr, 0, ptr, MPOL_F_ADDR | MPOL_F_NODE);
96-
UT_ASSERTeq(ret, 0);
95+
int nodeId = getNumaNodeByPtr(ptr);
9796
allocNodeId = static_cast<size_t>(nodeId);
9897
}
9998

test/provider_os_memory_multiple_numa_nodes.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44

55
#include "base.hpp"
6+
#include "numa_helpers.h"
67

78
#include <numa.h>
89
#include <numaif.h>
@@ -52,14 +53,6 @@ struct testNumaNodes : public testing::TestWithParam<int> {
5253
ASSERT_NE(os_memory_provider, nullptr);
5354
}
5455

55-
int retrieve_numa_node_number(void *addr) {
56-
int numa_node;
57-
int ret = get_mempolicy(&numa_node, nullptr, 0, addr,
58-
MPOL_F_NODE | MPOL_F_ADDR);
59-
EXPECT_EQ(ret, 0);
60-
return numa_node;
61-
}
62-
6356
void TearDown() override {
6457
umf_result_t umf_result;
6558
if (ptr) {
@@ -108,6 +101,6 @@ TEST_P(testNumaNodes, checkNumaNodesAllocations) {
108101
// This pointer must point to an initialized value before retrieving a number of
109102
// the numa node that the pointer was allocated on (calling get_mempolicy).
110103
memset(ptr, 0xFF, alloc_size);
111-
int retrieved_numa_node_number = retrieve_numa_node_number(ptr);
104+
int retrieved_numa_node_number = getNumaNodeByPtr(ptr);
112105
ASSERT_EQ(retrieved_numa_node_number, numa_node_number);
113106
}

0 commit comments

Comments
 (0)