blob: 11ad6511fee7c4fff8ee19b7dfd7fb2f7e60776d [file] [log] [blame]
//
// Copyright © 2019 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//
#include "PeriodicCounterCapture.hpp"
#include <armnn/Logging.hpp>
#include <iostream>
namespace arm
{
namespace pipe
{
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<Timestamp>& timestampValues)
{
// Report counter values
for (const auto& timestampInfo : timestampValues)
{
std::vector<CounterValue> 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(IReadCounterValues& readCounterValues)
{
do
{
// Check if the current capture data indicates that there's data capture
auto currentCaptureData = ReadCaptureData();
const std::vector<uint16_t>& 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<CounterValue> 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.GetDeltaCounterValue(requestedId);
}
catch (const armnn::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_BackendProfilingContexts.at(backendId)->ReportCounterValues());
});
// Wait the indicated capture period (microseconds)
std::this_thread::sleep_for(std::chrono::microseconds(capturePeriod));
}
while (m_KeepRunning.load());
}
} // namespace pipe
} // namespace arm