Skip to content

Commit 66baf7a

Browse files
committed
Add IPC example with Level 0 provider
1 parent 34c584d commit 66baf7a

File tree

5 files changed

+425
-0
lines changed

5 files changed

+425
-0
lines changed

examples/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,5 @@ else()
3434
"Basic example requires UMF_BUILD_LIBUMF_POOL_SCALABLE and UMF_ENABLE_POOL_TRACKING
3535
to be turned ON - skipping")
3636
endif()
37+
38+
add_subdirectory(ipc_level_zero)

examples/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,11 @@ This example covers the basics of UMF API. It walks you through a basic usage of
99
### Required CMake configuration flags
1010
* UMF_BUILD_LIBUMF_POOL_SCALABLE=ON
1111
* UMF_ENABLE_POOL_TRACKING=ON
12+
13+
## IPC example with Level Zero memory provider
14+
This example demonstrates how to use UMF IPC API. The example creates two memory pools of Level Zero device memory: the producer pool (where the buffer is allocated) and the consumer pool (where the IPC handle is mapped). To run and build this example Level Zero development package should be installed.
15+
16+
### Required CMake configuration flags
17+
* UMF_BUILD_LIBUMF_POOL_DISJOINT=ON
18+
* UMF_BUILD_LEVEL_ZERO_PROVIDER=ON
19+
* UMF_ENABLE_POOL_TRACKING=ON
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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+
if(UMF_BUILD_LIBUMF_POOL_DISJOINT AND UMF_ENABLE_POOL_TRACKING AND UMF_BUILD_LEVEL_ZERO_PROVIDER)
6+
set(EXAMPLE_NAME umf_example_ipc_level_zero)
7+
8+
add_umf_executable(
9+
NAME ${EXAMPLE_NAME}
10+
SRCS ipc_level_zero.c
11+
LIBS umf disjoint_pool ze_loader)
12+
13+
target_include_directories(
14+
${EXAMPLE_NAME} PRIVATE ${UMF_CMAKE_SOURCE_DIR}/src/utils
15+
${UMF_CMAKE_SOURCE_DIR}/include)
16+
17+
target_link_directories(${EXAMPLE_NAME} PRIVATE ${LIBHWLOC_LIBRARY_DIRS})
18+
19+
add_test(
20+
NAME ${EXAMPLE_NAME}
21+
COMMAND ${EXAMPLE_NAME}
22+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
23+
24+
set_tests_properties(${EXAMPLE_NAME} PROPERTIES LABELS "example")
25+
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(
33+
STATUS
34+
"IPC Level 0 example requires UMF_BUILD_LIBUMF_POOL_DISJOINT, UMF_ENABLE_POOL_TRACKING
35+
and UMF_BUILD_LEVEL_ZERO_PROVIDER to be turned ON - skipping")
36+
endif()
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
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 <stdio.h>
11+
12+
#include "umf/ipc.h"
13+
#include "umf/memory_pool.h"
14+
#include "umf/pools/pool_disjoint.h"
15+
#include "umf/providers/provider_level_zero.h"
16+
17+
#include "utils_level_zero.h"
18+
19+
int create_level_zero_pool(ze_context_handle_t context,
20+
ze_device_handle_t device,
21+
umf_memory_pool_handle_t *pool) {
22+
// setup params
23+
level_zero_memory_provider_params_t params = {0};
24+
params.level_zero_context_handle = context;
25+
params.level_zero_device_handle = device;
26+
params.memory_type = UMF_MEMORY_TYPE_DEVICE;
27+
// create Level Zero provider
28+
umf_memory_provider_handle_t provider = 0;
29+
umf_result_t umf_result = umfMemoryProviderCreate(
30+
umfLevelZeroMemoryProviderOps(), &params, &provider);
31+
if (umf_result != UMF_RESULT_SUCCESS) {
32+
fprintf(stderr, "Failed to create Level Zero memory provider!\n");
33+
return -1;
34+
}
35+
36+
// create pool
37+
umf_pool_create_flags_t flags = UMF_POOL_CREATE_FLAG_OWN_PROVIDER;
38+
umf_disjoint_pool_params_t disjoint_params = umfDisjointPoolParamsDefault();
39+
umf_result = umfPoolCreate(umfDisjointPoolOps(), provider, &disjoint_params,
40+
flags, pool);
41+
if (umf_result != UMF_RESULT_SUCCESS) {
42+
fprintf(stderr, "Failed to create pool!\n");
43+
return -1;
44+
}
45+
46+
return 0;
47+
}
48+
49+
int main(void) {
50+
uint32_t driver_idx = 0;
51+
ze_driver_handle_t driver = NULL;
52+
ze_device_handle_t device = NULL;
53+
ze_context_handle_t producer_context = NULL;
54+
ze_context_handle_t consumer_context = NULL;
55+
int ret = init_level_zero();
56+
if (ret != 0) {
57+
fprintf(stderr, "Failed to init Level 0!\n");
58+
return ret;
59+
}
60+
61+
ret = find_driver_with_gpu(&driver_idx, &driver);
62+
if (ret || driver == NULL) {
63+
fprintf(stderr, "Cannot find L0 driver with GPU device!\n");
64+
return ret;
65+
}
66+
67+
ret = create_context(driver, &producer_context);
68+
if (ret != 0) {
69+
fprintf(stderr, "Failed to create L0 context!\n");
70+
return ret;
71+
}
72+
73+
ret = create_context(driver, &consumer_context);
74+
if (ret != 0) {
75+
fprintf(stderr, "Failed to create L0 context!\n");
76+
return ret;
77+
}
78+
79+
ret = find_gpu_device(driver, &device);
80+
if (ret || device == NULL) {
81+
fprintf(stderr, "Cannot find GPU device!\n");
82+
return ret;
83+
}
84+
85+
// create producer pool
86+
umf_memory_pool_handle_t producer_pool = 0;
87+
ret = create_level_zero_pool(producer_context, device, &producer_pool);
88+
if (ret != 0) {
89+
fprintf(stderr, "Failed to create producer pool!\n");
90+
return ret;
91+
}
92+
93+
fprintf(stdout, "Producer pool created.\n");
94+
95+
void *initial_buf = umfPoolMalloc(producer_pool, 1024);
96+
if (!initial_buf) {
97+
fprintf(stderr, "Failed to allocate buffer from UMF pool!\n");
98+
return -1;
99+
}
100+
101+
fprintf(stdout, "Buffer allocated from the producer pool.\n");
102+
103+
umf_ipc_handle_t ipc_handle = NULL;
104+
size_t handle_size = 0;
105+
umf_result_t umf_result =
106+
umfGetIPCHandle(initial_buf, &ipc_handle, &handle_size);
107+
if (umf_result != UMF_RESULT_SUCCESS) {
108+
fprintf(stderr, "Failed to get IPC handle!\n");
109+
return -1;
110+
}
111+
112+
fprintf(stdout, "IPC handle obtained.\n");
113+
114+
// create consumer pool
115+
umf_memory_pool_handle_t consumer_pool = 0;
116+
ret = create_level_zero_pool(consumer_context, device, &consumer_pool);
117+
if (ret != 0) {
118+
fprintf(stderr, "Failed to create consumer pool!\n");
119+
return ret;
120+
}
121+
122+
fprintf(stdout, "Consumer pool created.\n");
123+
124+
void *mapped_buf = NULL;
125+
umf_result = umfOpenIPCHandle(consumer_pool, ipc_handle, &mapped_buf);
126+
if (umf_result != UMF_RESULT_SUCCESS) {
127+
fprintf(stderr, "Failed to open IPC handle!\n");
128+
return -1;
129+
}
130+
131+
fprintf(stdout, "IPC handle opened in the consumer pool.\n");
132+
133+
umf_result = umfPutIPCHandle(ipc_handle);
134+
if (umf_result != UMF_RESULT_SUCCESS) {
135+
fprintf(stderr, "Failed to put IPC handle!\n");
136+
return -1;
137+
}
138+
139+
fprintf(stdout, "IPC handle released in the producer pool.\n");
140+
141+
umf_result = umfCloseIPCHandle(mapped_buf);
142+
if (umf_result != UMF_RESULT_SUCCESS) {
143+
fprintf(stderr, "Failed to close IPC handle!\n");
144+
return -1;
145+
}
146+
147+
fprintf(stdout, "IPC handle closed in the consumer pool.\n");
148+
149+
umfFree(initial_buf);
150+
151+
umfPoolDestroy(producer_pool);
152+
umfPoolDestroy(consumer_pool);
153+
154+
return 0;
155+
}

0 commit comments

Comments
 (0)