Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

L0 provider: implement min/recommended page size query #1059

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion include/umf/providers/provider_level_zero.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2024 Intel Corporation
* Copyright (C) 2024-2025 Intel Corporation
*
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Expand Down Expand Up @@ -83,6 +83,14 @@ umf_result_t umfLevelZeroMemoryProviderParamsSetFreePolicy(
umf_level_zero_memory_provider_params_handle_t hParams,
umf_level_zero_memory_provider_free_policy_t policy);

/// @brief Set the device ordinal in the parameters struct.
/// @param hParams handle to the parameters of the Level Zero Memory Provider.
/// @param deviceOrdinal device ordinal.
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
umf_result_t umfLevelZeroMemoryProviderSetDeviceOrdinal(
umf_level_zero_memory_provider_params_handle_t hParams,
uint32_t deviceOrdinal);

umf_memory_provider_ops_t *umfLevelZeroMemoryProviderOps(void);

#ifdef __cplusplus
Expand Down
277 changes: 167 additions & 110 deletions src/provider/provider_level_zero.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2024 Intel Corporation
* Copyright (C) 2024-2025 Intel Corporation
*
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Expand Down Expand Up @@ -118,6 +118,8 @@ typedef struct umf_level_zero_memory_provider_params_t {

umf_level_zero_memory_provider_free_policy_t
freePolicy; ///< Memory free policy

uint32_t device_ordinal;
} umf_level_zero_memory_provider_params_t;

