// // Copyright © 2019 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // #include "PeriodicCounterCapture.hpp" #include #include namespace armnn { namespace profiling { void PeriodicCounterCapture::Start() { // Check if the capture thread is already running if (m_IsRunning) { // The capture thread is already running return; } // Mark the capture thread as running m_IsRunning = true; // Keep the capture procedure going until the capture thread is signalled to stop m_KeepRunning.store(true); // Start the new capture thread. m_PeriodCaptureThread = std::thread(&PeriodicCounterCapture::Capture, this, std::ref(m_ReadCounterValues)); } void PeriodicCounterCapture::Stop() { // Signal the capture thread to stop m_KeepRunning.store(false); // Check that the capture thread is running if (m_PeriodCaptureThread.joinable()) { // Wait for the capture thread to complete operations m_PeriodCaptureThread.join(); } // Mark the capture thread as not running m_IsRunning = false; } CaptureData PeriodicCounterCapture::ReadCaptureData() { return m_CaptureDataHolder.GetCaptureData(); } void PeriodicCounterCapture::DispatchPeriodicCounterCapturePacket( const armnn::BackendId& backendId, const std::vector& timestampValues) { // Report counter values for (const auto timestampInfo : timestampValues) { std::vector backendCounterValues = timestampInfo.counterValues; for_each(backendCounterValues.begin(), backendCounterValues.end(), [&](CounterValue& backendCounterValue) { // translate the counterId to globalCounterId backendCounterValue.counterId = m_CounterIdMap.GetGlobalId(backendCounterValue.counterId, backendId); }); // Send Periodic Counter Capture Packet for the Timestamp m_SendCounterPacket.SendPeriodicCounterCapturePacket(timestampInfo.timestamp, backendCounterValues); } } void PeriodicCounterCapture::Capture(const IReadCounterValues& readCounterValues) { do { // Check if the current capture data indicates that there's data capture auto currentCaptureData = ReadCaptureData(); const std::vector& counterIds = currentCaptureData.GetCounterIds(); const uint32_t capturePeriod = currentCaptureData.GetCapturePeriod(); if (capturePeriod == 0) { // No data capture, wait the indicated capture period (milliseconds), if it is not zero std::this_thread::sleep_for(std::chrono::milliseconds(50u)); continue; } if(counterIds.size() != 0) { std::vector counterValues; auto numCounters = counterIds.size(); counterValues.reserve(numCounters); // Create a vector of pairs of CounterIndexes and Values for (uint16_t index = 0; index < numCounters; ++index) { auto requestedId = counterIds[index]; uint32_t counterValue = 0; try { counterValue = readCounterValues.GetCounterValue(requestedId); } catch (const Exception& e) { // Report the error and continue ARMNN_LOG(warning) << "An error has occurred when getting a counter value: " << e.what(); continue; } counterValues.emplace_back(CounterValue {requestedId, counterValue }); } // Send Periodic Counter Capture Packet for the Timestamp m_SendCounterPacket.SendPeriodicCounterCapturePacket(GetTimestamp(), counterValues); } // Report counter values for each active backend auto activeBackends = currentCaptureData.GetActiveBackends(); for_each(activeBackends.begin(), activeBackends.end(), [&](const armnn::BackendId& backendId) { DispatchPeriodicCounterCapturePacket( backendId, m_BackendProfilingContext.at(backendId)->ReportCounterValues()); }); // Wait the indicated capture period (microseconds) std::this_thread::sleep_for(std::chrono::microseconds(capturePeriod)); } while (m_KeepRunning.load()); } } // namespace profiling } // namespace armnn