aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt5
-rw-r--r--src/profiling/BufferManager.cpp93
-rw-r--r--src/profiling/BufferManager.hpp59
-rw-r--r--src/profiling/PacketBuffer.cpp60
-rw-r--r--src/profiling/PacketBuffer.hpp45
-rw-r--r--src/profiling/test/BufferTests.cpp279
-rw-r--r--src/profiling/test/SendCounterPacketTests.hpp4
7 files changed, 543 insertions, 2 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 11afe7ad17..6ae352d94c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -424,6 +424,8 @@ list(APPEND armnn_sources
src/armnn/optimizations/PermuteAndBatchToSpaceAsDepthToSpace.cpp
src/armnn/optimizations/PermuteAsReshape.hpp
src/armnn/optimizations/SquashEqualSiblings.hpp
+ src/profiling/BufferManager.cpp
+ src/profiling/BufferManager.hpp
src/profiling/CommandHandlerFunctor.cpp
src/profiling/CommandHandlerFunctor.hpp
src/profiling/CommandHandlerKey.cpp
@@ -449,6 +451,8 @@ list(APPEND armnn_sources
src/profiling/IReadCounterValue.hpp
src/profiling/Packet.cpp
src/profiling/Packet.hpp
+ src/profiling/PacketBuffer.cpp
+ src/profiling/PacketBuffer.hpp
src/profiling/PacketVersionResolver.cpp
src/profiling/PacketVersionResolver.hpp
src/profiling/PeriodicCounterCapture.hpp
@@ -590,6 +594,7 @@ if(BUILD_UNIT_TESTS)
src/armnnUtils/test/PrototxtConversionsTest.cpp
src/armnnUtils/test/ParserHelperTest.cpp
src/armnnUtils/test/TensorUtilsTest.cpp
+ src/profiling/test/BufferTests.cpp
src/profiling/test/ProfilingConnectionDumpToFileDecoratorTests.cpp
src/profiling/test/ProfilingTests.cpp
src/profiling/test/SendCounterPacketTests.cpp
diff --git a/src/profiling/BufferManager.cpp b/src/profiling/BufferManager.cpp
new file mode 100644
index 0000000000..91ad1c5f3a
--- /dev/null
+++ b/src/profiling/BufferManager.cpp
@@ -0,0 +1,93 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "BufferManager.hpp"
+#include "PacketBuffer.hpp"
+#include "ProfilingUtils.hpp"
+
+#include <armnn/Exceptions.hpp>
+
+namespace armnn
+{
+
+namespace profiling
+{
+
+BufferManager::BufferManager(unsigned int numberOfBuffers, unsigned int maxPacketSize)
+ : m_MaxBufferSize(maxPacketSize)
+{
+ m_AvailableList.reserve(numberOfBuffers);
+ for (unsigned int i = 0; i < numberOfBuffers; ++i)
+ {
+ std::unique_ptr<IPacketBuffer> buffer = std::make_unique<PacketBuffer>(maxPacketSize);
+ m_AvailableList.emplace_back(std::move(buffer));
+ }
+ m_ReadableList.reserve(numberOfBuffers);
+}
+
+std::unique_ptr<IPacketBuffer> BufferManager::Reserve(unsigned int requestedSize, unsigned int& reservedSize)
+{
+ std::unique_lock<std::mutex> availableListLock(m_AvailableMutex, std::defer_lock);
+ if (requestedSize > m_MaxBufferSize)
+ {
+ throw armnn::RuntimeException("Maximum buffer size that can be requested is [" +
+ std::to_string(m_MaxBufferSize) + "] bytes");
+ }
+ availableListLock.lock();
+ if (m_AvailableList.empty())
+ {
+ throw armnn::profiling::BufferExhaustion("Buffer not available");
+ }
+ std::unique_ptr<IPacketBuffer> buffer = std::move(m_AvailableList.back());
+ m_AvailableList.pop_back();
+ availableListLock.unlock();
+ reservedSize = requestedSize;
+ return buffer;
+}
+
+void BufferManager::Commit(std::unique_ptr<IPacketBuffer>& packetBuffer, unsigned int size)
+{
+ std::unique_lock<std::mutex> readableListLock(m_ReadableMutex, std::defer_lock);
+ packetBuffer->Commit(size);
+ readableListLock.lock();
+ m_ReadableList.push_back(std::move(packetBuffer));
+ readableListLock.unlock();
+ m_ReadDataAvailable.notify_one();
+}
+
+void BufferManager::Release(std::unique_ptr<IPacketBuffer>& packetBuffer)
+{
+ std::unique_lock<std::mutex> availableListLock(m_AvailableMutex, std::defer_lock);
+ packetBuffer->Release();
+ availableListLock.lock();
+ m_AvailableList.push_back(std::move(packetBuffer));
+ availableListLock.unlock();
+}
+
+std::unique_ptr<IPacketBuffer> BufferManager::GetReadableBuffer()
+{
+ std::unique_lock<std::mutex> readableListLock(m_ReadableMutex);
+ if (!m_ReadableList.empty())
+ {
+ std::unique_ptr<IPacketBuffer> buffer = std::move(m_ReadableList.back());
+ m_ReadableList.pop_back();
+ readableListLock.unlock();
+ return buffer;
+ }
+ return nullptr;
+}
+
+void BufferManager::MarkRead(std::unique_ptr<IPacketBuffer>& packetBuffer)
+{
+ std::unique_lock<std::mutex> availableListLock(m_AvailableMutex, std::defer_lock);
+ packetBuffer->MarkRead();
+ availableListLock.lock();
+ m_AvailableList.push_back(std::move(packetBuffer));
+ availableListLock.unlock();
+}
+
+} // namespace profiling
+
+} // namespace armnn
diff --git a/src/profiling/BufferManager.hpp b/src/profiling/BufferManager.hpp
new file mode 100644
index 0000000000..04a1507512
--- /dev/null
+++ b/src/profiling/BufferManager.hpp
@@ -0,0 +1,59 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "IBufferManager.hpp"
+
+#include <condition_variable>
+#include <mutex>
+#include <vector>
+
+namespace armnn
+{
+
+namespace profiling
+{
+
+class BufferManager : public IBufferManager
+{
+public:
+ BufferManager(unsigned int numberOfBuffers = 5, unsigned int maxPacketSize = 4096);
+
+ ~BufferManager() {}
+
+ std::unique_ptr<IPacketBuffer> Reserve(unsigned int requestedSize, unsigned int& reservedSize) override;
+
+ void Commit(std::unique_ptr<IPacketBuffer>& packetBuffer, unsigned int size) override;
+
+ void Release(std::unique_ptr<IPacketBuffer>& packetBuffer) override;
+
+ std::unique_ptr<IPacketBuffer> GetReadableBuffer() override;
+
+ void MarkRead(std::unique_ptr<IPacketBuffer>& packetBuffer) override;
+
+private:
+ // Maximum buffer size
+ unsigned int m_MaxBufferSize;
+
+ // List of available packet buffers
+ std::vector<std::unique_ptr<IPacketBuffer>> m_AvailableList;
+
+ // List of readable packet buffers
+ std::vector<std::unique_ptr<IPacketBuffer>> m_ReadableList;
+
+ // Mutex for available packet buffer list
+ std::mutex m_AvailableMutex;
+
+ // Mutex for readable packet buffer list
+ std::mutex m_ReadableMutex;
+
+ // Condition to notify when data is availabe to be read
+ std::condition_variable m_ReadDataAvailable;
+};
+
+} // namespace profiling
+
+} // namespace armnn
diff --git a/src/profiling/PacketBuffer.cpp b/src/profiling/PacketBuffer.cpp
new file mode 100644
index 0000000000..88133d7674
--- /dev/null
+++ b/src/profiling/PacketBuffer.cpp
@@ -0,0 +1,60 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "PacketBuffer.hpp"
+
+#include <armnn/Exceptions.hpp>
+
+namespace armnn
+{
+
+namespace profiling
+{
+
+PacketBuffer::PacketBuffer(unsigned int maxSize)
+ : m_MaxSize(maxSize)
+ , m_Size(0)
+{
+ m_Data = std::make_unique<unsigned char[]>(m_MaxSize);
+}
+
+const unsigned char* const PacketBuffer::GetReadableData() const
+{
+ return m_Data.get();
+}
+
+unsigned int PacketBuffer::GetSize() const
+{
+ return m_Size;
+}
+
+void PacketBuffer::MarkRead()
+{
+ m_Size = 0;
+}
+
+void PacketBuffer::Commit(unsigned int size)
+{
+ if (size > m_MaxSize)
+ {
+ throw armnn::RuntimeException("Cannot commit [" + std::to_string(size) +
+ "] bytes which is more than the maximum size of the buffer [" + std::to_string(m_MaxSize) + "]");
+ }
+ m_Size = size;
+}
+
+void PacketBuffer::Release()
+{
+ m_Size = 0;
+}
+
+unsigned char* PacketBuffer::GetWritableData()
+{
+ return m_Data.get();
+}
+
+} // namespace profiling
+
+} // namespace armnn
diff --git a/src/profiling/PacketBuffer.hpp b/src/profiling/PacketBuffer.hpp
new file mode 100644
index 0000000000..a3d95d4108
--- /dev/null
+++ b/src/profiling/PacketBuffer.hpp
@@ -0,0 +1,45 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "IPacketBuffer.hpp"
+
+#include <memory>
+
+namespace armnn
+{
+
+namespace profiling
+{
+
+class PacketBuffer : public IPacketBuffer
+{
+public:
+ PacketBuffer(unsigned int maxSize);
+
+ ~PacketBuffer() {}
+
+ const unsigned char* const GetReadableData() const override;
+
+ unsigned int GetSize() const override;
+
+ void MarkRead() override;
+
+ void Commit(unsigned int size) override;
+
+ void Release() override;
+
+ unsigned char* GetWritableData() override;
+
+private:
+ unsigned int m_MaxSize;
+ unsigned int m_Size;
+ std::unique_ptr<unsigned char[]> m_Data;
+};
+
+} // namespace profiling
+
+} // namespace armnn \ No newline at end of file
diff --git a/src/profiling/test/BufferTests.cpp b/src/profiling/test/BufferTests.cpp
new file mode 100644
index 0000000000..b678350bb3
--- /dev/null
+++ b/src/profiling/test/BufferTests.cpp
@@ -0,0 +1,279 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "BufferManager.hpp"
+#include "PacketBuffer.hpp"
+#include "ProfilingUtils.hpp"
+
+#include <armnn/Exceptions.hpp>
+
+#include <boost/test/unit_test.hpp>
+
+using namespace armnn::profiling;
+
+BOOST_AUTO_TEST_SUITE(BufferTests)
+
+BOOST_AUTO_TEST_CASE(PacketBufferTest0)
+{
+ std::unique_ptr<IPacketBuffer> packetBuffer = std::make_unique<PacketBuffer>(512);
+
+ BOOST_TEST(packetBuffer->GetSize() == 0);
+
+ // Write data to the buffer
+ WriteUint32(packetBuffer, 0, 10);
+ WriteUint32(packetBuffer, 4, 20);
+ WriteUint32(packetBuffer, 8, 30);
+ WriteUint32(packetBuffer, 12, 40);
+
+ // Commit
+ packetBuffer->Commit(16);
+
+ // Size of buffer is equal to committed data
+ BOOST_TEST(packetBuffer->GetSize() == 16);
+
+ // Read data from the buffer
+ auto readBuffer = packetBuffer->GetReadableData();
+ uint32_t readData0 = ReadUint32(readBuffer, 0);
+ uint32_t readData1 = ReadUint32(readBuffer, 4);
+ uint32_t readData2 = ReadUint32(readBuffer, 8);
+ uint32_t readData3 = ReadUint32(readBuffer, 12);
+
+ // Check that data is correct
+ BOOST_TEST(readData0 == 10);
+ BOOST_TEST(readData1 == 20);
+ BOOST_TEST(readData2 == 30);
+ BOOST_TEST(readData3 == 40);
+
+ // Mark read
+ packetBuffer->MarkRead();
+
+ // Size of buffer become 0 after marked read
+ BOOST_TEST(packetBuffer->GetSize() == 0);
+}
+
+BOOST_AUTO_TEST_CASE(PacketBufferTest1)
+{
+ std::unique_ptr<IPacketBuffer> packetBuffer = std::make_unique<PacketBuffer>(512);
+
+ BOOST_TEST(packetBuffer->GetSize() == 0);
+
+ // Write data to the buffer using GetWritableData
+ auto writeBuffer = packetBuffer->GetWritableData();
+ WriteUint32(writeBuffer, 0, 10);
+ WriteUint32(writeBuffer, 4, 20);
+ WriteUint32(writeBuffer, 8, 30);
+ WriteUint32(writeBuffer, 12, 40);
+
+ packetBuffer->Commit(16);
+
+ BOOST_TEST(packetBuffer->GetSize() == 16);
+
+ // Read data from the buffer
+ auto readBuffer = packetBuffer->GetReadableData();
+ uint32_t readData0 = ReadUint32(readBuffer, 0);
+ uint32_t readData1 = ReadUint32(readBuffer, 4);
+ uint32_t readData2 = ReadUint32(readBuffer, 8);
+ uint32_t readData3 = ReadUint32(readBuffer, 12);
+
+ BOOST_TEST(readData0 == 10);
+ BOOST_TEST(readData1 == 20);
+ BOOST_TEST(readData2 == 30);
+ BOOST_TEST(readData3 == 40);
+
+ packetBuffer->MarkRead();
+
+ BOOST_TEST(packetBuffer->GetSize() == 0);
+}
+
+BOOST_AUTO_TEST_CASE(PacketBufferReleaseTest) {
+ std::unique_ptr<IPacketBuffer> packetBuffer = std::make_unique<PacketBuffer>(512);
+
+ BOOST_TEST(packetBuffer->GetSize() == 0);
+
+ auto writeBuffer = packetBuffer->GetWritableData();
+
+ WriteUint32(writeBuffer, 0, 10);
+ WriteUint32(writeBuffer, 4, 20);
+ WriteUint32(writeBuffer, 8, 30);
+ WriteUint32(writeBuffer, 12, 40);
+
+ packetBuffer->Release();
+
+ // Size of buffer become 0 after release
+ BOOST_TEST(packetBuffer->GetSize() == 0);
+}
+
+BOOST_AUTO_TEST_CASE(PacketBufferCommitErrorTest)
+{
+ std::unique_ptr<IPacketBuffer> packetBuffer = std::make_unique<PacketBuffer>(8);
+
+ // Cannot commit data bigger than the max size of the buffer
+ BOOST_CHECK_THROW(packetBuffer->Commit(16);, armnn::RuntimeException);
+}
+
+BOOST_AUTO_TEST_CASE(BufferReserveTest)
+{
+ BufferManager bufferManager(1, 512);
+ unsigned int reservedSize = 0;
+ auto packetBuffer = bufferManager.Reserve(512, reservedSize);
+
+ // Successfully reserved the buffer with requested size
+ BOOST_TEST(reservedSize == 512);
+ BOOST_TEST(packetBuffer.get());
+}
+
+BOOST_AUTO_TEST_CASE(BufferReserveExceedingSpaceTest)
+{
+ BufferManager bufferManager(1, 512);
+ unsigned int reservedSize = 0;
+
+ // Cannot reserve buffer bigger than maximum buffer size
+ BOOST_CHECK_THROW(bufferManager.Reserve(1024, reservedSize), armnn::RuntimeException);
+}
+
+BOOST_AUTO_TEST_CASE(BufferExhaustionTest)
+{
+ BufferManager bufferManager(1, 512);
+ unsigned int reservedSize = 0;
+ auto packetBuffer = bufferManager.Reserve(512, reservedSize);
+
+ // Successfully reserved the buffer with requested size
+ BOOST_TEST(reservedSize == 512);
+ BOOST_TEST(packetBuffer.get());
+
+ // Cannot reserve buffer when buffer is not available
+ BOOST_CHECK_THROW(bufferManager.Reserve(512, reservedSize), BufferExhaustion);
+}
+
+BOOST_AUTO_TEST_CASE(BufferReserveMultipleTest)
+{
+ BufferManager bufferManager(3, 512);
+ unsigned int reservedSize0 = 0;
+ auto packetBuffer0 = bufferManager.Reserve(512, reservedSize0);
+
+ // Successfully reserved the buffer with requested size
+ BOOST_TEST(reservedSize0 == 512);
+ BOOST_TEST(packetBuffer0.get());
+
+ unsigned int reservedSize1 = 0;
+ auto packetBuffer1 = bufferManager.Reserve(128, reservedSize1);
+
+ // Successfully reserved the buffer with requested size
+ BOOST_TEST(reservedSize1 == 128);
+ BOOST_TEST(packetBuffer1.get());
+
+ unsigned int reservedSize2 = 0;
+ auto packetBuffer2 = bufferManager.Reserve(512, reservedSize2);
+
+ // Successfully reserved the buffer with requested size
+ BOOST_TEST(reservedSize2 == 512);
+ BOOST_TEST(packetBuffer2.get());
+
+ // Cannot reserve when buffer is not available
+ unsigned int reservedSize3 = 0;
+ BOOST_CHECK_THROW(bufferManager.Reserve(512, reservedSize3), BufferExhaustion);
+}
+
+BOOST_AUTO_TEST_CASE(BufferReleaseTest)
+{
+ BufferManager bufferManager(2, 512);
+ unsigned int reservedSize0 = 0;
+ auto packetBuffer0 = bufferManager.Reserve(512, reservedSize0);
+
+ // Successfully reserved the buffer with requested size
+ BOOST_TEST(reservedSize0 == 512);
+ BOOST_TEST(packetBuffer0.get());
+
+ unsigned int reservedSize1 = 0;
+ auto packetBuffer1 = bufferManager.Reserve(128, reservedSize1);
+
+ // Successfully reserved the buffer with requested size
+ BOOST_TEST(reservedSize1 == 128);
+ BOOST_TEST(packetBuffer1.get());
+
+ // Cannot reserve when buffer is not available
+ unsigned int reservedSize2 = 0;
+ BOOST_CHECK_THROW(bufferManager.Reserve(512, reservedSize2), BufferExhaustion);
+
+ bufferManager.Release(packetBuffer0);
+
+ // Buffer should become available after release
+ auto packetBuffer2 = bufferManager.Reserve(128, reservedSize2);
+
+ BOOST_TEST(reservedSize2 == 128);
+ BOOST_TEST(packetBuffer2.get());
+}
+
+BOOST_AUTO_TEST_CASE(BufferCommitTest)
+{
+ BufferManager bufferManager(2, 512);
+ unsigned int reservedSize0 = 0;
+ auto packetBuffer0 = bufferManager.Reserve(512, reservedSize0);
+
+ BOOST_TEST(reservedSize0 == 512);
+ BOOST_TEST(packetBuffer0.get());
+
+ unsigned int reservedSize1 = 0;
+ auto packetBuffer1 = bufferManager.Reserve(128, reservedSize1);
+
+ BOOST_TEST(reservedSize1 == 128);
+ BOOST_TEST(packetBuffer1.get());
+
+ unsigned int reservedSize2 = 0;
+ BOOST_CHECK_THROW(bufferManager.Reserve(512, reservedSize2), BufferExhaustion);
+
+ bufferManager.Commit(packetBuffer0, 256);
+
+ // Buffer should become readable after commit
+ auto packetBuffer2 = bufferManager.GetReadableBuffer();
+ BOOST_TEST(packetBuffer2.get());
+ BOOST_TEST(packetBuffer2->GetSize() == 256);
+
+ // Buffer not set back to available list after commit
+ BOOST_CHECK_THROW(bufferManager.Reserve(512, reservedSize2), BufferExhaustion);
+}
+
+BOOST_AUTO_TEST_CASE(BufferMarkReadTest)
+{
+ BufferManager bufferManager(2, 512);
+ unsigned int reservedSize0 = 0;
+ auto packetBuffer0 = bufferManager.Reserve(512, reservedSize0);
+
+ BOOST_TEST(reservedSize0 == 512);
+ BOOST_TEST(packetBuffer0.get());
+
+ unsigned int reservedSize1 = 0;
+ auto packetBuffer1 = bufferManager.Reserve(128, reservedSize1);
+
+ BOOST_TEST(reservedSize1 == 128);
+ BOOST_TEST(packetBuffer1.get());
+
+ // Cannot reserve when buffer is not available
+ unsigned int reservedSize2 = 0;
+ BOOST_CHECK_THROW(bufferManager.Reserve(512, reservedSize2), BufferExhaustion);
+
+ bufferManager.Commit(packetBuffer0, 256);
+
+ // Buffer should become readable after commit
+ auto packetBuffer2 = bufferManager.GetReadableBuffer();
+ BOOST_TEST(packetBuffer2.get());
+ BOOST_TEST(packetBuffer2->GetSize() == 256);
+
+ // Buffer not set back to available list after commit
+ BOOST_CHECK_THROW(bufferManager.Reserve(512, reservedSize2), BufferExhaustion);
+
+ bufferManager.MarkRead(packetBuffer2);
+
+ //Buffer should set back to available list after marked read and can be reserved
+ auto readBuffer = bufferManager.GetReadableBuffer();
+ BOOST_TEST(!readBuffer);
+ unsigned int reservedSize3 = 0;
+ auto packetBuffer3 = bufferManager.Reserve(56, reservedSize3);
+
+ BOOST_TEST(reservedSize3 == 56);
+ BOOST_TEST(packetBuffer3.get());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/profiling/test/SendCounterPacketTests.hpp b/src/profiling/test/SendCounterPacketTests.hpp
index c3d47157d0..243731cb2c 100644
--- a/src/profiling/test/SendCounterPacketTests.hpp
+++ b/src/profiling/test/SendCounterPacketTests.hpp
@@ -147,10 +147,10 @@ public:
{
std::unique_lock<std::mutex> availableListLock(m_AvailableMutex, std::defer_lock);
if (requestedSize > m_MaxBufferSize)
- {
+ {
throw armnn::Exception("Maximum buffer size that can be requested is [" +
std::to_string(m_MaxBufferSize) + "] bytes");
- }
+ }
availableListLock.lock();
if (m_AvailableList.empty())
{