CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
276 lines
7.5 KiB
C++
276 lines
7.5 KiB
C++
/*
|
|
* Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
/**
|
|
Testcase Scenarios :
|
|
|
|
1) Regress hipMalloc()/hipFree() in loop for bigger chunk of allocation
|
|
with adequate number of iterations and later test for kernel execution on
|
|
default gpu.
|
|
|
|
2) Regress hipMalloc()/hipFree() in loop while allocating smaller chunks
|
|
keeping maximum number of iterations and then run kernel code on default
|
|
gpu, perfom data validation.
|
|
|
|
3) Check hipMalloc() api adaptability when app creates small chunks of memory
|
|
continuously, stores it for later use and then frees it at later point
|
|
of time.
|
|
|
|
4) Multithread Scenario : Exercise hipMalloc() api parellely on all gpus from
|
|
multiple threads and regress the api.
|
|
|
|
5) Validate memory usage with hipMemGetInfo() while regressing hipMalloc()
|
|
api. Check for any possible memory leaks.
|
|
*/
|
|
|
|
#include <hip_test_common.hh>
|
|
#include <hip_test_checkers.hh>
|
|
#include <hip_test_kernels.hh>
|
|
|
|
#include <atomic>
|
|
#include <limits>
|
|
#include <vector>
|
|
|
|
|
|
/* Buffer size for bigger chunks in alloc/free cycles */
|
|
static constexpr auto BuffSizeBC = 5 * 1024 * 1024;
|
|
|
|
/* Buffer size for smaller chunks in alloc/free cycles */
|
|
static constexpr auto BuffSizeSC = 16;
|
|
|
|
/* Max alloc/free iterations for smaller chunks */
|
|
static constexpr auto MaxAllocFree_SmallChunks = 5000000;
|
|
|
|
/* Max alloc/free iterations for bigger chunks */
|
|
static constexpr auto MaxAllocFree_BigChunks = 10000;
|
|
|
|
/* Max alloc and pool iterations */
|
|
static constexpr auto MaxAllocPoolIter = 2000000;
|
|
|
|
/* Test status shared across threads */
|
|
static std::atomic<bool> g_thTestPassed{true};
|
|
|
|
|
|
/**
|
|
* Validates data consistency on supplied gpu
|
|
*/
|
|
static bool validateMemoryOnGPU(int gpu) {
|
|
int *A_d, *B_d, *C_d;
|
|
int *A_h, *B_h, *C_h;
|
|
bool TestPassed = true;
|
|
constexpr auto N = 4 * 1024 * 1024;
|
|
constexpr auto blocksPerCU = 6; // to hide latency
|
|
constexpr auto threadsPerBlock = 256;
|
|
size_t Nbytes = N * sizeof(int);
|
|
|
|
HIP_CHECK(hipSetDevice(gpu));
|
|
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, false);
|
|
|
|
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
|
|
|
HIP_CHECK(hipMemcpy(A_d, A_h, Nbytes, hipMemcpyHostToDevice));
|
|
HIP_CHECK(hipMemcpy(B_d, B_h, Nbytes, hipMemcpyHostToDevice));
|
|
|
|
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock), 0, 0,
|
|
static_cast<const int*>(A_d), static_cast<const int*>(B_d), C_d, N);
|
|
HIP_CHECK(hipGetLastError());
|
|
HIP_CHECK(hipMemcpy(C_h, C_d, Nbytes, hipMemcpyDeviceToHost));
|
|
|
|
if (!HipTest::checkVectorADD(A_h, B_h, C_h, N)) {
|
|
UNSCOPED_INFO("Validation PASSED for gpu " << gpu);
|
|
} else {
|
|
UNSCOPED_INFO("Validation FAILED for gpu " << gpu);
|
|
TestPassed = false;
|
|
}
|
|
|
|
HipTest::freeArrays(A_d, B_d, C_d, A_h, B_h, C_h, false);
|
|
|
|
return TestPassed;
|
|
}
|
|
|
|
|
|
/**
|
|
* Regress memory allocation and free in loop
|
|
*/
|
|
static bool regressAllocInLoop(int gpu) {
|
|
size_t numBytes;
|
|
int i = 0;
|
|
int* ptr;
|
|
|
|
HIP_CHECK(hipSetDevice(gpu));
|
|
numBytes = BuffSizeBC;
|
|
|
|
// Exercise allocation in loop with bigger chunks
|
|
for (i = 0; i < MaxAllocFree_BigChunks; i++) {
|
|
HIP_CHECK(hipMalloc(&ptr, numBytes));
|
|
HIP_CHECK(hipFree(ptr));
|
|
}
|
|
|
|
// Exercise allocation in loop with smaller chunks and maximum iters
|
|
numBytes = BuffSizeSC;
|
|
|
|
for (i = 0; i < MaxAllocFree_SmallChunks; i++) {
|
|
HIP_CHECK(hipMalloc(&ptr, numBytes));
|
|
HIP_CHECK(hipFree(ptr));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Validates data consistency on supplied gpu
|
|
* In Multithreaded Environment
|
|
*/
|
|
static bool validateMemoryOnGpuMThread(int gpu) {
|
|
int *A_d, *B_d, *C_d;
|
|
int *A_h, *B_h, *C_h;
|
|
bool TestPassed = true;
|
|
constexpr auto N = 4 * 1024 * 1024;
|
|
constexpr auto blocksPerCU = 6; // to hide latency
|
|
constexpr auto threadsPerBlock = 256;
|
|
size_t Nbytes = N * sizeof(int);
|
|
HIPCHECK(hipSetDevice(gpu));
|
|
HipTest::initArrays(&A_d, &B_d, &C_d, &A_h, &B_h, &C_h, N, false);
|
|
|
|
unsigned blocks = HipTest::setNumBlocks(blocksPerCU, threadsPerBlock, N);
|
|
|
|
HIPCHECK(hipMemcpy(A_d, A_h, Nbytes, hipMemcpyHostToDevice));
|
|
HIPCHECK(hipMemcpy(B_d, B_h, Nbytes, hipMemcpyHostToDevice));
|
|
|
|
hipLaunchKernelGGL(HipTest::vectorADD, dim3(blocks), dim3(threadsPerBlock), 0, 0,
|
|
static_cast<const int*>(A_d), static_cast<const int*>(B_d), C_d, N);
|
|
HIP_CHECK(hipGetLastError());
|
|
HIPCHECK(hipMemcpy(C_h, C_d, Nbytes, hipMemcpyDeviceToHost));
|
|
|
|
if (!HipTest::checkVectorADD(A_h, B_h, C_h, N)) {
|
|
UNSCOPED_INFO("Validation PASSED for gpu " << gpu);
|
|
} else {
|
|
UNSCOPED_INFO("Validation FAILED for gpu " << gpu);
|
|
TestPassed = false;
|
|
}
|
|
|
|
HipTest::freeArrays(A_d, B_d, C_d, A_h, B_h, C_h, false);
|
|
|
|
return TestPassed;
|
|
}
|
|
|
|
/**
|
|
* Regress memory allocation and free in loop
|
|
* In Multithreaded Environment
|
|
*/
|
|
static bool regressAllocInLoopMthread(int gpu) {
|
|
size_t numBytes;
|
|
int i = 0;
|
|
int* ptr;
|
|
|
|
HIPCHECK(hipSetDevice(gpu));
|
|
numBytes = BuffSizeBC;
|
|
|
|
// Exercise allocation in loop with bigger chunks
|
|
for (i = 0; i < MaxAllocFree_BigChunks; i++) {
|
|
HIPCHECK(hipMalloc(&ptr, numBytes));
|
|
HIPCHECK(hipFree(ptr));
|
|
}
|
|
|
|
// Exercise allocation in loop with smaller chunks and maximum iters
|
|
numBytes = BuffSizeSC;
|
|
for (i = 0; i < MaxAllocFree_SmallChunks; i++) {
|
|
HIPCHECK(hipMalloc(&ptr, numBytes));
|
|
HIPCHECK(hipFree(ptr));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Thread func to regress alloc and check data consistency
|
|
*/
|
|
static void threadFunc(int gpu) {
|
|
g_thTestPassed = regressAllocInLoopMthread(gpu) && validateMemoryOnGpuMThread(gpu);
|
|
|
|
UNSCOPED_INFO("thread execution status on gpu" << gpu << ":" << g_thTestPassed.load());
|
|
}
|
|
|
|
/**
|
|
* Regress hipMalloc()/hipFree() in loop for bigger chunks and
|
|
* smaller chunks of memory allocation
|
|
*/
|
|
HIP_TEST_CASE(Stress_hipMalloc_LoopRegressionAllocFreeCycles) {
|
|
int devCnt = 0;
|
|
|
|
// Get GPU count
|
|
HIP_CHECK(hipGetDeviceCount(&devCnt));
|
|
REQUIRE(devCnt > 0);
|
|
|
|
CHECK(regressAllocInLoop(0) == true);
|
|
CHECK(validateMemoryOnGPU(0) == true);
|
|
}
|
|
|
|
/**
|
|
* Application Behavior Modelling.
|
|
* Check hipMalloc() api adaptability when app creates small chunks of memory
|
|
* continuously, stores it for later use and then frees it at later point
|
|
* of time.
|
|
*/
|
|
HIP_TEST_CASE(Stress_hipMalloc_AllocateAndPoolBuffers) {
|
|
size_t avail{0}, tot{0};
|
|
bool ret{false};
|
|
hipError_t err{};
|
|
std::vector<int*> ptrlist{};
|
|
constexpr auto BuffSize = 10;
|
|
int devCnt{0}, *ptr{nullptr};
|
|
|
|
// Get GPU count
|
|
HIP_CHECK(hipGetDeviceCount(&devCnt));
|
|
REQUIRE(devCnt > 0);
|
|
|
|
// Allocate small chunks of memory million times
|
|
for (int i = 0; i < MaxAllocPoolIter; i++) {
|
|
if ((err = hipMalloc(&ptr, BuffSize)) != hipSuccess) {
|
|
HIP_CHECK(hipMemGetInfo(&avail, &tot));
|
|
|
|
INFO("Loop regression pool allocation failure. "
|
|
<< "Total gpu memory " << tot / (1024.0 * 1024.0) << ", Free memory "
|
|
<< avail / (1024.0 * 1024.0) << " iter " << i << " error " << hipGetErrorString(err));
|
|
|
|
REQUIRE(false);
|
|
}
|
|
|
|
// Store pointers allocated to emulate memory pool of app
|
|
ptrlist.push_back(ptr);
|
|
}
|
|
|
|
// Free ptrs at later point of time
|
|
for (auto& t : ptrlist) {
|
|
HIP_CHECK(hipFree(t));
|
|
}
|
|
ret = validateMemoryOnGPU(0);
|
|
REQUIRE(ret == true);
|
|
}
|
|
|
|
|
|
/**
|
|
* Exercise hipMalloc() api parellely on all gpus from
|
|
* multiple threads and regress the api.
|
|
*/
|
|
HIP_TEST_CASE(Stress_hipMalloc_Multithreaded_MultiGPU) {
|
|
std::vector<std::thread> threadlist;
|
|
int devCnt;
|
|
|
|
// Get GPU count
|
|
HIP_CHECK(hipGetDeviceCount(&devCnt));
|
|
REQUIRE(devCnt > 0);
|
|
|
|
for (int i = 0; i < devCnt; i++) {
|
|
threadlist.push_back(std::thread(threadFunc, i));
|
|
}
|
|
|
|
for (auto& t : threadlist) {
|
|
t.join();
|
|
}
|
|
|
|
REQUIRE(g_thTestPassed == true);
|
|
}
|