aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancis Murtagh <francis.murtagh@arm.com>2019-09-20 15:40:09 +0100
committerFrancis Murtagh <francis.murtagh@arm.com>2019-09-20 15:30:54 +0000
commitfcb8ef6b36873d06ddae7553aad28e726aa5be33 (patch)
tree4c1cf74a38ebfcf8c134bdb1b25568c04ca90e09
parentda9d2d34ae57e18f631d4b42ad694a1d48270fe7 (diff)
downloadarmnn-fcb8ef6b36873d06ddae7553aad28e726aa5be33.tar.gz
IVGCVSW-3433 Create the Periodic Counter Capture Thread
* Add Periodic counter thread object * Add Unit test for thread * Move MockBuffer to header file to allow reuse Change-Id: Id2a8ea636723ab35e8a50efc200c8c76059bba02 Signed-off-by: Ferran Balaguer <ferran.balaguer@arm.com> Signed-off-by: Francis Murtagh <francis.murtagh@arm.com>
-rw-r--r--CMakeLists.txt3
-rw-r--r--src/profiling/IReadCounterValue.hpp23
-rw-r--r--src/profiling/PeriodicCounterCapture.cpp94
-rw-r--r--src/profiling/PeriodicCounterCapture.hpp48
-rw-r--r--src/profiling/test/ProfilingTests.cpp101
-rw-r--r--src/profiling/test/SendCounterPacketTests.hpp4
6 files changed, 271 insertions, 2 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6556c102bf..ef09fc02b2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -440,10 +440,13 @@ list(APPEND armnn_sources
src/profiling/ISendCounterPacket.hpp
src/profiling/IPeriodicCounterCapture.hpp
src/profiling/IProfilingConnection.hpp
+ src/profiling/IReadCounterValue.hpp
src/profiling/Packet.cpp
src/profiling/Packet.hpp
src/profiling/PacketVersionResolver.cpp
src/profiling/PacketVersionResolver.hpp
+ src/profiling/PeriodicCounterCapture.hpp
+ src/profiling/PeriodicCounterCapture.cpp
src/profiling/PeriodicCounterSelectionCommandHandler.cpp
src/profiling/PeriodicCounterSelectionCommandHandler.hpp
src/profiling/ProfilingConnectionFactory.cpp
diff --git a/src/profiling/IReadCounterValue.hpp b/src/profiling/IReadCounterValue.hpp
new file mode 100644
index 0000000000..3a8236a0f4
--- /dev/null
+++ b/src/profiling/IReadCounterValue.hpp
@@ -0,0 +1,23 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+namespace armnn
+{
+
+namespace profiling
+{
+
+class IReadCounterValue
+{
+public:
+ virtual void GetCounterValue(uint16_t index, uint32_t &value) const = 0;
+ virtual ~IReadCounterValue() {}
+};
+
+} // namespace profiling
+
+} // namespace armnn \ No newline at end of file
diff --git a/src/profiling/PeriodicCounterCapture.cpp b/src/profiling/PeriodicCounterCapture.cpp
new file mode 100644
index 0000000000..5fbaa5d035
--- /dev/null
+++ b/src/profiling/PeriodicCounterCapture.cpp
@@ -0,0 +1,94 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "PeriodicCounterCapture.hpp"
+
+namespace armnn
+{
+
+namespace profiling
+{
+
+PeriodicCounterCapture::PeriodicCounterCapture(const Holder& data, ISendCounterPacket& packet,
+ const IReadCounterValue& readCounterValue)
+ : m_CaptureDataHolder(data)
+ , m_IsRunning(false)
+ , m_ReadCounterValue(readCounterValue)
+ , m_SendCounterPacket(packet)
+{}
+
+CaptureData PeriodicCounterCapture::ReadCaptureData()
+{
+ return m_CaptureDataHolder.GetCaptureData();
+}
+
+void PeriodicCounterCapture::Functionality(const IReadCounterValue& readCounterValue)
+{
+ bool threadRunning = true;
+
+ while(threadRunning)
+ {
+ auto currentCaptureData = ReadCaptureData();
+ std::vector<uint16_t> counterIds = currentCaptureData.GetCounterIds();
+ if (currentCaptureData.GetCapturePeriod() == 0 || counterIds.empty())
+ {
+ threadRunning = false;
+ m_IsRunning.store(false, std::memory_order_relaxed);
+ }
+ else
+ {
+ std::vector<std::pair<uint16_t, uint32_t>> values;
+ auto numCounters = counterIds.size();
+ values.reserve(numCounters);
+
+ // Create vector of pairs of CounterIndexes and Values
+ uint32_t counterValue;
+ for (uint16_t index = 0; index < numCounters; ++index)
+ {
+ auto requestedId = counterIds[index];
+ readCounterValue.GetCounterValue(requestedId, counterValue);
+ values.emplace_back(std::make_pair(requestedId, counterValue));
+ }
+
+ #if USE_CLOCK_MONOTONIC_RAW
+ using clock = MonotonicClockRaw;
+ #else
+ using clock = std::chrono::steady_clock;
+ #endif
+ // Take a timestamp
+ auto timestamp = clock::now();
+
+ m_SendCounterPacket.SendPeriodicCounterCapturePacket(
+ static_cast<uint64_t>(timestamp.time_since_epoch().count()), values);
+ std::this_thread::sleep_for(std::chrono::milliseconds(currentCaptureData.GetCapturePeriod()));
+ }
+ }
+}
+
+void PeriodicCounterCapture::Start()
+{
+ bool tstVal = false;
+
+ if (m_IsRunning.compare_exchange_strong(tstVal, true, std::memory_order_relaxed))
+ {
+ // Check that the thread execution is finished.
+ if (m_PeriodCaptureThread.joinable())
+ {
+ m_PeriodCaptureThread.join();
+ }
+ // Starts the new thread.
+ m_PeriodCaptureThread = std::thread(&PeriodicCounterCapture::Functionality, this,
+ std::ref(m_ReadCounterValue));
+ }
+}
+
+void PeriodicCounterCapture::Join()
+{
+ m_PeriodCaptureThread.join();
+}
+
+} // namespace profiling
+
+} // namespace armnn
diff --git a/src/profiling/PeriodicCounterCapture.hpp b/src/profiling/PeriodicCounterCapture.hpp
new file mode 100644
index 0000000000..8a7ff37bf9
--- /dev/null
+++ b/src/profiling/PeriodicCounterCapture.hpp
@@ -0,0 +1,48 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "Holder.hpp"
+#include "IPeriodicCounterCapture.hpp"
+#include "Packet.hpp"
+#include "IReadCounterValue.hpp"
+#include "SendCounterPacket.hpp"
+
+#include "WallClockTimer.hpp"
+
+#include <atomic>
+#include <chrono>
+#include <mutex>
+#include <thread>
+
+namespace armnn
+{
+
+namespace profiling
+{
+
+class PeriodicCounterCapture final : public IPeriodicCounterCapture
+{
+public:
+ PeriodicCounterCapture(const Holder& data, ISendCounterPacket& packet, const IReadCounterValue& readCounterValue);
+
+ void Start() override;
+ void Join();
+
+private:
+ CaptureData ReadCaptureData();
+ void Functionality(const IReadCounterValue& readCounterValue);
+
+ const Holder& m_CaptureDataHolder;
+ std::atomic<bool> m_IsRunning;
+ std::thread m_PeriodCaptureThread;
+ const IReadCounterValue& m_ReadCounterValue;
+ ISendCounterPacket& m_SendCounterPacket;
+};
+
+} // namespace profiling
+
+} // namespace armnn
diff --git a/src/profiling/test/ProfilingTests.cpp b/src/profiling/test/ProfilingTests.cpp
index 1cf0e1e4b9..aec66d31ca 100644
--- a/src/profiling/test/ProfilingTests.cpp
+++ b/src/profiling/test/ProfilingTests.cpp
@@ -14,12 +14,14 @@
#include <Holder.hpp>
#include <Packet.hpp>
#include <PacketVersionResolver.hpp>
+#include <PeriodicCounterCapture.hpp>
#include <PeriodicCounterSelectionCommandHandler.hpp>
#include <ProfilingStateMachine.hpp>
#include <ProfilingService.hpp>
#include <ProfilingUtils.hpp>
#include <Runtime.hpp>
#include <SocketProfilingConnection.hpp>
+#include <IReadCounterValue.hpp>
#include <armnn/Conversion.hpp>
@@ -1878,4 +1880,103 @@ BOOST_AUTO_TEST_CASE(StringToSwTraceNameStringTest)
BOOST_CHECK(buffer.empty());
}
+BOOST_AUTO_TEST_CASE(CheckPeriodicCounterCaptureThread)
+{
+ class CaptureReader : public IReadCounterValue
+ {
+ public:
+ CaptureReader() {}
+
+ void GetCounterValue(uint16_t index, uint32_t &value) const override
+ {
+ if (m_Data.count(index))
+ {
+ value = m_Data.at(index);
+ }
+ else
+ {
+ value = 0;
+ }
+ }
+
+ void SetCounterValue(uint16_t index, uint32_t value)
+ {
+ if (!m_Data.count(index))
+ {
+ m_Data.insert(std::pair<uint16_t, uint32_t>(index, value));
+ }
+ else
+ {
+ m_Data.at(index) = value;
+ }
+ }
+
+ private:
+ std::map<uint16_t, uint32_t> m_Data;
+ };
+
+ Holder data;
+ std::vector<uint16_t> captureIds1 = { 0, 1 };
+ std::vector<uint16_t> captureIds2;
+
+ MockBuffer mockBuffer(512);
+ SendCounterPacket sendCounterPacket(mockBuffer);
+
+ std::vector<uint16_t> counterIds;
+ CaptureReader captureReader;
+
+ unsigned int valueA = 10;
+ unsigned int valueB = 15;
+ unsigned int numSteps = 5;
+
+ PeriodicCounterCapture periodicCounterCapture(std::ref(data), std::ref(sendCounterPacket), captureReader);
+
+ for(unsigned int i = 0; i < numSteps; ++i)
+ {
+ data.SetCaptureData(1, captureIds1);
+ captureReader.SetCounterValue(0, valueA * (i + 1));
+ captureReader.SetCounterValue(1, valueB * (i + 1));
+
+ periodicCounterCapture.Start();
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
+
+ periodicCounterCapture.Start();
+
+ data.SetCaptureData(0, captureIds2);
+
+ periodicCounterCapture.Start();
+ }
+
+ periodicCounterCapture.Join();
+
+ unsigned int size = 0;
+
+ const unsigned char* buffer = mockBuffer.GetReadBuffer(size);
+
+ uint32_t headerWord0 = ReadUint32(buffer, 0);
+ uint32_t headerWord1 = ReadUint32(buffer, 4);
+
+ BOOST_TEST(((headerWord0 >> 26) & 0x3F) == 1); // packet family
+ BOOST_TEST(((headerWord0 >> 19) & 0x3F) == 0); // packet class
+ BOOST_TEST(((headerWord0 >> 16) & 0x3) == 0); // packet type
+ BOOST_TEST(headerWord1 == 20); // data length
+
+ uint32_t offset = 16;
+ uint16_t readIndex = ReadUint16(buffer, offset);
+ BOOST_TEST(0 == readIndex);
+
+ offset += 2;
+ uint32_t readValue = ReadUint32(buffer, offset);
+ BOOST_TEST((valueA * numSteps) == readValue);
+
+ offset += 4;
+ readIndex = ReadUint16(buffer, offset);
+ BOOST_TEST(1 == readIndex);
+
+ offset += 2;
+ readValue = ReadUint32(buffer, offset);
+ BOOST_TEST((valueB * numSteps) == readValue);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/profiling/test/SendCounterPacketTests.hpp b/src/profiling/test/SendCounterPacketTests.hpp
index 6c7bb50362..5d5dfd14c7 100644
--- a/src/profiling/test/SendCounterPacketTests.hpp
+++ b/src/profiling/test/SendCounterPacketTests.hpp
@@ -21,8 +21,8 @@ class MockBuffer : public IBufferWrapper
{
public:
MockBuffer(unsigned int size)
- : m_BufferSize(size),
- m_Buffer(std::make_unique<unsigned char[]>(size)) {}
+ : m_BufferSize(size),
+ m_Buffer(std::make_unique<unsigned char[]>(size)) {}
unsigned char* Reserve(unsigned int requestedSize, unsigned int& reservedSize) override
{