COMPMID-1848: Account alignment in Offset-based pool allocations

Change-Id: I061d612341bf951a7d0e7ddd04a42139c8400d41
Reviewed-on: https://review.mlplatform.org/554
Tested-by: Arm Jenkins <bsgcomp@arm.com>
Reviewed-by: Michalis Spyrou <michalis.spyrou@arm.com>
diff --git a/arm_compute/runtime/BlobLifetimeManager.h b/arm_compute/runtime/BlobLifetimeManager.h
index 2dbe92d..586ad10 100644
--- a/arm_compute/runtime/BlobLifetimeManager.h
+++ b/arm_compute/runtime/BlobLifetimeManager.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -26,15 +26,16 @@
 
 #include "arm_compute/runtime/ISimpleLifetimeManager.h"
 
-#include "arm_compute/runtime/BlobMemoryPool.h"
 #include "arm_compute/runtime/Types.h"
 
-#include <cstddef>
 #include <memory>
 #include <vector>
 
 namespace arm_compute
 {
+// Forward declarations
+class IMemoryPool;
+
 /** Concrete class that tracks the lifetime of registered tensors and
  *  calculates the systems memory requirements in terms of blobs */
 class BlobLifetimeManager : public ISimpleLifetimeManager
diff --git a/arm_compute/runtime/BlobMemoryPool.h b/arm_compute/runtime/BlobMemoryPool.h
index ba97dbd..c2e0902 100644
--- a/arm_compute/runtime/BlobMemoryPool.h
+++ b/arm_compute/runtime/BlobMemoryPool.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -38,17 +38,6 @@
 // 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
 {
diff --git a/arm_compute/runtime/OffsetLifetimeManager.h b/arm_compute/runtime/OffsetLifetimeManager.h
index e39d6a0..26aeb1e 100644
--- a/arm_compute/runtime/OffsetLifetimeManager.h
+++ b/arm_compute/runtime/OffsetLifetimeManager.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -28,12 +28,12 @@
 
 #include "arm_compute/runtime/Types.h"
 
-#include <cstddef>
 #include <map>
 #include <vector>
 
 namespace arm_compute
 {
+// Forward declarations
 class IMemoryPool;
 
 /** Concrete class that tracks the lifetime of registered tensors and
@@ -61,7 +61,7 @@
     void update_blobs_and_mappings() override;
 
 private:
-    size_t _blob; /**< Memory blob size */
+    BlobInfo _blob; /**< Memory blob size */
 };
 } // namespace arm_compute
 #endif /* __ARM_COMPUTE_OFFSETLIFETIMEMANAGER_H__ */
diff --git a/arm_compute/runtime/OffsetMemoryPool.h b/arm_compute/runtime/OffsetMemoryPool.h
index 480d424..bc09de6 100644
--- a/arm_compute/runtime/OffsetMemoryPool.h
+++ b/arm_compute/runtime/OffsetMemoryPool.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -30,6 +30,7 @@
 #include "arm_compute/runtime/Types.h"
 
 #include <cstddef>
+#include <memory>
 
 namespace arm_compute
 {
@@ -44,9 +45,9 @@
      * @note allocator should outlive the memory pool
      *
      * @param[in] allocator Backing memory allocator
-     * @param[in] blob_size Size of the memory be allocated
+     * @param[in] blob_info Configuration information of the blob to be allocated
      */
-    OffsetMemoryPool(IAllocator *allocator, size_t blob_size);
+    OffsetMemoryPool(IAllocator *allocator, BlobInfo blob_info);
     /** Default Destructor */
     ~OffsetMemoryPool() = default;
     /** Prevent instances of this class to be copy constructed */
@@ -67,7 +68,7 @@
 private:
     IAllocator                    *_allocator; /**< Allocator to use for internal allocation */
     std::unique_ptr<IMemoryRegion> _blob;      /**< Memory blob */
-    size_t                         _blob_size; /**< Sizes of the allocated memory blob */
+    BlobInfo                       _blob_info; /**< Information for the blob to allocate */
 };
 } // namespace arm_compute
 #endif /* __ARM_COMPUTE_OFFSETMEMORYPOOL_H__ */
diff --git a/arm_compute/runtime/Types.h b/arm_compute/runtime/Types.h
index f2607c0..fece513 100644
--- a/arm_compute/runtime/Types.h
+++ b/arm_compute/runtime/Types.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018 ARM Limited.
+ * Copyright (c) 2016-2019 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -46,5 +46,17 @@
 
 /** A map of the groups and memory mappings */
 using GroupMappings = std::map<size_t, MemoryMappings>;
+
+/** Meta-data information for each blob */
+struct BlobInfo
+{
+    BlobInfo(size_t size_ = 0, size_t alignment_ = 0, size_t owners_ = 1)
+        : size(size_), alignment(alignment_), owners(owners_)
+    {
+    }
+    size_t size;      /**< Blob size */
+    size_t alignment; /**< Blob alignment */
+    size_t owners;    /**< Number of owners in parallel of the blob */
+};
 } // namespace arm_compute
 #endif /* __ARM_COMPUTE_RUNTIME_TYPES_H__ */
