diff --git a/projects/clr/rocclr/device/device.cpp b/projects/clr/rocclr/device/device.cpp index a25622ac18..3e8a284dec 100644 --- a/projects/clr/rocclr/device/device.cpp +++ b/projects/clr/rocclr/device/device.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008 - 2022 Advanced Micro Devices, Inc. +/* Copyright (c) 2008 - 2023 Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -817,6 +817,116 @@ char* Device::getExtensionString() { return result; } +// ================================================================================================ +bool Device::IpcCreate(void* dev_ptr, size_t* mem_size, void* handle, size_t* mem_offset) const { + amd::Memory* amd_mem_obj = amd::MemObjMap::FindMemObj(dev_ptr); + if (amd_mem_obj == nullptr) { + DevLogPrintfError("Cannot retrieve amd_mem_obj for dev_ptr: 0x%x", dev_ptr); + return false; + } + + // Get the original pointer from the amd::Memory object + void* orig_dev_ptr = nullptr; + if (amd_mem_obj->getSvmPtr() != nullptr) { + orig_dev_ptr = amd_mem_obj->getSvmPtr(); + } else if (amd_mem_obj->getHostMem() != nullptr) { + orig_dev_ptr = amd_mem_obj->getHostMem(); + } else { + ShouldNotReachHere(); + } + + // Check if the dev_ptr is lesser than original dev_ptr + if (orig_dev_ptr > dev_ptr) { + // If this happens, then revisit FindMemObj logic + DevLogPrintfError("Original dev_ptr: 0x%x cannot be greater than dev_ptr: 0x%x", orig_dev_ptr, + dev_ptr); + return false; + } + + // Calculate the memory offset from the original base ptr + *mem_offset = reinterpret_cast
(dev_ptr) - reinterpret_cast
(orig_dev_ptr); + *mem_size = amd_mem_obj->getSize(); + + // Check if the dev_ptr is greater than memory allocated + if (*mem_offset > *mem_size) { + DevLogPrintfError( + "Memory offset: %u cannot be greater than size of original memory allocated: %u", *mem_size, + *mem_offset); + return false; + } + auto dev_mem = static_cast(amd_mem_obj->getDeviceMemory(*this)); + auto result = dev_mem->ExportHandle(handle); + + return true; +} + +// ================================================================================================ +bool Device::IpcAttach(const void* handle, size_t mem_size, size_t mem_offset, unsigned int flags, + void** dev_ptr) const { + amd::Memory* amd_mem_obj = nullptr; + + // Create an amd Memory object for the handle + amd_mem_obj = new (context()) amd::IpcBuffer(context(), flags, mem_offset, mem_size, handle); + if (amd_mem_obj == nullptr) { + LogError("failed to create a mem object!"); + return false; + } + + if (!amd_mem_obj->create(nullptr)) { + LogError("failed to create a svm hidden buffer!"); + amd_mem_obj->release(); + return false; + } + + auto mem_obj_exist = amd::MemObjMap::FindMemObj(amd_mem_obj->getSvmPtr()); + if (mem_obj_exist == nullptr) { + // Add the original mem_ptr to the MemObjMap with newly created amd_mem_obj + amd::MemObjMap::AddMemObj(amd_mem_obj->getSvmPtr(), amd_mem_obj); + + // Make sure the mem_offset doesnt overflow the allocated memory + guarantee((mem_offset < mem_size), "IPC mem offset greater than allocated size"); + } else { + amd_mem_obj->release(); + amd_mem_obj = mem_obj_exist; + // Memory already exists, just retain the old one. + amd_mem_obj->retain(); + } + + *dev_ptr = amd_mem_obj->getSvmPtr(); + + return true; +} + +// ================================================================================================ +bool Device::IpcDetach(void* dev_ptr) const { + amd::Memory* amd_mem_obj = amd::MemObjMap::FindMemObj(dev_ptr); + if (amd_mem_obj == nullptr) { + DevLogPrintfError("Memory object for the ptr: 0x%x cannot be null \n", dev_ptr); + return false; + } + + if (!amd_mem_obj->ipcShared()) { + DevLogPrintfError("Memory object for the ptr: 0x%x is not ipcShared \n", dev_ptr); + return false; + } + + // Get the original pointer from the amd::Memory object + void* orig_dev_ptr = nullptr; + if (amd_mem_obj->getSvmPtr() != nullptr) { + orig_dev_ptr = amd_mem_obj->getSvmPtr(); + } else if (amd_mem_obj->getHostMem() != nullptr) { + orig_dev_ptr = amd_mem_obj->getHostMem(); + } else { + ShouldNotReachHere(); + } + + if (amd_mem_obj->release() == 0) { + amd::MemObjMap::RemoveMemObj(orig_dev_ptr); + } + + return true; +} + } // namespace amd namespace device { diff --git a/projects/clr/rocclr/device/device.hpp b/projects/clr/rocclr/device/device.hpp index 1a37677864..5074c6fb72 100644 --- a/projects/clr/rocclr/device/device.hpp +++ b/projects/clr/rocclr/device/device.hpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008 - 2022 Advanced Micro Devices, Inc. +/* Copyright (c) 2008 - 2023 Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -884,6 +884,9 @@ class Memory : public amd::HeapObject { //! Returns CPU pointer to HW state virtual const address cpuSrd() const { return nullptr; } + //! Returns an export handle for the interprocess communication + virtual bool ExportHandle(void* handle) const { return false; } + bool getAllowedPeerAccess() const { return (flags_ & AllowedPeerAccess) ? true : false; } void setAllowedPeerAccess(bool flag) { if (flag == true) { @@ -1894,21 +1897,12 @@ class Device : public RuntimeObject { //! Checks if OCL runtime can use hsail for compilation bool ValidateHsail(); - virtual bool IpcCreate(void* dev_ptr, size_t* mem_size, void* handle, size_t* mem_offset) const { - ShouldNotReachHere(); - return false; - } + bool IpcCreate(void* dev_ptr, size_t* mem_size, void* handle, size_t* mem_offset) const; - virtual bool IpcAttach(const void* handle, size_t mem_size, size_t mem_offset, - unsigned int flags, void** dev_ptr) const { - ShouldNotReachHere(); - return false; - } + bool IpcAttach(const void* handle, size_t mem_size, size_t mem_offset, unsigned int flags, + void** dev_ptr) const; - virtual bool IpcDetach(void* dev_ptr) const { - ShouldNotReachHere(); - return false; - } + bool IpcDetach(void* dev_ptr) const; //! Return context amd::Context& context() const { return *context_; } diff --git a/projects/clr/rocclr/device/pal/paldevice.cpp b/projects/clr/rocclr/device/pal/paldevice.cpp index 3bfaf31844..9b951eb258 100644 --- a/projects/clr/rocclr/device/pal/paldevice.cpp +++ b/projects/clr/rocclr/device/pal/paldevice.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008 - 2021 Advanced Micro Devices, Inc. +/* Copyright (c) 2008 - 2023 Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -2345,116 +2345,6 @@ void Device::virtualFree(void* addr) { } } -// ================================================================================================ -bool Device::IpcCreate(void* dev_ptr, size_t* mem_size, void* handle, size_t* mem_offset) const { - hsa_status_t hsa_status = HSA_STATUS_SUCCESS; - - amd::Memory* amd_mem_obj = amd::MemObjMap::FindMemObj(dev_ptr); - if (amd_mem_obj == nullptr) { - DevLogPrintfError("Cannot retrieve amd_mem_obj for dev_ptr: 0x%x", dev_ptr); - return false; - } - - // Get the original pointer from the amd::Memory object - void* orig_dev_ptr = nullptr; - if (amd_mem_obj->getSvmPtr() != nullptr) { - orig_dev_ptr = amd_mem_obj->getSvmPtr(); - } else if (amd_mem_obj->getHostMem() != nullptr) { - orig_dev_ptr = amd_mem_obj->getHostMem(); - } else { - ShouldNotReachHere(); - } - - // Check if the dev_ptr is lesser than original dev_ptr - if (orig_dev_ptr > dev_ptr) { - // If this happens, then revisit FindMemObj logic - DevLogPrintfError("Original dev_ptr: 0x%x cannot be greater than dev_ptr: 0x%x", orig_dev_ptr, - dev_ptr); - return false; - } - - // Calculate the memory offset from the original base ptr - *mem_offset = reinterpret_cast
(dev_ptr) - reinterpret_cast
(orig_dev_ptr); - *mem_size = amd_mem_obj->getSize(); - - // Check if the dev_ptr is greater than memory allocated - if (*mem_offset > *mem_size) { - DevLogPrintfError( - "Memory offset: %u cannot be greater than size of original memory allocated: %u", *mem_size, - *mem_offset); - return false; - } - auto dev_mem = getGpuMemory(amd_mem_obj); - *reinterpret_cast(handle) = dev_mem->ExportHandle(); - - return true; -} - -// ================================================================================================ -bool Device::IpcAttach(const void* handle, size_t mem_size, size_t mem_offset, unsigned int flags, - void** dev_ptr) const { - amd::Memory* amd_mem_obj = nullptr; - - // Note: ROCr path has a validation for duplicated IPC memory, but PAL currently can't - // identify the duplicates - - // Create an amd Memory object for the handle - amd_mem_obj = new (context()) amd::IpcBuffer(context(), flags, mem_offset, mem_size, - *reinterpret_cast(const_cast(handle))); - if (amd_mem_obj == nullptr) { - LogError("failed to create a mem object!"); - return false; - } - - if (!amd_mem_obj->create(nullptr)) { - LogError("failed to create a svm hidden buffer!"); - amd_mem_obj->release(); - return false; - } - - // Add the original mem_ptr to the MemObjMap with newly created amd_mem_obj - amd::MemObjMap::AddMemObj(amd_mem_obj->getSvmPtr(), amd_mem_obj); - - // Make sure the mem_offset doesnt overflow the allocated memory - guarantee((mem_offset < mem_size), "IPC mem offset greater than allocated size"); - - *dev_ptr = amd_mem_obj->getSvmPtr(); - - return true; -} - -// ================================================================================================ -bool Device::IpcDetach(void* dev_ptr) const { - hsa_status_t hsa_status = HSA_STATUS_SUCCESS; - - amd::Memory* amd_mem_obj = amd::MemObjMap::FindMemObj(dev_ptr); - if (amd_mem_obj == nullptr) { - DevLogPrintfError("Memory object for the ptr: 0x%x cannot be null \n", dev_ptr); - return false; - } - - if (!amd_mem_obj->ipcShared()) { - DevLogPrintfError("Memory object for the ptr: 0x%x is not ipcShared \n", dev_ptr); - return false; - } - - // Get the original pointer from the amd::Memory object - void* orig_dev_ptr = nullptr; - if (amd_mem_obj->getSvmPtr() != nullptr) { - orig_dev_ptr = amd_mem_obj->getSvmPtr(); - } else if (amd_mem_obj->getHostMem() != nullptr) { - orig_dev_ptr = amd_mem_obj->getHostMem(); - } else { - ShouldNotReachHere(); - } - - if (amd_mem_obj->release() == 0) { - amd::MemObjMap::RemoveMemObj(orig_dev_ptr); - } - - return true; -} - // ================================================================================================ bool Device::AcquireExclusiveGpuAccess() { // Lock the virtual GPU list diff --git a/projects/clr/rocclr/device/pal/paldevice.hpp b/projects/clr/rocclr/device/pal/paldevice.hpp index 3efc171729..da584569c3 100644 --- a/projects/clr/rocclr/device/pal/paldevice.hpp +++ b/projects/clr/rocclr/device/pal/paldevice.hpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2015 - 2021 Advanced Micro Devices, Inc. +/* Copyright (c) 2015 - 2023 Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -533,15 +533,6 @@ class Device : public NullDevice { virtual void* virtualAlloc(void* addr, size_t size, size_t alignment); virtual void virtualFree(void* addr); - //! Creates IPC memory handle from a provided SVM pointer - virtual bool IpcCreate(void* dev_ptr, size_t* mem_size, - void* handle, size_t* mem_offset) const override; - //! Attch IPC memory to the current device - virtual bool IpcAttach(const void* handle, size_t mem_size, size_t mem_offset, unsigned int flags, - void** dev_ptr) const override; - //! Detach IPC memory from the current device - virtual bool IpcDetach(void* dev_ptr) const override; - //! Returns SRD manger object SrdManager& srds() const { return *srdManager_; } diff --git a/projects/clr/rocclr/device/pal/palmemory.cpp b/projects/clr/rocclr/device/pal/palmemory.cpp index 2799aae9b1..33f356086d 100644 --- a/projects/clr/rocclr/device/pal/palmemory.cpp +++ b/projects/clr/rocclr/device/pal/palmemory.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2015 - 2022 Advanced Micro Devices, Inc. +/* Copyright (c) 2015 - 2023 Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -989,6 +989,7 @@ void Memory::mgpuCacheWriteBack(VirtualGPU& gpu) { } } +// ================================================================================================ Memory* Buffer::createBufferView(amd::Memory& subBufferOwner) const { pal::Memory* subBuffer; Resource::ViewParams params; @@ -1017,6 +1018,16 @@ Memory* Buffer::createBufferView(amd::Memory& subBufferOwner) const { return subBuffer; } +// ================================================================================================ +bool Buffer::ExportHandle(void* handle) const { + Pal::GpuMemoryExportInfo exportInfo = {}; + // Set default flags in case they are not provided by application + exportInfo.accessFlags = GENERIC_READ | GENERIC_WRITE; + *reinterpret_cast(handle) = iMem()->ExportExternalHandle(exportInfo); + return true; +} + +// ================================================================================================ void* Image::allocMapTarget(const amd::Coord3D& origin, const amd::Coord3D& region, uint mapFlags, size_t* rowPitch, size_t* slicePitch) { // Sanity checks diff --git a/projects/clr/rocclr/device/pal/palmemory.hpp b/projects/clr/rocclr/device/pal/palmemory.hpp index 6d8d0cd832..4a557c7ee7 100644 --- a/projects/clr/rocclr/device/pal/palmemory.hpp +++ b/projects/clr/rocclr/device/pal/palmemory.hpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2015 - 2022 Advanced Micro Devices, Inc. +/* Copyright (c) 2015 - 2023 Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -207,6 +207,9 @@ class Buffer : public pal::Memory { amd::Memory& subBufferOwner //!< The abstraction layer subbuf owner ) const; + //! Returns an export handle for the interprocess communication + virtual bool ExportHandle(void* handle) const final; + private: //! Disable copy constructor Buffer(const Buffer&); diff --git a/projects/clr/rocclr/device/pal/palresource.cpp b/projects/clr/rocclr/device/pal/palresource.cpp index 2380c48e80..552c5395a5 100644 --- a/projects/clr/rocclr/device/pal/palresource.cpp +++ b/projects/clr/rocclr/device/pal/palresource.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2015 - 2021 Advanced Micro Devices, Inc. +/* Copyright (c) 2015 - 2023 Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -1032,7 +1032,8 @@ bool Resource::CreateIpc(CreateParams* params) { Pal::ExternalGpuMemoryOpenInfo gpuMemOpenInfo = {}; Pal::ExternalResourceOpenInfo& openInfo = gpuMemOpenInfo.resourceInfo; - openInfo.hExternalResource = reinterpret_cast(params->owner_)->Handle(); + openInfo.hExternalResource = *reinterpret_cast( + reinterpret_cast(params->owner_)->Handle()); openInfo.flags.ntHandle = false; memRef_ = GpuMemoryReference::Create(dev(), gpuMemOpenInfo); @@ -1336,14 +1337,6 @@ bool Resource::create(MemoryType memType, CreateParams* params, bool forceLinear return true; } -// ================================================================================================ -void* Resource::ExportHandle() const { - Pal::GpuMemoryExportInfo exportInfo = {}; - // Set default flags in case they are not provided by application - exportInfo.accessFlags = GENERIC_READ | GENERIC_WRITE; - Pal::OsExternalHandle handle = iMem()->ExportExternalHandle(exportInfo); - return reinterpret_cast(handle); -} // ================================================================================================ void Resource::free() { if (memRef_ == nullptr) { diff --git a/projects/clr/rocclr/device/pal/palresource.hpp b/projects/clr/rocclr/device/pal/palresource.hpp index 5350442671..e868c75077 100644 --- a/projects/clr/rocclr/device/pal/palresource.hpp +++ b/projects/clr/rocclr/device/pal/palresource.hpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2015 - 2021 Advanced Micro Devices, Inc. +/* Copyright (c) 2015 - 2023 Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -433,8 +433,6 @@ class Resource : public amd::HeapObject { */ bool CreateP2PAccess(CreateParams* params //!< special parameters for resource allocation ); - //! Returns an export handle for the interprocess communication - void* ExportHandle() const; protected: /*! \brief Creates a PAL memory object, from IPC handle diff --git a/projects/clr/rocclr/device/rocm/rocdevice.cpp b/projects/clr/rocclr/device/rocm/rocdevice.cpp index e05ccf4898..22018bd945 100644 --- a/projects/clr/rocclr/device/rocm/rocdevice.cpp +++ b/projects/clr/rocclr/device/rocm/rocdevice.cpp @@ -2220,142 +2220,6 @@ void Device::updateFreeMemory(size_t size, bool free) { ClPrint(amd::LOG_INFO, amd::LOG_MEM, "device=0x%lx, freeMem_ = 0x%zx", this, freeMem_.load()); } -bool Device::IpcCreate(void* dev_ptr, size_t* mem_size, void* handle, size_t* mem_offset) const { - hsa_status_t hsa_status = HSA_STATUS_SUCCESS; - - amd::Memory* amd_mem_obj = amd::MemObjMap::FindMemObj(dev_ptr); - if (amd_mem_obj == nullptr) { - DevLogPrintfError("Cannot retrieve amd_mem_obj for dev_ptr: 0x%x", dev_ptr); - return false; - } - - // Get the original pointer from the amd::Memory object - void* orig_dev_ptr = nullptr; - if (amd_mem_obj->getSvmPtr() != nullptr) { - orig_dev_ptr = amd_mem_obj->getSvmPtr(); - } else if (amd_mem_obj->getHostMem() != nullptr) { - orig_dev_ptr = amd_mem_obj->getHostMem(); - } else { - ShouldNotReachHere(); - } - - // Check if the dev_ptr is lesser than original dev_ptr - if (orig_dev_ptr > dev_ptr) { - //If this happens, then revisit FindMemObj logic - DevLogPrintfError("Original dev_ptr: 0x%x cannot be greater than dev_ptr: 0x%x", - orig_dev_ptr, dev_ptr); - return false; - } - - //Calculate the memory offset from the original base ptr - *mem_offset = reinterpret_cast
(dev_ptr) - reinterpret_cast
(orig_dev_ptr); - *mem_size = amd_mem_obj->getSize(); - - //Check if the dev_ptr is greater than memory allocated - if (*mem_offset > *mem_size) { - DevLogPrintfError("Memory offset: %u cannot be greater than size of " - "original memory allocated: %u", *mem_size, *mem_offset); - return false; - } - - hsa_status = hsa_amd_ipc_memory_create(orig_dev_ptr, *mem_size, - reinterpret_cast(handle)); - - if (hsa_status != HSA_STATUS_SUCCESS) { - LogPrintfError("Failed to create memory for IPC, failed with hsa_status: %d \n", hsa_status); - return false; - } - - return true; -} - -bool Device::IpcAttach(const void* handle, size_t mem_size, size_t mem_offset, - unsigned int flags, void** dev_ptr) const { - amd::Memory* amd_mem_obj = nullptr; - void* orig_dev_ptr = nullptr; - - // Retrieve the devPtr from the handle - hsa_status_t hsa_status = - hsa_amd_ipc_memory_attach(reinterpret_cast(handle), - mem_size, (1 + p2p_agents_.size()), p2p_agents_list_, - &orig_dev_ptr); - - if (hsa_status != HSA_STATUS_SUCCESS) { - LogPrintfError("HSA failed to attach IPC memory with status: %d \n", hsa_status); - return false; - } - - amd_mem_obj = amd::MemObjMap::FindMemObj(orig_dev_ptr); - if (amd_mem_obj == nullptr) { - - // Memory does not exist, create an amd Memory object for the pointer - amd_mem_obj = new (context()) amd::Buffer(context(), flags, mem_size, orig_dev_ptr); - if (amd_mem_obj == nullptr) { - LogError("failed to create a mem object!"); - return false; - } - - if (!amd_mem_obj->create(nullptr)) { - LogError("failed to create a svm hidden buffer!"); - amd_mem_obj->release(); - return false; - } - amd_mem_obj->setIpcShared(true); - // Add the original mem_ptr to the MemObjMap with newly created amd_mem_obj - amd::MemObjMap::AddMemObj(orig_dev_ptr, amd_mem_obj); - - } else { - //Memory already exists, just retain the old one. - amd_mem_obj->retain(); - } - - //Make sure the mem_offset doesnt overflow the allocated memory - guarantee((mem_offset < mem_size), "IPC mem offset greater than allocated size"); - - // Return orig_dev_ptr - *dev_ptr = reinterpret_cast
(orig_dev_ptr); - - return true; -} - -bool Device::IpcDetach (void* dev_ptr) const { - hsa_status_t hsa_status = HSA_STATUS_SUCCESS; - - amd::Memory* amd_mem_obj = amd::MemObjMap::FindMemObj(dev_ptr); - if (amd_mem_obj == nullptr) { - DevLogPrintfError("Memory object for the ptr: 0x%x cannot be null \n", dev_ptr); - return false; - } - - if (!amd_mem_obj->ipcShared()) { - DevLogPrintfError("Memory object for the ptr: 0x%x is not ipcShared \n", dev_ptr); - return false; - } - - // Get the original pointer from the amd::Memory object - void* orig_dev_ptr = nullptr; - if (amd_mem_obj->getSvmPtr() != nullptr) { - orig_dev_ptr = amd_mem_obj->getSvmPtr(); - } else if (amd_mem_obj->getHostMem() != nullptr) { - orig_dev_ptr = amd_mem_obj->getHostMem(); - } else { - ShouldNotReachHere(); - } - - if (amd_mem_obj->release() == 0) { - amd::MemObjMap::RemoveMemObj(orig_dev_ptr); - - // Detach the memory from HSA - hsa_status = hsa_amd_ipc_memory_detach(orig_dev_ptr); - if (hsa_status != HSA_STATUS_SUCCESS) { - LogPrintfError("HSA failed to detach memory with status: %d \n", hsa_status); - return false; - } - } - - return true; -} - // ================================================================================================ void* Device::svmAlloc(amd::Context& context, size_t size, size_t alignment, cl_svm_mem_flags flags, void* svmPtr) const { diff --git a/projects/clr/rocclr/device/rocm/rocdevice.hpp b/projects/clr/rocclr/device/rocm/rocdevice.hpp index 8618e0a89b..db67b17070 100644 --- a/projects/clr/rocclr/device/rocm/rocdevice.hpp +++ b/projects/clr/rocclr/device/rocm/rocdevice.hpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2009 - 2021 Advanced Micro Devices, Inc. +/* Copyright (c) 2009 - 2023 Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -483,17 +483,15 @@ class Device : public NullDevice { // P2P agents avaialble for this device const std::vector& p2pAgents() const { return p2p_agents_; } + //! Returns the list of HSA agents used for IPC memory attach + const hsa_agent_t* IpcAgents() const { return p2p_agents_list_; } + // User enabled peer devices const bool isP2pEnabled() const { return (enabled_p2p_devices_.size() > 0) ? true : false; } // Update the global free memory size void updateFreeMemory(size_t size, bool free); - virtual bool IpcCreate(void* dev_ptr, size_t* mem_size, void* handle, size_t* mem_offset) const; - virtual bool IpcAttach(const void* handle, size_t mem_size, size_t mem_offset, - unsigned int flags, void** dev_ptr) const; - virtual bool IpcDetach (void* dev_ptr) const; - bool AcquireExclusiveGpuAccess(); void ReleaseExclusiveGpuAccess(VirtualGPU& vgpu) const; diff --git a/projects/clr/rocclr/device/rocm/rocmemory.cpp b/projects/clr/rocclr/device/rocm/rocmemory.cpp index cbe0e6cb2b..08cbc5f508 100644 --- a/projects/clr/rocclr/device/rocm/rocmemory.cpp +++ b/projects/clr/rocclr/device/rocm/rocmemory.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2008 - 2022 Advanced Micro Devices, Inc. +/* Copyright (c) 2008 - 2023 Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -618,6 +618,14 @@ Buffer::~Buffer() { dev().hostFree(deviceMemory_, size()); } else { destroy(); + + if (owner()->ipcShared()) { + // Detach the memory from HSA + auto hsa_status = hsa_amd_ipc_memory_detach(owner()->getHostMem()); + if (hsa_status != HSA_STATUS_SUCCESS) { + LogPrintfError("HSA failed to detach memory with status: %d \n", hsa_status); + } + } } } @@ -724,6 +732,22 @@ bool Buffer::create(bool alloc_local) { return false; } + if (owner()->ipcShared()) { + void* orig_dev_ptr = nullptr; + // Extra 1 for the current device + const uint32_t ipc_agents_num = dev().p2pAgents().size() + 1; + // Retrieve the devPtr from the handle + auto hsa_status = hsa_amd_ipc_memory_attach( + reinterpret_cast( + reinterpret_cast(owner())->Handle()), + owner()->getSize(), ipc_agents_num, dev().IpcAgents(), &orig_dev_ptr); + if (hsa_status != HSA_STATUS_SUCCESS) { + LogPrintfError("HSA failed to attach IPC memory with status: %d \n", hsa_status); + return false; + } + owner()->setSvmPtr(orig_dev_ptr); + } + // Allocate backing storage in device local memory unless UHP or AHP are set cl_mem_flags memFlags = owner()->getMemFlags(); @@ -955,6 +979,24 @@ bool Buffer::create(bool alloc_local) { return deviceMemory_ != nullptr; } +// ================================================================================================ +bool Buffer::ExportHandle(void* handle) const { + void* orig_dev_ptr = nullptr; + if (owner()->getSvmPtr() != nullptr) { + orig_dev_ptr = owner()->getSvmPtr(); + } else if (owner()->getHostMem() != nullptr) { + orig_dev_ptr = owner()->getHostMem(); + } + + auto hsa_status = hsa_amd_ipc_memory_create(orig_dev_ptr, owner()->getSize(), + reinterpret_cast(handle)); + if (hsa_status != HSA_STATUS_SUCCESS) { + LogPrintfError("Failed to create memory for IPC, failed with hsa_status: %d \n", hsa_status); + return false; + } + return true; +} + // ======================================= roc::Image ============================================= typedef struct ChannelOrderMap { uint32_t cl_channel_order; diff --git a/projects/clr/rocclr/device/rocm/rocmemory.hpp b/projects/clr/rocclr/device/rocm/rocmemory.hpp index bcffcf3de1..8a420c54ca 100644 --- a/projects/clr/rocclr/device/rocm/rocmemory.hpp +++ b/projects/clr/rocclr/device/rocm/rocmemory.hpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2016 - 2022 Advanced Micro Devices, Inc. +/* Copyright (c) 2016 - 2023 Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -171,6 +171,8 @@ class Buffer : public roc::Memory { // Create device memory according to OpenCL memory flag. virtual bool create(bool local_alloc = false); + virtual bool ExportHandle(void* handle) const final; + // Recreate the device memory using new size and alignment. bool recreate(size_t newSize, size_t newAlignment, bool forceSystem); diff --git a/projects/clr/rocclr/platform/memory.hpp b/projects/clr/rocclr/platform/memory.hpp index 847e848a8e..1ea2ff0e4f 100644 --- a/projects/clr/rocclr/platform/memory.hpp +++ b/projects/clr/rocclr/platform/memory.hpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2010 - 2022 Advanced Micro Devices, Inc. +/* Copyright (c) 2010 - 2023 Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -675,16 +675,17 @@ public: class IpcBuffer : public Buffer { public: - IpcBuffer(Context& context, Flags flags, size_t offset, size_t size, amd::Os::FileDesc handle) + IpcBuffer(Context& context, Flags flags, size_t offset, size_t size, const void* handle) : Buffer(context, flags, offset, size), handle_(handle) { setIpcShared(true); } virtual void initDeviceMemory(); - amd::Os::FileDesc Handle() const { return handle_; } + + const void* Handle() const { return handle_; } private: - amd::Os::FileDesc handle_; //!< Ipc handle, associated with this memory object + const void* handle_; //!< Ipc handle, associated with this memory object };