2023-08-14 21:17:55 +05:30
|
|
|
|
/*
|
|
|
|
|
|
Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
|
THE SOFTWARE.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2025-08-15 16:09:19 -04:00
|
|
|
|
* @addtogroup hipMemcpyKernel hipMemcpyKernel
|
|
|
|
|
|
* @{
|
|
|
|
|
|
* @ingroup perfMemoryTest
|
|
|
|
|
|
* `hipMemcpy(void* dst, const void* src, size_t count, hipMemcpyKind kind)` -
|
|
|
|
|
|
* Copies data between host and device.
|
|
|
|
|
|
*/
|
2025-10-23 21:56:15 -04:00
|
|
|
|
#include <unistd.h>
|
2023-08-14 21:17:55 +05:30
|
|
|
|
#include <numaif.h>
|
2025-10-23 21:56:15 -04:00
|
|
|
|
#include <numa.h>
|
2023-08-14 21:17:55 +05:30
|
|
|
|
#include <hip_test_common.hh>
|
2025-08-15 16:09:19 -04:00
|
|
|
|
// #define ENABLE_DEBUG 1
|
2023-08-14 21:17:55 +05:30
|
|
|
|
// To run it correctly, we must not export HIP_VISIBLE_DEVICES.
|
|
|
|
|
|
// And we must explicitly link libnuma because of numa api move_pages().
|
2025-10-23 21:56:15 -04:00
|
|
|
|
#define NUM_PAGES 100
|
2025-08-15 16:09:19 -04:00
|
|
|
|
char* h = nullptr;
|
|
|
|
|
|
char* d_h = nullptr;
|
|
|
|
|
|
char* m = nullptr;
|
|
|
|
|
|
char* d_m = nullptr;
|
2025-10-23 21:56:15 -04:00
|
|
|
|
int page_size = 0;
|
2023-08-14 21:17:55 +05:30
|
|
|
|
|
2025-08-15 16:09:19 -04:00
|
|
|
|
const int mode[] = {MPOL_DEFAULT, MPOL_BIND, MPOL_PREFERRED, MPOL_INTERLEAVE};
|
|
|
|
|
|
const char* modeStr[] = {"MPOL_DEFAULT", "MPOL_BIND", "MPOL_PREFERRED", "MPOL_INTERLEAVE"};
|
2023-08-14 21:17:55 +05:30
|
|
|
|
|
|
|
|
|
|
bool test(int cpuId, int gpuId, int numaMode, unsigned int hostMallocflags) {
|
2025-08-15 16:09:19 -04:00
|
|
|
|
void* pages[NUM_PAGES];
|
2023-08-14 21:17:55 +05:30
|
|
|
|
int status[NUM_PAGES];
|
|
|
|
|
|
int ret_code;
|
|
|
|
|
|
|
2025-08-15 16:09:19 -04:00
|
|
|
|
CONSOLE_PRINT("set cpu %d, gpu %d, numaMode %d, hostMallocflags %u\n", cpuId, gpuId, numaMode,
|
|
|
|
|
|
hostMallocflags);
|
2025-10-23 21:56:15 -04:00
|
|
|
|
if (gpuId >= 0) {
|
|
|
|
|
|
HIP_CHECK(hipSetDevice(gpuId));
|
|
|
|
|
|
}
|
2023-08-14 21:17:55 +05:30
|
|
|
|
|
|
|
|
|
|
if (cpuId >= 0) {
|
2025-08-15 16:09:19 -04:00
|
|
|
|
unsigned long nodeMask = 1 << cpuId; // NOLINT
|
|
|
|
|
|
unsigned long maxNode = sizeof(nodeMask) * 8; // NOLINT
|
2025-10-23 21:56:15 -04:00
|
|
|
|
// Will override existing numa policy in memory
|
2023-08-14 21:17:55 +05:30
|
|
|
|
if (set_mempolicy(numaMode, numaMode == MPOL_DEFAULT ? NULL : &nodeMask,
|
|
|
|
|
|
numaMode == MPOL_DEFAULT ? 0 : maxNode) == -1) {
|
|
|
|
|
|
WARN("set_mempolicy() failed with err " << errno << "\n");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-15 16:09:19 -04:00
|
|
|
|
posix_memalign(reinterpret_cast<void**>(&m), page_size, page_size * NUM_PAGES);
|
2023-08-14 21:17:55 +05:30
|
|
|
|
HIP_CHECK(hipHostRegister(m, page_size * NUM_PAGES, hipHostRegisterMapped));
|
|
|
|
|
|
HIP_CHECK(hipHostGetDevicePointer(reinterpret_cast<void**>(&d_m), m, 0));
|
|
|
|
|
|
|
|
|
|
|
|
status[0] = -1;
|
|
|
|
|
|
pages[0] = m;
|
|
|
|
|
|
for (int i = 1; i < NUM_PAGES; i++) {
|
|
|
|
|
|
pages[i] = reinterpret_cast<char*>(pages[0]) + page_size;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ret_code = move_pages(0, NUM_PAGES, pages, NULL, status, 0);
|
2025-08-15 16:09:19 -04:00
|
|
|
|
CONSOLE_PRINT("Memory (malloc) ret %d at %p (dev %p) is at node: ", ret_code, m, d_m);
|
2023-08-14 21:17:55 +05:30
|
|
|
|
for (int i = 0; i < NUM_PAGES; i++) {
|
2025-08-15 16:09:19 -04:00
|
|
|
|
CONSOLE_PRINT("%d ", status[i]); // Don't verify as it's out of our control
|
2023-08-14 21:17:55 +05:30
|
|
|
|
}
|
2025-08-15 16:09:19 -04:00
|
|
|
|
CONSOLE_PRINT("\n");
|
2023-08-14 21:17:55 +05:30
|
|
|
|
|
2025-08-15 16:09:19 -04:00
|
|
|
|
HIP_CHECK(hipHostMalloc(reinterpret_cast<void**>(&h), page_size * NUM_PAGES, hostMallocflags));
|
2023-08-14 21:17:55 +05:30
|
|
|
|
pages[0] = h;
|
|
|
|
|
|
for (int i = 1; i < NUM_PAGES; i++) {
|
|
|
|
|
|
pages[i] = reinterpret_cast<char*>(pages[0]) + page_size;
|
|
|
|
|
|
}
|
|
|
|
|
|
ret_code = move_pages(0, NUM_PAGES, pages, NULL, status, 0);
|
|
|
|
|
|
d_h = nullptr;
|
|
|
|
|
|
if (hostMallocflags & hipHostMallocMapped) {
|
|
|
|
|
|
HIP_CHECK(hipHostGetDevicePointer(reinterpret_cast<void**>(&d_h), h, 0));
|
2025-08-15 16:09:19 -04:00
|
|
|
|
CONSOLE_PRINT("Memory (hipHostMalloc) ret %d at %p (dev %p) is at node: ", ret_code, h, d_h);
|
2023-08-14 21:17:55 +05:30
|
|
|
|
} else {
|
2025-08-15 16:09:19 -04:00
|
|
|
|
CONSOLE_PRINT("Memory (hipHostMalloc) ret %d at %p is at node: ", ret_code, h);
|
2023-08-14 21:17:55 +05:30
|
|
|
|
}
|
|
|
|
|
|
for (int i = 0; i < NUM_PAGES; i++) {
|
2025-08-15 16:09:19 -04:00
|
|
|
|
CONSOLE_PRINT("%d ", status[i]); // Always print it even if it's wrong. Verify later
|
2023-08-14 21:17:55 +05:30
|
|
|
|
}
|
2025-08-15 16:09:19 -04:00
|
|
|
|
CONSOLE_PRINT("\n");
|
2023-08-14 21:17:55 +05:30
|
|
|
|
|
|
|
|
|
|
HIP_CHECK(hipHostFree(reinterpret_cast<void*>(h)));
|
|
|
|
|
|
HIP_CHECK(hipHostUnregister(m));
|
|
|
|
|
|
free(m);
|
|
|
|
|
|
|
|
|
|
|
|
if (cpuId >= 0 && (numaMode == MPOL_BIND || numaMode == MPOL_PREFERRED)) {
|
|
|
|
|
|
for (int i = 0; i < NUM_PAGES; i++) {
|
|
|
|
|
|
if (status[i] != cpuId) { // Now verify
|
2025-08-15 16:09:19 -04:00
|
|
|
|
WARN("Failed at " << i << " status[i] = " << status[i] << " cpuId " << cpuId << "\n");
|
2023-08-14 21:17:55 +05:30
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-15 16:09:19 -04:00
|
|
|
|
bool runTest(const int& cpuCount, const int& gpuCount, unsigned int hostMallocflags,
|
|
|
|
|
|
const std::string& str) {
|
|
|
|
|
|
CONSOLE_PRINT("Test- %s\n", str.c_str());
|
2023-08-14 21:17:55 +05:30
|
|
|
|
|
|
|
|
|
|
for (int m = 0; m < sizeof(mode) / sizeof(mode[0]); m++) {
|
2025-08-15 16:09:19 -04:00
|
|
|
|
CONSOLE_PRINT("Testing %s\n", modeStr[m]);
|
2023-08-14 21:17:55 +05:30
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < cpuCount; i++) {
|
|
|
|
|
|
for (int j = 0; j < gpuCount; j++) {
|
|
|
|
|
|
if (!test(i, j, mode[m], hostMallocflags)) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2025-08-15 16:09:19 -04:00
|
|
|
|
* Test Description
|
|
|
|
|
|
* ------------------------
|
|
|
|
|
|
* - Verify hipPerfHostNumaAlloc status.
|
|
|
|
|
|
* Test source
|
|
|
|
|
|
* ------------------------
|
|
|
|
|
|
* - perftests/memory/hipPerfHostNumaAlloc.cc
|
|
|
|
|
|
* Test requirements
|
|
|
|
|
|
* ------------------------
|
|
|
|
|
|
* - HIP_VERSION >= 5.6
|
|
|
|
|
|
*/
|
2023-08-14 21:17:55 +05:30
|
|
|
|
|
|
|
|
|
|
TEST_CASE("Perf_hipPerfHostNumaAlloc_test") {
|
|
|
|
|
|
int gpuCount = 0;
|
|
|
|
|
|
HIP_CHECK(hipGetDeviceCount(&gpuCount));
|
2025-10-23 21:56:15 -04:00
|
|
|
|
int cpuCount = numa_max_node() + 1; // number of numa nodes
|
|
|
|
|
|
page_size = getpagesize();
|
|
|
|
|
|
CONSOLE_PRINT("Cpu count %d, Gpu count %d, page_size %d\n", cpuCount, gpuCount, page_size);
|
2023-08-14 21:17:55 +05:30
|
|
|
|
|
|
|
|
|
|
if (cpuCount < 0 || gpuCount < 0) {
|
2025-08-15 16:09:19 -04:00
|
|
|
|
SUCCEED(
|
|
|
|
|
|
"Skipped testcase hipPerfHostNumaAlloc as "
|
|
|
|
|
|
"there is no device to test.\n");
|
2023-08-14 21:17:55 +05:30
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-15 16:09:19 -04:00
|
|
|
|
REQUIRE(true == runTest(cpuCount, gpuCount, hipHostMallocDefault | hipHostMallocNumaUser,
|
|
|
|
|
|
"Testing hipHostMallocDefault | hipHostMallocNumaUser......"));
|
2023-08-14 21:17:55 +05:30
|
|
|
|
|
2025-08-15 16:09:19 -04:00
|
|
|
|
REQUIRE(true == runTest(cpuCount, gpuCount, hipHostMallocMapped | hipHostMallocNumaUser,
|
|
|
|
|
|
"Testing hipHostMallocMapped | hipHostMallocNumaUser......."));
|
2023-08-14 21:17:55 +05:30
|
|
|
|
}
|
2024-03-22 11:17:00 +01:00
|
|
|
|
|
|
|
|
|
|
/**
|
2025-08-15 16:09:19 -04:00
|
|
|
|
* End doxygen group perfMemoryTest.
|
|
|
|
|
|
* @}
|
|
|
|
|
|
*/
|