Skip to content

Commit daa3c56

Browse files
committed
mem props API
1 parent d079399 commit daa3c56

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1453
-94
lines changed

.github/workflows/.spellcheck-conf.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[default]
22
# Don't correct the following words:
3-
extend-ignore-words-re = ["ASSER", "Tne", "ba", "BA", "PN"]
3+
extend-ignore-words-re = ["ASSER", "Tne", "ba", "BA", "PN", "usm"]
44

55
[files]
66
# completely exclude those files from consideration:

.github/workflows/reusable_basic.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,12 @@ jobs:
195195
${{ matrix.compiler.cxx == 'icpx' && '. /opt/intel/oneapi/setvars.sh' || true }}
196196
cmake --build ${{env.BUILD_DIR}} -j $(nproc)
197197
198+
# UMF_LOG="level:debug;flush:debug;output:stderr;pid:no"
198199
- name: Run tests
199200
working-directory: ${{env.BUILD_DIR}}
200201
run: |
201202
${{ matrix.compiler.cxx == 'icpx' && '. /opt/intel/oneapi/setvars.sh' || true }}
202-
LD_LIBRARY_PATH="${{env.BUILD_DIR}}/lib/:${LD_LIBRARY_PATH}" ctest --output-on-failure
203+
LD_LIBRARY_PATH="${{env.BUILD_DIR}}/lib/:${LD_LIBRARY_PATH}" ctest --output-on-failure -R "test_provider_os_memory"
203204
204205
- name: Check coverage
205206
if: ${{ matrix.build_type == 'Debug' && matrix.compiler.c == 'gcc' }}

benchmark/ubench.c

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include <umf/ipc.h>
1717
#include <umf/memory_pool.h>
18+
#include <umf/memory_props.h>
1819
#include <umf/pools/pool_disjoint.h>
1920
#include <umf/pools/pool_proxy.h>
2021
#include <umf/pools/pool_scalable.h>
@@ -438,6 +439,48 @@ static void do_ipc_get_put_benchmark(alloc_t *allocs, size_t num_allocs,
438439
}
439440
}
440441

