Skip to content

Commit 5c76d4c

Browse files
authored
[UR] Remove unnecessary and confusing unique_ptr usage (#17144)
`std::unique_ptr` was being used as a scoped deleter for a UMF value, but this was both confusing and more expensive than it needed to be. Here we introduce the simple `OnScopeExit` class which calls a callable when it goes out of scope, and use it here to simplify the meaning and overhead of the CUDA adapter's UMF pool allocation.
1 parent d411af4 commit 5c76d4c

File tree

4 files changed

+37
-24
lines changed

4 files changed

+37
-24
lines changed

unified-runtime/source/adapters/cuda/common.hpp

-4
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,6 @@ void assertion(bool Condition, const char *Message = nullptr);
7373

7474
namespace umf {
7575

76-
using cuda_params_unique_handle_t = std::unique_ptr<
77-
umf_cuda_memory_provider_params_t,
78-
std::function<umf_result_t(umf_cuda_memory_provider_params_handle_t)>>;
79-
8076
inline umf_result_t setCUMemoryProviderParams(
8177
umf_cuda_memory_provider_params_handle_t CUMemoryProviderParams,
8278
int cuDevice, void *cuContext, umf_usm_memory_type_t memType) {

unified-runtime/source/adapters/cuda/context.hpp

+7-10
Original file line numberDiff line numberDiff line change
@@ -80,28 +80,25 @@ static ur_result_t
8080
CreateHostMemoryProviderPool(ur_device_handle_t_ *DeviceHandle,
8181
umf_memory_provider_handle_t *MemoryProviderHost,
8282
umf_memory_pool_handle_t *MemoryPoolHost) {
83-
umf_cuda_memory_provider_params_handle_t CUMemoryProviderParams = nullptr;
8483

8584
*MemoryProviderHost = nullptr;
8685
CUcontext context = DeviceHandle->getNativeContext();
8786

87+
umf_cuda_memory_provider_params_handle_t CUMemoryProviderParams = nullptr;
8888
umf_result_t UmfResult =
8989
umfCUDAMemoryProviderParamsCreate(&CUMemoryProviderParams);
9090
UMF_RETURN_UR_ERROR(UmfResult);
91+
OnScopeExit Cleanup(
92+
[=]() { umfCUDAMemoryProviderParamsDestroy(CUMemoryProviderParams); });
9193

92-
umf::cuda_params_unique_handle_t CUMemoryProviderParamsUnique(
93-
CUMemoryProviderParams, umfCUDAMemoryProviderParamsDestroy);
94-
95-
UmfResult = umf::setCUMemoryProviderParams(CUMemoryProviderParamsUnique.get(),
96-
0 /* cuDevice */, context,
97-
UMF_MEMORY_TYPE_HOST);
94+
UmfResult = umf::setCUMemoryProviderParams(
95+
CUMemoryProviderParams, 0 /* cuDevice */, context, UMF_MEMORY_TYPE_HOST);
9896
UMF_RETURN_UR_ERROR(UmfResult);
9997

10098
// create UMF CUDA memory provider and pool for the host memory
10199
// (UMF_MEMORY_TYPE_HOST)
102-
UmfResult = umfMemoryProviderCreate(umfCUDAMemoryProviderOps(),
103-
CUMemoryProviderParamsUnique.get(),
104-
MemoryProviderHost);
100+
UmfResult = umfMemoryProviderCreate(
101+
umfCUDAMemoryProviderOps(), CUMemoryProviderParams, MemoryProviderHost);
105102
UMF_RETURN_UR_ERROR(UmfResult);
106103

107104
UmfResult = umfPoolCreate(umfProxyPoolOps(), *MemoryProviderHost, nullptr, 0,

unified-runtime/source/adapters/cuda/platform.cpp

+8-10
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ CreateDeviceMemoryProvidersPools(ur_platform_handle_t_ *Platform) {
2727
umfCUDAMemoryProviderParamsCreate(&CUMemoryProviderParams);
2828
UMF_RETURN_UR_ERROR(UmfResult);
2929

30-
umf::cuda_params_unique_handle_t CUMemoryProviderParamsUnique(
31-
CUMemoryProviderParams, umfCUDAMemoryProviderParamsDestroy);
30+
OnScopeExit Cleanup(
31+
[=]() { umfCUDAMemoryProviderParamsDestroy(CUMemoryProviderParams); });
3232

3333
for (auto &Device : Platform->Devices) {
3434
ur_device_handle_t_ *device_handle = Device.get();
@@ -37,25 +37,23 @@ CreateDeviceMemoryProvidersPools(ur_platform_handle_t_ *Platform) {
3737

3838
// create UMF CUDA memory provider for the device memory
3939
// (UMF_MEMORY_TYPE_DEVICE)
40-
UmfResult =
41-
umf::setCUMemoryProviderParams(CUMemoryProviderParamsUnique.get(),
42-
device, context, UMF_MEMORY_TYPE_DEVICE);
40+
UmfResult = umf::setCUMemoryProviderParams(CUMemoryProviderParams, device,
41+
context, UMF_MEMORY_TYPE_DEVICE);
4342
UMF_RETURN_UR_ERROR(UmfResult);
4443

4544
UmfResult = umfMemoryProviderCreate(umfCUDAMemoryProviderOps(),
46-
CUMemoryProviderParamsUnique.get(),
45+
CUMemoryProviderParams,
4746
&device_handle->MemoryProviderDevice);
4847
UMF_RETURN_UR_ERROR(UmfResult);
4948

5049
// create UMF CUDA memory provider for the shared memory
5150
// (UMF_MEMORY_TYPE_SHARED)
52-
UmfResult =
53-
umf::setCUMemoryProviderParams(CUMemoryProviderParamsUnique.get(),
54-
device, context, UMF_MEMORY_TYPE_SHARED);
51+
UmfResult = umf::setCUMemoryProviderParams(CUMemoryProviderParams, device,
52+
context, UMF_MEMORY_TYPE_SHARED);
5553
UMF_RETURN_UR_ERROR(UmfResult);
5654

5755
UmfResult = umfMemoryProviderCreate(umfCUDAMemoryProviderOps(),
58-
CUMemoryProviderParamsUnique.get(),
56+
CUMemoryProviderParams,
5957
&device_handle->MemoryProviderShared);
6058
UMF_RETURN_UR_ERROR(UmfResult);
6159

unified-runtime/source/common/ur_util.hpp

+22
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <sstream>
2626
#include <string.h>
2727
#include <string>
28+
#include <type_traits>
2829
#include <vector>
2930

3031
int ur_getpid(void);
@@ -484,6 +485,27 @@ template <typename T> class AtomicSingleton {
484485
}
485486
};
486487

488+
// A type that will call your function on exit of the current scope. Useful for
489+
// avoiding leaks with C APIs.
490+
// e.g.
491+
//
492+
// {
493+
// OnScopeExit _([]() { puts("out of scope"); };
494+
// }
495+
//
496+
// Decent compilers (and MSVC) will optimize the above to a simple call to puts
497+
template <class Callable> struct OnScopeExit {
498+
const Callable Fn;
499+
OnScopeExit(Callable Fn) : Fn(Fn) {}
500+
// We don't want copies because this should only ever call the user function
501+
// once and we don't know where we might end up if we allow copies
502+
OnScopeExit(OnScopeExit &) = delete;
503+
OnScopeExit(OnScopeExit &&) = delete;
504+
~OnScopeExit() { Fn(); }
505+
};
506+
// Silence a warning about unintended deduction
507+
template <class Callable> OnScopeExit(Callable) -> OnScopeExit<Callable>;
508+
487509
template <typename Numeric>
488510
static inline std::string groupDigits(Numeric numeric) {
489511
auto number = std::to_string(numeric);

0 commit comments

Comments
 (0)