diff options
author | Keith Davis <keith.davis@arm.com> | 2019-10-24 17:30:41 +0100 |
---|---|---|
committer | Colm Donelan <colm.donelan@arm.com> | 2019-11-06 08:30:31 +0000 |
commit | 3201eea0565ce2bb0418d1936fec71bdeb14c084 (patch) | |
tree | f73017f6338d707165dbcfd717ddc9793b1858e0 /src/profiling/FileOnlyProfilingConnection.cpp | |
parent | fe2e2cbbbe5294072b2d58755b8a095f32a97e75 (diff) | |
download | armnn-3201eea0565ce2bb0418d1936fec71bdeb14c084.tar.gz |
IVGCVSW-3444 File Only Profiling Connection
* Add FileOnlyProfilingConnection Decorator
* Fix bug where Conn Ack not automatically sent back
* Modify GatordMock to use the Counter Directory class.
* Promote DirectoryCaptureCommandHandler from GatordMock into ArmNN.
* Remove MockUtils as it's contents were moved or deleted.
* Rewrite GatordMockTests to use Counter Directory class.
* Flush streams in ProfilingConnectionDumpToFileDecorator::Close.
Signed-off-by: Keith Davis <keith.davis@arm.com>
Signed-off-by: Colm Donelan <Colm.Donelan@arm.com>
Change-Id: I77b2aedece24150dd31691b577f3b5d81b2e226f
Diffstat (limited to 'src/profiling/FileOnlyProfilingConnection.cpp')
-rw-r--r-- | src/profiling/FileOnlyProfilingConnection.cpp | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/src/profiling/FileOnlyProfilingConnection.cpp b/src/profiling/FileOnlyProfilingConnection.cpp new file mode 100644 index 0000000000..b32ae49911 --- /dev/null +++ b/src/profiling/FileOnlyProfilingConnection.cpp @@ -0,0 +1,216 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "FileOnlyProfilingConnection.hpp" +#include "PacketVersionResolver.hpp" + +#include <armnn/Exceptions.hpp> + +#include <boost/numeric/conversion/cast.hpp> +#include <iostream> +#include <thread> + +namespace armnn +{ + +namespace profiling +{ + +FileOnlyProfilingConnection::~FileOnlyProfilingConnection() +{ + Close(); +} + +bool FileOnlyProfilingConnection::IsOpen() const +{ + // This type of connection is always open. + return true; +} + +void FileOnlyProfilingConnection::Close() +{ + // Dump any unread packets out of the queue. + for (unsigned int i = 0; i < m_PacketQueue.size(); i++) + { + m_PacketQueue.pop(); + } +} + +bool FileOnlyProfilingConnection::WaitForStreamMeta(const unsigned char* buffer, uint32_t length) +{ + // The first word, stream_metadata_identifer, should always be 0. + if (ToUint32(buffer, TargetEndianness::BeWire) != 0) + { + Fail("Protocol error. The stream_metadata_identifer was not 0."); + } + + // Before we interpret the length we need to read the pipe_magic word to determine endianness. + if (ToUint32(buffer + 8, TargetEndianness::BeWire) == PIPE_MAGIC) + { + m_Endianness = TargetEndianness::BeWire; + } + else if (ToUint32(buffer + 8, TargetEndianness::LeWire) == PIPE_MAGIC) + { + m_Endianness = TargetEndianness::LeWire; + } + else + { + Fail("Protocol read error. Unable to read PIPE_MAGIC value."); + } + return true; +} + +void FileOnlyProfilingConnection::SendConnectionAck() +{ + if (!m_QuietOp) + { + std::cout << "Sending connection acknowledgement." << std::endl; + } + std::unique_ptr<unsigned char[]> uniqueNullPtr = nullptr; + m_PacketQueue.push(Packet(0x10000, 0, uniqueNullPtr)); +} + +bool FileOnlyProfilingConnection::SendCounterSelectionPacket() +{ + uint32_t uint16_t_size = sizeof(uint16_t); + uint32_t uint32_t_size = sizeof(uint32_t); + + uint32_t offset = 0; + uint32_t bodySize = uint32_t_size + boost::numeric_cast<uint32_t>(m_IdList.size()) * uint16_t_size; + + auto uniqueData = std::make_unique<unsigned char[]>(bodySize); + unsigned char* data = reinterpret_cast<unsigned char*>(uniqueData.get()); + + // Copy capturePeriod + WriteUint32(data, offset, m_Options.m_CapturePeriod); + + // Copy m_IdList + offset += uint32_t_size; + for (const uint16_t& id : m_IdList) + { + WriteUint16(data, offset, id); + offset += uint16_t_size; + } + + m_PacketQueue.push(Packet(0x40000, bodySize, uniqueData)); + + return true; +} + +bool FileOnlyProfilingConnection::WritePacket(const unsigned char* buffer, uint32_t length) +{ + BOOST_ASSERT(buffer); + + // Read Header and determine case + uint32_t outgoingHeaderAsWords[2]; + PackageActivity packageActivity = GetPackageActivity(buffer, outgoingHeaderAsWords); + + switch (packageActivity) + { + case PackageActivity::StreamMetaData: + { + if (!WaitForStreamMeta(buffer, length)) + { + return EXIT_FAILURE; + } + + SendConnectionAck(); + break; + } + case PackageActivity::CounterDirectory: + { + std::unique_ptr<unsigned char[]> uniqueCounterData = std::make_unique<unsigned char[]>(length - 8); + + std::memcpy(uniqueCounterData.get(), buffer + 8, length - 8); + + Packet directoryPacket(outgoingHeaderAsWords[0], length - 8, uniqueCounterData); + + armnn::profiling::PacketVersionResolver packetVersionResolver; + DirectoryCaptureCommandHandler directoryCaptureCommandHandler( + 0, 2, packetVersionResolver.ResolvePacketVersion(0, 2).GetEncodedValue()); + directoryCaptureCommandHandler.operator()(directoryPacket); + const ICounterDirectory& counterDirectory = directoryCaptureCommandHandler.GetCounterDirectory(); + for (auto& category : counterDirectory.GetCategories()) + { + // Remember we need to translate the Uid's from our CounterDirectory instance to the parent one. + std::vector<uint16_t> translatedCounters; + for (auto const& copyUid : category->m_Counters) + { + translatedCounters.emplace_back(directoryCaptureCommandHandler.TranslateUIDCopyToOriginal(copyUid)); + } + m_IdList.insert(std::end(m_IdList), std::begin(translatedCounters), std::end(translatedCounters)); + } + SendCounterSelectionPacket(); + break; + } + default: + { + break; + } + } + return true; +} + +Packet FileOnlyProfilingConnection::ReadPacket(uint32_t timeout) +{ + uint16_t loopCount = 10; + uint32_t timeoutFraction = timeout / loopCount; + while (m_PacketQueue.empty()) + { + std::this_thread::sleep_for(std::chrono::milliseconds(timeoutFraction)); + --loopCount; + if ((loopCount) == 0) + { + throw armnn::TimeoutException("Thread has timed out as per requested time limit"); + } + } + Packet returnedPacket = std::move(m_PacketQueue.front()); + m_PacketQueue.pop(); + return returnedPacket; +} + +PackageActivity FileOnlyProfilingConnection::GetPackageActivity(const unsigned char* buffer, uint32_t headerAsWords[2]) +{ + headerAsWords[0] = ToUint32(buffer, m_Endianness); + headerAsWords[1] = ToUint32(buffer + 4, m_Endianness); + if (headerAsWords[0] == 0x20000) // Packet family = 0 Packet Id = 2 + { + return PackageActivity::CounterDirectory; + } + else if (headerAsWords[0] == 0) // Packet family = 0 Packet Id = 0 + { + return PackageActivity::StreamMetaData; + } + else + { + return PackageActivity::Unknown; + } +} + +uint32_t FileOnlyProfilingConnection::ToUint32(const unsigned char* data, TargetEndianness endianness) +{ + // Extract the first 4 bytes starting at data and push them into a 32bit integer based on the + // specified endianness. + if (endianness == TargetEndianness::BeWire) + { + return static_cast<uint32_t>(data[0]) << 24 | static_cast<uint32_t>(data[1]) << 16 | + static_cast<uint32_t>(data[2]) << 8 | static_cast<uint32_t>(data[3]); + } + else + { + return static_cast<uint32_t>(data[3]) << 24 | static_cast<uint32_t>(data[2]) << 16 | + static_cast<uint32_t>(data[1]) << 8 | static_cast<uint32_t>(data[0]); + } +} + +void FileOnlyProfilingConnection::Fail(const std::string& errorMessage) +{ + Close(); + throw RuntimeException(errorMessage); +} + +} // namespace profiling + +} // namespace armnn |