IVGCVSW-4794 Change ArmNN counters to report delta values

Signed-off-by: Finn Williams <Finn.Williams@arm.com>
Change-Id: I7957ee41fd700ee502cc14aa313a60664d4caec9
diff --git a/src/backends/backendsCommon/test/BackendProfilingTests.cpp b/src/backends/backendsCommon/test/BackendProfilingTests.cpp
index 9f1898a..52b6e23 100644
--- a/src/backends/backendsCommon/test/BackendProfilingTests.cpp
+++ b/src/backends/backendsCommon/test/BackendProfilingTests.cpp
@@ -41,7 +41,11 @@
     {
         return 1;
     }
-    virtual uint32_t GetCounterValue(uint16_t counterUid) const override
+    virtual uint32_t GetAbsoluteCounterValue(uint16_t counterUid) const override
+    {
+        return counterUid;
+    }
+    virtual uint32_t GetDeltaCounterValue(uint16_t counterUid) override
     {
         return counterUid;
     }
diff --git a/src/profiling/ICounterValues.hpp b/src/profiling/ICounterValues.hpp
index cef0266..09c26b6 100644
--- a/src/profiling/ICounterValues.hpp
+++ b/src/profiling/ICounterValues.hpp
@@ -20,7 +20,8 @@
 
     virtual bool IsCounterRegistered(uint16_t counterUid) const = 0;
     virtual uint16_t GetCounterCount() const = 0;
-    virtual uint32_t GetCounterValue(uint16_t counterUid) const = 0;
+    virtual uint32_t GetAbsoluteCounterValue(uint16_t counterUid) const = 0;
+    virtual uint32_t GetDeltaCounterValue(uint16_t counterUid) = 0;
 };
 
 class IWriteCounterValues
diff --git a/src/profiling/PeriodicCounterCapture.cpp b/src/profiling/PeriodicCounterCapture.cpp
index 4ad1d11..8ff5e7e 100644
--- a/src/profiling/PeriodicCounterCapture.cpp
+++ b/src/profiling/PeriodicCounterCapture.cpp
@@ -73,7 +73,7 @@
     }
 }
 
