From 2f380870df40405a2d083680b4b0b3aca2fc9cde Mon Sep 17 00:00:00 2001 From: German Andryeyev Date: Tue, 29 Mar 2022 17:26:38 -0400 Subject: [PATCH] SWDEV-328670 - Enable arena for ROCr interops Add ROCR memory detection and enable arena mem object for possible access in HIP Change-Id: Icf86ac789176bfee4ea8d36b0970a817d4c6a2f7 [ROCm/clr commit: 28597ec5b567f94d87e3979f600aaf13d1eab3c2] --- projects/clr/rocclr/device/device.hpp | 2 +- projects/clr/rocclr/device/rocm/rocdevice.cpp | 56 ++++++++++++++----- projects/clr/rocclr/device/rocm/rocdevice.hpp | 5 +- projects/clr/rocclr/platform/memory.hpp | 2 +- 4 files changed, 48 insertions(+), 17 deletions(-) diff --git a/projects/clr/rocclr/device/device.hpp b/projects/clr/rocclr/device/device.hpp index 4908a58b98..4db0dc6bc8 100644 --- a/projects/clr/rocclr/device/device.hpp +++ b/projects/clr/rocclr/device/device.hpp @@ -1887,7 +1887,7 @@ class Device : public RuntimeObject { void SetActiveWait(bool state) { activeWait_ = state; } - virtual amd::Memory* GetArenaMemObj(const void* ptr, size_t& offset) { + virtual amd::Memory* GetArenaMemObj(const void* ptr, size_t& offset, size_t size = 0) { return nullptr; } #if defined(__clang__) diff --git a/projects/clr/rocclr/device/rocm/rocdevice.cpp b/projects/clr/rocclr/device/rocm/rocdevice.cpp index 7fd144f8ec..8b7c33f7cc 100644 --- a/projects/clr/rocclr/device/rocm/rocdevice.cpp +++ b/projects/clr/rocclr/device/rocm/rocdevice.cpp @@ -774,16 +774,6 @@ bool Device::create() { return false; } - // only create arena_mem_object if CPU memory is accessible. - if (info_.hmmCpuMemoryAccessible_) { - arena_mem_obj_ = new (context()) amd::ArenaMemory(context()); - if (!arena_mem_obj_->create(nullptr)) { - LogError("Arena Memory Creation failed!"); - arena_mem_obj_->release(); - arena_mem_obj_ = nullptr; - } - } - if (amd::IS_HIP) { // Allocate initial heap for device memory allocator static constexpr size_t HeapBufferSize = 1024 * Ki; @@ -2386,7 +2376,7 @@ bool Device::GetSvmAttributes(void** data, size_t* data_sizes, int* attributes, // Query ptr type to see if it's a HMM allocation hsa_status_t status = hsa_amd_pointer_info( const_cast(dev_ptr), &ptr_info, nullptr, nullptr, nullptr); - // The call shoudl never fail in ROCR, but just check for an error and continue + // The call should never fail in ROCR, but just check for an error and continue if (status != HSA_STATUS_SUCCESS) { LogError("hsa_amd_pointer_info() failed"); } @@ -3084,12 +3074,25 @@ device::Signal* Device::createSignal() const { } // ================================================================================================ -amd::Memory* Device::GetArenaMemObj(const void* ptr, size_t& offset) { - // If arena_mem_obj_ is null, then HMM and Xnack is disabled. Return nullptr. - if (arena_mem_obj_ == nullptr) { +amd::Memory* Device::GetArenaMemObj(const void* ptr, size_t& offset, size_t size) { + // Only create arena_mem_object if CPU memory is accessible from HMM + // or if runtime received an interop from another ROCr's client + if (!info_.hmmCpuMemoryAccessible_ && !IsValidAllocation(ptr, size)) { return nullptr; } + if (arena_mem_obj_ == nullptr) { + arena_mem_obj_ = new (context()) amd::ArenaMemory(context()); + if ((arena_mem_obj_ != nullptr) && !arena_mem_obj_->create(nullptr)) { + LogError("Arena Memory Creation failed!"); + arena_mem_obj_->release(); + arena_mem_obj_ = nullptr; + } + if (arena_mem_obj_ == nullptr) { + return arena_mem_obj_; + } + } + // Calculate the offset of the pointer. const void* dev_ptr = reinterpret_cast(arena_mem_obj_->getDeviceMemory( *arena_mem_obj_->getContext().devices()[0])->virtualAddress()); @@ -3105,6 +3108,31 @@ void Device::ReleaseGlobalSignal(void* signal) const { } } +// ================================================================================================ +bool Device::IsValidAllocation(const void* dev_ptr, size_t size) const { + //! @todo Temporarily disable pointer detection feature, + //! until the new interfaces will be accepted in HIP API + return false; + hsa_amd_pointer_info_t ptr_info = {}; + ptr_info.size = sizeof(hsa_amd_pointer_info_t); + // Query ptr type to see if it's a HMM allocation + hsa_status_t status = hsa_amd_pointer_info( + const_cast(dev_ptr), &ptr_info, nullptr, nullptr, nullptr); + // The call should never fail in ROCR, but just check for an error and continue + if (status != HSA_STATUS_SUCCESS) { + LogError("hsa_amd_pointer_info() failed"); + } + // Check if it's a legacy non-HMM allocation in ROCr + if (ptr_info.type != HSA_EXT_POINTER_TYPE_UNKNOWN) { + if ((size != 0) && ((reinterpret_cast(dev_ptr) - + reinterpret_cast(ptr_info.agentBaseAddress)) > size)) { + return false; + } + return true; + } + return false; +} + // ================================================================================================ ProfilingSignal::~ProfilingSignal() { if (signal_.handle != 0) { diff --git a/projects/clr/rocclr/device/rocm/rocdevice.hpp b/projects/clr/rocclr/device/rocm/rocdevice.hpp index 5294d7780f..5004941a90 100644 --- a/projects/clr/rocclr/device/rocm/rocdevice.hpp +++ b/projects/clr/rocclr/device/rocm/rocdevice.hpp @@ -539,11 +539,14 @@ class Device : public NullDevice { void getGlobalCUMask(std::string cuMaskStr); - virtual amd::Memory* GetArenaMemObj(const void* ptr, size_t& offset); + virtual amd::Memory* GetArenaMemObj(const void* ptr, size_t& offset, size_t size = 0); const uint32_t getPreferredNumaNode() const { return preferred_numa_node_; } const bool isFineGrainSupported() const; + //! Returns True if memory pointer is known to ROCr (excludes HMM allocations) + bool IsValidAllocation(const void* dev_ptr, size_t size) const; + private: bool create(); diff --git a/projects/clr/rocclr/platform/memory.hpp b/projects/clr/rocclr/platform/memory.hpp index 7f1d8372bc..98e67a4de5 100644 --- a/projects/clr/rocclr/platform/memory.hpp +++ b/projects/clr/rocclr/platform/memory.hpp @@ -138,7 +138,7 @@ class Memory : public amd::RuntimeObject { public: enum MemoryType { kSvmMemoryPtr = 0x1, - kArenaMemoryPtr = 0x2 + kArenaMemoryPtr = 0x100 }; struct UserData