442+
static void do_umf_mem_props_benchmark(ze_context_handle_t context,
443+
bool use_umf, alloc_t *allocs,
444+
size_t num_allocs, size_t repeats) {
445+
assert(context != NULL);
446+
447+
for (size_t r = 0; r < repeats * 10; ++r) {
448+
for (size_t i = 0; i < num_allocs; ++i) {
449+
if (use_umf) {
450+
umf_memory_properties_handle_t props_handle = NULL;
451+
umf_result_t res =
452+
umfGetMemoryPropertiesHandle(allocs[i].ptr, &props_handle);
453+
(void)res;
454+
assert(res == UMF_RESULT_SUCCESS);
455+
456+
umf_usm_memory_type_t type = UMF_MEMORY_TYPE_UNKNOWN;
457+
res = umfGetMemoryProperty(props_handle,
458+
UMF_MEMORY_PROPERTY_POINTER_TYPE,
459+
sizeof(type), &type);
460+
assert(res == UMF_RESULT_SUCCESS);
461+
if (type != UMF_MEMORY_TYPE_DEVICE) {
462+
fprintf(stderr,
463+
"error: unexpected alloc_props.type value: %d\n",
464+
type);
465+
exit(-1);
466+
}
467+
} else {
468+
ze_memory_allocation_properties_t alloc_props = {0};
469+
ze_device_handle_t device = 0;
470+
// calls zeMemGetAllocProperties()
471+
utils_ze_get_mem_props(context, allocs[i].ptr, &alloc_props,
472+
&device);
473+
if (alloc_props.type != ZE_MEMORY_TYPE_DEVICE) {
474+
fprintf(stderr,
475+
"error: unexpected alloc_props.type value: %d\n",
476+
alloc_props.type);
477+
exit(-1);
478+
}
479+
}
480+
}
481+
}
482+
}
483+
441484
static int create_level_zero_params(ze_context_handle_t *context,
442485
ze_device_handle_t *device) {
443486
uint32_t driver_idx = 0;
@@ -623,6 +666,198 @@ UBENCH_EX(ipc, disjoint_pool_with_level_zero_provider) {
623666
err_destroy_context:
624667
utils_ze_destroy_context(context);
625668
}
669+
670+
UBENCH_EX(mem_props, level_zero) {
671+
const size_t BUFFER_SIZE = 100;
672+
const size_t N_BUFFERS = 1000;
673+
674+
alloc_t *allocs = alloc_array(N_BUFFERS);
675+
if (allocs == NULL) {
676+
fprintf(stderr, "error: alloc_array() failed\n");
677+
}
678+
679+
ze_context_handle_t context = NULL;
680+
ze_device_handle_t device = NULL;
681+
int ret = create_level_zero_params(&context, &device);
682+
if (ret != 0) {
683+
fprintf(stderr, "error: create_level_zero_params() failed\n");
684+
exit(-1);
685+
}
686+
687+
ze_device_mem_alloc_desc_t dev_desc = {
688+
.stype = ZE_STRUCTURE_TYPE_DEVICE_MEM_ALLOC_DESC,
689+
.pNext = NULL,
690+
.flags = 0,
691+
.ordinal = 0};
692+
693+
for (size_t i = 0; i < N_BUFFERS; ++i) {
694+
ze_result_t ze_result = zeMemAllocDevice(
695+
context, &dev_desc, BUFFER_SIZE, 0, device, &allocs[i].ptr);
696+
if (ze_result != ZE_RESULT_SUCCESS) {
697+
fprintf(stderr, "error: zeMemAllocDevice() failed\n");
698+
}
699+
allocs[i].size = BUFFER_SIZE;
700+
}
701+
702+
do_umf_mem_props_benchmark(context, false, allocs, N_BUFFERS,
703+
1); // WARMUP
704+
UBENCH_DO_BENCHMARK() {
705+
do_umf_mem_props_benchmark(context, false, allocs, N_BUFFERS,
706+
N_ITERATIONS);
707+
}
708+
709+
for (size_t i = 0; i < N_BUFFERS; ++i) {
710+
zeMemFree(context, allocs[i].ptr);
711+
}
712+
713+
free(allocs);
714+
utils_ze_destroy_context(context);
715+
}
716+
717+
UBENCH_EX(mem_props, disjoint_pool_with_level_zero_provider_use_umf) {
718+
const size_t BUFFER_SIZE = 4 * 1024;
719+
const size_t N_BUFFERS = 1000;
720+
umf_result_t umf_result;
721+
ze_context_handle_t context = NULL;
722+
ze_device_handle_t device = NULL;
723+
umf_level_zero_memory_provider_params_handle_t level_zero_params = NULL;
724+
725+
int ret = create_level_zero_params(&context, &device);
726+
if (ret != 0) {
727+
fprintf(stderr, "error: create_level_zero_params() failed\n");
728+
exit(-1);
729+
}
730+
731+
umf_result = umfLevelZeroMemoryProviderParamsCreate(&level_zero_params);
732+
if (umf_result != UMF_RESULT_SUCCESS) {
733+
fprintf(stderr,
734+
"error: umfLevelZeroMemoryProviderParamsCreate() failed\n");
735+
goto err_destroy_context;
736+
}
737+
738+
umf_result =
739+
umfLevelZeroMemoryProviderParamsSetContext(level_zero_params, context);
740+
if (umf_result != UMF_RESULT_SUCCESS) {
741+
fprintf(stderr,
742+
"error: umfLevelZeroMemoryProviderParamsSetContext() failed\n");
743+
goto err_destroy_params;
744+
}
745+
746+
umf_result =
747+
umfLevelZeroMemoryProviderParamsSetDevice(level_zero_params, device);
748+
if (umf_result != UMF_RESULT_SUCCESS) {
749+
fprintf(stderr,
750+
"error: umfLevelZeroMemoryProviderParamsSetDevice() failed\n");
751+
goto err_destroy_params;
752+
}
753+
754+
umf_result = umfLevelZeroMemoryProviderParamsSetMemoryType(
755+
level_zero_params, UMF_MEMORY_TYPE_DEVICE);
756+
if (umf_result != UMF_RESULT_SUCCESS) {
757+
fprintf(
758+
stderr,
759+
"error: umfLevelZeroMemoryProviderParamsSetMemoryType() failed\n");
760+
goto err_destroy_params;
761+
}
762+
763+
alloc_t *allocs = alloc_array(N_BUFFERS);
764+
if (allocs == NULL) {
765+
fprintf(stderr, "error: alloc_array() failed\n");
766+
goto err_destroy_context;
767+
}
768+
769+
umf_memory_provider_handle_t provider = NULL;
770+
umf_result = umfMemoryProviderCreate(umfLevelZeroMemoryProviderOps(),
771+
level_zero_params, &provider);
772+
if (umf_result != UMF_RESULT_SUCCESS) {
773+
fprintf(stderr, "error: umfMemoryProviderCreate() failed\n");
774+
goto err_free_allocs;
775+
}
776+
777+
umf_disjoint_pool_params_handle_t disjoint_params = NULL;
778+
umf_result = umfDisjointPoolParamsCreate(&disjoint_params);
779+
if (umf_result != UMF_RESULT_SUCCESS) {
780+
fprintf(stderr, "ERROR: umfDisjointPoolParamsCreate failed\n");
781+
goto err_provider_destroy;
782+
}
783+
784+
umf_result =
785+
umfDisjointPoolParamsSetSlabMinSize(disjoint_params, BUFFER_SIZE * 10);
786+
if (umf_result != UMF_RESULT_SUCCESS) {
787+
fprintf(stderr,
788+
"error: umfDisjointPoolParamsSetSlabMinSize() failed\n");
789+
goto err_params_destroy;
790+
}
791+
792+
umf_result = umfDisjointPoolParamsSetMaxPoolableSize(
793+
disjoint_params, 4ull * 1024ull * 1024ull);
794+
if (umf_result != UMF_RESULT_SUCCESS) {
795+
fprintf(stderr,
796+
"error: umfDisjointPoolParamsSetMaxPoolableSize() failed\n");
797+
goto err_params_destroy;
798+
}
799+
800+
umf_result =
801+
umfDisjointPoolParamsSetCapacity(disjoint_params, 64ull * 1024ull);
802+
if (umf_result != UMF_RESULT_SUCCESS) {
803+
fprintf(stderr, "error: umfDisjointPoolParamsSetCapacity() failed\n");
804+
goto err_params_destroy;
805+
}
806+
807+
umf_result = umfDisjointPoolParamsSetMinBucketSize(disjoint_params, 64);
808+
if (umf_result != UMF_RESULT_SUCCESS) {
809+
fprintf(stderr,
810+
"error: umfDisjointPoolParamsSetMinBucketSize() failed\n");
811+
goto err_params_destroy;
812+
}
813+
814+
umf_pool_create_flags_t flags = UMF_POOL_CREATE_FLAG_NONE;
815+
umf_memory_pool_handle_t pool;
816+
umf_result = umfPoolCreate(umfDisjointPoolOps(), provider, disjoint_params,
817+
flags, &pool);
818+
if (umf_result != UMF_RESULT_SUCCESS) {
819+
fprintf(stderr, "error: umfPoolCreate() failed\n");
820+
goto err_params_destroy;
821+
}
822+
823+
for (size_t i = 0; i < N_BUFFERS; ++i) {
824+
allocs[i].ptr = umfPoolMalloc(pool, BUFFER_SIZE);
825+
if (allocs[i].ptr == NULL) {
826+
goto err_buffer_destroy;
827+
}
828+
allocs[i].size = BUFFER_SIZE;
829+
}
830+
831+
do_umf_mem_props_benchmark(context, true, allocs, N_BUFFERS,
832+
1); // WARMUP
833+
UBENCH_DO_BENCHMARK() {
834+
do_umf_mem_props_benchmark(context, true, allocs, N_BUFFERS,
835+
N_ITERATIONS);
836+
}
837+
838+
err_buffer_destroy:
839+
for (size_t i = 0; i < N_BUFFERS; ++i) {
840+
umfPoolFree(pool, allocs[i].ptr);
841+
}
842+
843+
umfPoolDestroy(pool);
844+
845+
err_params_destroy:
846+
umfDisjointPoolParamsDestroy(disjoint_params);
847+
848+
err_provider_destroy:
849+
umfMemoryProviderDestroy(provider);
850+
851+
err_free_allocs:
852+
free(allocs);
853+
854+
err_destroy_params:
855+
umfLevelZeroMemoryProviderParamsDestroy(level_zero_params);
856+
857+
err_destroy_context:
858+
utils_ze_destroy_context(context);
859+
}
860+
626861
#endif /* (defined UMF_BUILD_LEVEL_ZERO_PROVIDER && defined UMF_BUILD_GPU_TESTS) */
627862

628863
// TODO add IPC benchmark for CUDA

docs/config/api.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ memory as well as functions that create, destroy and operate on the pool.
2828
.. doxygenfile:: memory_pool.h
2929
:sections: define enum typedef func var
3030

31+
TODO
32+
------------------------------------------
33+
34+
TODO
35+
36+
.. doxygenfile:: memory_props.h
37+
:sections: define enum typedef func var
38+
3139
Disjoint Pool
3240
------------------------------------------
3341

docs/config/spelling_exceptions.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ partList
4747
pid
4848
poolable
4949
preallocated
50+
propertyId
5051
providerIpcData
5152
providential
5253
ptr
@@ -71,4 +72,5 @@ umfPoolMallocUsableSize
7172
umfPoolRealloc
7273
umfMemspaceUserFilter
7374
umfMemspaceMemtargetAdd
74-
unfreed
75+
unfreed
76+
usm

include/umf/base.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,33 @@ typedef enum umf_result_t {
5151
UMF_RESULT_ERROR_UNKNOWN = 0x7ffffffe ///< Unknown error
5252
} umf_result_t;
5353

54+
/// @brief Handle to the memory properties structure
55+
typedef struct umf_memory_properties_t *umf_memory_properties_handle_t;
56+
57+
/// @brief ID of the memory property
58+
typedef enum umf_memory_property_id_t {
59+
UMF_MEMORY_PROPERTY_INVALID = -1, ///< Invalid property
60+
61+
// UMF specific
62+
UMF_MEMORY_PROPERTY_PROVIDER_HANDLE = 0, ///< Handle to the memory provider
63+
UMF_MEMORY_PROPERTY_POOL_HANDLE = 1, ///< Handle to the memory pool
64+
65+
// generic pointer properties
66+
UMF_MEMORY_PROPERTY_POINTER_TYPE =
67+
2, ///< Type of the pointer (umf_usm_memory_type_t)
68+
UMF_MEMORY_PROPERTY_BASE_ADDRESS = 3, ///< Base address of the allocation
69+
UMF_MEMORY_PROPERTY_BASE_SIZE = 4, ///< Base size of the allocation
70+
UMF_MEMORY_PROPERTY_BUFFER_ID = 5, ///< Unique identifier for the buffer
71+
72+
// GPU specific
73+
UMF_MEMORY_PROPERTY_CONTEXT = 6, ///< GPU context of the allocation
74+
UMF_MEMORY_PROPERTY_DEVICE = 7, ///< GPU device where the allocation resides
75+
76+
/// @cond
77+
UMF_MEMORY_PROPERTY_MAX_RESERVED = 0x1000, ///< Maximum reserved value
78+
/// @endcond
79+
} umf_memory_property_id_t;
80+
5481
/// @brief Type of the CTL query
5582
typedef enum umf_ctl_query_type {
5683
CTL_QUERY_READ,

include/umf/memory_props.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
*
3+
* Copyright (C) 2025 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+
#ifndef UMF_MEMORY_PROPS_H
11+
#define UMF_MEMORY_PROPS_H 1
12+
13+
#include <umf/base.h>
14+
15+
#ifdef __cplusplus
16+
extern "C" {
17+
#endif
18+
19+
/// @brief Get the memory properties handle for a given pointer
20+
/// @param ptr pointer to the allocated memory
21+
/// @param props_handle [out] pointer to the memory properties handle
22+
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure
23+
umf_result_t
24+
umfGetMemoryPropertiesHandle(const void *ptr,
25+
umf_memory_properties_handle_t *props_handle);
26+
27+
/// @brief Get a specific memory property from the properties handle
28+
/// @param props_handle handle to the memory properties
29+
/// @param memory_property_id ID of the memory property to get
30+
/// @param max_property_size size of the property value buffer
31+
/// @param property_value [out] pointer to the value of the memory property
32+
/// which will be filled
33+
// TODO check return type
34+
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure
35+
umf_result_t umfGetMemoryProperty(umf_memory_properties_handle_t props_handle,
36+
umf_memory_property_id_t memory_property_id,
37+
size_t max_property_size,
38+
void *property_value);
39+
40+
#ifdef __cplusplus
41+
}
42+
#endif
43+
44+
#endif /* UMF_MEMORY_PROPS_H */

0 commit comments

Comments
 (0)