aboutsummaryrefslogtreecommitdiff
path: root/src/profiling/PeriodicCounterCapture.cpp
blob: d60cbd7d1559d346faf776570b9b0c08e3d7e735 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//
// Copyright © 2019 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include "PeriodicCounterCapture.hpp"

#include <armnn/Logging.hpp>

#include <iostream>

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::Capture(const 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();

        if (currentCaptureData.GetCapturePeriod() == 0 || counterIds.empty())
        {
            // No data capture, wait the indicated capture period (milliseconds)
            std::this_thread::sleep_for(std::chrono::milliseconds(5));
            continue;
        }

        std::vector<std::pair<uint16_t, uint32_t>> values;
        auto numCounters = counterIds.size();
        values.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;
            }
            values.emplace_back(std::make_pair(requestedId, counterValue));
        }

        // Take a timestamp
        uint64_t timestamp = GetTimestamp();

        // Write a Periodic Counter Capture packet to the Counter Stream Buffer
        m_SendCounterPacket.SendPeriodicCounterCapturePacket(timestamp, values);

        // Wait the indicated capture period (microseconds)
        std::this_thread::sleep_for(std::chrono::microseconds(currentCaptureData.GetCapturePeriod()));

    }
    while (m_KeepRunning.load());
}

} // namespace profiling

} // namespace armnn