mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-16 05:26:31 +00:00
229 lines
7.5 KiB
C
229 lines
7.5 KiB
C
![]() |
// RUN: %libomp-compile -Wl,--export-dynamic && %libomp-run
|
||
|
|
||
|
// REQUIRES: linux
|
||
|
|
||
|
// Test OpenMP 6.0 memory management routines.
|
||
|
// Test host runtime's basic support with an emulated offload runtime.
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <omp.h>
|
||
|
|
||
|
#define NUM_DEVICES 4
|
||
|
|
||
|
//
|
||
|
// Required offload runtime interfaces
|
||
|
//
|
||
|
extern int __tgt_get_num_devices(void) { return NUM_DEVICES; }
|
||
|
|
||
|
extern int __tgt_get_mem_resources(int num_devices, const int *devices,
|
||
|
int host, omp_memspace_handle_t memspace,
|
||
|
int *resources) {
|
||
|
int i;
|
||
|
// We expect valid inputs within this test.
|
||
|
int num_resources = num_devices;
|
||
|
if (resources) {
|
||
|
// Simple resouce ID mapping example in the backend (=device ID).
|
||
|
// This does not represent any real backend.
|
||
|
for (i = 0; i < num_devices; i++)
|
||
|
resources[i] = devices[i];
|
||
|
}
|
||
|
return num_resources;
|
||
|
}
|
||
|
|
||
|
extern void *__tgt_omp_alloc(size_t size, omp_allocator_handle_t allocator) {
|
||
|
return malloc(size);
|
||
|
}
|
||
|
|
||
|
extern void __tgt_omp_free(void *ptr, omp_allocator_handle_t allocator) {
|
||
|
free(ptr);
|
||
|
}
|
||
|
|
||
|
// Code above is also used by the corresponding Fortran test
|
||
|
|
||
|
#define CHECK_OR_RET_FAIL(Expr) \
|
||
|
do { \
|
||
|
if (!(Expr)) \
|
||
|
return EXIT_FAILURE; \
|
||
|
} while (0)
|
||
|
|
||
|
// Test user-initialized allocator with the given memory space
|
||
|
static int test_user_allocator(omp_memspace_handle_t ms) {
|
||
|
omp_allocator_handle_t al = omp_null_allocator;
|
||
|
al = omp_init_allocator(ms, 0, NULL);
|
||
|
CHECK_OR_RET_FAIL(al != omp_null_allocator);
|
||
|
void *m = omp_alloc(1024, al);
|
||
|
CHECK_OR_RET_FAIL(m != NULL);
|
||
|
omp_free(m, al);
|
||
|
omp_destroy_allocator(al);
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static int test_allocator(omp_allocator_handle_t al) {
|
||
|
void *m = omp_alloc(1024, al);
|
||
|
CHECK_OR_RET_FAIL(m != NULL);
|
||
|
omp_free(m, al);
|
||
|
omp_destroy_allocator(al);
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static int test_mem_space(void) {
|
||
|
int i, count;
|
||
|
int num_devices = omp_get_num_devices();
|
||
|
CHECK_OR_RET_FAIL(num_devices == NUM_DEVICES);
|
||
|
|
||
|
int *all_devices = (int *)malloc(sizeof(int) * num_devices);
|
||
|
for (i = 0; i < num_devices; i++)
|
||
|
all_devices[i] = i;
|
||
|
|
||
|
omp_memspace_handle_t predef = omp_default_mem_space;
|
||
|
omp_memspace_handle_t ms1 = omp_null_mem_space;
|
||
|
omp_memspace_handle_t ms2 = omp_null_mem_space;
|
||
|
|
||
|
// Test the following API routines.
|
||
|
// * omp_get_device_memspace
|
||
|
// * omp_get_device_and_host_memspace
|
||
|
// * omp_get_devices_memspace
|
||
|
// * omp_get_devices_and_host_memspace
|
||
|
// Test if runtime returns the same memory space handle for the same input.
|
||
|
// Test if we can use the memory space to intialize allocator.
|
||
|
for (i = 0; i < num_devices; i++) {
|
||
|
ms1 = omp_get_device_memspace(i, predef);
|
||
|
CHECK_OR_RET_FAIL(ms1 != omp_null_mem_space);
|
||
|
ms2 = omp_get_device_memspace(i, predef);
|
||
|
CHECK_OR_RET_FAIL(ms1 == ms2);
|
||
|
CHECK_OR_RET_FAIL(test_user_allocator(ms1) == EXIT_SUCCESS);
|
||
|
ms1 = ms2 = omp_null_mem_space;
|
||
|
|
||
|
ms1 = omp_get_device_and_host_memspace(i, predef);
|
||
|
CHECK_OR_RET_FAIL(ms1 != omp_null_mem_space);
|
||
|
ms2 = omp_get_device_and_host_memspace(i, predef);
|
||
|
CHECK_OR_RET_FAIL(ms1 == ms2);
|
||
|
CHECK_OR_RET_FAIL(test_user_allocator(ms1) == EXIT_SUCCESS);
|
||
|
ms1 = ms2 = omp_null_mem_space;
|
||
|
|
||
|
for (count = 1; i + count <= num_devices; count++) {
|
||
|
int *devices = &all_devices[i];
|
||
|
ms1 = omp_get_devices_memspace(count, devices, predef);
|
||
|
CHECK_OR_RET_FAIL(ms1 != omp_null_mem_space);
|
||
|
ms2 = omp_get_devices_memspace(count, devices, predef);
|
||
|
CHECK_OR_RET_FAIL(ms1 == ms2);
|
||
|
CHECK_OR_RET_FAIL(test_user_allocator(ms1) == EXIT_SUCCESS);
|
||
|
ms1 = ms2 = omp_null_mem_space;
|
||
|
|
||
|
ms1 = omp_get_devices_and_host_memspace(count, devices, predef);
|
||
|
CHECK_OR_RET_FAIL(ms1 != omp_null_mem_space);
|
||
|
ms2 = omp_get_devices_and_host_memspace(count, devices, predef);
|
||
|
CHECK_OR_RET_FAIL(ms1 == ms2);
|
||
|
CHECK_OR_RET_FAIL(test_user_allocator(ms1) == EXIT_SUCCESS);
|
||
|
ms1 = ms2 = omp_null_mem_space;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Test the following API routines.
|
||
|
// * omp_get_devices_all_memspace
|
||
|
// Test if runtime returns the same memory space handle for the same input.
|
||
|
ms1 = omp_get_devices_all_memspace(predef);
|
||
|
CHECK_OR_RET_FAIL(ms1 != omp_null_mem_space);
|
||
|
ms2 = omp_get_devices_all_memspace(predef);
|
||
|
CHECK_OR_RET_FAIL(ms1 == ms2);
|
||
|
|
||
|
free(all_devices);
|
||
|
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static int test_mem_allocator(void) {
|
||
|
int i, count;
|
||
|
int num_devices = omp_get_num_devices();
|
||
|
CHECK_OR_RET_FAIL(num_devices == NUM_DEVICES);
|
||
|
|
||
|
int *all_devices = (int *)malloc(sizeof(int) * num_devices);
|
||
|
for (i = 0; i < num_devices; i++)
|
||
|
all_devices[i] = i;
|
||
|
|
||
|
omp_memspace_handle_t predef = omp_default_mem_space;
|
||
|
omp_allocator_handle_t al = omp_null_allocator;
|
||
|
|
||
|
// Test the following API routines.
|
||
|
// * omp_get_device_allocator
|
||
|
// * omp_get_device_and_host_allocator
|
||
|
// * omp_get_devices_allocator
|
||
|
// * omp_get_devices_and_host_allocator
|
||
|
for (i = 0; i < num_devices; i++) {
|
||
|
al = omp_get_device_allocator(i, predef);
|
||
|
CHECK_OR_RET_FAIL(al != omp_null_allocator);
|
||
|
CHECK_OR_RET_FAIL(test_allocator(al) == EXIT_SUCCESS);
|
||
|
al = omp_null_allocator;
|
||
|
|
||
|
al = omp_get_device_and_host_allocator(i, predef);
|
||
|
CHECK_OR_RET_FAIL(al != omp_null_allocator);
|
||
|
CHECK_OR_RET_FAIL(test_allocator(al) == EXIT_SUCCESS);
|
||
|
al = omp_null_allocator;
|
||
|
|
||
|
for (count = 1; i + count <= num_devices; count++) {
|
||
|
int *devices = &all_devices[i];
|
||
|
al = omp_get_devices_allocator(count, devices, predef);
|
||
|
CHECK_OR_RET_FAIL(al != omp_null_allocator);
|
||
|
CHECK_OR_RET_FAIL(test_allocator(al) == EXIT_SUCCESS);
|
||
|
al = omp_null_allocator;
|
||
|
|
||
|
al = omp_get_devices_and_host_allocator(count, devices, predef);
|
||
|
CHECK_OR_RET_FAIL(al != omp_null_allocator);
|
||
|
CHECK_OR_RET_FAIL(test_allocator(al) == EXIT_SUCCESS);
|
||
|
al = omp_null_allocator;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Test the following API routines.
|
||
|
// * omp_get_devices_all_allocator
|
||
|
al = omp_get_devices_all_allocator(predef);
|
||
|
CHECK_OR_RET_FAIL(al != omp_null_allocator);
|
||
|
CHECK_OR_RET_FAIL(test_allocator(al) == EXIT_SUCCESS);
|
||
|
|
||
|
free(all_devices);
|
||
|
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|
||
|
|
||
|
// Just test what we can expect from the emulated backend.
|
||
|
static int test_sub_mem_space(void) {
|
||
|
int i;
|
||
|
omp_memspace_handle_t ms = omp_null_mem_space;
|
||
|
ms = omp_get_devices_all_memspace(omp_default_mem_space);
|
||
|
CHECK_OR_RET_FAIL(ms != omp_null_mem_space);
|
||
|
int num_resources = omp_get_memspace_num_resources(ms);
|
||
|
CHECK_OR_RET_FAIL(num_resources == NUM_DEVICES);
|
||
|
|
||
|
// Check if single-resource sub memspace is correctly returned.
|
||
|
for (i = 0; i < num_resources; i++) {
|
||
|
omp_memspace_handle_t sub = omp_get_submemspace(ms, 1, &i);
|
||
|
CHECK_OR_RET_FAIL(sub != omp_null_mem_space);
|
||
|
CHECK_OR_RET_FAIL(sub != ms);
|
||
|
int num_sub_resources = omp_get_memspace_num_resources(sub);
|
||
|
CHECK_OR_RET_FAIL(num_sub_resources == 1);
|
||
|
}
|
||
|
|
||
|
// Check if all-resrouce sub memspace is correctly returned.
|
||
|
int *resources = (int *)malloc(sizeof(int) * num_resources);
|
||
|
for (i = 0; i < num_resources; i++)
|
||
|
resources[i] = i;
|
||
|
omp_memspace_handle_t sub = omp_get_submemspace(ms, num_resources, resources);
|
||
|
CHECK_OR_RET_FAIL(sub != omp_null_mem_space);
|
||
|
CHECK_OR_RET_FAIL(sub == ms);
|
||
|
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|
||
|
|
||
|
int main() {
|
||
|
int rc = test_mem_space();
|
||
|
CHECK_OR_RET_FAIL(rc == EXIT_SUCCESS);
|
||
|
|
||
|
rc = test_mem_allocator();
|
||
|
CHECK_OR_RET_FAIL(rc == EXIT_SUCCESS);
|
||
|
|
||
|
rc = test_sub_mem_space();
|
||
|
CHECK_OR_RET_FAIL(rc == EXIT_SUCCESS);
|
||
|
|
||
|
return rc;
|
||
|
}
|