diff options
author | Jim Flynn <jim.flynn@arm.com> | 2020-06-22 20:41:43 +0100 |
---|---|---|
committer | James Conroy <james.conroy@arm.com> | 2020-06-23 09:14:51 +0000 |
commit | 0204f09cb7462c675c45c76cd13d677d67f73589 (patch) | |
tree | 880f018f376b04652730715d1bc3fbaff1f90df7 /src | |
parent | 1f45dc3e7f955a6d75c8516ba6fd7eade2b03cb7 (diff) | |
download | armnn-0204f09cb7462c675c45c76cd13d677d67f73589.tar.gz |
IVGCVSW-5022 Fix master intermittent failure by providing surge buffer capacity
Change-Id: I028aec48d89d7348836223029aa1e8c315f160fa
Signed-off-by: Jim Flynn <jim.flynn@arm.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/profiling/BufferManager.cpp | 50 | ||||
-rw-r--r-- | src/profiling/BufferManager.hpp | 4 | ||||
-rw-r--r-- | src/profiling/IPacketBuffer.hpp | 4 | ||||
-rw-r--r-- | src/profiling/PacketBuffer.cpp | 7 | ||||
-rw-r--r-- | src/profiling/PacketBuffer.hpp | 2 | ||||
-rw-r--r-- | src/profiling/SendTimelinePacket.cpp | 8 | ||||
-rw-r--r-- | src/profiling/test/BufferTests.cpp | 70 | ||||
-rw-r--r-- | src/profiling/test/ProfilingMocks.hpp | 2 |
8 files changed, 139 insertions, 8 deletions
diff --git a/src/profiling/BufferManager.cpp b/src/profiling/BufferManager.cpp index a7b71e5fa1..be60f2788d 100644 --- a/src/profiling/BufferManager.cpp +++ b/src/profiling/BufferManager.cpp @@ -14,7 +14,9 @@ namespace profiling BufferManager::BufferManager(unsigned int numberOfBuffers, unsigned int maxPacketSize) : m_MaxBufferSize(maxPacketSize), - m_NumberOfBuffers(numberOfBuffers) + m_NumberOfBuffers(numberOfBuffers), + m_MaxNumberOfBuffers(numberOfBuffers * 3), + m_CurrentNumberOfBuffers(numberOfBuffers) { Initialize(); } @@ -30,8 +32,21 @@ IPacketBufferPtr BufferManager::Reserve(unsigned int requestedSize, unsigned int availableListLock.lock(); if (m_AvailableList.empty()) { - availableListLock.unlock(); - return nullptr; + if (m_CurrentNumberOfBuffers < m_MaxNumberOfBuffers) + { + // create a temporary overflow/surge buffer and hand it back + m_CurrentNumberOfBuffers++; + availableListLock.unlock(); + IPacketBufferPtr buffer = std::make_unique<PacketBuffer>(m_MaxBufferSize); + reservedSize = requestedSize; + return buffer; + } + else + { + // we have totally busted the limit. call a halt to new memory allocations. + availableListLock.unlock(); + return nullptr; + } } IPacketBufferPtr buffer = std::move(m_AvailableList.back()); m_AvailableList.pop_back(); @@ -57,6 +72,7 @@ void BufferManager::Commit(IPacketBufferPtr& packetBuffer, unsigned int size, bo void BufferManager::Initialize() { m_AvailableList.reserve(m_NumberOfBuffers); + m_CurrentNumberOfBuffers = m_NumberOfBuffers; for (unsigned int i = 0; i < m_NumberOfBuffers; ++i) { IPacketBufferPtr buffer = std::make_unique<PacketBuffer>(m_MaxBufferSize); @@ -69,7 +85,19 @@ void BufferManager::Release(IPacketBufferPtr& packetBuffer) std::unique_lock<std::mutex> availableListLock(m_AvailableMutex, std::defer_lock); packetBuffer->Release(); availableListLock.lock(); - m_AvailableList.push_back(std::move(packetBuffer)); + if (m_AvailableList.size() <= m_NumberOfBuffers) + { + m_AvailableList.push_back(std::move(packetBuffer)); + } + else + { + // we have been handed a temporary overflow/surge buffer get rid of it + packetBuffer->Destroy(); + if (m_CurrentNumberOfBuffers > m_NumberOfBuffers) + { + --m_CurrentNumberOfBuffers; + } + } availableListLock.unlock(); } @@ -103,7 +131,19 @@ void BufferManager::MarkRead(IPacketBufferPtr& packetBuffer) std::unique_lock<std::mutex> availableListLock(m_AvailableMutex, std::defer_lock); packetBuffer->MarkRead(); availableListLock.lock(); - m_AvailableList.push_back(std::move(packetBuffer)); + if (m_AvailableList.size() <= m_NumberOfBuffers) + { + m_AvailableList.push_back(std::move(packetBuffer)); + } + else + { + // we have been handed a temporary overflow/surge buffer get rid of it + packetBuffer->Destroy(); + if (m_CurrentNumberOfBuffers > m_NumberOfBuffers) + { + --m_CurrentNumberOfBuffers; + } + } availableListLock.unlock(); } diff --git a/src/profiling/BufferManager.hpp b/src/profiling/BufferManager.hpp index f4e63dab11..4bc7725721 100644 --- a/src/profiling/BufferManager.hpp +++ b/src/profiling/BufferManager.hpp @@ -51,7 +51,9 @@ private: // Maximum buffer size unsigned int m_MaxBufferSize; // Number of buffers - unsigned int m_NumberOfBuffers; + const unsigned int m_NumberOfBuffers; + const unsigned int m_MaxNumberOfBuffers; + unsigned int m_CurrentNumberOfBuffers; // List of available packet buffers std::vector<IPacketBufferPtr> m_AvailableList; diff --git a/src/profiling/IPacketBuffer.hpp b/src/profiling/IPacketBuffer.hpp index 1a97ca741c..15687a81e9 100644 --- a/src/profiling/IPacketBuffer.hpp +++ b/src/profiling/IPacketBuffer.hpp @@ -35,6 +35,10 @@ public: virtual void Release() = 0; virtual unsigned char* GetWritableData() = 0; + + /// release the memory held and reset internal point to null. + /// After this function is invoked the PacketBuffer is unusable. + virtual void Destroy() = 0; }; using IPacketBufferPtr = std::unique_ptr<IPacketBuffer>; diff --git a/src/profiling/PacketBuffer.cpp b/src/profiling/PacketBuffer.cpp index 886561ae75..6010493002 100644 --- a/src/profiling/PacketBuffer.cpp +++ b/src/profiling/PacketBuffer.cpp @@ -55,6 +55,13 @@ unsigned char* PacketBuffer::GetWritableData() return m_Data.get(); } +void PacketBuffer::Destroy() +{ + m_Data.reset(nullptr); + m_Size = 0; + m_MaxSize = 0; +} + } // namespace profiling } // namespace armnn diff --git a/src/profiling/PacketBuffer.hpp b/src/profiling/PacketBuffer.hpp index f03b301697..02fe3b99d8 100644 --- a/src/profiling/PacketBuffer.hpp +++ b/src/profiling/PacketBuffer.hpp @@ -34,6 +34,8 @@ public: unsigned char* GetWritableData() override; + void Destroy() override; + private: unsigned int m_MaxSize; unsigned int m_Size; diff --git a/src/profiling/SendTimelinePacket.cpp b/src/profiling/SendTimelinePacket.cpp index b749b5dc72..2ca5f5470b 100644 --- a/src/profiling/SendTimelinePacket.cpp +++ b/src/profiling/SendTimelinePacket.cpp @@ -64,9 +64,13 @@ void SendTimelinePacket::ReserveBuffer() m_WriteBuffer = m_BufferManager.Reserve(MAX_METADATA_PACKET_LENGTH, reserved); // Check if there is enough space in the buffer - if (m_WriteBuffer == nullptr || reserved < m_Offset) + if (m_WriteBuffer == nullptr) + { + throw BufferExhaustion("No free buffers left", CHECK_LOCATION()); + } + if (reserved < m_Offset) { - throw BufferExhaustion("No space left on buffer", CHECK_LOCATION()); + throw BufferExhaustion("Reserved space too small for use", CHECK_LOCATION()); } if (m_DirectoryPackage) diff --git a/src/profiling/test/BufferTests.cpp b/src/profiling/test/BufferTests.cpp index cba209c9a2..0225d750a7 100644 --- a/src/profiling/test/BufferTests.cpp +++ b/src/profiling/test/BufferTests.cpp @@ -146,6 +146,21 @@ BOOST_AUTO_TEST_CASE(BufferExhaustionTest) BOOST_TEST(packetBuffer.get()); // Cannot reserve buffer when buffer is not available + // NOTE: because the buffer manager now has surge capacity of + // initial size * 3 we should be able to reserve three + // buffers before exhaustion + packetBuffer = bufferManager.Reserve(512, reservedSize); + + // Successfully reserved the second buffer with requested size + BOOST_TEST(reservedSize == 512); + BOOST_TEST(packetBuffer.get()); + + packetBuffer = bufferManager.Reserve(512, reservedSize); + + // Successfully reserved the third buffer with requested size + BOOST_TEST(reservedSize == 512); + BOOST_TEST(packetBuffer.get()); + auto reservedBuffer = bufferManager.Reserve(512, reservedSize); BOOST_TEST(reservedSize == 0); BOOST_TEST(!reservedBuffer.get()); @@ -175,6 +190,19 @@ BOOST_AUTO_TEST_CASE(BufferReserveMultipleTest) BOOST_TEST(reservedSize2 == 512); BOOST_TEST(packetBuffer2.get()); + // NOTE: the buffer now has a surge capacity of initial size * 3 + // so we can grab 9 of them prior to exhaustion now + for (unsigned int i = 0; i < 6 ; ++i) + { + // grab another six buffers to exhaust the surge capacity + unsigned int reservedSize = 0; + auto packetBuffer = bufferManager.Reserve(512, reservedSize); + + // Successfully reserved the third buffer with requested size + BOOST_TEST(reservedSize == 512); + BOOST_TEST(packetBuffer.get()); + } + // Cannot reserve when buffer is not available unsigned int reservedSize3 = 0; auto reservedBuffer = bufferManager.Reserve(512, reservedSize3); @@ -199,6 +227,20 @@ BOOST_AUTO_TEST_CASE(BufferReleaseTest) BOOST_TEST(reservedSize1 == 128); BOOST_TEST(packetBuffer1.get()); + // NOTE: now that we have a surge capacity of up to + // initial size * 3 we need to allocate four more + // buffers to exhaust the manager + for (unsigned int i = 0; i < 4 ; ++i) + { + // grab another six buffers to exhaust the surge capacity + unsigned int reservedSize = 0; + auto packetBuffer = bufferManager.Reserve(512, reservedSize); + + // Successfully reserved the third buffer with requested size + BOOST_TEST(reservedSize == 512); + BOOST_TEST(packetBuffer.get()); + } + // Cannot reserve when buffer is not available unsigned int reservedSize2 = 0; auto reservedBuffer = bufferManager.Reserve(512, reservedSize2); @@ -229,6 +271,20 @@ BOOST_AUTO_TEST_CASE(BufferCommitTest) BOOST_TEST(reservedSize1 == 128); BOOST_TEST(packetBuffer1.get()); + // NOTE: now that we have a surge capacity of up to + // initial size * 3 we need to allocate four more + // buffers to exhaust the manager + for (unsigned int i = 0; i < 4 ; ++i) + { + // grab another six buffers to exhaust the surge capacity + unsigned int reservedSize = 0; + auto packetBuffer = bufferManager.Reserve(512, reservedSize); + + // Successfully reserved the third buffer with requested size + BOOST_TEST(reservedSize == 512); + BOOST_TEST(packetBuffer.get()); + } + unsigned int reservedSize2 = 0; auto reservedBuffer = bufferManager.Reserve(512, reservedSize2); BOOST_TEST(reservedSize2 == 0); @@ -263,6 +319,20 @@ BOOST_AUTO_TEST_CASE(BufferMarkReadTest) BOOST_TEST(reservedSize1 == 128); BOOST_TEST(packetBuffer1.get()); + // NOTE: now that we have a surge capacity of up to + // initial size * 3 we need to allocate four more + // buffers to exhaust the manager + for (unsigned int i = 0; i < 4 ; ++i) + { + // grab another six buffers to exhaust the surge capacity + unsigned int reservedSize = 0; + auto packetBuffer = bufferManager.Reserve(512, reservedSize); + + // Successfully reserved the third buffer with requested size + BOOST_TEST(reservedSize == 512); + BOOST_TEST(packetBuffer.get()); + } + // Cannot reserve when buffer is not available unsigned int reservedSize2 = 0; auto reservedBuffer = bufferManager.Reserve(512, reservedSize2); diff --git a/src/profiling/test/ProfilingMocks.hpp b/src/profiling/test/ProfilingMocks.hpp index fe8fbd7db9..e4f71f932c 100644 --- a/src/profiling/test/ProfilingMocks.hpp +++ b/src/profiling/test/ProfilingMocks.hpp @@ -193,6 +193,8 @@ public: unsigned char* GetWritableData() override { return m_Data.get(); } + void Destroy() override {m_Data.reset(nullptr); m_Size = 0; m_MaxSize =0;} + private: unsigned int m_MaxSize; unsigned int m_Size; |