Skip to content

Commit ebb8ea1

Browse files
committed
add an example for mix of Disjoint Pool and L0
1 parent e331e55 commit ebb8ea1

File tree

9 files changed

+460
-15
lines changed

9 files changed

+460
-15
lines changed

.github/workflows/gpu.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ jobs:
4141
-DUMF_BUILD_BENCHMARKS=ON
4242
-DUMF_BUILD_TESTS=ON
4343
-DUMF_BUILD_GPU_TESTS=ON
44+
-DUMF_BUILD_GPU_EXAMPLES=ON
4445
-DUMF_FORMAT_CODE_STYLE=ON
4546
-DUMF_DEVELOPER_MODE=ON
4647
-DUMF_BUILD_LIBUMF_POOL_DISJOINT=ON

CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ option(UMF_BUILD_GPU_TESTS "Build UMF GPU tests" OFF)
2222
option(UMF_BUILD_BENCHMARKS "Build UMF benchmarks" OFF)
2323
option(UMF_BUILD_BENCHMARKS_MT "Build UMF multithreaded benchmarks" OFF)
2424
option(UMF_BUILD_EXAMPLES "Build UMF examples" ON)
25+
option(UMF_BUILD_GPU_EXAMPLES "Build UMF GPU examples" OFF)
2526
option(UMF_ENABLE_POOL_TRACKING "Build UMF with pool tracking" ON)
2627
option(UMF_DEVELOPER_MODE "Enable developer checks, treats warnings as errors"
2728
OFF)
@@ -435,7 +436,8 @@ endif()
435436
install(FILES ${CMAKE_SOURCE_DIR}/LICENSE.TXT
436437
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}/")
437438

