From fcb8ef6b36873d06ddae7553aad28e726aa5be33 Mon Sep 17 00:00:00 2001 From: Francis Murtagh Date: Fri, 20 Sep 2019 15:40:09 +0100 Subject: 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 Signed-off-by: Francis Murtagh --- src/profiling/IReadCounterValue.hpp | 23 ++++++ src/profiling/PeriodicCounterCapture.cpp | 94 ++++++++++++++++++++++++ src/profiling/PeriodicCounterCapture.hpp | 48 ++++++++++++ src/profiling/test/ProfilingTests.cpp | 101 ++++++++++++++++++++++++++ src/profiling/test/SendCounterPacketTests.hpp | 4 +- 5 files changed, 268 insertions(+), 2 deletions(-) create mode 100644 src/profiling/IReadCounterValue.hpp create mode 100644 src/profiling/PeriodicCounterCapture.cpp create mode 100644 src/profiling/PeriodicCounterCapture.hpp (limited to 'src/profiling') 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 counterIds = currentCaptureData.GetCounterIds(); + if (currentCaptureData.GetCapturePeriod() == 0 || counterIds.empty()) + { + threadRunning = false; + m_IsRunning.store(false, std::memory_order_relaxed); + } + else + { + std::vector> 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(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 +#include +#include +#include + +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 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 #include #include +#include #include #include #include #include #include #include +#include #include @@ -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(index, value)); + } + else + { + m_Data.at(index) = value; + } + } + + private: + std::map m_Data; + }; + + Holder data; + std::vector captureIds1 = { 0, 1 }; + std::vector captureIds2; + + MockBuffer mockBuffer(512); + SendCounterPacket sendCounterPacket(mockBuffer); + + std::vector 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(size)) {} + : m_BufferSize(size), + m_Buffer(std::make_unique(size)) {} unsigned char* Reserve(unsigned int requestedSize, unsigned int& reservedSize) override { -- cgit v1.2.1