Skip to content

Commit b94c444

Browse files
committed
Expand DEFAULT memspace tests
Those tests confirm that the DEFAULT memspace is composed of memory targets that correspond to all available NUMA node ids. They also affirm that the memory obtained from DEFAULT memspace follows UMF_NUMA_MODE_BIND policy and is made available to all discovered NUMA nodes.
1 parent 2774a9e commit b94c444

File tree

4 files changed

+190
-119
lines changed

4 files changed

+190
-119
lines changed

test/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ if(UMF_BUILD_OS_MEMORY_PROVIDER AND LINUX) # OS-specific functions are implement
123123
SRCS provider_os_memory_config.cpp
124124
LIBS umf_utils numa)
125125
add_umf_test(NAME memspace_default
126-
SRCS memspaces/memspace_default.cpp)
126+
SRCS memspaces/memspace_default.cpp
127+
LIBS numa)
127128
endif()
128129

129130
if(UMF_BUILD_SHARED_LIBRARY)

test/memspaces/memspace_default.cpp

Lines changed: 63 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,64 +2,90 @@
22
// Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
33
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44

5-
#include "base.hpp"
5+
#include "memory_target_numa.h"
6+
#include "memspace_helpers.hpp"
7+
#include "memspace_internal.h"
68
#include "test_helpers.h"
79

10+
#include <numa.h>
11+
#include <numaif.h>
812
#include <umf/memspace.h>
913

1014
using umf_test::test;
1115

