From 555f1c2241d6fa8c84926a72a0c54e4158817df4 Mon Sep 17 00:00:00 2001 From: Georgios Pinitas Date: Fri, 14 Dec 2018 17:11:20 +0000 Subject: COMPMID-1710: Account alignment for blob-base allocations Change-Id: I290d33e25a5966d25a91df39ebc01c28bfa31f78 Reviewed-on: https://review.mlplatform.org/402 Reviewed-by: Anthony Barbier Tested-by: Arm Jenkins --- arm_compute/runtime/BlobLifetimeManager.h | 6 +++--- arm_compute/runtime/BlobMemoryPool.h | 28 ++++++++++++++++++++-------- arm_compute/runtime/ILifetimeManager.h | 3 ++- arm_compute/runtime/ISimpleLifetimeManager.h | 16 +++++++++------- arm_compute/runtime/MemoryGroupBase.h | 7 ++++--- arm_compute/runtime/Types.h | 3 +-- src/runtime/Allocator.cpp | 3 +-- src/runtime/BlobLifetimeManager.cpp | 14 ++++++++------ src/runtime/BlobMemoryPool.cpp | 14 +++++++------- src/runtime/ISimpleLifetimeManager.cpp | 18 ++++++++++-------- src/runtime/TensorAllocator.cpp | 2 +- 11 files changed, 66 insertions(+), 48 deletions(-) diff --git a/arm_compute/runtime/BlobLifetimeManager.h b/arm_compute/runtime/BlobLifetimeManager.h index edf4d43421..2dbe92d7b6 100644 --- a/arm_compute/runtime/BlobLifetimeManager.h +++ b/arm_compute/runtime/BlobLifetimeManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 ARM Limited. + * Copyright (c) 2017-2018 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -26,7 +26,7 @@ #include "arm_compute/runtime/ISimpleLifetimeManager.h" -#include "arm_compute/runtime/IMemoryPool.h" +#include "arm_compute/runtime/BlobMemoryPool.h" #include "arm_compute/runtime/Types.h" #include @@ -60,7 +60,7 @@ private: void update_blobs_and_mappings() override; private: - std::vector _blobs; /**< Memory blobs' sizes */ + std::vector _blobs; /**< Memory blobs */ }; } // namespace arm_compute #endif /* __ARM_COMPUTE_BLOBLIFETIMEMANAGER_H__ */ diff --git a/arm_compute/runtime/BlobMemoryPool.h b/arm_compute/runtime/BlobMemoryPool.h index c9c4da0f54..ba97dbd94e 100644 --- a/arm_compute/runtime/BlobMemoryPool.h +++ b/arm_compute/runtime/BlobMemoryPool.h @@ -35,8 +35,20 @@ namespace arm_compute { +// Forward declaration class IAllocator; +/** Meta-data information for each blob */ +struct BlobInfo +{ + BlobInfo(size_t size_ = 0, size_t alignment_ = 0) + : size(size_), alignment(alignment_) + { + } + size_t size; /**< Blob size */ + size_t alignment; /**< Blob alignment */ +}; + /** Blob memory pool */ class BlobMemoryPool : public IMemoryPool { @@ -45,10 +57,10 @@ public: * * @note allocator should outlive the memory pool * - * @param[in] allocator Backing memory allocator - * @param[in] blob_sizes Sizes of the blobs to be allocated + * @param[in] allocator Backing memory allocator + * @param[in] blob_info Configuration information of the blobs to be allocated */ - BlobMemoryPool(IAllocator *allocator, std::vector blob_sizes); + BlobMemoryPool(IAllocator *allocator, std::vector blob_info); /** Default Destructor */ ~BlobMemoryPool(); /** Prevent instances of this class to be copy constructed */ @@ -69,16 +81,16 @@ public: private: /** Allocates internal blobs * - * @param sizes Size of each blob + * @param blob_info Size of each blob */ - void allocate_blobs(const std::vector &sizes); + void allocate_blobs(const std::vector &blob_info); /** 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 */ + IAllocator *_allocator; /**< Allocator to use for internal allocation */ + std::vector> _blobs; /**< Vector holding all the memory blobs */ + std::vector _blob_info; /**< Information of each blob */ }; } // namespace arm_compute #endif /* __ARM_COMPUTE_BLOBMEMORYPOOL_H__ */ diff --git a/arm_compute/runtime/ILifetimeManager.h b/arm_compute/runtime/ILifetimeManager.h index f2e9b497c9..3684ddf8fb 100644 --- a/arm_compute/runtime/ILifetimeManager.h +++ b/arm_compute/runtime/ILifetimeManager.h @@ -58,8 +58,9 @@ public: * @param[in] obj Object * @param[in] obj_memory Object memory * @param[in] size Size of the given object at given time + * @param[in] alignment Alignment requirements for the object */ - virtual void end_lifetime(void *obj, IMemory &obj_memory, size_t size) = 0; + virtual void end_lifetime(void *obj, IMemory &obj_memory, size_t size, size_t alignment) = 0; /** Checks if the lifetime of the registered object is complete * * @return True if all object lifetimes are finalized else false. diff --git a/arm_compute/runtime/ISimpleLifetimeManager.h b/arm_compute/runtime/ISimpleLifetimeManager.h index f2eb4f5904..4384283b94 100644 --- a/arm_compute/runtime/ISimpleLifetimeManager.h +++ b/arm_compute/runtime/ISimpleLifetimeManager.h @@ -58,7 +58,7 @@ public: // Inherited methods overridden: void register_group(IMemoryGroup *group) override; void start_lifetime(void *obj) override; - void end_lifetime(void *obj, IMemory &obj_memory, size_t size) override; + void end_lifetime(void *obj, IMemory &obj_memory, size_t size, size_t alignment) override; bool are_all_finalized() const override; protected: @@ -69,14 +69,15 @@ protected: /** Element struct */ struct Element { - Element(void *id_ = nullptr, IMemory *handle_ = nullptr, size_t size_ = 0, bool status_ = false) - : id(id_), handle(handle_), size(size_), status(status_) + Element(void *id_ = nullptr, IMemory *handle_ = nullptr, size_t size_ = 0, size_t alignment_ = 0, bool status_ = false) + : id(id_), handle(handle_), size(size_), alignment(alignment_), status(status_) { } - void *id; /**< Element id */ - IMemory *handle; /**< Element's memory handle */ - size_t size; /**< Element's size */ - bool status; /**< Lifetime status */ + void *id; /**< Element id */ + IMemory *handle; /**< Element's memory handle */ + size_t size; /**< Element's size */ + size_t alignment; /**< Alignment requirement */ + bool status; /**< Lifetime status */ }; /** Blob struct */ @@ -84,6 +85,7 @@ protected: { void *id; size_t max_size; + size_t max_alignment; std::set bound_elements; }; diff --git a/arm_compute/runtime/MemoryGroupBase.h b/arm_compute/runtime/MemoryGroupBase.h index 0ceaa900c5..7dc18c8b4f 100644 --- a/arm_compute/runtime/MemoryGroupBase.h +++ b/arm_compute/runtime/MemoryGroupBase.h @@ -70,8 +70,9 @@ public: * @param[in, out] obj_memory Object's memory handling interface which can be used to alter the underlying memory * that is used by the object. * @param[in] size Size of memory to allocate + * @param[in] alignment (Optional) Alignment to use */ - void finalize_memory(TensorType *obj, IMemory &obj_memory, size_t size); + void finalize_memory(TensorType *obj, IMemory &obj_memory, size_t size, size_t alignment = 0); // Inherited methods overridden: void acquire() override; @@ -116,7 +117,7 @@ inline void MemoryGroupBase::manage(TensorType *obj) } template -inline void MemoryGroupBase::finalize_memory(TensorType *obj, IMemory &obj_memory, size_t size) +inline void MemoryGroupBase::finalize_memory(TensorType *obj, IMemory &obj_memory, size_t size, size_t alignment) { // TODO (geopin01) : Check size (track size in MemoryMappings) // Check if existing mapping is valid @@ -125,7 +126,7 @@ inline void MemoryGroupBase::finalize_memory(TensorType *obj, IMemor if(_memory_manager && _mappings.empty()) { ARM_COMPUTE_ERROR_ON(!_memory_manager->lifetime_manager()); - _memory_manager->lifetime_manager()->end_lifetime(obj, obj_memory, size); + _memory_manager->lifetime_manager()->end_lifetime(obj, obj_memory, size, alignment); } } diff --git a/arm_compute/runtime/Types.h b/arm_compute/runtime/Types.h index b962427ef8..f2607c0204 100644 --- a/arm_compute/runtime/Types.h +++ b/arm_compute/runtime/Types.h @@ -46,6 +46,5 @@ using MemoryMappings = std::map; /** A map of the groups and memory mappings */ using GroupMappings = std::map; - -} // arm_compute +} // namespace arm_compute #endif /* __ARM_COMPUTE_RUNTIME_TYPES_H__ */ diff --git a/src/runtime/Allocator.cpp b/src/runtime/Allocator.cpp index 7f0e37495e..d9de11ebbf 100644 --- a/src/runtime/Allocator.cpp +++ b/src/runtime/Allocator.cpp @@ -44,6 +44,5 @@ void Allocator::free(void *ptr) std::unique_ptr Allocator::make_region(size_t size, size_t alignment) { - ARM_COMPUTE_UNUSED(alignment); - return arm_compute::support::cpp14::make_unique(size); + return arm_compute::support::cpp14::make_unique(size, alignment); } \ No newline at end of file diff --git a/src/runtime/BlobLifetimeManager.cpp b/src/runtime/BlobLifetimeManager.cpp index 2a4ab6ec0d..9fef943fb5 100644 --- a/src/runtime/BlobLifetimeManager.cpp +++ b/src/runtime/BlobLifetimeManager.cpp @@ -62,19 +62,21 @@ void BlobLifetimeManager::update_blobs_and_mappings() { return ba.max_size > bb.max_size; }); - std::vector group_sizes; + + // Create group sizes vector + std::vector group_sizes; std::transform(std::begin(_free_blobs), std::end(_free_blobs), std::back_inserter(group_sizes), [](const Blob & b) { - return b.max_size; + return BlobInfo(b.max_size, b.max_alignment); }); // Update blob sizes size_t max_size = std::max(_blobs.size(), group_sizes.size()); - _blobs.resize(max_size, 0); - group_sizes.resize(max_size, 0); - std::transform(std::begin(_blobs), std::end(_blobs), std::begin(group_sizes), std::begin(_blobs), [](size_t lhs, size_t rhs) + _blobs.resize(max_size); + group_sizes.resize(max_size); + std::transform(std::begin(_blobs), std::end(_blobs), std::begin(group_sizes), std::begin(_blobs), [](BlobInfo lhs, BlobInfo rhs) { - return std::max(lhs, rhs); + return BlobInfo(std::max(lhs.size, rhs.size), std::max(lhs.alignment, rhs.alignment)); }); // Calculate group mappings diff --git a/src/runtime/BlobMemoryPool.cpp b/src/runtime/BlobMemoryPool.cpp index e09451cd62..812cbdd673 100644 --- a/src/runtime/BlobMemoryPool.cpp +++ b/src/runtime/BlobMemoryPool.cpp @@ -33,11 +33,11 @@ using namespace arm_compute; -BlobMemoryPool::BlobMemoryPool(IAllocator *allocator, std::vector blob_sizes) - : _allocator(allocator), _blobs(), _blob_sizes(std::move(blob_sizes)) +BlobMemoryPool::BlobMemoryPool(IAllocator *allocator, std::vector blob_info) + : _allocator(allocator), _blobs(), _blob_info(std::move(blob_info)) { ARM_COMPUTE_ERROR_ON(!allocator); - allocate_blobs(_blob_sizes); + allocate_blobs(_blob_info); } BlobMemoryPool::~BlobMemoryPool() @@ -73,16 +73,16 @@ MappingType BlobMemoryPool::mapping_type() const std::unique_ptr BlobMemoryPool::duplicate() { ARM_COMPUTE_ERROR_ON(!_allocator); - return support::cpp14::make_unique(_allocator, _blob_sizes); + return support::cpp14::make_unique(_allocator, _blob_info); } -void BlobMemoryPool::allocate_blobs(const std::vector &sizes) +void BlobMemoryPool::allocate_blobs(const std::vector &blob_info) { ARM_COMPUTE_ERROR_ON(!_allocator); - for(const auto &size : sizes) + for(const auto &bi : blob_info) { - _blobs.push_back(_allocator->make_region(size, 0)); + _blobs.push_back(_allocator->make_region(bi.size, bi.alignment)); } } diff --git a/src/runtime/ISimpleLifetimeManager.cpp b/src/runtime/ISimpleLifetimeManager.cpp index 7d928d6a7a..97c20d1882 100644 --- a/src/runtime/ISimpleLifetimeManager.cpp +++ b/src/runtime/ISimpleLifetimeManager.cpp @@ -59,7 +59,7 @@ void ISimpleLifetimeManager::start_lifetime(void *obj) // Check if there is a free blob if(_free_blobs.empty()) { - _occupied_blobs.emplace_front(Blob{ obj, 0, { obj } }); + _occupied_blobs.emplace_front(Blob{ obj, 0, 0, { obj } }); } else { @@ -71,7 +71,7 @@ void ISimpleLifetimeManager::start_lifetime(void *obj) _active_elements.insert(std::make_pair(obj, obj)); } -void ISimpleLifetimeManager::end_lifetime(void *obj, IMemory &obj_memory, size_t size) +void ISimpleLifetimeManager::end_lifetime(void *obj, IMemory &obj_memory, size_t size, size_t alignment) { ARM_COMPUTE_ERROR_ON(obj == nullptr); @@ -80,10 +80,11 @@ void ISimpleLifetimeManager::end_lifetime(void *obj, IMemory &obj_memory, size_t ARM_COMPUTE_ERROR_ON(active_object_it == std::end(_active_elements)); // Update object fields and mark object as complete - Element &el = active_object_it->second; - el.handle = &obj_memory; - el.size = size; - el.status = true; + Element &el = active_object_it->second; + el.handle = &obj_memory; + el.size = size; + el.alignment = alignment; + el.status = true; // Find object in the occupied lists auto occupied_blob_it = std::find_if(std::begin(_occupied_blobs), std::end(_occupied_blobs), [&obj](const Blob & b) @@ -94,8 +95,9 @@ void ISimpleLifetimeManager::end_lifetime(void *obj, IMemory &obj_memory, size_t // Update occupied blob and return as free occupied_blob_it->bound_elements.insert(obj); - occupied_blob_it->max_size = std::max(occupied_blob_it->max_size, size); - occupied_blob_it->id = nullptr; + occupied_blob_it->max_size = std::max(occupied_blob_it->max_size, size); + occupied_blob_it->max_alignment = std::max(occupied_blob_it->max_alignment, alignment); + occupied_blob_it->id = nullptr; _free_blobs.splice(std::begin(_free_blobs), _occupied_blobs, occupied_blob_it); // Check if all object are finalized and reset active group diff --git a/src/runtime/TensorAllocator.cpp b/src/runtime/TensorAllocator.cpp index 5fa51d7140..38edb8ba03 100644 --- a/src/runtime/TensorAllocator.cpp +++ b/src/runtime/TensorAllocator.cpp @@ -138,7 +138,7 @@ void TensorAllocator::allocate() } else { - _associated_memory_group->finalize_memory(_owner, _memory, info().total_size()); + _associated_memory_group->finalize_memory(_owner, _memory, info().total_size(), alignment()); } info().set_is_resizable(false); } -- cgit v1.2.1