aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Flynn <jim.flynn@arm.com>2020-06-22 20:41:43 +0100
committerJames Conroy <james.conroy@arm.com>2020-06-23 09:14:51 +0000
commit0204f09cb7462c675c45c76cd13d677d67f73589 (patch)
tree880f018f376b04652730715d1bc3fbaff1f90df7
parent1f45dc3e7f955a6d75c8516ba6fd7eade2b03cb7 (diff)
downloadarmnn-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>
-rw-r--r--src/profiling/BufferManager.cpp50
-rw-r--r--src/profiling/BufferManager.hpp4
-rw-r--r--src/profiling/IPacketBuffer.hpp4
-rw-r--r--src/profiling/PacketBuffer.cpp7
-rw-r--r--src/profiling/PacketBuffer.hpp2
-rw-r--r--src/profiling/SendTimelinePacket.cpp8
-rw-r--r--src/profiling/test/BufferTests.cpp70
-rw-r--r--src/profiling/test/ProfilingMocks.hpp2
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;