From baf174e85ddb5399355281cd34d0f459d92124a7 Mon Sep 17 00:00:00 2001 From: Georgios Pinitas Date: Fri, 8 Sep 2017 19:47:30 +0100 Subject: COMPMID-485: Memory Manager Change-Id: Ib421b7622838f050038cd81e7426bb1413a7d6e6 Reviewed-on: http://mpd-gerrit.cambridge.arm.com/87376 Tested-by: Kaizen Reviewed-by: Anthony Barbier --- arm_compute/core/CL/OpenCL.h | 2 + arm_compute/core/Helpers.inl | 8 +- arm_compute/runtime/Allocator.h | 45 ++++++ arm_compute/runtime/BlobLifetimeManager.h | 87 +++++++++++ arm_compute/runtime/BlobMemoryPool.h | 75 ++++++++++ arm_compute/runtime/CL/CLBufferAllocator.h | 51 +++++++ arm_compute/runtime/CL/CLMemoryGroup.h | 45 ++++++ arm_compute/runtime/CL/CLTensorAllocator.h | 25 +++- .../runtime/CL/functions/CLConvolutionLayer.h | 10 +- .../runtime/CL/functions/CLFullyConnectedLayer.h | 4 +- arm_compute/runtime/CL/functions/CLSoftmaxLayer.h | 7 +- arm_compute/runtime/IAllocator.h | 49 +++++++ arm_compute/runtime/ILifetimeManager.h | 80 +++++++++++ arm_compute/runtime/IMemoryGroup.h | 45 ++++++ arm_compute/runtime/IMemoryManager.h | 56 ++++++++ arm_compute/runtime/IMemoryPool.h | 64 +++++++++ arm_compute/runtime/IPoolManager.h | 58 ++++++++ arm_compute/runtime/MemoryGroup.h | 44 ++++++ arm_compute/runtime/MemoryGroupBase.h | 159 +++++++++++++++++++++ arm_compute/runtime/MemoryManagerOnDemand.h | 84 +++++++++++ .../runtime/NEON/functions/NEConvolutionLayer.h | 7 +- .../runtime/NEON/functions/NEFullyConnectedLayer.h | 7 +- .../runtime/NEON/functions/NESoftmaxLayer.h | 4 +- arm_compute/runtime/PoolManager.h | 67 +++++++++ arm_compute/runtime/TensorAllocator.h | 25 +++- arm_compute/runtime/Types.h | 49 +++++++ 26 files changed, 1138 insertions(+), 19 deletions(-) create mode 100644 arm_compute/runtime/Allocator.h create mode 100644 arm_compute/runtime/BlobLifetimeManager.h create mode 100644 arm_compute/runtime/BlobMemoryPool.h create mode 100644 arm_compute/runtime/CL/CLBufferAllocator.h create mode 100644 arm_compute/runtime/CL/CLMemoryGroup.h create mode 100644 arm_compute/runtime/IAllocator.h create mode 100644 arm_compute/runtime/ILifetimeManager.h create mode 100644 arm_compute/runtime/IMemoryGroup.h create mode 100644 arm_compute/runtime/IMemoryManager.h create mode 100644 arm_compute/runtime/IMemoryPool.h create mode 100644 arm_compute/runtime/IPoolManager.h create mode 100644 arm_compute/runtime/MemoryGroup.h create mode 100644 arm_compute/runtime/MemoryGroupBase.h create mode 100644 arm_compute/runtime/MemoryManagerOnDemand.h create mode 100644 arm_compute/runtime/PoolManager.h create mode 100644 arm_compute/runtime/Types.h (limited to 'arm_compute') diff --git a/arm_compute/core/CL/OpenCL.h b/arm_compute/core/CL/OpenCL.h index bea9743f48..562f30bf14 100644 --- a/arm_compute/core/CL/OpenCL.h +++ b/arm_compute/core/CL/OpenCL.h @@ -57,6 +57,7 @@ public: using clBuildProgram_func = cl_int (*)(cl_program, cl_uint, const cl_device_id *, const char *, void (*pfn_notify)(cl_program, void *), void *); using clEnqueueNDRangeKernel_func = cl_int (*)(cl_command_queue, cl_kernel, cl_uint, const size_t *, const size_t *, const size_t *, cl_uint, const cl_event *, cl_event *); using clSetKernelArg_func = cl_int (*)(cl_kernel, cl_uint, size_t, const void *); + using clRetainMemObject_func = cl_int (*)(cl_mem); using clReleaseMemObject_func = cl_int (*)(cl_mem); using clEnqueueUnmapMemObject_func = cl_int (*)(cl_command_queue, cl_mem, void *, cl_uint, const cl_event *, cl_event *); using clRetainCommandQueue_func = cl_int (*)(cl_command_queue command_queue); @@ -106,6 +107,7 @@ public: clReleaseContext_func clReleaseContext = nullptr; clRetainCommandQueue_func clRetainCommandQueue = nullptr; clEnqueueUnmapMemObject_func clEnqueueUnmapMemObject = nullptr; + clRetainMemObject_func clRetainMemObject = nullptr; clReleaseMemObject_func clReleaseMemObject = nullptr; clGetDeviceInfo_func clGetDeviceInfo = nullptr; clGetDeviceIDs_func clGetDeviceIDs = nullptr; diff --git a/arm_compute/core/Helpers.inl b/arm_compute/core/Helpers.inl index 90a4618fcc..e20bdb58a1 100644 --- a/arm_compute/core/Helpers.inl +++ b/arm_compute/core/Helpers.inl @@ -311,9 +311,13 @@ inline ValidRegion calculate_valid_region_scale(const ITensorInfo &src_info, con Coordinates anchor; anchor.set_num_dimensions(src_info.tensor_shape().num_dimensions()); TensorShape new_dst_shape(dst_shape); - anchor.set(0, (policy == InterpolationPolicy::BILINEAR && border_undefined) ? ((static_cast(src_info.valid_region().anchor[0]) + border_size.left + 0.5f) * wr - 0.5f) : + anchor.set(0, (policy == InterpolationPolicy::BILINEAR + && border_undefined) ? + ((static_cast(src_info.valid_region().anchor[0]) + border_size.left + 0.5f) * wr - 0.5f) : ((static_cast(src_info.valid_region().anchor[0]) + 0.5f) * wr - 0.5f)); - anchor.set(1, (policy == InterpolationPolicy::BILINEAR && border_undefined) ? ((static_cast(src_info.valid_region().anchor[1]) + border_size.top + 0.5f) * hr - 0.5f) : + anchor.set(1, (policy == InterpolationPolicy::BILINEAR + && border_undefined) ? + ((static_cast(src_info.valid_region().anchor[1]) + border_size.top + 0.5f) * hr - 0.5f) : ((static_cast(src_info.valid_region().anchor[1]) + 0.5f) * hr - 0.5f)); float shape_out_x = (policy == InterpolationPolicy::BILINEAR && border_undefined) ? diff --git a/arm_compute/runtime/Allocator.h b/arm_compute/runtime/Allocator.h new file mode 100644 index 0000000000..cf6f07b211 --- /dev/null +++ b/arm_compute/runtime/Allocator.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_ALLOCATOR_H__ +#define __ARM_COMPUTE_ALLOCATOR_H__ + +#include "arm_compute/runtime/IAllocator.h" + +#include + +namespace arm_compute +{ +/** Default malloc allocator implementation */ +class Allocator : public IAllocator +{ +public: + /** Default constructor */ + Allocator() = default; + + // Inherited methods overridden: + void *allocate(size_t size, size_t alignment) override; + void free(void *ptr) override; +}; +} // arm_compute +#endif /*__ARM_COMPUTE_ALLOCATOR_H__ */ diff --git a/arm_compute/runtime/BlobLifetimeManager.h b/arm_compute/runtime/BlobLifetimeManager.h new file mode 100644 index 0000000000..ec43f47fe6 --- /dev/null +++ b/arm_compute/runtime/BlobLifetimeManager.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_BLOBLIFETIMEMANAGER_H__ +#define __ARM_COMPUTE_BLOBLIFETIMEMANAGER_H__ + +#include "arm_compute/runtime/ILifetimeManager.h" + +#include "arm_compute/runtime/IMemoryGroup.h" +#include "arm_compute/runtime/Types.h" + +#include +#include +#include + +namespace arm_compute +{ +class IMemoryGroup; + +/** Class that tracks the lifetime of registered tensors and calculates the systems memory requirements in terms of blobs */ +class BlobLifetimeManager : public ILifetimeManager +{ +public: + /** Constructor */ + BlobLifetimeManager(); + /** Prevent instances of this class to be copy constructed */ + BlobLifetimeManager(const BlobLifetimeManager &) = delete; + /** Prevent instances of this class to be copied */ + BlobLifetimeManager &operator=(const BlobLifetimeManager &) = delete; + /** Allow instances of this class to be move constructed */ + BlobLifetimeManager(BlobLifetimeManager &&) = default; + /** Allow instances of this class to be moved */ + BlobLifetimeManager &operator=(BlobLifetimeManager &&) = default; + + // Inherited methods overridden: + void register_group(IMemoryGroup *group) override; + void start_lifetime(void *obj) override; + void end_lifetime(void *obj, void **handle, size_t size) override; + std::unique_ptr create_pool(IAllocator *allocator) override; + bool are_all_finalized() const override; + MappingType mapping_type() const override; + +private: + /** Update blobs and mappings */ + void update_blobs_and_mappings(); + +private: + /** Element struct */ + struct Element + { + Element(void *id_ = nullptr, void **handle_ = nullptr, size_t size_ = 0, bool status_ = false) + : id(id_), handle(handle_), size(size_), status(status_) + { + } + void *id; /**< Element id */ + void **handle; /**< Element's memory handle */ + size_t size; /**< Element's size */ + bool status; /**< Lifetime status */ + }; + + IMemoryGroup *_active_group; /**< Active group */ + std::vector _active_elements; /**< A map that contains the active elements */ + std::map> _finalized_groups; /**< A map that contains the finalized groups */ + std::vector _blobs; +}; +} // arm_compute +#endif /* __ARM_COMPUTE_BLOBLIFETIMEMANAGER_H__ */ diff --git a/arm_compute/runtime/BlobMemoryPool.h b/arm_compute/runtime/BlobMemoryPool.h new file mode 100644 index 0000000000..f2be2dd8df --- /dev/null +++ b/arm_compute/runtime/BlobMemoryPool.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_BLOBMEMORYPOOL_H__ +#define __ARM_COMPUTE_BLOBMEMORYPOOL_H__ + +#include "arm_compute/runtime/IMemoryPool.h" + +#include "arm_compute/runtime/IAllocator.h" +#include "arm_compute/runtime/Types.h" + +#include +#include + +namespace arm_compute +{ +/** Blob memory pool */ +class BlobMemoryPool : public IMemoryPool +{ +public: + /** Default Constructor */ + BlobMemoryPool(IAllocator *allocator, std::vector blob_sizes); + /** Default Destructor */ + ~BlobMemoryPool(); + /** Prevent instances of this class to be copy constructed */ + BlobMemoryPool(const BlobMemoryPool &) = delete; + /** Prevent instances of this class to be copy assigned */ + BlobMemoryPool &operator=(const BlobMemoryPool &) = delete; + /** Allow instances of this class to be move constructed */ + BlobMemoryPool(BlobMemoryPool &&) = default; + /** Allow instances of this class to be move assigned */ + BlobMemoryPool &operator=(BlobMemoryPool &&) = default; + + // Inherited methods overridden: + void acquire(MemoryMappings &handles) override; + void release(MemoryMappings &handles) override; + MappingType mapping_type() const override; + std::unique_ptr duplicate() override; + +private: + /** Allocates internal blobs + * + * @param sizes Size of each blob + */ + void allocate_blobs(const std::vector &sizes); + /** Frees blobs **/ + void free_blobs(); + +private: + IAllocator *_allocator; /**< Allocator to use for internal allocation */ + std::vector _blobs; /**< Vector holding all the memory blobs */ + std::vector _blob_sizes; /**< Sizes of each blob */ +}; +} // arm_compute +#endif /* __ARM_COMPUTE_BLOBMEMORYPOOL_H__ */ diff --git a/arm_compute/runtime/CL/CLBufferAllocator.h b/arm_compute/runtime/CL/CLBufferAllocator.h new file mode 100644 index 0000000000..05b0363dc3 --- /dev/null +++ b/arm_compute/runtime/CL/CLBufferAllocator.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_CLBUFFERALLOCATOR_H__ +#define __ARM_COMPUTE_CLBUFFERALLOCATOR_H__ + +#include "arm_compute/runtime/IAllocator.h" + +#include "arm_compute/core/CL/OpenCL.h" +#include "arm_compute/runtime/CL/CLScheduler.h" + +#include + +namespace arm_compute +{ +/** Default OpenCL cl buffer allocator implementation */ +class CLBufferAllocator : public IAllocator +{ +public: + /** Default constructor */ + explicit CLBufferAllocator(cl::Context context = CLScheduler::get().context()); + + // Inherited methods overridden: + void *allocate(size_t size, size_t alignment) override; + void free(void *ptr) override; + +private: + cl::Context _context; +}; +} // arm_compute +#endif /*__ARM_COMPUTE_CLBUFFERALLOCATOR_H__ */ diff --git a/arm_compute/runtime/CL/CLMemoryGroup.h b/arm_compute/runtime/CL/CLMemoryGroup.h new file mode 100644 index 0000000000..a6f3eb1c3c --- /dev/null +++ b/arm_compute/runtime/CL/CLMemoryGroup.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_CLMEMORYGROUP_H__ +#define __ARM_COMPUTE_CLMEMORYGROUP_H__ + +#include "arm_compute/runtime/MemoryGroupBase.h" + +#include "arm_compute/core/CL/OpenCL.h" +#include "arm_compute/runtime/CL/CLTensor.h" + +namespace arm_compute +{ +using CLMemoryGroup = MemoryGroupBase; + +template <> +inline void MemoryGroupBase::associate_memory_group(CLTensor *obj) +{ + ARM_COMPUTE_ERROR_ON(obj == nullptr); + auto allocator = dynamic_cast(obj->allocator()); + ARM_COMPUTE_ERROR_ON(allocator == nullptr); + allocator->set_associated_memory_group(this); +} +} // arm_compute +#endif /*__ARM_COMPUTE_CLMEMORYGROUP_H__ */ diff --git a/arm_compute/runtime/CL/CLTensorAllocator.h b/arm_compute/runtime/CL/CLTensorAllocator.h index ed371e0642..682de174a8 100644 --- a/arm_compute/runtime/CL/CLTensorAllocator.h +++ b/arm_compute/runtime/CL/CLTensorAllocator.h @@ -24,19 +24,27 @@ #ifndef __ARM_COMPUTE_CLTENSORALLOCATOR_H__ #define __ARM_COMPUTE_CLTENSORALLOCATOR_H__ -#include "arm_compute/core/CL/OpenCL.h" #include "arm_compute/runtime/ITensorAllocator.h" +#include "arm_compute/core/CL/OpenCL.h" + #include namespace arm_compute { +class CLTensor; +template +class MemoryGroupBase; +using CLMemoryGroup = MemoryGroupBase; + /** Basic implementation of a CL memory tensor allocator. */ class CLTensorAllocator : public ITensorAllocator { public: /** Default constructor. */ - CLTensorAllocator(); + CLTensorAllocator(CLTensor *owner = nullptr); + /** Default destructor */ + ~CLTensorAllocator(); /** Prevent instances of this class from being copied (As this class contains pointers). */ CLTensorAllocator(const CLTensorAllocator &) = delete; /** Prevent instances of this class from being copy assigned (As this class contains pointers). */ @@ -45,8 +53,6 @@ public: CLTensorAllocator(CLTensorAllocator &&) = default; /** Allow instances of this class to be moved */ CLTensorAllocator &operator=(CLTensorAllocator &&) = default; - /** Default destructor */ - ~CLTensorAllocator() = default; /** Interface to be implemented by the child class to return the pointer to the mapped data. */ uint8_t *data(); @@ -85,6 +91,11 @@ public: * */ void free() override; + /** Associates the tensor with a memory group + * + * @param[in] associated_memory_group Memory group to associate the tensor with + */ + void set_associated_memory_group(CLMemoryGroup *associated_memory_group); protected: /** Call map() on the OpenCL buffer. @@ -96,8 +107,10 @@ protected: void unlock() override; private: - cl::Buffer _buffer; /**< OpenCL buffer containing the tensor data. */ - uint8_t *_mapping; /**< Pointer to the CPU mapping of the OpenCL buffer. */ + CLMemoryGroup *_associated_memory_group; /**< Registered memory manager */ + cl::Buffer _buffer; /**< OpenCL buffer containing the tensor data. */ + uint8_t *_mapping; /**< Pointer to the CPU mapping of the OpenCL buffer. */ + CLTensor *_owner; /**< Owner of the allocator */ }; } #endif /* __ARM_COMPUTE_CLTENSORALLOCATOR_H__ */ diff --git a/arm_compute/runtime/CL/functions/CLConvolutionLayer.h b/arm_compute/runtime/CL/functions/CLConvolutionLayer.h index 2057b6ff8a..cd1ea70a23 100644 --- a/arm_compute/runtime/CL/functions/CLConvolutionLayer.h +++ b/arm_compute/runtime/CL/functions/CLConvolutionLayer.h @@ -34,7 +34,11 @@ #include "arm_compute/core/CL/kernels/CLIm2ColKernel.h" #include "arm_compute/core/CL/kernels/CLWeightsReshapeKernel.h" #include "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/CLMemoryGroup.h" #include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/IMemoryManager.h" + +#include namespace arm_compute { @@ -48,7 +52,7 @@ class CLConvolutionLayerReshapeWeights : public IFunction { public: /** Constructor */ - CLConvolutionLayerReshapeWeights(); + CLConvolutionLayerReshapeWeights(std::shared_ptr memory_manager = nullptr); /** Set the input and output tensors. * * @param[in] weights Weights tensor. Weights are 4D tensor with dimensions [kernel_x, kernel_y, IFM, OFM]. Data type supported: QS8/QS16/F16/F32. @@ -62,6 +66,7 @@ public: void run() override; private: + CLMemoryGroup _memory_group; CLWeightsReshapeKernel _weights_reshape_kernel; CLGEMMTranspose1xWKernel _weights_transposed_kernel; CLTensor _weights_reshaped; @@ -81,7 +86,7 @@ class CLConvolutionLayer : public IFunction { public: /** Default constructor */ - CLConvolutionLayer(); + CLConvolutionLayer(std::shared_ptr memory_manager = nullptr); /** Set the input and output tensors. * * @param[in] input Source tensor. 3 lower dimensions represent a single input [width, height, IFM], @@ -101,6 +106,7 @@ public: void run() override; private: + CLMemoryGroup _memory_group; CLConvolutionLayerReshapeWeights _reshape_weights; CLIm2ColKernel _input_im2col_kernel; CLGEMMInterleave4x4Kernel _input_interleave_kernel; diff --git a/arm_compute/runtime/CL/functions/CLFullyConnectedLayer.h b/arm_compute/runtime/CL/functions/CLFullyConnectedLayer.h index e076f51b26..f71e2a33f9 100644 --- a/arm_compute/runtime/CL/functions/CLFullyConnectedLayer.h +++ b/arm_compute/runtime/CL/functions/CLFullyConnectedLayer.h @@ -30,6 +30,7 @@ #include "arm_compute/core/CL/kernels/CLGEMMMatrixMultiplyKernel.h" #include "arm_compute/core/CL/kernels/CLIm2ColKernel.h" #include "arm_compute/core/CL/kernels/CLTransposeKernel.h" +#include "arm_compute/runtime/CL/CLMemoryGroup.h" #include "arm_compute/runtime/CL/CLTensor.h" namespace arm_compute @@ -64,7 +65,7 @@ class CLFullyConnectedLayer : public IFunction { public: /** Constructor */ - CLFullyConnectedLayer(); + CLFullyConnectedLayer(std::shared_ptr memory_manager = nullptr); /** Set the input and output tensors. * * @param[in] input Source tensor. Data type supported: QS8/QS16/F16/F32. @@ -83,6 +84,7 @@ private: void configure_fc_fc(const ICLTensor *input, const ICLTensor *weights, ICLTensor *output); void configure_conv_fc(const ICLTensor *input, const ICLTensor *weights, ICLTensor *output); + CLMemoryGroup _memory_group; CLIm2ColKernel _im2col_kernel; CLFullyConnectedLayerReshapeWeights _reshape_weights_kernel; CLGEMMMatrixMultiplyKernel _mm_kernel; diff --git a/arm_compute/runtime/CL/functions/CLSoftmaxLayer.h b/arm_compute/runtime/CL/functions/CLSoftmaxLayer.h index 18f7a02a3e..70a265c1ae 100644 --- a/arm_compute/runtime/CL/functions/CLSoftmaxLayer.h +++ b/arm_compute/runtime/CL/functions/CLSoftmaxLayer.h @@ -25,8 +25,12 @@ #define __ARM_COMPUTE_CLSOFTMAXLAYER_H__ #include "arm_compute/core/CL/kernels/CLSoftmaxLayerKernel.h" +#include "arm_compute/runtime/CL/CLMemoryGroup.h" #include "arm_compute/runtime/CL/CLTensor.h" #include "arm_compute/runtime/IFunction.h" +#include "arm_compute/runtime/IMemoryManager.h" + +#include namespace arm_compute { @@ -46,7 +50,7 @@ class CLSoftmaxLayer : public IFunction { public: /** Constructor */ - CLSoftmaxLayer(); + CLSoftmaxLayer(std::shared_ptr memory_manager = nullptr); /** Set the input and output tensors. * * @param[in] input Source tensor. Data types supported: QS8/QS16/F16/F32 @@ -58,6 +62,7 @@ public: void run() override; private: + CLMemoryGroup _memory_group; CLLogits1DMaxKernel _max_kernel; CLLogits1DShiftExpSumKernel _shift_exp_sum_kernel; CLLogits1DNormKernel _norm_kernel; diff --git a/arm_compute/runtime/IAllocator.h b/arm_compute/runtime/IAllocator.h new file mode 100644 index 0000000000..3edb34a9ea --- /dev/null +++ b/arm_compute/runtime/IAllocator.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_IALLOCATOR_H__ +#define __ARM_COMPUTE_IALLOCATOR_H__ + +#include + +namespace arm_compute +{ +/** Allocator interface */ +class IAllocator +{ +public: + /** Default virtual destructor. */ + virtual ~IAllocator() = default; + /** Interface to be implemented by the child class to allocate bytes + * + * @param[in] size Size to allocate + * @param[in] alignment Alignment that the returned pointer should comply with + * + * @return A pointer to the allocated memory + */ + virtual void *allocate(size_t size, size_t alignment) = 0; + /** Interface to be implemented by the child class to free the allocated tensor */ + virtual void free(void *ptr) = 0; +}; +} // arm_compute +#endif /*__ARM_COMPUTE_IALLOCATOR_H__ */ diff --git a/arm_compute/runtime/ILifetimeManager.h b/arm_compute/runtime/ILifetimeManager.h new file mode 100644 index 0000000000..4f9af6f535 --- /dev/null +++ b/arm_compute/runtime/ILifetimeManager.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_ILIFETIMEMANAGER_H__ +#define __ARM_COMPUTE_ILIFETIMEMANAGER_H__ + +#include "arm_compute/runtime/IMemoryPool.h" +#include "arm_compute/runtime/Types.h" + +#include +#include + +namespace arm_compute +{ +class IMemoryGroup; +class IAllocator; + +/** Interface for managing the lifetime of objects */ +class ILifetimeManager +{ +public: + /** Virtual Destructor */ + virtual ~ILifetimeManager() = default; + /** Registers a group to the lifetime manager and assigns a group id + * + * @return The group id of the group + */ + virtual void register_group(IMemoryGroup *group) = 0; + /** Registers and starts lifetime of an object + * + * @param[in] obj Object to register + */ + virtual void start_lifetime(void *obj) = 0; + /** Ends lifetime of an object + * + * @param[in] obj Object + * @param[in] handle Memory handle of the object + * @param[in] size Size of the given object at given time + */ + virtual void end_lifetime(void *obj, void **handle, size_t size) = 0; + /** Creates a memory pool depending on the memory requirements + * + * @param allocator Allocator to use + * + * @return A memory pool + */ + virtual std::unique_ptr create_pool(IAllocator *allocator) = 0; + /** Checks if the lifetime of the registered object is complete + * + * @return True if all object lifetimes are finalized else false. + */ + virtual bool are_all_finalized() const = 0; + /** Returns the type of mappings that the lifetime manager returns + * + * @return Mapping type of the lifetime manager + */ + virtual MappingType mapping_type() const = 0; +}; +} // arm_compute +#endif /* __ARM_COMPUTE_ILIFETIMEMANAGER_H__ */ diff --git a/arm_compute/runtime/IMemoryGroup.h b/arm_compute/runtime/IMemoryGroup.h new file mode 100644 index 0000000000..be03ea4a01 --- /dev/null +++ b/arm_compute/runtime/IMemoryGroup.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_IMEMORYGROUP_H__ +#define __ARM_COMPUTE_IMEMORYGROUP_H__ + +#include "arm_compute/runtime/Types.h" + +namespace arm_compute +{ +/** Memory group interface */ +class IMemoryGroup +{ +public: + /** Default virtual destructor */ + virtual ~IMemoryGroup() = default; + /** Acquires backing memory for the whole group */ + virtual void acquire() = 0; + /** Releases backing memory of the whole group */ + virtual void release() = 0; + /** Gets the memory mapping of the group */ + virtual MemoryMappings &mappings() = 0; +}; +} // arm_compute +#endif /*__ARM_COMPUTE_IMEMORYGROUP_H__ */ diff --git a/arm_compute/runtime/IMemoryManager.h b/arm_compute/runtime/IMemoryManager.h new file mode 100644 index 0000000000..00aa566a50 --- /dev/null +++ b/arm_compute/runtime/IMemoryManager.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_IMEMORYMANAGER_H__ +#define __ARM_COMPUTE_IMEMORYMANAGER_H__ + +#include "arm_compute/runtime/ILifetimeManager.h" +#include "arm_compute/runtime/IPoolManager.h" + +#include + +namespace arm_compute +{ +class IMemoryGroup; + +/** Memory manager interface to handle allocations of backing memory */ +class IMemoryManager +{ +public: + /** Default virtual destructor */ + virtual ~IMemoryManager() = default; + /** Returns the lifetime manager used by the memory manager + * + * @return The lifetime manager + */ + virtual ILifetimeManager *lifetime_manager() = 0; + /** Returns the pool manager used by the memory manager + * + * @return The pool manager + */ + virtual IPoolManager *pool_manager() = 0; + /** Finalize memory manager */ + virtual void finalize() = 0; +}; +} // arm_compute +#endif /*__ARM_COMPUTE_IMEMORYMANAGER_H__ */ diff --git a/arm_compute/runtime/IMemoryPool.h b/arm_compute/runtime/IMemoryPool.h new file mode 100644 index 0000000000..aee6ad274b --- /dev/null +++ b/arm_compute/runtime/IMemoryPool.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_IMEMORYPOOL_H__ +#define __ARM_COMPUTE_IMEMORYPOOL_H__ + +#include "arm_compute/runtime/Types.h" + +#include +#include +#include +#include + +namespace arm_compute +{ +/** Memory Pool Inteface */ +class IMemoryPool +{ +public: + /** Default Virtual Destructor */ + virtual ~IMemoryPool() = default; + /** Sets occupant to the memory pool + * + * @param[in] handles A vector of pairs (handle, index) + */ + virtual void acquire(MemoryMappings &handles) = 0; + /** Releases a memory block + * + * @param[in] handles A vector containing a pair of handles and indices + */ + virtual void release(MemoryMappings &handles) = 0; + /** Returns the mapping types that this pool accepts + * + * @return the mapping type of the memory + */ + virtual MappingType mapping_type() const = 0; + /** Duplicates the existing memory pool + * + * @return A duplicate of the existing pool + */ + virtual std::unique_ptr duplicate() = 0; +}; +} // arm_compute +#endif /* __ARM_COMPUTE_IMEMORYPOOL_H__ */ diff --git a/arm_compute/runtime/IPoolManager.h b/arm_compute/runtime/IPoolManager.h new file mode 100644 index 0000000000..03cccdd605 --- /dev/null +++ b/arm_compute/runtime/IPoolManager.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_IPOOLMANAGER_H__ +#define __ARM_COMPUTE_IPOOLMANAGER_H__ + +#include + +namespace arm_compute +{ +class IMemoryPool; + +/** Memory pool manager interface */ +class IPoolManager +{ +public: + /** Default virtual destructor */ + virtual ~IPoolManager() = default; + /** Locks a pool for execution + * + * @return Locked pool that workload will be mapped on + */ + virtual IMemoryPool *lock_pool() = 0; + /** Releases memory pool + * + * @param[in] pool Memory pool to release + */ + virtual void unlock_pool(IMemoryPool *pool) = 0; + /** Register pool to be managed by the pool + * + * @note Ownership of the pools is being transferred to the pool manager + * + * @param[in] pool Pool to be managed + */ + virtual void register_pool(std::unique_ptr pool) = 0; +}; +} // arm_compute +#endif /*__ARM_COMPUTE_IPOOLMANAGER_H__ */ diff --git a/arm_compute/runtime/MemoryGroup.h b/arm_compute/runtime/MemoryGroup.h new file mode 100644 index 0000000000..d3f647e7d4 --- /dev/null +++ b/arm_compute/runtime/MemoryGroup.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_MEMORYGROUP_H__ +#define __ARM_COMPUTE_MEMORYGROUP_H__ + +#include "arm_compute/runtime/MemoryGroupBase.h" + +#include "arm_compute/runtime/Tensor.h" + +namespace arm_compute +{ +using MemoryGroup = MemoryGroupBase; + +template <> +inline void MemoryGroupBase::associate_memory_group(Tensor *obj) +{ + ARM_COMPUTE_ERROR_ON(obj == nullptr); + auto allocator = dynamic_cast(obj->allocator()); + ARM_COMPUTE_ERROR_ON(allocator == nullptr); + allocator->set_associated_memory_group(this); +} +} // arm_compute +#endif /*__ARM_COMPUTE_MEMORYGROUP_H__ */ diff --git a/arm_compute/runtime/MemoryGroupBase.h b/arm_compute/runtime/MemoryGroupBase.h new file mode 100644 index 0000000000..ab8acb3494 --- /dev/null +++ b/arm_compute/runtime/MemoryGroupBase.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_MEMORYGROUPBASE_H__ +#define __ARM_COMPUTE_MEMORYGROUPBASE_H__ + +#include "arm_compute/runtime/IMemoryGroup.h" + +#include "arm_compute/runtime/IMemoryManager.h" +#include "arm_compute/runtime/IMemoryPool.h" + +#include +#include + +namespace arm_compute +{ +/** Memory group */ +template +class MemoryGroupBase : public IMemoryGroup +{ +public: + /** Default Constructor */ + MemoryGroupBase(std::shared_ptr memory_manager = nullptr); + /** Default destructor */ + ~MemoryGroupBase() = default; + /** Prevent instances of this class from being copied (As this class contains pointers). */ + MemoryGroupBase(const MemoryGroupBase &) = delete; + /** Prevent instances of this class from being copy assigned (As this class contains pointers). */ + MemoryGroupBase &operator=(const MemoryGroupBase &) = delete; + /** Allow instances of this class to be moved */ + MemoryGroupBase(MemoryGroupBase &&) = default; + /** Allow instances of this class to be moved */ + MemoryGroupBase &operator=(MemoryGroupBase &&) = default; + /** Sets a object to be managed by the given memory group + * + * @note Manager must not be finalized + * + * @param[in] obj Object to be managed + */ + void manage(TensorType *obj); + /** Finalizes memory for a given object + * + * @note Manager must not be finalized + * + * @param[in] obj Object to request memory for + * @param[in] handle Handle to store the memory + * @param[in] size Size of memory to allocate + */ + void finalize_memory(TensorType *obj, void **handle, size_t size); + + // Inherited methods overridden: + void acquire() override; + void release() override; + MemoryMappings &mappings() override; + +private: + void associate_memory_group(TensorType *obj); + +private: + std::shared_ptr _memory_manager; /**< Memory manager to be used by the group */ + IMemoryPool *_pool; /**< Memory pool that the group is scheduled with */ + MemoryMappings _mappings; /**< Memory mappings of the group */ +}; + +template +inline MemoryGroupBase::MemoryGroupBase(std::shared_ptr memory_manager) + : _memory_manager(std::move(memory_manager)), _pool(nullptr), _mappings() +{ + if(_memory_manager) + { + ARM_COMPUTE_ERROR_ON(!_memory_manager->lifetime_manager()); + } +} + +template +inline void MemoryGroupBase::manage(TensorType *obj) +{ + if(_memory_manager) + { + ARM_COMPUTE_ERROR_ON(!_memory_manager->lifetime_manager()); + + // Defer registration to the first managed object + _memory_manager->lifetime_manager()->register_group(this); + + // Associate this memory group with the tensor + associate_memory_group(obj); + + // Start object lifetime + _memory_manager->lifetime_manager()->start_lifetime(obj); + } +} + +template +inline void MemoryGroupBase::finalize_memory(TensorType *obj, void **handle, size_t size) +{ + if(_memory_manager) + { + ARM_COMPUTE_ERROR_ON(!_memory_manager->lifetime_manager()); + _memory_manager->lifetime_manager()->end_lifetime(obj, handle, size); + } +} + +template +inline void MemoryGroupBase::acquire() +{ + if(!_mappings.empty()) + { + ARM_COMPUTE_ERROR_ON(!_memory_manager->pool_manager()); + _pool = _memory_manager->pool_manager()->lock_pool(); + _pool->acquire(_mappings); + } +} + +template +inline void MemoryGroupBase::release() +{ + if(_pool != nullptr) + { + ARM_COMPUTE_ERROR_ON(!_memory_manager->pool_manager()); + ARM_COMPUTE_ERROR_ON(_mappings.empty()); + _pool->release(_mappings); + _memory_manager->pool_manager()->unlock_pool(_pool); + _pool = nullptr; + } +} + +template +inline MemoryMappings &MemoryGroupBase::mappings() +{ + return _mappings; +} + +template +inline void MemoryGroupBase::associate_memory_group(TensorType *) +{ + ARM_COMPUTE_ERROR("Must be implemented by child class"); +} +} // arm_compute +#endif /*__ARM_COMPUTE_MEMORYGROUPBASE_H__ */ diff --git a/arm_compute/runtime/MemoryManagerOnDemand.h b/arm_compute/runtime/MemoryManagerOnDemand.h new file mode 100644 index 0000000000..ad4b831e1f --- /dev/null +++ b/arm_compute/runtime/MemoryManagerOnDemand.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_MEMORYMANAGERONDEMAND_H__ +#define __ARM_COMPUTE_MEMORYMANAGERONDEMAND_H__ + +#include "arm_compute/runtime/IMemoryManager.h" + +#include "IAllocator.h" +#include "arm_compute/runtime/ILifetimeManager.h" +#include "arm_compute/runtime/IMemoryGroup.h" +#include "arm_compute/runtime/IPoolManager.h" + +#include +#include + +namespace arm_compute +{ +class IAllocator; + +/** On-demand memory manager */ +class MemoryManagerOnDemand : public IMemoryManager +{ +public: + /** Default Constructor */ + MemoryManagerOnDemand(std::shared_ptr lifetime_manager, std::shared_ptr pool_manager); + /** Prevent instances of this class to be copy constructed */ + MemoryManagerOnDemand(const MemoryManagerOnDemand &) = delete; + /** Prevent instances of this class to be copied */ + MemoryManagerOnDemand &operator=(const MemoryManagerOnDemand &) = delete; + /** Allow instances of this class to be move constructed */ + MemoryManagerOnDemand(MemoryManagerOnDemand &&) = default; + /** Allow instances of this class to be moved */ + MemoryManagerOnDemand &operator=(MemoryManagerOnDemand &&) = default; + /** Sets the number of pools to create + * + * @param[in] num_pools Number of pools + */ + void set_num_pools(unsigned int num_pools); + /** Sets the allocator to be used for configuring the pools + * + * @param[in] allocator Allocator to use + */ + void set_allocator(IAllocator *allocator); + /** Checks if the memory manager has been finalized + * + * @return True if the memory manager has been finalized else false + */ + bool is_finalized() const; + + // Inherited methods overridden: + ILifetimeManager *lifetime_manager() override; + IPoolManager *pool_manager() override; + void finalize() override; + +private: + std::shared_ptr _lifetime_mgr; /**< Lifetime manager */ + std::shared_ptr _pool_mgr; /**< Memory pool manager */ + IAllocator *_allocator; /**< Allocator used for backend allocations */ + bool _is_finalized; /**< Flag that notes if the memory manager has been finalized */ + unsigned int _num_pools; /**< Number of pools to create */ +}; +} // arm_compute +#endif /*__ARM_COMPUTE_MEMORYMANAGERONDEMAND_H__ */ diff --git a/arm_compute/runtime/NEON/functions/NEConvolutionLayer.h b/arm_compute/runtime/NEON/functions/NEConvolutionLayer.h index 1bd7e6a95f..8e040b3055 100644 --- a/arm_compute/runtime/NEON/functions/NEConvolutionLayer.h +++ b/arm_compute/runtime/NEON/functions/NEConvolutionLayer.h @@ -34,6 +34,7 @@ #include "arm_compute/core/NEON/kernels/NEIm2ColKernel.h" #include "arm_compute/core/NEON/kernels/NEWeightsReshapeKernel.h" #include "arm_compute/core/Types.h" +#include "arm_compute/runtime/MemoryGroup.h" #include "arm_compute/runtime/Tensor.h" namespace arm_compute @@ -48,7 +49,7 @@ class NEConvolutionLayerReshapeWeights : public IFunction { public: /** Constructor */ - NEConvolutionLayerReshapeWeights(); + NEConvolutionLayerReshapeWeights(std::shared_ptr memory_manager = nullptr); /** Set the input and output tensors. * * @param[in] weights Weights tensor. Weights are 4D tensor with dimensions [kernel_x, kernel_y, IFM, OFM]. Data type supported: QS8/QS16/F32. @@ -62,6 +63,7 @@ public: void run() override; private: + MemoryGroup _memory_group; NEWeightsReshapeKernel _weights_reshape_kernel; NEGEMMTranspose1xWKernel _weights_transposed_kernel; Tensor _weights_reshaped; @@ -79,7 +81,7 @@ class NEConvolutionLayer : public IFunction { public: /** Constructor */ - NEConvolutionLayer(); + NEConvolutionLayer(std::shared_ptr memory_manager = nullptr); /** Set the input and output tensors. * * @param[in] input Source tensor. 3 lower dimensions represent a single input [width, height, IFM], @@ -98,6 +100,7 @@ public: void run() override; private: + MemoryGroup _memory_group; NEIm2ColKernel _input_im2col_kernel; NEGEMMInterleave4x4Kernel _input_interleave_kernel; NEConvolutionLayerReshapeWeights _reshape_weights; diff --git a/arm_compute/runtime/NEON/functions/NEFullyConnectedLayer.h b/arm_compute/runtime/NEON/functions/NEFullyConnectedLayer.h index 08099b8539..463a7d53e3 100644 --- a/arm_compute/runtime/NEON/functions/NEFullyConnectedLayer.h +++ b/arm_compute/runtime/NEON/functions/NEFullyConnectedLayer.h @@ -32,6 +32,7 @@ #include "arm_compute/core/NEON/kernels/NEGEMMTranspose1xWKernel.h" #include "arm_compute/core/NEON/kernels/NEIm2ColKernel.h" #include "arm_compute/core/NEON/kernels/NETransposeKernel.h" +#include "arm_compute/runtime/MemoryGroup.h" #include "arm_compute/runtime/Tensor.h" namespace arm_compute @@ -47,7 +48,7 @@ class NEFullyConnectedLayerReshapeWeights : public IFunction { public: /** Constructor */ - NEFullyConnectedLayerReshapeWeights(); + NEFullyConnectedLayerReshapeWeights(std::shared_ptr memory_manager = nullptr); /** Set the input and output tensors. * * @param[in] input Weights tensor. The weights must be 2 dimensional. Data types supported: QS8/QS16/F32. @@ -61,6 +62,7 @@ public: void run() override; private: + MemoryGroup _memory_group; NETransposeKernel _transpose_kernel; NEGEMMTranspose1xWKernel _transpose1xW_kernel; Tensor _transpose_output; @@ -81,7 +83,7 @@ class NEFullyConnectedLayer : public IFunction { public: /** Constructor */ - NEFullyConnectedLayer(); + NEFullyConnectedLayer(std::shared_ptr memory_manager = nullptr); /** Set the input and output tensors. * * @param[in] input Source tensor. Data type supported: QS8/QS16/F32. @@ -97,6 +99,7 @@ public: void run() override; private: + MemoryGroup _memory_group; NEIm2ColKernel _im2col_kernel; NEFullyConnectedLayerReshapeWeights _reshape_weights_kernel; NEGEMMInterleave4x4Kernel _interleave4x4_kernel; diff --git a/arm_compute/runtime/NEON/functions/NESoftmaxLayer.h b/arm_compute/runtime/NEON/functions/NESoftmaxLayer.h index 01402aee63..a265f70043 100644 --- a/arm_compute/runtime/NEON/functions/NESoftmaxLayer.h +++ b/arm_compute/runtime/NEON/functions/NESoftmaxLayer.h @@ -27,6 +27,7 @@ #include "arm_compute/core/NEON/kernels/NEFillBorderKernel.h" #include "arm_compute/core/NEON/kernels/NESoftmaxLayerKernel.h" #include "arm_compute/runtime/IFunction.h" +#include "arm_compute/runtime/MemoryGroup.h" #include "arm_compute/runtime/Tensor.h" namespace arm_compute @@ -47,7 +48,7 @@ class NESoftmaxLayer : public IFunction { public: /** Constructor */ - NESoftmaxLayer(); + NESoftmaxLayer(std::shared_ptr memory_manager = nullptr); /** Set the input and output tensors. * * @param[in] input Source tensor. Data types supported: QS8/QS16/F16/F32. @@ -59,6 +60,7 @@ public: void run() override; private: + MemoryGroup _memory_group; NELogits1DMaxKernel _max_kernel; NELogits1DShiftExpSumKernel _shift_exp_sum_kernel; NELogits1DNormKernel _norm_kernel; diff --git a/arm_compute/runtime/PoolManager.h b/arm_compute/runtime/PoolManager.h new file mode 100644 index 0000000000..6549350e8f --- /dev/null +++ b/arm_compute/runtime/PoolManager.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_POOLMANAGER_H__ +#define __ARM_COMPUTE_POOLMANAGER_H__ + +#include "arm_compute/runtime/IPoolManager.h" + +#include "arm_compute/core/Error.h" +#include "arm_compute/runtime/IMemoryPool.h" +#include "support/Mutex.h" +#include "support/Semaphore.h" + +#include +#include +#include + +namespace arm_compute +{ +/** Memory pool manager */ +class PoolManager : public IPoolManager +{ +public: + /** Default Constructor */ + PoolManager(); + /** Prevent instances of this class to be copy constructed */ + PoolManager(const PoolManager &) = delete; + /** Prevent instances of this class to be copied */ + PoolManager &operator=(const PoolManager &) = delete; + /** Allow instances of this class to be move constructed */ + PoolManager(PoolManager &&) = default; + /** Allow instances of this class to be moved */ + PoolManager &operator=(PoolManager &&) = default; + + // Inherited methods overridden: + IMemoryPool *lock_pool() override; + void unlock_pool(IMemoryPool *pool) override; + void register_pool(std::unique_ptr pool) override; + +private: + std::list> _free_pools; /**< List of free pools */ + std::list> _occupied_pools; /**< List of occupied pools */ + std::unique_ptr _sem; /**< Semaphore to control the queues */ + arm_compute::Mutex _mtx; /**< Mutex to control access to the queues */ +}; +} // arm_compute +#endif /*__ARM_COMPUTE_POOLMANAGER_H__ */ diff --git a/arm_compute/runtime/TensorAllocator.h b/arm_compute/runtime/TensorAllocator.h index 450323b3ab..40704c0a17 100644 --- a/arm_compute/runtime/TensorAllocator.h +++ b/arm_compute/runtime/TensorAllocator.h @@ -34,13 +34,27 @@ namespace arm_compute { class Coordinates; class TensorInfo; +class Tensor; +template +class MemoryGroupBase; +using MemoryGroup = MemoryGroupBase; /** Basic implementation of a CPU memory tensor allocator. */ class TensorAllocator : public ITensorAllocator { public: /** Default constructor. */ - TensorAllocator(); + TensorAllocator(Tensor *owner = nullptr); + /** Default destructor */ + ~TensorAllocator(); + /** Prevent instances of this class from being copied (As this class contains pointers). */ + TensorAllocator(const TensorAllocator &) = delete; + /** Prevent instances of this class from being copy assigned (As this class contains pointers). */ + TensorAllocator &operator=(const TensorAllocator &) = delete; + /** Allow instances of this class to be moved */ + TensorAllocator(TensorAllocator &&) noexcept; + /** Allow instances of this class to be moved */ + TensorAllocator &operator=(TensorAllocator &&) noexcept; /** Make ITensorAllocator's init methods available */ using ITensorAllocator::init; @@ -72,6 +86,11 @@ public: * */ void free() override; + /** Associates the tensor with a memory group + * + * @param[in] associated_memory_group Memory group to associate the tensor with + */ + void set_associated_memory_group(MemoryGroup *associated_memory_group); protected: /** No-op for CPU memory @@ -84,7 +103,9 @@ protected: void unlock() override; private: - std::shared_ptr> _buffer; /**< CPU memory allocation. */ + MemoryGroup *_associated_memory_group; /**< Registered memory manager */ + uint8_t *_buffer; /**< CPU memory allocation. */ + Tensor *_owner; /**< Owner of the allocator */ }; } #endif /* __ARM_COMPUTE_TENSORALLOCATOR_H__ */ diff --git a/arm_compute/runtime/Types.h b/arm_compute/runtime/Types.h new file mode 100644 index 0000000000..9916e6d47b --- /dev/null +++ b/arm_compute/runtime/Types.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016, 2017 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __ARM_COMPUTE_RUNTIME_TYPES_H__ +#define __ARM_COMPUTE_RUNTIME_TYPES_H__ + +#include + +namespace arm_compute +{ +/** Mapping type */ +enum class MappingType +{ + BLOBS, /**< Mappings are in blob granularity */ + OFFSETS /**< Mappings are in offset granularity in the same blob */ +}; + +/** A map of (handle, index/offset), where handle is the memory handle of the object + * to provide the memory for and index/offset is the buffer/offset from the pool that should be used + * + * @note All objects are pre-pinned to specific buffers to avoid any relevant overheads + */ +using MemoryMappings = std::map; + +/** A map of the groups and memory mappings */ +using GroupMappings = std::map; + +} // arm_compute +#endif /* __ARM_COMPUTE_RUNTIME_TYPES_H__ */ -- cgit v1.2.1