diff --git a/src/graph/backends/NEON/NEDeviceBackend.cpp b/src/graph/backends/NEON/NEDeviceBackend.cpp
index 7b1f6bf..f94cd97 100644
--- a/src/graph/backends/NEON/NEDeviceBackend.cpp
+++ b/src/graph/backends/NEON/NEDeviceBackend.cpp
@@ -83,8 +83,8 @@
     {
         MemoryManagerContext mm_ctx;
         mm_ctx.target      = Target::NEON;
-        mm_ctx.intra_mm    = create_memory_manager(MemoryManagerAffinity::Buffer);
-        mm_ctx.cross_mm    = create_memory_manager(MemoryManagerAffinity::Buffer);
+        mm_ctx.intra_mm    = create_memory_manager(MemoryManagerAffinity::Offset);
+        mm_ctx.cross_mm    = create_memory_manager(MemoryManagerAffinity::Offset);
         mm_ctx.cross_group = std::make_shared<MemoryGroup>(mm_ctx.cross_mm);
         mm_ctx.allocator   = &_allocator;
 
diff --git a/src/runtime/BlobLifetimeManager.cpp b/src/runtime/BlobLifetimeManager.cpp
index 9fef943..c5d42b1 100644
--- a/src/runtime/BlobLifetimeManager.cpp
+++ b/src/runtime/BlobLifetimeManager.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -32,7 +32,6 @@
 #include <algorithm>
 #include <cmath>
 #include <map>
-#include <vector>
 
 using namespace arm_compute;
 
diff --git a/src/runtime/OffsetLifetimeManager.cpp b/src/runtime/OffsetLifetimeManager.cpp
index d0b3bde..ad23220 100644
--- a/src/runtime/OffsetLifetimeManager.cpp
+++ b/src/runtime/OffsetLifetimeManager.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -34,8 +34,16 @@
 #include <map>
 #include <vector>
 
-using namespace arm_compute;
-
+namespace arm_compute
+{
+namespace
+{
+size_t align_offset(size_t offset, size_t alignment)
+{
+    const size_t remainder = (alignment != 0U) ? offset % alignment : 0U;
+    return (remainder != 0U) ? offset + (alignment - remainder) : offset;
+}
+} // namespace
 OffsetLifetimeManager::OffsetLifetimeManager()
     : _blob(0)
 {
@@ -58,11 +66,15 @@
     ARM_COMPUTE_ERROR_ON(_active_group == nullptr);
 
     // Update blob size
-    size_t max_group_size = std::accumulate(std::begin(_free_blobs), std::end(_free_blobs), static_cast<size_t>(0), [](size_t s, const Blob & b)
+    size_t max_aggregated_size = 0;
+    std::for_each(std::begin(_free_blobs), std::end(_free_blobs), [&](const Blob & b)
     {
-        return s + b.max_size;
+        max_aggregated_size += b.max_size;
+        _blob.alignment = std::max(_blob.alignment, b.max_alignment);
     });
-    _blob = std::max(_blob, max_group_size);
+    max_aggregated_size += _free_blobs.size() * _blob.alignment;
+    _blob.owners = std::max(_blob.owners, _free_blobs.size());
+    _blob.size   = std::max(_blob.size, max_aggregated_size);
 
     // Calculate group mappings
     auto &group_mappings = _active_group->mappings();
@@ -76,6 +88,8 @@
             group_mappings[bound_element.handle] = offset;
         }
         offset += free_blob.max_size;
-        ARM_COMPUTE_ERROR_ON(offset > _blob);
+        offset = align_offset(offset, _blob.alignment);
+        ARM_COMPUTE_ERROR_ON(offset > _blob.size);
     }
 }
+} // namespace arm_compute
diff --git a/src/runtime/OffsetMemoryPool.cpp b/src/runtime/OffsetMemoryPool.cpp
index 36eaf0b..70cbe90 100644
--- a/src/runtime/OffsetMemoryPool.cpp
+++ b/src/runtime/OffsetMemoryPool.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -34,11 +34,11 @@
 
 using namespace arm_compute;
 
-OffsetMemoryPool::OffsetMemoryPool(IAllocator *allocator, size_t blob_size)
-    : _allocator(allocator), _blob(), _blob_size(blob_size)
+OffsetMemoryPool::OffsetMemoryPool(IAllocator *allocator, BlobInfo blob_info)
+    : _allocator(allocator), _blob(), _blob_info(blob_info)
 {
     ARM_COMPUTE_ERROR_ON(!allocator);
-    _blob = _allocator->make_region(blob_size, 0);
+    _blob = _allocator->make_region(blob_info.size, blob_info.alignment);
 }
 
 void OffsetMemoryPool::acquire(MemoryMappings &handles)
@@ -49,7 +49,7 @@
     for(auto &handle : handles)
     {
         ARM_COMPUTE_ERROR_ON(handle.first == nullptr);
-        handle.first->set_owned_region(_blob->extract_subregion(handle.second, _blob_size - handle.second));
+        handle.first->set_owned_region(_blob->extract_subregion(handle.second, _blob_info.size - handle.second));
     }
 }
 
@@ -70,5 +70,5 @@
 std::unique_ptr<IMemoryPool> OffsetMemoryPool::duplicate()
 {
     ARM_COMPUTE_ERROR_ON(!_allocator);
-    return support::cpp14::make_unique<OffsetMemoryPool>(_allocator, _blob_size);
+    return support::cpp14::make_unique<OffsetMemoryPool>(_allocator, _blob_info);
 }
\ No newline at end of file