-
Notifications
You must be signed in to change notification settings - Fork 37
Make it possible to create Fixed Provider from pointer of UMF memory pool #1121
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -267,6 +267,58 @@ static umf_result_t trackingAllocationSplit(void *hProvider, void *ptr, | |
return ret; | ||
} | ||
|
||
// shrink (or remove) an entry in the tracker and return the totalSize of the original entry | ||
umf_result_t trackerShrinkEntry(void *hProvider, void *ptr, size_t shrinkSize, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do not think it is a good idea for several reasons:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we could restrict this functionality to using only the whole allocations, splitting and merging would not be needed. I will prepare an additional commit with those changes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @vinser52 I have prepared one commit with this change (only the whole allocation can be used) - on the https://github.com/ldorau/unified-memory-framework/tree/Replace_trackerShrinkEntry_with_trackerRemoveEntry branch. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @vinser52 Just a brief explanation to paint the background for the later discussion: This new functionality is needed for async API in UR/SYCL/LLVM (oneapi-src/unified-runtime#2180). We need to create a native pool based on the Fixed-size Memory Provider created from a user-provided buffer that comes from a USM pool based on Disjoint Pool with the L0 memory provider (see here) - @kswiecicki please correct me if I am wrong. Using Disjoint Pool we cannot guarantee that we will receive from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
We have to create a nested UMF pool here, what causes that we have to add the same entry to the tracker for the second time. This seems to be the simplest and the fastest solution of this issue.
The upstream provider is L0 memory provider that does not support splitting and merging.
This feature is enabled only in the Fixed-size memory provider that does not support IPC at all yet. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, the pool handle param seems to be optional here: https://github.com/intel/llvm/pull/17117/files#diff-b4c22134fb720af1413e8c0d1a8c737092bae2a747ce73ca4d803773249eb81bR242. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In case of NULL pool handle the default pool is used. And UR knows the default pool handle There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is also a matter of UR queries: urUSMGetMemAllocInfo with https://github.com/intel/llvm/blob/sycl/unified-runtime/include/ur_api.h#L4230 I'm not sure if the spec for async says anything about this, but I think returning the underlying pool here would be a misleading. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
We can't implement this feature (if we indeed need tracking capabilities) without changing the tracker behavior somehow. I do agree that we lose some information in the tracker with this approach. Now, only the fixed_provider knows everything about the original allocation, and to support IPC, I think the fixed_provider would have to forward calls to the original provider. (this might also apply to other functions, like get_recommended_page_size()). If we extended the provider to allow multiple values to be kept on a stack for every key, as @lplewa proposed, we would keep all the information, but then the IPC implementation would need to have some extra logic to extract the correct provider. Also, merge/split implementation might become a bit complicated. By the way, in the current implementation instead of adding trackerShrinkEntry/trackerShrinkGrow I think we could just add extra argument to trackerSplit/trackerMerge to specify whether to call upstream provider split/merge and use them. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I understand that we have to change somehow our tracking mechanism. Don't get me wrong I am not against of any changes, I just try to figure out the right way.
That is what I am worried about. Today we are implementing the Fixed provider and we are UMF experts. Imagine tomorrow some external people want to implement a provider similar to the Fixed provider do we want to propose them that way or should we think of a solution that exposes as little as possible UMF internals (memory tracker, IPC implementation, etc.).
If this extra logic that you have in mind will be encapsulated inside UMF it is fine, what we should avoid/decrease is delegating the challenges we have to the pool/provider implementers.
I did not get the idea, did you mean |
||
size_t *totalSize) { | ||
umf_result_t ret = UMF_RESULT_SUCCESS; | ||
umf_tracking_memory_provider_t *provider = | ||
(umf_tracking_memory_provider_t *)hProvider; | ||
|
||
int r = utils_mutex_lock(&provider->hTracker->splitMergeMutex); | ||
if (r) { | ||
return UMF_RESULT_ERROR_UNKNOWN; | ||
} | ||
|
||
tracker_alloc_info_t *value = (tracker_alloc_info_t *)critnib_get( | ||
provider->hTracker->alloc_segments_map, (uintptr_t)ptr); | ||
if (!value) { | ||
LOG_ERR("region for shrinking is not found in the tracker"); | ||
ret = UMF_RESULT_ERROR_INVALID_ARGUMENT; | ||
goto err; | ||
} | ||
if (shrinkSize > value->size) { | ||
LOG_ERR("requested size %zu to shrink exceeds the tracked size %zu", | ||
shrinkSize, value->size); | ||
ret = UMF_RESULT_ERROR_INVALID_ARGUMENT; | ||
goto err; | ||
} | ||
|
||
if (shrinkSize < value->size) { | ||
void *highPtr = (void *)(((uintptr_t)ptr) + shrinkSize); | ||
size_t secondSize = value->size - shrinkSize; | ||
kswiecicki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ret = umfMemoryTrackerAdd(provider->hTracker, provider->pool, highPtr, | ||
secondSize); | ||
if (ret != UMF_RESULT_SUCCESS) { | ||
LOG_ERR("failed to add the new shrunk region to the tracker, ptr = " | ||
"%p, size = %zu, ret = %d", | ||
highPtr, secondSize, ret); | ||
goto err; | ||
} | ||
} | ||
|
||
*totalSize = value->size; | ||
|
||
void *erasedValue = | ||
critnib_remove(provider->hTracker->alloc_segments_map, (uintptr_t)ptr); | ||
assert(erasedValue == value); | ||
umf_ba_free(provider->hTracker->alloc_info_allocator, erasedValue); | ||
|
||
err: | ||
utils_mutex_unlock(&provider->hTracker->splitMergeMutex); | ||
|
||
return ret; | ||
} | ||
|
||
static umf_result_t trackingAllocationMerge(void *hProvider, void *lowPtr, | ||
void *highPtr, size_t totalSize) { | ||
umf_result_t ret = UMF_RESULT_ERROR_UNKNOWN; | ||
|
@@ -353,6 +405,65 @@ static umf_result_t trackingAllocationMerge(void *hProvider, void *lowPtr, | |
return ret; | ||
} | ||
|
||
// grow (or add) an entry in the tracker to its original size | ||
umf_result_t trackerGrowEntry(void *hProvider, void *ptr, size_t growSize, | ||
size_t origSize) { | ||
umf_result_t ret = UMF_RESULT_SUCCESS; | ||
umf_tracking_memory_provider_t *provider = | ||
(umf_tracking_memory_provider_t *)hProvider; | ||
|
||
if (growSize > origSize) { | ||
LOG_ERR("Invalid grow size %zu (larger than the original size %zu)", | ||
growSize, origSize); | ||
return UMF_RESULT_ERROR_INVALID_ARGUMENT; | ||
} | ||
|
||
int r = utils_mutex_lock(&provider->hTracker->splitMergeMutex); | ||
if (r) { | ||
return UMF_RESULT_ERROR_UNKNOWN; | ||
} | ||
|
||
void *highPtr = (void *)(((uintptr_t)ptr) + growSize); | ||
tracker_alloc_info_t *highValue = NULL; | ||
|
||
if (growSize < origSize) { | ||
highValue = (tracker_alloc_info_t *)critnib_get( | ||
provider->hTracker->alloc_segments_map, (uintptr_t)highPtr); | ||
if (!highValue) { | ||
LOG_ERR("cannot find the tracker entry to grow %p", highPtr); | ||
ret = UMF_RESULT_ERROR_INVALID_ARGUMENT; | ||
goto err; | ||
} | ||
if (growSize + highValue->size != origSize) { | ||
LOG_ERR("Grow size plus the current size does not equal the " | ||
"original size"); | ||
ret = UMF_RESULT_ERROR_INVALID_ARGUMENT; | ||
goto err; | ||
} | ||
} | ||
|
||
ret = | ||
umfMemoryTrackerAdd(provider->hTracker, provider->pool, ptr, origSize); | ||
if (ret != UMF_RESULT_SUCCESS) { | ||
LOG_ERR("failed to add the new grown region to the tracker, ptr = %p, " | ||
"size = %zu, ret = %d", | ||
ptr, origSize, ret); | ||
goto err; | ||
} | ||
|
||
if (growSize < origSize) { | ||
void *erasedhighValue = critnib_remove( | ||
provider->hTracker->alloc_segments_map, (uintptr_t)highPtr); | ||
assert(erasedhighValue == highValue); | ||
umf_ba_free(provider->hTracker->alloc_info_allocator, erasedhighValue); | ||
} | ||
|
||
err: | ||
utils_mutex_unlock(&provider->hTracker->splitMergeMutex); | ||
|
||
return ret; | ||
} | ||
|
||
static umf_result_t trackingFree(void *hProvider, void *ptr, size_t size) { | ||
umf_result_t ret; | ||
umf_result_t ret_remove = UMF_RESULT_ERROR_UNKNOWN; | ||
|
Uh oh!
There was an error while loading. Please reload this page.