From 4e2ef636c9d6498e64cbf12e5d9e6f4ffedcc1b2 Mon Sep 17 00:00:00 2001 From: Alejandro Saucedo Date: Thu, 27 Aug 2020 06:27:24 +0100 Subject: [PATCH] Added logic to clean memory on operations --- README.md | 12 +++-- single_include/kompute/Kompute.hpp | 5 +++ src/Manager.cpp | 14 ++++-- src/OpCreateTensor.cpp | 26 +++++++++++ src/Tensor.cpp | 61 ++++++++++++++++---------- src/include/kompute/Manager.hpp | 5 ++- src/include/kompute/OpCreateTensor.hpp | 2 + src/include/kompute/Tensor.hpp | 4 ++ 8 files changed, 94 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index c1b7894..864d07c 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ int main() { Create your own custom operations to leverage Vulkan Compute for your specialised use-cases. ```c++ -class CustomOp : kp::OpBase { +class OpCustom : kp::OpBase { // ... void init(std::shared_ptr tensors) { // ... extra steps to initialise tensors @@ -102,14 +102,12 @@ class CustomOp : kp::OpBase { } int main() { - kp::Manager kManager(); // Chooses device 0 + kp::Manager mgr; // Automatically selects Device 0 - kp::Tensor inputOne({0, 1, 2, 3}); + std::shared_ptr tensor{ new kp::Tensor({ 0.0, 1.0, 2.0 }) }; + mgr.evalOp({ tensorLHS }); - kp::Tensor inputTwo({0, 1, 2, 3}); - - kp::Tensor output( {0, 0, 0, 0} ); - kManager.eval({ inputOne, inputTwo, output }); + mgr.evalOp({ tensorLHS, tensorRHS, tensorOutput }); std::cout << fmt::format("Output: {}", tensorOutput.data()) << std::endl; } diff --git a/single_include/kompute/Kompute.hpp b/single_include/kompute/Kompute.hpp index dd7dc73..920e0ae 100755 --- a/single_include/kompute/Kompute.hpp +++ b/single_include/kompute/Kompute.hpp @@ -178,6 +178,9 @@ class Tensor // Create functions void createBuffer(); + // Destroy/Free functions + void freeMemoryDestroyGPUResources(); + // Getter functions std::vector data(); uint32_t size(); @@ -692,7 +695,9 @@ class OpCreateTensor : public OpBase private: std::shared_ptr mPrimaryTensor; + bool mFreePrimaryTensorResources = false; std::shared_ptr mStagingTensor; + bool mFreeStagingTensorResources = false; }; } // End namespace kp diff --git a/src/Manager.cpp b/src/Manager.cpp index 3445c60..9d875b2 100644 --- a/src/Manager.cpp +++ b/src/Manager.cpp @@ -39,6 +39,11 @@ Manager::~Manager() return; } + if (this->mManagedSequences.size()) { + SPDLOG_DEBUG("Releasing managed sequence"); + this->mManagedSequences.clear(); + } + if (this->mFreeDevice) { spdlog::info("Destroying device"); this->mDevice->destroy(); @@ -65,14 +70,17 @@ Manager::~Manager() } } -Sequence -Manager::constructSequence() +std::weak_ptr +Manager::managedSequence() { SPDLOG_DEBUG("Kompute Manager creating Sequence object"); - return Sequence(this->mPhysicalDevice, + std::shared_ptr sq = std::make_shared( + this->mPhysicalDevice, this->mDevice, this->mComputeQueue, this->mComputeQueueFamilyIndex); + this->mManagedSequences.push_back(sq); + return sq; } void diff --git a/src/OpCreateTensor.cpp b/src/OpCreateTensor.cpp index 5638e87..da96625 100644 --- a/src/OpCreateTensor.cpp +++ b/src/OpCreateTensor.cpp @@ -22,6 +22,29 @@ OpCreateTensor::OpCreateTensor( OpCreateTensor::~OpCreateTensor() { SPDLOG_DEBUG("Kompute OpCreateTensor destructor started"); + + if(!this->mDevice) { + spdlog::warn("Kompute OpCreateTensor destructor called with empty device"); + return; + } + + if (!this->mFreePrimaryTensorResources) { + SPDLOG_DEBUG("Kompute OpCreateTensor removing primary tensor"); + if (this->mPrimaryTensor && this->mPrimaryTensor->isInit()) { + this->mPrimaryTensor->freeMemoryDestroyGPUResources(); + } else { + spdlog::error("Kompute OpCreateTensor expected to free primary tensor but has already been freed."); + } + } + + if (!this->mFreeStagingTensorResources) { + SPDLOG_DEBUG("Kompute OpCreateTensor removing primary tensor"); + if (this->mStagingTensor && this->mStagingTensor->isInit()) { + this->mStagingTensor->freeMemoryDestroyGPUResources(); + } else { + spdlog::error("Kompute OpCreateTensor expected to free secondary tensor but has already been freed."); + } + } } void @@ -36,6 +59,9 @@ OpCreateTensor::init(std::vector> tensors) spdlog::warn("Kompute OpCreateTensor called with more than 1 tensor"); } + this->mFreePrimaryTensorResources = true; + this->mFreeStagingTensorResources = true; + this->mPrimaryTensor = tensors[0]; if (this->mPrimaryTensor->tensorType() == Tensor::TensorTypes::eDevice) { diff --git a/src/Tensor.cpp b/src/Tensor.cpp index 7e51600..843df42 100644 --- a/src/Tensor.cpp +++ b/src/Tensor.cpp @@ -27,30 +27,8 @@ Tensor::~Tensor() { SPDLOG_DEBUG("Kompute Tensor destructor started"); - if (!this->mDevice) { - spdlog::error( - "Kompute Sequence destructor reached with null Device pointer"); - return; - } - - if (this->mFreeBuffer) { - if (!this->mBuffer) { - spdlog::error( - "Kompose Tensor expected to free buffer but got null buffer"); - } else { - SPDLOG_DEBUG("Kompose Tensor destroying buffer"); - this->mDevice->destroy(*this->mBuffer); - } - } - - if (this->mFreeMemory) { - if (!this->mMemory) { - spdlog::error( - "Kompose Tensor expected to free buffer but got null memory"); - } else { - SPDLOG_DEBUG("Kompose Tensor freeing memory"); - this->mDevice->freeMemory(*this->mMemory); - } + if (this->isInit()) { + this->freeMemoryDestroyGPUResources(); } SPDLOG_DEBUG("Kompute Tensor destructor success"); @@ -345,4 +323,39 @@ Tensor::createBuffer() SPDLOG_DEBUG("Kompute Tensor buffer & memory creation successful"); } +void Tensor::freeMemoryDestroyGPUResources() { + SPDLOG_DEBUG("Kompute Tensor started freeMemoryDestroyGPUResources"); + + this->mIsInit = false; + + if (!this->mDevice) { + spdlog::error( + "Kompute Tensor destructor reached with null Device pointer"); + return; + } + + if (this->mFreeBuffer) { + if (!this->mBuffer) { + spdlog::error( + "Kompose Tensor expected to free buffer but got null buffer"); + } else { + SPDLOG_DEBUG("Kompose Tensor destroying buffer"); + this->mDevice->destroy(*this->mBuffer); + } + } + + if (this->mFreeMemory) { + if (!this->mMemory) { + spdlog::error( + "Kompose Tensor expected to free buffer but got null memory"); + } else { + SPDLOG_DEBUG("Kompose Tensor freeing memory"); + this->mDevice->freeMemory(*this->mMemory); + } + } + + SPDLOG_DEBUG("Kompute Tensor successful freeMemoryDestroyGPUResources"); + +} + } diff --git a/src/include/kompute/Manager.hpp b/src/include/kompute/Manager.hpp index 9b788c2..a8e02e0 100644 --- a/src/include/kompute/Manager.hpp +++ b/src/include/kompute/Manager.hpp @@ -18,7 +18,7 @@ class Manager ~Manager(); - Sequence constructSequence(); + std::weak_ptr managedSequence(); template void evalOp(std::vector> tensors) @@ -49,6 +49,9 @@ class Manager uint32_t mComputeQueueFamilyIndex = -1; std::shared_ptr mComputeQueue = nullptr; + // Always owned resources + std::vector> mManagedSequences; + #if DEBUG vk::DebugReportCallbackEXT mDebugReportCallback; vk::DispatchLoaderDynamic mDebugDispatcher; diff --git a/src/include/kompute/OpCreateTensor.hpp b/src/include/kompute/OpCreateTensor.hpp index 3c3cf45..978e8cc 100644 --- a/src/include/kompute/OpCreateTensor.hpp +++ b/src/include/kompute/OpCreateTensor.hpp @@ -27,7 +27,9 @@ class OpCreateTensor : public OpBase private: std::shared_ptr mPrimaryTensor; + bool mFreePrimaryTensorResources = false; std::shared_ptr mStagingTensor; + bool mFreeStagingTensorResources = false; }; } // End namespace kp diff --git a/src/include/kompute/Tensor.hpp b/src/include/kompute/Tensor.hpp index 5933e34..602eea5 100644 --- a/src/include/kompute/Tensor.hpp +++ b/src/include/kompute/Tensor.hpp @@ -30,6 +30,9 @@ class Tensor // Create functions void createBuffer(); + // Destroy/Free functions + void freeMemoryDestroyGPUResources(); + // Getter functions std::vector data(); uint32_t size(); @@ -54,6 +57,7 @@ class Tensor void mapDataFromHostMemory(); void mapDataIntoHostMemory(); + private: std::shared_ptr mPhysicalDevice; std::shared_ptr mDevice;