typedef struct ze_memory_provider_t {
Expand All @@ -131,6 +133,10 @@ typedef struct ze_memory_provider_t {
ze_device_properties_t device_properties;

ze_driver_memory_free_policy_ext_flags_t freePolicyFlags;

size_t min_page_size;

uint32_t device_ordinal;
} ze_memory_provider_t;

typedef struct ze_ops_t {
Expand Down Expand Up @@ -159,6 +165,9 @@ typedef struct ze_ops_t {
ze_device_properties_t *);
ze_result_t (*zeMemFreeExt)(ze_context_handle_t,
ze_memory_free_ext_desc_t *, void *);
ze_result_t (*zeMemGetAllocProperties)(ze_context_handle_t, const void *,
ze_memory_allocation_properties_t *,
ze_device_handle_t *);
} ze_ops_t;

static ze_ops_t g_ze_ops;
Expand Down Expand Up @@ -214,13 +223,15 @@ static void init_ze_global_state(void) {
utils_get_symbol_addr(0, "zeDeviceGetProperties", lib_name);
*(void **)&g_ze_ops.zeMemFreeExt =
utils_get_symbol_addr(0, "zeMemFreeExt", lib_name);
*(void **)&g_ze_ops.zeMemGetAllocProperties =
utils_get_symbol_addr(0, "zeMemGetAllocProperties", lib_name);

if (!g_ze_ops.zeMemAllocHost || !g_ze_ops.zeMemAllocDevice ||
!g_ze_ops.zeMemAllocShared || !g_ze_ops.zeMemFree ||
!g_ze_ops.zeMemGetIpcHandle || !g_ze_ops.zeMemOpenIpcHandle ||
!g_ze_ops.zeMemCloseIpcHandle ||
!g_ze_ops.zeContextMakeMemoryResident ||
!g_ze_ops.zeDeviceGetProperties) {
!g_ze_ops.zeDeviceGetProperties || !g_ze_ops.zeMemGetAllocProperties) {
// g_ze_ops.zeMemPutIpcHandle can be NULL because it was introduced
// starting from Level Zero 1.6
LOG_ERR("Required Level Zero symbols not found.");
Expand Down Expand Up @@ -250,6 +261,7 @@ umf_result_t umfLevelZeroMemoryProviderParamsCreate(
params->resident_device_handles = NULL;
params->resident_device_count = 0;
params->freePolicy = UMF_LEVEL_ZERO_MEMORY_PROVIDER_FREE_POLICY_DEFAULT;
params->device_ordinal = 0;

*hParams = params;

Expand Down Expand Up @@ -307,6 +319,18 @@ umf_result_t umfLevelZeroMemoryProviderParamsSetMemoryType(
return UMF_RESULT_SUCCESS;
}

umf_result_t umfLevelZeroMemoryProviderSetDeviceOrdinal(
umf_level_zero_memory_provider_params_handle_t hParams,
uint32_t deviceOrdinal) {
if (!hParams) {
LOG_ERR("Level zero memory provider params handle is NULL");
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}
hParams->device_ordinal = deviceOrdinal;

return UMF_RESULT_SUCCESS;
}

umf_result_t umfLevelZeroMemoryProviderParamsSetResidentDevices(
umf_level_zero_memory_provider_params_handle_t hParams,
ze_device_handle_t *hDevices, uint32_t deviceCount) {
Expand Down Expand Up @@ -351,100 +375,6 @@ umfFreePolicyToZePolicy(umf_level_zero_memory_provider_free_policy_t policy) {
return 0;
}
}

static umf_result_t ze_memory_provider_initialize(void *params,
void **provider) {
if (params == NULL) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

umf_level_zero_memory_provider_params_handle_t ze_params =
(umf_level_zero_memory_provider_params_handle_t)params;

if (!ze_params->level_zero_context_handle) {
LOG_ERR("Level Zero context handle is NULL");
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

if ((ze_params->memory_type == UMF_MEMORY_TYPE_HOST) ==
(ze_params->level_zero_device_handle != NULL)) {
LOG_ERR("Level Zero device handle is NULL");
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

if ((bool)ze_params->resident_device_count &&
(ze_params->resident_device_handles == NULL)) {
LOG_ERR("Resident devices handles array is NULL, but device_count is "
"not zero");
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

utils_init_once(&ze_is_initialized, init_ze_global_state);
if (Init_ze_global_state_failed) {
LOG_ERR("Loading Level Zero symbols failed");
return UMF_RESULT_ERROR_UNKNOWN;
}

ze_memory_provider_t *ze_provider =
umf_ba_global_alloc(sizeof(ze_memory_provider_t));
if (!ze_provider) {
LOG_ERR("Cannot allocate memory for Level Zero Memory Provider");
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
}

ze_provider->context = ze_params->level_zero_context_handle;
ze_provider->device = ze_params->level_zero_device_handle;
ze_provider->memory_type = (ze_memory_type_t)ze_params->memory_type;
ze_provider->freePolicyFlags =
umfFreePolicyToZePolicy(ze_params->freePolicy);

memset(&ze_provider->device_properties, 0,
sizeof(ze_provider->device_properties));
ze_provider->device_properties.stype = ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES;

if (ze_provider->device) {
umf_result_t ret = ze2umf_result(g_ze_ops.zeDeviceGetProperties(
ze_provider->device, &ze_provider->device_properties));

if (ret != UMF_RESULT_SUCCESS) {
LOG_ERR("Cannot get device properties");
umf_ba_global_free(ze_provider);
return ret;
}
}

if (ze_params->resident_device_count) {
ze_provider->resident_device_handles = umf_ba_global_alloc(
sizeof(ze_device_handle_t) * ze_params->resident_device_count);
if (!ze_provider->resident_device_handles) {
LOG_ERR("Cannot allocate memory for resident devices");
umf_ba_global_free(ze_provider);
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
}

ze_provider->resident_device_count = ze_params->resident_device_count;

for (uint32_t i = 0; i < ze_provider->resident_device_count; i++) {
ze_provider->resident_device_handles[i] =
ze_params->resident_device_handles[i];
}
} else {
ze_provider->resident_device_handles = NULL;
ze_provider->resident_device_count = 0;
}

*provider = ze_provider;

return UMF_RESULT_SUCCESS;
}

static void ze_memory_provider_finalize(void *provider) {
ze_memory_provider_t *ze_provider = (ze_memory_provider_t *)provider;
umf_ba_global_free(ze_provider->resident_device_handles);

umf_ba_global_free(provider);
}

static bool use_relaxed_allocation(ze_memory_provider_t *ze_provider,
size_t size) {
assert(ze_provider);
Expand Down Expand Up @@ -482,8 +412,7 @@ static umf_result_t ze_memory_provider_alloc(void *provider, size_t size,
? &relaxed_device_allocation_desc
: NULL,
.flags = 0,
.ordinal = 0 // TODO
};
.ordinal = ze_provider->device_ordinal};
ze_result = g_ze_ops.zeMemAllocDevice(ze_provider->context, &dev_desc,
size, alignment,
ze_provider->device, resultPtr);
Expand All @@ -500,8 +429,7 @@ static umf_result_t ze_memory_provider_alloc(void *provider, size_t size,
? &relaxed_device_allocation_desc
: NULL,
.flags = 0,
.ordinal = 0 // TODO
};
.ordinal = ze_provider->device_ordinal};
ze_result = g_ze_ops.zeMemAllocShared(ze_provider->context, &dev_desc,
&host_desc, size, alignment,
ze_provider->device, resultPtr);
Expand Down Expand Up @@ -553,6 +481,132 @@ static umf_result_t ze_memory_provider_free(void *provider, void *ptr,
g_ze_ops.zeMemFreeExt(ze_provider->context, &desc, ptr));
}

static umf_result_t query_min_page_size(ze_memory_provider_t *ze_provider,
size_t *min_page_size) {
assert(min_page_size);

LOG_DEBUG("Querying minimum page size");

void *ptr;
umf_result_t result = ze_memory_provider_alloc(ze_provider, 1, 0, &ptr);
if (result != UMF_RESULT_SUCCESS) {
return result;
}

ze_memory_allocation_properties_t properties = {
.stype = ZE_STRUCTURE_TYPE_MEMORY_ALLOCATION_PROPERTIES};
ze_result_t ze_result = g_ze_ops.zeMemGetAllocProperties(
ze_provider->context, ptr, &properties, NULL);

*min_page_size = properties.pageSize;

ze_memory_provider_free(ze_provider, ptr, 1);

return ze2umf_result(ze_result);
}

static void ze_memory_provider_finalize(void *provider) {
ze_memory_provider_t *ze_provider = (ze_memory_provider_t *)provider;
umf_ba_global_free(ze_provider->resident_device_handles);

umf_ba_global_free(provider);
}

static umf_result_t ze_memory_provider_initialize(void *params,
void **provider) {
if (params == NULL) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

umf_level_zero_memory_provider_params_handle_t ze_params =
(umf_level_zero_memory_provider_params_handle_t)params;

if (!ze_params->level_zero_context_handle) {
LOG_ERR("Level Zero context handle is NULL");
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

if ((ze_params->memory_type == UMF_MEMORY_TYPE_HOST) ==
(ze_params->level_zero_device_handle != NULL)) {
LOG_ERR("Level Zero device handle is NULL");
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

if ((bool)ze_params->resident_device_count &&
(ze_params->resident_device_handles == NULL)) {
LOG_ERR("Resident devices handles array is NULL, but device_count is "
"not zero");
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

utils_init_once(&ze_is_initialized, init_ze_global_state);
if (Init_ze_global_state_failed) {
LOG_ERR("Loading Level Zero symbols failed");
return UMF_RESULT_ERROR_UNKNOWN;
}

ze_memory_provider_t *ze_provider =
umf_ba_global_alloc(sizeof(ze_memory_provider_t));
if (!ze_provider) {
LOG_ERR("Cannot allocate memory for Level Zero Memory Provider");
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
}

ze_provider->context = ze_params->level_zero_context_handle;
ze_provider->device = ze_params->level_zero_device_handle;
ze_provider->memory_type = (ze_memory_type_t)ze_params->memory_type;
ze_provider->freePolicyFlags =
umfFreePolicyToZePolicy(ze_params->freePolicy);
ze_provider->min_page_size = 0;
ze_provider->device_ordinal = ze_params->device_ordinal;

memset(&ze_provider->device_properties, 0,
sizeof(ze_provider->device_properties));
ze_provider->device_properties.stype = ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES;

if (ze_provider->device) {
umf_result_t ret = ze2umf_result(g_ze_ops.zeDeviceGetProperties(
ze_provider->device, &ze_provider->device_properties));

if (ret != UMF_RESULT_SUCCESS) {
LOG_ERR("Cannot get device properties");
umf_ba_global_free(ze_provider);
return ret;
}
}

if (ze_params->resident_device_count) {
ze_provider->resident_device_handles = umf_ba_global_alloc(
sizeof(ze_device_handle_t) * ze_params->resident_device_count);
if (!ze_provider->resident_device_handles) {
LOG_ERR("Cannot allocate memory for resident devices");
umf_ba_global_free(ze_provider);
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
}

ze_provider->resident_device_count = ze_params->resident_device_count;

for (uint32_t i = 0; i < ze_provider->resident_device_count; i++) {
ze_provider->resident_device_handles[i] =
ze_params->resident_device_handles[i];
}
} else {
ze_provider->resident_device_handles = NULL;
ze_provider->resident_device_count = 0;
}

umf_result_t result =
query_min_page_size(ze_provider, &ze_provider->min_page_size);
if (result != UMF_RESULT_SUCCESS) {
ze_memory_provider_finalize(provider);
return result;
}

*provider = ze_provider;

return UMF_RESULT_SUCCESS;
}

static void ze_memory_provider_get_last_native_error(void *provider,
const char **ppMessage,
int32_t *pError) {
Expand All @@ -569,12 +623,19 @@ static void ze_memory_provider_get_last_native_error(void *provider,
static umf_result_t ze_memory_provider_get_min_page_size(void *provider,
void *ptr,
size_t *pageSize) {
(void)provider;
(void)ptr;
ze_memory_provider_t *ze_provider = (ze_memory_provider_t *)provider;

// TODO
*pageSize = 1024 * 64;
return UMF_RESULT_SUCCESS;
if (!ptr) {
*pageSize = ze_provider->min_page_size;
return UMF_RESULT_SUCCESS;
}

ze_memory_allocation_properties_t properties = {
.stype = ZE_STRUCTURE_TYPE_MEMORY_ALLOCATION_PROPERTIES};
ze_result_t ze_result = g_ze_ops.zeMemGetAllocProperties(
ze_provider->context, ptr, &properties, NULL);

return ze2umf_result(ze_result);
}

static umf_result_t ze_memory_provider_purge_lazy(void *provider, void *ptr,
Expand All @@ -600,12 +661,8 @@ static umf_result_t ze_memory_provider_purge_force(void *provider, void *ptr,
static umf_result_t
ze_memory_provider_get_recommended_page_size(void *provider, size_t size,
size_t *pageSize) {
(void)provider;
(void)size;

// TODO
*pageSize = 1024 * 64;
return UMF_RESULT_SUCCESS;
return ze_memory_provider_get_min_page_size(provider, NULL, pageSize);
}

static const char *ze_memory_provider_get_name(void *provider) {
Expand Down
Loading
Loading