12-
#define SIZE_4K (4096)
13-
14-
struct predefinedMemspaceTest : test {
15-
16-
void SetUp() override {
17-
::test::SetUp();
18-
19-
hMemspace = umfMemspaceDefaultGet();
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();
16+
TEST_F(numaNodesTest, memspaceGet) {
17+
umf_memspace_handle_t hMemspace = umfMemspaceDefaultGet();
18+
UT_ASSERTne(hMemspace, nullptr);
3919

40-
umfMemoryProviderDestroy(provider);
20+
// Confirm that the DEFAULT memspace is composed of all available NUMA nodes.
21+
UT_ASSERTeq(hMemspace->size, nodeIds.size());
22+
for (size_t i = 0; i < hMemspace->size; i++) {
23+
// NUMA memory target internally casts the config directly into priv.
24+
struct umf_numa_memory_target_config_t *numaTargetCfg =
25+
(struct umf_numa_memory_target_config_t *)hMemspace->nodes[i]->priv;
26+
UT_ASSERT(std::find(nodeIds.begin(), nodeIds.end(),
27+
numaTargetCfg->id) != nodeIds.end());
4128
}
29+
}
4230

43-
umf_memory_provider_handle_t provider = nullptr;
44-
};
31+
TEST_F(memspaceDefaultTest, providerFromDefaultMemspace) {
32+
umf_memory_provider_handle_t hProvider = nullptr;
33+
enum umf_result_t ret =
34+
umfMemoryProviderCreateFromMemspace(hMemspace, nullptr, &hProvider);
35+
UT_ASSERTeq(ret, UMF_RESULT_SUCCESS);
36+
UT_ASSERTne(hProvider, nullptr);
4537

46-
TEST_F(test, memspaceGet) {
47-
umf_memspace_handle_t hMemspace = umfMemspaceDefaultGet();
48-
UT_ASSERTne(hMemspace, nullptr);
38+
umfMemoryProviderDestroy(hProvider);
4939
}
5040

51-
TEST_F(predefinedMemspaceProviderTest, allocFree) {
41+
TEST_F(memspaceDefaultProviderTest, allocFree) {
5242
void *ptr = nullptr;
5343
size_t size = SIZE_4K;
5444
size_t alignment = 0;
5545

5646
enum umf_result_t ret =
57-
umfMemoryProviderAlloc(provider, size, alignment, &ptr);
47+
umfMemoryProviderAlloc(hProvider, size, alignment, &ptr);
5848
UT_ASSERTeq(ret, UMF_RESULT_SUCCESS);
5949
UT_ASSERTne(ptr, nullptr);
6050

6151
memset(ptr, 0xFF, size);
6252

63-
ret = umfMemoryProviderFree(provider, ptr, size);
53+
ret = umfMemoryProviderFree(hProvider, ptr, size);
6454
UT_ASSERTeq(ret, UMF_RESULT_SUCCESS);
6555
}
56+
57+
TEST_F(memspaceDefaultProviderTest, memoryPolicy) {
58+
void *ptr = nullptr;
59+
size_t size = SIZE_4K;
60+
size_t alignment = 0;
61+
62+
enum umf_result_t umf_ret =
63+
umfMemoryProviderAlloc(hProvider, size, alignment, &ptr);
64+
UT_ASSERTeq(umf_ret, UMF_RESULT_SUCCESS);
65+
UT_ASSERTne(ptr, nullptr);
66+
67+
auto it = std::max_element(nodeIds.begin(), nodeIds.end());
68+
UT_ASSERT(it != nodeIds.end());
69+
70+
unsigned long maxNodeId = *it;
71+
72+
unsigned bitsPerUlong = sizeof(unsigned long) * 8;
73+
unsigned nrUlongs = (maxNodeId + bitsPerUlong) / bitsPerUlong;
74+
std::vector<unsigned long> memNodeMasks(nrUlongs, 0);
75+
76+
int memMode = -1;
77+
int ret = get_mempolicy(&memMode, memNodeMasks.data(),
78+
nrUlongs * bitsPerUlong, ptr, MPOL_F_ADDR);
79+
UT_ASSERTeq(ret, 0);
80+
// Obtained memory should be bound to all available NUMA nodes.
81+
UT_ASSERTeq(memMode, MPOL_BIND);
82+
for (auto &nodeId : nodeIds) {
83+
size_t memNodeMaskIdx = ((nodeId + bitsPerUlong) / bitsPerUlong) - 1;
84+
auto &memNodeMask = memNodeMasks.at(memNodeMaskIdx);
85+
86+
UT_ASSERT(memNodeMask && (1UL << (nodeId % bitsPerUlong)));
87+
}
88+
89+
umf_ret = umfMemoryProviderFree(hProvider, ptr, size);
90+
UT_ASSERTeq(umf_ret, UMF_RESULT_SUCCESS);
91+
}

test/memspaces/memspace_helpers.hpp

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
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_MEMSPACE_HELPERS_HPP
6+
#define UMF_MEMSPACE_HELPERS_HPP
7+
8+
#include "base.hpp"
9+
#include "memspace_internal.h"
10+
#include "memspaces/memspace_numa.h"
11+
12+
#include <numa.h>
13+
#include <umf/providers/provider_os_memory.h>
14+
15+
#define SIZE_4K (4096)
16+
17+
struct numaNodesTest : ::umf_test::test {
18+
void SetUp() override {
19+
::umf_test::test::SetUp();
20+
21+
if (numa_available() == -1 || numa_all_nodes_ptr == nullptr) {
22+
GTEST_SKIP() << "Failed to initialize libnuma";
23+
}
24+
25+
int maxNode = numa_max_node();
26+
if (maxNode < 0) {
27+
GTEST_SKIP() << "No available numa nodes";
28+
}
29+
30+
for (int i = 0; i <= maxNode; i++) {
31+
if (numa_bitmask_isbitset(numa_all_nodes_ptr, i) == 1) {
32+
nodeIds.emplace_back(i);
33+
}
34+
}
35+
}
36+
37+
std::vector<size_t> nodeIds;
38+
};
39+
40+
struct memspaceNumaTest : ::numaNodesTest {
41+
void SetUp() override {
42+
::numaNodesTest::SetUp();
43+
44+
if (nodeIds.size()) {
45+
enum umf_result_t ret = umfMemspaceCreateFromNumaArray(
46+
nodeIds.data(), nodeIds.size(), &hMemspace);
47+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
48+
ASSERT_NE(hMemspace, nullptr);
49+
}
50+
}
51+
52+
void TearDown() override {
53+
::numaNodesTest::TearDown();
54+
if (hMemspace) {
55+
umfMemspaceDestroy(hMemspace);
56+
}
57+
}
58+
59+
umf_memspace_handle_t hMemspace = nullptr;
60+
};
61+
62+
struct memspaceNumaProviderTest : ::memspaceNumaTest {
63+
void SetUp() override {
64+
::memspaceNumaTest::SetUp();
65+
66+
umf_result_t ret =
67+
umfMemoryProviderCreateFromMemspace(hMemspace, nullptr, &hProvider);
68+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
69+
ASSERT_NE(hProvider, nullptr);
70+
}
71+
72+
void TearDown() override {
73+
::memspaceNumaTest::TearDown();
74+
75+
umfMemoryProviderDestroy(hProvider);
76+
}
77+
78+
umf_memory_provider_handle_t hProvider = nullptr;
79+
};
80+
81+
struct memspaceDefaultTest : ::numaNodesTest {
82+
void SetUp() override {
83+
::numaNodesTest::SetUp();
84+
85+
hMemspace = umfMemspaceDefaultGet();
86+
ASSERT_NE(hMemspace, nullptr);
87+
}
88+
89+
umf_memspace_handle_t hMemspace = nullptr;
90+
};
91+
92+
struct memspaceDefaultProviderTest : ::memspaceDefaultTest {
93+
void SetUp() override {
94+
::memspaceDefaultTest::SetUp();
95+
96+
umf_result_t ret =
97+
umfMemoryProviderCreateFromMemspace(hMemspace, nullptr, &hProvider);
98+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
99+
ASSERT_NE(hProvider, nullptr);
100+
}
101+
102+
void TearDown() override {
103+
::memspaceDefaultTest::TearDown();
104+
105+
umfMemoryProviderDestroy(hProvider);
106+
}
107+
108+
umf_memory_provider_handle_t hProvider = nullptr;
109+
};
110+
111+
#endif /* UMF_MEMSPACE_HELPERS_HPP */

test/memspaces/memspace_numa.cpp

Lines changed: 14 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -2,81 +2,14 @@
22
// Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
33
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44

5+
#include "memspaces/memspace_numa.h"
56
#include "base.hpp"
6-
7+
#include "memspace_helpers.hpp"
78
#include "memspace_internal.h"
8-
#include "memspaces/memspace_numa.h"
99

1010
#include <umf/providers/provider_os_memory.h>
1111

12-
#include <numa.h>
13-
14-
#define SIZE_4K (4096)
15-
16-
struct numa_nodes_test : ::umf_test::test {
17-
void SetUp() override {
18-
::umf_test::test::SetUp();
19-
20-
if (numa_available() == -1) {
21-
GTEST_SKIP() << "Failed to initialize libnuma";
22-
}
23-
24-
int numNodes = numa_max_node();
25-
if (numNodes < 0) {
26-
GTEST_SKIP() << "No available numa nodes";
27-
}
28-
29-
for (int i = 0; i <= numNodes; i++) {
30-
nodeIds.emplace_back(i);
31-
}
32-
}
33-
34-
std::vector<size_t> nodeIds;
35-
};
36-
37-
struct numa_memspace_test : ::numa_nodes_test {
38-
void SetUp() override {
39-
::numa_nodes_test::SetUp();
40-
if (nodeIds.size()) {
41-
enum umf_result_t ret = umfMemspaceCreateFromNumaArray(
42-
nodeIds.data(), nodeIds.size(), &memspace);
43-
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
44-
ASSERT_NE(memspace, nullptr);
45-
}
46-
}
47-
48-
void TearDown() override {
49-
::numa_nodes_test::TearDown();
50-
if (memspace) {
51-
umfMemspaceDestroy(memspace);
52-
}
53-
}
54-
55-
umf_memspace_handle_t memspace = nullptr;
56-
};
57-
58-
struct numa_memspace_provider_test : ::numa_memspace_test {
59-
void SetUp() override {
60-
::numa_memspace_test::SetUp();
61-
if (nodeIds.size()) {
62-
umf_result_t ret = umfMemoryProviderCreateFromMemspace(
63-
memspace, nullptr, &provider);
64-
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
65-
ASSERT_NE(provider, nullptr);
66-
}
67-
}
68-
69-
void TearDown() override {
70-
::numa_memspace_test::TearDown();
71-
if (provider) {
72-
umfMemoryProviderDestroy(provider);
73-
}
74-
}
75-
76-
umf_memory_provider_handle_t provider = nullptr;
77-
};
78-
79-
TEST_F(numa_nodes_test, create_destroy) {
12+
TEST_F(numaNodesTest, createDestroy) {
8013
umf_memspace_handle_t hMemspace = nullptr;
8114
enum umf_result_t ret = umfMemspaceCreateFromNumaArray(
8215
nodeIds.data(), nodeIds.size(), &hMemspace);
@@ -86,49 +19,49 @@ TEST_F(numa_nodes_test, create_destroy) {
8619
umfMemspaceDestroy(hMemspace);
8720
}
8821

89-
TEST_F(numa_nodes_test, create_null_array) {
22+
TEST_F(numaNodesTest, createNullArray) {
9023
umf_memspace_handle_t hMemspace = nullptr;
9124
enum umf_result_t ret = umfMemspaceCreateFromNumaArray(NULL, 0, &hMemspace);
9225
ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT);
9326
ASSERT_EQ(hMemspace, nullptr);
9427
}
9528

96-
TEST_F(numa_nodes_test, create_zero_size) {
29+
TEST_F(numaNodesTest, createZeroSize) {
9730
umf_memspace_handle_t hMemspace = nullptr;
9831
enum umf_result_t ret =
9932
umfMemspaceCreateFromNumaArray(nodeIds.data(), 0, &hMemspace);
10033
ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT);
10134
ASSERT_EQ(hMemspace, nullptr);
10235
}
10336

104-
TEST_F(numa_nodes_test, create_null_handle) {
37+
TEST_F(numaNodesTest, createNullHandle) {
10538
enum umf_result_t ret =
10639
umfMemspaceCreateFromNumaArray(nodeIds.data(), nodeIds.size(), nullptr);
10740
ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT);
10841
}
10942

110-
TEST_F(numa_memspace_test, provider_from_numa_memspace) {
111-
umf_memory_provider_handle_t provider = nullptr;
43+
TEST_F(memspaceNumaTest, providerFromNumaMemspace) {
44+
umf_memory_provider_handle_t hProvider = nullptr;
11245
enum umf_result_t ret =
113-
umfMemoryProviderCreateFromMemspace(memspace, nullptr, &provider);
46+
umfMemoryProviderCreateFromMemspace(hMemspace, nullptr, &hProvider);
11447
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
115-
ASSERT_NE(provider, nullptr);
48+
ASSERT_NE(hProvider, nullptr);
11649

117-
umfMemoryProviderDestroy(provider);
50+
umfMemoryProviderDestroy(hProvider);
11851
}
11952

120-
TEST_F(numa_memspace_provider_test, alloc_free) {
53+
TEST_F(memspaceNumaProviderTest, allocFree) {
12154
void *ptr = nullptr;
12255
size_t size = SIZE_4K;
12356
size_t alignment = 0;
12457

12558
enum umf_result_t ret =
126-
umfMemoryProviderAlloc(provider, size, alignment, &ptr);
59+
umfMemoryProviderAlloc(hProvider, size, alignment, &ptr);
12760
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
12861
ASSERT_NE(ptr, nullptr);
12962

13063
memset(ptr, 0xFF, size);
13164

132-
ret = umfMemoryProviderFree(provider, ptr, size);
65+
ret = umfMemoryProviderFree(hProvider, ptr, size);
13366
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
13467
}

0 commit comments

Comments
 (0)