438-
install(FILES examples/basic/basic.c
439+
install(FILES examples/basic/gpu_shared_memory.c
440+
examples/basic/utils_level_zero.h examples/basic/basic.c
439441
DESTINATION "${CMAKE_INSTALL_DOCDIR}/examples")
440442

441443
# Add the include directory and the headers target to the install.

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@ The Unified Memory Framework (UMF) is a library for constructing allocators and
1717

1818
## Usage
1919

20-
For a quick introduction to UMF usage, see [Example usage](https://oneapi-src.github.io/unified-memory-framework/example-usage.html),
21-
which includes the code of the basic [example](https://github.com/oneapi-src/unified-memory-framework/blob/main/examples/basic/basic.c).
20+
For a quick introduction to UMF usage, see
21+
[Example usage](https://oneapi-src.github.io/unified-memory-framework/examples.html),
22+
which includes the code of the basic [example](https://github.com/oneapi-src/unified-memory-framework/blob/main/examples/basic/basic.c)
23+
and the more advanced one that allocates
24+
[USM memory from the GPU device](https://github.com/oneapi-src/unified-memory-framework/blob/main/examples/basic/gpu_shared_memory.c)
25+
using the Level Zero API and UMF Level Zero memory provider.
2226

2327
## Build
2428

@@ -100,6 +104,7 @@ List of options provided by CMake:
100104
| UMF_BUILD_GPU_TESTS | Build UMF GPU tests | ON/OFF | OFF |
101105
| UMF_BUILD_BENCHMARKS | Build UMF benchmarks | ON/OFF | OFF |
102106
| UMF_BUILD_EXAMPLES | Build UMF examples | ON/OFF | ON |
107+
| UMF_BUILD_GPU_EXAMPLES | Build UMF GPU examples | ON/OFF | OFF |
103108
| UMF_ENABLE_POOL_TRACKING | Build UMF with pool tracking | ON/OFF | ON |
104109
| UMF_DEVELOPER_MODE | Treat warnings as errors and enables additional checks | ON/OFF | OFF |
105110
| UMF_FORMAT_CODE_STYLE | Add clang, cmake, and black -format-check and -format-apply targets to make | ON/OFF | OFF |

examples/CMakeLists.txt

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,41 @@ if(UMF_BUILD_LIBUMF_POOL_SCALABLE AND UMF_ENABLE_POOL_TRACKING)
2323

2424
set_tests_properties(${EXAMPLE_NAME} PROPERTIES LABELS "example")
2525

26+
if(WINDOWS)
27+
# append PATH to DLLs
28+
set_property(TEST ${EXAMPLE_NAME} PROPERTY ENVIRONMENT_MODIFICATION
29+
"${DLL_PATH_LIST}")
30+
endif()
31+
else()
32+
message(STATUS "Basic example requires UMF_BUILD_LIBUMF_POOL_SCALABLE and "
33+
"UMF_ENABLE_POOL_TRACKING to be turned ON - skipping")
34+
endif()
35+
36+
if(UMF_BUILD_GPU_EXAMPLES
37+
AND UMF_BUILD_LIBUMF_POOL_DISJOINT
38+
AND UMF_BUILD_LEVEL_ZERO_PROVIDER
39+
AND LINUX)
40+
set(EXAMPLE_NAME umf_example_gpu_shared_memory)
41+
42+
add_umf_executable(
43+
NAME ${EXAMPLE_NAME}
44+
SRCS basic/gpu_shared_memory.c
45+
LIBS umf disjoint_pool ze_loader)
46+
47+
target_include_directories(
48+
${EXAMPLE_NAME}
49+
PRIVATE ${LEVEL_ZERO_INCLUDE_DIRS} ${UMF_CMAKE_SOURCE_DIR}/src/utils
50+
${UMF_CMAKE_SOURCE_DIR}/include)
51+
52+
target_link_directories(${EXAMPLE_NAME} PRIVATE ${LIBHWLOC_LIBRARY_DIRS})
53+
54+
add_test(
55+
NAME ${EXAMPLE_NAME}
56+
COMMAND ${EXAMPLE_NAME}
57+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
58+
59+
set_tests_properties(${EXAMPLE_NAME} PROPERTIES LABELS "example")
60+
2661
if(WINDOWS)
2762
# append PATH to DLLs
2863
set_property(TEST ${EXAMPLE_NAME} PROPERTY ENVIRONMENT_MODIFICATION
@@ -31,6 +66,7 @@ if(UMF_BUILD_LIBUMF_POOL_SCALABLE AND UMF_ENABLE_POOL_TRACKING)
3166
else()
3267
message(
3368
STATUS
34-
"Basic example requires UMF_BUILD_LIBUMF_POOL_SCALABLE and UMF_ENABLE_POOL_TRACKING
35-
to be turned ON - skipping")
69+
"GPU shared memory example requires UMF_BUILD_GPU_EXAMPLES, "
70+
"UMF_BUILD_LEVEL_ZERO_PROVIDER and UMF_BUILD_LIBUMF_POOL_DISJOINT "
71+
"to be turned ON - skipping")
3672
endif()

examples/README.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,28 @@
11
# Examples
22

3-
This directory contains examples of UMF usage. Each example has a brief description below.
3+
This directory contains examples of UMF usage. Each example has a brief
4+
description below.
45

56
## Basic
67

7-
This example covers the basics of UMF API. It walks you through a basic usage of a memory provider and a pool allocator. OS memory provider and Scalable pool are used for this purpose.
8+
This example covers the basics of UMF API. It walks you through a basic usage
9+
of a memory provider and a pool allocator. OS memory provider and Scalable pool
10+
are used for this purpose.
811

912
### Required CMake configuration flags
1013
* UMF_BUILD_LIBUMF_POOL_SCALABLE=ON
1114
* UMF_ENABLE_POOL_TRACKING=ON
15+
16+
## GPU shared memory
17+
18+
This example demonstrates the usage of Intel's Level Zero API for accessing GPU
19+
memory. It initializes the Level Zero driver, discovers all the driver
20+
instances, and creates GPU context for the first found GPU device. Next, it
21+
sets up a combination of UMF Level Zero memory provider and a Disjoint Pool
22+
memory pool to allocate from shared memory. If any step fails, the program
23+
cleans up and exits with an error status.
24+
25+
### Required CMake configuration flags
26+
* UMF_BUILD_GPU_EXAMPLES=ON
27+
* UMF_BUILD_LIBUMF_POOL_DISJOINT=ON
28+
* UMF_BUILD_LEVEL_ZERO_PROVIDER=ON

examples/basic/gpu_shared_memory.c

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
*
3+
* Copyright (C) 2024 Intel Corporation
4+
*
5+
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
6+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
*
8+
*/
9+
10+
#include "utils_level_zero.h"
11+
12+
#include <umf/memory_pool.h>
13+
#include <umf/pools/pool_disjoint.h>
14+
#include <umf/providers/provider_level_zero.h>
15+
16+
int main(void) {
17+
// A result object for storing UMF API result status
18+
umf_result_t res;
19+
20+
uint32_t driverId = 0;
21+
ze_driver_handle_t hDriver = NULL;
22+
ze_device_handle_t hDevice = NULL;
23+
ze_context_handle_t hContext = NULL;
24+
25+
// Initialize Level Zero
26+
int ret = init_level_zero();
27+
if (ret != 0) {
28+
fprintf(stderr, "Failed to init Level 0!\n");
29+
return ret;
30+
}
31+
32+
ret = find_driver_with_gpu(&driverId, &hDriver);
33+
if (ret || hDriver == NULL) {
34+
fprintf(stderr, "Cannot find L0 driver with GPU device!\n");
35+
return ret;
36+
}
37+
38+
ret = find_gpu_device(hDriver, &hDevice);
39+
if (ret || hDevice == NULL) {
40+
fprintf(stderr, "Cannot find GPU device!\n");
41+
return ret;
42+
}
43+
44+
ret = create_context(hDriver, &hContext);
45+
if (ret != 0) {
46+
fprintf(stderr, "Failed to create L0 context!\n");
47+
return ret;
48+
}
49+
50+
// Setup parameters for the Level Zero memory provider. It will be used for
51+
// allocating memory from Level Zero devices.
52+
level_zero_memory_provider_params_t ze_memory_provider_params;
53+
ze_memory_provider_params.level_zero_context_handle = hContext;
54+
ze_memory_provider_params.level_zero_device_handle = hDevice;
55+
// Set the memory type to shared to allow the memory to be accessed on both
56+
// CPU and GPU.
57+
ze_memory_provider_params.memory_type = UMF_MEMORY_TYPE_SHARED;
58+
59+
// Create Level Zero memory provider
60+
umf_memory_provider_handle_t ze_memory_provider;
61+
res = umfMemoryProviderCreate(umfLevelZeroMemoryProviderOps(),
62+
&ze_memory_provider_params,
63+
&ze_memory_provider);
64+
if (res != UMF_RESULT_SUCCESS) {
65+
fprintf(stderr, "Failed to create a memory provider!\n");
66+
goto level_zero_destroy;
67+
}
68+
69+
printf("Level Zero memory provider created at %p\n",
70+
(void *)ze_memory_provider);
71+
72+
// Setup parameters for the Disjoint Pool. It will be used for managing the
73+
// memory allocated using memory provider.
74+
umf_disjoint_pool_params_t disjoint_memory_pool_params =
75+
umfDisjointPoolParamsDefault();
76+
// Set the Slab Min Size to 64KB - the page size for GPU allocations
77+
disjoint_memory_pool_params.SlabMinSize = 64 * 1024L;
78+
// We would keep only single slab per each allocation bucket
79+
disjoint_memory_pool_params.Capacity = 1;
80+
// Set the maximum poolable size to 64KB - objects with size above this
81+
// limit will not be stored/allocated from the pool.
82+
disjoint_memory_pool_params.MaxPoolableSize = 64 * 1024L;
83+
// Enable tracing
84+
disjoint_memory_pool_params.PoolTrace = 1;
85+
86+
// Create Disjoint Pool memory pool.
87+
umf_memory_pool_handle_t ze_disjoint_memory_pool;
88+
res = umfPoolCreate(umfDisjointPoolOps(), ze_memory_provider,
89+
&disjoint_memory_pool_params, UMF_POOL_CREATE_FLAG_NONE,
90+
&ze_disjoint_memory_pool);
91+
if (res != UMF_RESULT_SUCCESS) {
92+
fprintf(stderr, "Failed to create a memory pool!\n");
93+
goto memory_provider_destroy;
94+
}
95+
96+
printf("Disjoint Pool created at %p\n", (void *)ze_disjoint_memory_pool);
97+
98+
// Allocate some memory from the pool
99+
int *ptr = (int *)umfPoolMalloc(ze_disjoint_memory_pool, sizeof(int));
100+
if (res != UMF_RESULT_SUCCESS) {
101+
fprintf(stderr, "Failed to allocate memory from the memory pool!\n");
102+
goto memory_pool_destroy;
103+
}
104+
105+
// Use allocated memory
106+
*ptr = 1;
107+
108+
// Free allocated memory
109+
res = umfFree(ptr);
110+
if (res != UMF_RESULT_SUCCESS) {
111+
fprintf(stderr, "Failed to free memory to the pool!\n");
112+
goto memory_pool_destroy;
113+
}
114+
printf("Freed memory at %p\n", (void *)ptr);
115+
116+
// Cleanup
117+
umfPoolDestroy(ze_disjoint_memory_pool);
118+
umfMemoryProviderDestroy(ze_memory_provider);
119+
zeContextDestroy(hContext);
120+
return 0;
121+
122+
memory_pool_destroy:
123+
umfPoolDestroy(ze_disjoint_memory_pool);
124+
125+
memory_provider_destroy:
126+
umfMemoryProviderDestroy(ze_memory_provider);
127+
128+
level_zero_destroy:
129+
zeContextDestroy(hContext);
130+
return -1;
131+
}

0 commit comments

Comments
 (0)