From cfccdd2865bdf33112e96d505d3bc022eb4aa453 Mon Sep 17 00:00:00 2001 From: Eric Lunderberg Date: Thu, 24 Mar 2022 13:44:05 -0500 Subject: [PATCH 1/2] [Hexagon] Use single allocation to back 2-d arrays Currently, each allocation allocates an entire page, so even a relatively small number of allocations can use very large amounts of VTCM. This commit changes calls to `AllocVtcmWorkspace` of shape `[N,M]` from performing `N` allocations of size `M`, to 1 allocation of size `N*M`. Since `N` is usually much smaller than a page, this reduces the total amount of memory required. This is an intermediate step, where the long-term solution is to use static planning for VTCM allocations. This returns the same `void**` type as the static planning eventually will, but avoids excess memory use in the meantime. --- src/runtime/hexagon/hexagon/hexagon_buffer.cc | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/runtime/hexagon/hexagon/hexagon_buffer.cc b/src/runtime/hexagon/hexagon/hexagon_buffer.cc index b1de44df330c..cb7303ee86b2 100644 --- a/src/runtime/hexagon/hexagon/hexagon_buffer.cc +++ b/src/runtime/hexagon/hexagon/hexagon_buffer.cc @@ -150,17 +150,21 @@ HexagonBuffer::HexagonBuffer(size_t nallocs, size_t nbytes, size_t alignment, Optional scope) : ndim_(2), nbytes_per_allocation_(nbytes) { SetStorageScope(scope); + + std::unique_ptr alloca = nullptr; + if (GetStorageScope() == StorageScope::kDDR) { + alloca = Allocator(nallocs * nbytes, alignment); + } else if (GetStorageScope() == StorageScope::kVTCM) { + alloca = Allocator(nallocs * nbytes, alignment); + } + CHECK(alloca) << "could not create allocation"; + for (size_t i = 0; i < nallocs; ++i) { - std::unique_ptr alloca = nullptr; - if (GetStorageScope() == StorageScope::kDDR) { - alloca = Allocator(nbytes, alignment); - } else if (GetStorageScope() == StorageScope::kVTCM) { - alloca = Allocator(nbytes, alignment); - } - CHECK(alloca != nullptr); - allocations_.push_back(alloca->data_); - managed_allocations_.push_back(std::move(alloca)); + void* alloc_offset = static_cast(alloca->data_) + i * nbytes; + allocations_.push_back(alloc_offset); } + + managed_allocations_.push_back(std::move(alloca)); } HexagonBuffer::HexagonBuffer(void* data, size_t nbytes, Optional scope) From 42e6e857bfb8a917b161a8afe6aa96aa6d80e244 Mon Sep 17 00:00:00 2001 From: Eric Lunderberg Date: Mon, 28 Mar 2022 13:39:35 -0500 Subject: [PATCH 2/2] [Hexagon] Maintain alignment of allocations Previously, when a single monolithic allocation is used to back a 2-d Hexagon buffer of shape `[nallocs, nbytes_per_allocation]`, the allocation itself is aligned, but each individual region is not. This commit ensures that each individual region also followed the alignment specified. --- src/runtime/hexagon/hexagon/hexagon_buffer.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/runtime/hexagon/hexagon/hexagon_buffer.cc b/src/runtime/hexagon/hexagon/hexagon_buffer.cc index cb7303ee86b2..fc8cfa4efb3a 100644 --- a/src/runtime/hexagon/hexagon/hexagon_buffer.cc +++ b/src/runtime/hexagon/hexagon/hexagon_buffer.cc @@ -151,16 +151,19 @@ HexagonBuffer::HexagonBuffer(size_t nallocs, size_t nbytes, size_t alignment, : ndim_(2), nbytes_per_allocation_(nbytes) { SetStorageScope(scope); + size_t nbytes_aligned = ((nbytes + (alignment - 1)) / alignment) * alignment; + size_t nbytes_monolithic = nallocs * nbytes_aligned; + std::unique_ptr alloca = nullptr; if (GetStorageScope() == StorageScope::kDDR) { - alloca = Allocator(nallocs * nbytes, alignment); + alloca = Allocator(nbytes_monolithic, alignment); } else if (GetStorageScope() == StorageScope::kVTCM) { - alloca = Allocator(nallocs * nbytes, alignment); + alloca = Allocator(nbytes_monolithic, alignment); } CHECK(alloca) << "could not create allocation"; for (size_t i = 0; i < nallocs; ++i) { - void* alloc_offset = static_cast(alloca->data_) + i * nbytes; + void* alloc_offset = static_cast(alloca->data_) + i * nbytes_aligned; allocations_.push_back(alloc_offset); }