-void PeriodicCounterCapture::Capture(const IReadCounterValues& readCounterValues)
+void PeriodicCounterCapture::Capture(IReadCounterValues& readCounterValues)
 {
     do
     {
@@ -103,7 +103,7 @@
                 uint32_t counterValue = 0;
                 try
                 {
-                    counterValue = readCounterValues.GetCounterValue(requestedId);
+                    counterValue = readCounterValues.GetDeltaCounterValue(requestedId);
                 }
                 catch (const Exception& e)
                 {
diff --git a/src/profiling/PeriodicCounterCapture.hpp b/src/profiling/PeriodicCounterCapture.hpp
index 796c494..5abad9e 100644
--- a/src/profiling/PeriodicCounterCapture.hpp
+++ b/src/profiling/PeriodicCounterCapture.hpp
@@ -28,7 +28,7 @@
 public:
     PeriodicCounterCapture(const Holder& data,
                            ISendCounterPacket& packet,
-                           const IReadCounterValues& readCounterValue,
+                           IReadCounterValues& readCounterValue,
                            const ICounterMappings& counterIdMap,
                            const std::unordered_map<armnn::BackendId,
                                    std::shared_ptr<armnn::profiling::IBackendProfilingContext>>&
@@ -49,7 +49,7 @@
 
 private:
     CaptureData ReadCaptureData();
-    void Capture(const IReadCounterValues& readCounterValues);
+    void Capture(IReadCounterValues& readCounterValues);
     void DispatchPeriodicCounterCapturePacket(
             const armnn::BackendId& backendId, const std::vector<Timestamp>& timestampValues);
 
@@ -57,7 +57,7 @@
     bool                      m_IsRunning;
     std::atomic<bool>         m_KeepRunning;
     std::thread               m_PeriodCaptureThread;
-    const IReadCounterValues& m_ReadCounterValues;
+    IReadCounterValues&       m_ReadCounterValues;
     ISendCounterPacket&       m_SendCounterPacket;
     const ICounterMappings&   m_CounterIdMap;
     const std::unordered_map<armnn::BackendId,
diff --git a/src/profiling/ProfilingService.cpp b/src/profiling/ProfilingService.cpp
index 294a294..f4957f9 100644
--- a/src/profiling/ProfilingService.cpp
+++ b/src/profiling/ProfilingService.cpp
@@ -235,7 +235,7 @@
     return counterUid < m_CounterIndex.size();
 }
 
-uint32_t ProfilingService::GetCounterValue(uint16_t counterUid) const
+uint32_t ProfilingService::GetAbsoluteCounterValue(uint16_t counterUid) const
 {
     CheckCounterUid(counterUid);
     std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
@@ -243,6 +243,16 @@
     return counterValuePtr->load(std::memory_order::memory_order_relaxed);
 }
 
+uint32_t ProfilingService::GetDeltaCounterValue(uint16_t counterUid)
+{
+    CheckCounterUid(counterUid);
+    std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
+    ARMNN_ASSERT(counterValuePtr);
+    const uint32_t counterValue = counterValuePtr->load(std::memory_order::memory_order_relaxed);
+    SubtractCounterValue(counterUid, counterValue);
+    return counterValue;
+}
+
 const ICounterMappings& ProfilingService::GetCounterMappings() const
 {
     return m_CounterIdMap;
@@ -327,7 +337,7 @@
                 m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
                                                    armnn::profiling::NETWORK_LOADS,
                                                    "ArmNN_Runtime",
-                                                   1,
+                                                   0,
                                                    0,
                                                    1.f,
                                                    "Network loads",
@@ -343,7 +353,7 @@
                 m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
                                                    armnn::profiling::NETWORK_UNLOADS,
                                                    "ArmNN_Runtime",
-                                                   1,
+                                                   0,
                                                    0,
                                                    1.f,
                                                    "Network unloads",
@@ -359,7 +369,7 @@
                 m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
                                                    armnn::profiling::REGISTERED_BACKENDS,
                                                    "ArmNN_Runtime",
-                                                   1,
+                                                   0,
                                                    0,
                                                    1.f,
                                                    "Backends registered",
@@ -375,7 +385,7 @@
                 m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
                                                    armnn::profiling::UNREGISTERED_BACKENDS,
                                                    "ArmNN_Runtime",
-                                                   1,
+                                                   0,
                                                    0,
                                                    1.f,
                                                    "Backends unregistered",
@@ -391,7 +401,7 @@
                 m_CounterDirectory.RegisterCounter(armnn::profiling::BACKEND_ID,
                                                    armnn::profiling::INFERENCES_RUN,
                                                    "ArmNN_Runtime",
-                                                   1,
+                                                   0,
                                                    0,
                                                    1.f,
                                                    "Inferences run",
diff --git a/src/profiling/ProfilingService.hpp b/src/profiling/ProfilingService.hpp
index ba5da7d..d7e4628 100644
--- a/src/profiling/ProfilingService.hpp
+++ b/src/profiling/ProfilingService.hpp
@@ -166,7 +166,8 @@
     ICounterRegistry& GetCounterRegistry();
     ProfilingState GetCurrentState() const;
     bool IsCounterRegistered(uint16_t counterUid) const override;
-    uint32_t GetCounterValue(uint16_t counterUid) const override;
+    uint32_t GetAbsoluteCounterValue(uint16_t counterUid) const override;
+    uint32_t GetDeltaCounterValue(uint16_t counterUid) override;
     uint16_t GetCounterCount() const override;
     // counter global/backend mapping functions
     const ICounterMappings& GetCounterMappings() const override;
diff --git a/src/profiling/test/FileOnlyProfilingDecoratorTests.cpp b/src/profiling/test/FileOnlyProfilingDecoratorTests.cpp
index 9644894..164a94a 100644
--- a/src/profiling/test/FileOnlyProfilingDecoratorTests.cpp
+++ b/src/profiling/test/FileOnlyProfilingDecoratorTests.cpp
@@ -141,7 +141,8 @@
     // Increment a counter.
     BOOST_CHECK(profilingService.IsCounterRegistered(0) == true);
     profilingService.IncrementCounterValue(0);
-    BOOST_CHECK(profilingService.GetCounterValue(0) > 0);
+    BOOST_CHECK(profilingService.GetAbsoluteCounterValue(0) > 0);
+    BOOST_CHECK(profilingService.GetDeltaCounterValue(0) > 0);
 
     // At this point the profiling service is active and we've activated all the counters. Waiting a collection
     // period should be enough to have some data in the file.
diff --git a/src/profiling/test/ProfilingTests.cpp b/src/profiling/test/ProfilingTests.cpp
index dd7d5b8..c541c82 100644
--- a/src/profiling/test/ProfilingTests.cpp
+++ b/src/profiling/test/ProfilingTests.cpp
@@ -687,43 +687,98 @@
     const Counters& counters                  = counterDirectory.GetCounters();
     BOOST_CHECK(!counters.empty());
 
-    // Get the UID of the first counter for testing;
-
-    ProfilingService* profilingServicePtr = &profilingService;
     std::vector<std::thread> writers;
 
-    for (int i = 0; i < 10; ++i)
+    BOOST_CHECK(!counters.empty());
+
+    // Test GetAbsoluteCounterValue
+    for (int i = 0; i < 4; ++i)
     {
-        // Increment and decrement the first counter
-        writers.push_back(std::thread(&ProfilingService::IncrementCounterValue,
-                          profilingServicePtr,
-                          armnn::profiling::REGISTERED_BACKENDS));
-
-        writers.push_back(std::thread(&ProfilingService::IncrementCounterValue,
-                          profilingServicePtr,
-                          armnn::profiling::UNREGISTERED_BACKENDS));
-
-        // Add 10 and subtract 5 from the first counter
-        writers.push_back(std::thread(&ProfilingService::AddCounterValue,
-                          profilingServicePtr,
-                          armnn::profiling::INFERENCES_RUN,
-                          10));
-        writers.push_back(std::thread(&ProfilingService::SubtractCounterValue,
-                          profilingServicePtr,
-                          armnn::profiling::INFERENCES_RUN,
-                          5));
+        // Increment and decrement the INFERENCES_RUN counter 250 times
+        writers.push_back(std::thread([&profilingService]()
+                                      {
+                                          for (int i = 0; i < 250; ++i)
+                                          {
+                                              profilingService.IncrementCounterValue(INFERENCES_RUN);
+                                          }
+                                      }));
+        // Add 10 to the INFERENCES_RUN counter 200 times
+        writers.push_back(std::thread([&profilingService]()
+                                      {
+                                          for (int i = 0; i < 200; ++i)
+                                          {
+                                              profilingService.AddCounterValue(INFERENCES_RUN, 10);
+                                          }
+                                      }));
+        // Subtract 5 from the INFERENCES_RUN counter 200 times
+        writers.push_back(std::thread([&profilingService]()
+                                      {
+                                          for (int i = 0; i < 200; ++i)
+                                          {
+                                              profilingService.SubtractCounterValue(INFERENCES_RUN, 5);
+                                          }
+                                      }));
     }
+
     std::for_each(writers.begin(), writers.end(), mem_fn(&std::thread::join));
 
-    uint32_t counterValue = 0;
-    BOOST_CHECK(counterValue ==
-               (profilingService.GetCounterValue(armnn::profiling::UNREGISTERED_BACKENDS)
-               - profilingService.GetCounterValue(armnn::profiling::REGISTERED_BACKENDS)));
-    BOOST_CHECK(profilingService.GetCounterValue(armnn::profiling::INFERENCES_RUN) == 50);
+    uint32_t absoluteCounterValue = 0;
 
-    BOOST_CHECK_NO_THROW(profilingService.SetCounterValue(armnn::profiling::UNREGISTERED_BACKENDS, 4));
-    BOOST_CHECK_NO_THROW(counterValue = profilingService.GetCounterValue(armnn::profiling::UNREGISTERED_BACKENDS));
-    BOOST_CHECK(counterValue == 4);
+    BOOST_CHECK_NO_THROW(absoluteCounterValue = profilingService.GetAbsoluteCounterValue(INFERENCES_RUN));
+    BOOST_CHECK(absoluteCounterValue = 5000);
+
+    // Test SetCounterValue
+    BOOST_CHECK_NO_THROW(profilingService.SetCounterValue(INFERENCES_RUN, 0));
+    BOOST_CHECK_NO_THROW(absoluteCounterValue = profilingService.GetAbsoluteCounterValue(INFERENCES_RUN));
+    BOOST_CHECK(absoluteCounterValue == 0);
+
+    // Test GetDeltaCounterValue
+    writers.clear();
+    uint32_t deltaCounterValue = 0;
+    //Start a reading thread to randomly read the INFERENCES_RUN counter value
+    std::thread reader([&profilingService](uint32_t& deltaCounterValue)
+                       {
+                           for (int i = 0; i < 300; ++i)
+                           {
+                               deltaCounterValue += profilingService.GetDeltaCounterValue(INFERENCES_RUN);
+                           }
+                       }, std::ref(deltaCounterValue));
+
+    for (int i = 0; i < 4; ++i)
+    {
+        // Increment and decrement the INFERENCES_RUN counter 250 times
+        writers.push_back(std::thread([&profilingService]()
+                                      {
+                                          for (int i = 0; i < 250; ++i)
+                                          {
+                                              profilingService.IncrementCounterValue(INFERENCES_RUN);
+                                          }
+                                      }));
+        // Add 10 to the INFERENCES_RUN counter 200 times
+        writers.push_back(std::thread([&profilingService]()
+                                      {
+                                          for (int i = 0; i < 200; ++i)
+                                          {
+                                              profilingService.AddCounterValue(INFERENCES_RUN, 10);
+                                          }
+                                      }));
+        // Subtract 5 from the INFERENCES_RUN counter 200 times
+        writers.push_back(std::thread([&profilingService]()
+                                      {
+                                          for (int i = 0; i < 200; ++i)
+                                          {
+                                              profilingService.SubtractCounterValue(INFERENCES_RUN, 5);
+                                          }
+                                      }));
+    }
+
+    std::for_each(writers.begin(), writers.end(), mem_fn(&std::thread::join));
+    reader.join();
+
+    // Do one last read in case the reader stopped early
+    deltaCounterValue += profilingService.GetDeltaCounterValue(INFERENCES_RUN);
+    BOOST_CHECK(deltaCounterValue == 5000);
+
     // Reset the profiling service to stop any running thread
     options.m_EnableProfiling = false;
     profilingService.ResetExternalProfilingOptions(options, true);
@@ -1705,7 +1760,12 @@
         {
             return 0;
         }
-        uint32_t GetCounterValue(uint16_t counterUid) const override
+        uint32_t GetAbsoluteCounterValue(uint16_t counterUid) const override
+        {
+            armnn::IgnoreUnused(counterUid);
+            return 0;
+        }
+        uint32_t GetDeltaCounterValue(uint16_t counterUid) override
         {
             armnn::IgnoreUnused(counterUid);
             return 0;
@@ -2228,7 +2288,16 @@
             return m_CounterSize;
         }
 
-        uint32_t GetCounterValue(uint16_t counterUid) const override
+        uint32_t GetAbsoluteCounterValue(uint16_t counterUid) const override
+        {
+            if (counterUid > m_CounterSize)
+            {
+                BOOST_FAIL("Invalid counter Uid");
+            }
+            return m_Data.at(counterUid).load();
+        }
+
+        uint32_t GetDeltaCounterValue(uint16_t counterUid)  override
         {
             if (counterUid > m_CounterSize)
             {