blob: 243731cb2cd8a72699f52dcb838685ded87f586d [file] [log] [blame]
Ferran Balaguer1b941722019-08-28 16:57:18 +01001//
2// Copyright © 2019 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#pragma once
7
Matteo Martincigh24e8f922019-09-19 11:57:46 +01008#include <SendCounterPacket.hpp>
9#include <ProfilingUtils.hpp>
Ferran Balaguer1b941722019-08-28 16:57:18 +010010
11#include <armnn/Exceptions.hpp>
Matteo Martincigh24e8f922019-09-19 11:57:46 +010012#include <armnn/Optional.hpp>
13#include <armnn/Conversion.hpp>
Ferran Balaguer1b941722019-08-28 16:57:18 +010014
Matteo Martincigh24e8f922019-09-19 11:57:46 +010015#include <boost/numeric/conversion/cast.hpp>
Ferran Balaguer1b941722019-08-28 16:57:18 +010016
Matteo Martincigh24e8f922019-09-19 11:57:46 +010017namespace armnn
18{
Ferran Balaguer1b941722019-08-28 16:57:18 +010019
Matteo Martincigh24e8f922019-09-19 11:57:46 +010020namespace profiling
21{
22
23class MockProfilingConnection : public IProfilingConnection
24{
25public:
26 MockProfilingConnection()
27 : m_IsOpen(true)
28 {}
29
30 bool IsOpen() override { return m_IsOpen; }
31
32 void Close() override { m_IsOpen = false; }
33
34 bool WritePacket(const unsigned char* buffer, uint32_t length) override
35 {
36 return buffer != nullptr && length > 0;
37 }
38
39 Packet ReadPacket(uint32_t timeout) override { return Packet(); }
40
41private:
42 bool m_IsOpen;
43};
Ferran Balaguer1b941722019-08-28 16:57:18 +010044
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010045class MockPacketBuffer : public IPacketBuffer
Ferran Balaguer1b941722019-08-28 16:57:18 +010046{
47public:
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010048 MockPacketBuffer(unsigned int maxSize)
49 : m_MaxSize(maxSize),
50 m_Size(0)
51 {
52 m_Data = std::make_unique<unsigned char[]>(m_MaxSize);
53 }
Ferran Balaguer1b941722019-08-28 16:57:18 +010054
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010055 ~MockPacketBuffer() {}
56
57 const unsigned char* const GetReadableData() const override { return m_Data.get(); }
58
59 unsigned int GetSize() const override { return m_Size; }
60
61 void MarkRead() override { m_Size = 0;}
62
63 void Commit(unsigned int size) override { m_Size = size; }
64
65 void Release() override { m_Size = 0; }
66
67 unsigned char* GetWritableData() override { return m_Data.get(); }
68
69private:
70 unsigned int m_MaxSize;
71 unsigned int m_Size;
72 std::unique_ptr<unsigned char[]> m_Data;
73};
74
75class MockBufferManager : public IBufferManager
76{
77public:
78 MockBufferManager(unsigned int size)
79 : m_BufferSize(size),
80 m_Buffer(std::make_unique<MockPacketBuffer>(size)) {}
81
82 ~MockBufferManager() {}
83
84 std::unique_ptr<IPacketBuffer> Reserve(unsigned int requestedSize, unsigned int& reservedSize) override
Ferran Balaguer1b941722019-08-28 16:57:18 +010085 {
86 if (requestedSize > m_BufferSize)
87 {
88 reservedSize = m_BufferSize;
89 }
90 else
91 {
92 reservedSize = requestedSize;
93 }
94
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010095 return std::move(m_Buffer);
Ferran Balaguer1b941722019-08-28 16:57:18 +010096 }
97
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010098 void Commit(std::unique_ptr<IPacketBuffer>& packetBuffer, unsigned int size) override
Ferran Balaguer1b941722019-08-28 16:57:18 +010099 {
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100100 packetBuffer->Commit(size);
101 m_Buffer = std::move(packetBuffer);
Ferran Balaguer1b941722019-08-28 16:57:18 +0100102 }
103
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100104 std::unique_ptr<IPacketBuffer> GetReadableBuffer() override
105 {
106 return std::move(m_Buffer);
107 }
108
109 void Release(std::unique_ptr<IPacketBuffer>& packetBuffer) override
110 {
111 packetBuffer->Release();
112 m_Buffer = std::move(packetBuffer);
113 }
114
115 void MarkRead(std::unique_ptr<IPacketBuffer>& packetBuffer) override
116 {
117 packetBuffer->MarkRead();
118 m_Buffer = std::move(packetBuffer);
119 }
Ferran Balaguer1b941722019-08-28 16:57:18 +0100120
121private:
122 unsigned int m_BufferSize;
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100123 std::unique_ptr<IPacketBuffer> m_Buffer;
Ferran Balaguer1b941722019-08-28 16:57:18 +0100124};
125
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100126class MockStreamCounterBuffer : public IBufferManager
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100127{
128public:
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100129 MockStreamCounterBuffer(unsigned int numberOfBuffers = 5, unsigned int maxPacketSize = 4096)
130 : m_MaxBufferSize(maxPacketSize)
131 , m_ReadableSize(0)
132 , m_CommittedSize(0)
133 , m_ReadSize(0)
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100134 {
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100135 m_AvailableList.reserve(numberOfBuffers);
136 for (unsigned int i = 0; i < numberOfBuffers; ++i)
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100137 {
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100138 std::unique_ptr<IPacketBuffer> buffer = std::make_unique<MockPacketBuffer>(maxPacketSize);
139 m_AvailableList.emplace_back(std::move(buffer));
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100140 }
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100141 m_ReadableList.reserve(numberOfBuffers);
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100142 }
143
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100144 ~MockStreamCounterBuffer() {}
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100145
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100146 std::unique_ptr<IPacketBuffer> Reserve(unsigned int requestedSize, unsigned int& reservedSize) override
147 {
148 std::unique_lock<std::mutex> availableListLock(m_AvailableMutex, std::defer_lock);
149 if (requestedSize > m_MaxBufferSize)
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +0100150 {
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100151 throw armnn::Exception("Maximum buffer size that can be requested is [" +
152 std::to_string(m_MaxBufferSize) + "] bytes");
Narumol Prangnawarat7be47ef2019-09-27 18:00:11 +0100153 }
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100154 availableListLock.lock();
155 if (m_AvailableList.empty())
156 {
157 throw armnn::profiling::BufferExhaustion("Buffer not available");
158 }
159 std::unique_ptr<IPacketBuffer> buffer = std::move(m_AvailableList.back());
160 m_AvailableList.pop_back();
161 availableListLock.unlock();
162 reservedSize = requestedSize;
163 return buffer;
164 }
165
166 void Commit(std::unique_ptr<IPacketBuffer>& packetBuffer, unsigned int size) override
167 {
168 std::unique_lock<std::mutex> readableListLock(m_ReadableMutex, std::defer_lock);
169 packetBuffer.get()->Commit(size);
170 readableListLock.lock();
171 m_ReadableList.push_back(std::move(packetBuffer));
172 readableListLock.unlock();
173 m_ReadDataAvailable.notify_one();
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100174 m_CommittedSize += size;
175 }
176
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100177 void Release(std::unique_ptr<IPacketBuffer>& packetBuffer) override
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100178 {
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100179 std::unique_lock<std::mutex> availableListLock(m_AvailableMutex, std::defer_lock);
180 packetBuffer.get()->Release();
181 availableListLock.lock();
182 m_AvailableList.push_back(std::move(packetBuffer));
183 availableListLock.unlock();
184 m_CommittedSize = 0;
185 m_ReadSize = 0;
186 m_ReadableSize = 0;
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100187 }
188
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100189 std::unique_ptr<IPacketBuffer> GetReadableBuffer() override
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100190 {
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100191 std::unique_lock<std::mutex> readableListLock(m_ReadableMutex);
192 if (!m_ReadableList.empty())
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100193 {
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100194 std::unique_ptr<IPacketBuffer> buffer = std::move(m_ReadableList.back());
195 m_ReadableSize+=buffer->GetSize();
196 m_ReadableList.pop_back();
197 readableListLock.unlock();
198 return buffer;
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100199 }
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100200 return nullptr;
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100201 }
202
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100203 void MarkRead(std::unique_ptr<IPacketBuffer>& packetBuffer) override
204 {
205 std::unique_lock<std::mutex> availableListLock(m_AvailableMutex, std::defer_lock);
206 // increase read size
207 m_ReadSize += packetBuffer->GetSize();
208 packetBuffer->MarkRead();
209 availableListLock.lock();
210 m_AvailableList.push_back(std::move(packetBuffer));
211 availableListLock.unlock();
212 }
213
214 unsigned int GetReadableBufferSize() const
215 {
216 return m_ReadableSize;
217 }
218 unsigned int GetCommittedSize() const { return m_CommittedSize; }
219 unsigned int GetReadSize() const { return m_ReadSize; }
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100220
221private:
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100222 unsigned int m_MaxBufferSize;
223 std::vector<std::unique_ptr<IPacketBuffer>> m_AvailableList;
224 std::vector<std::unique_ptr<IPacketBuffer>> m_ReadableList;
225 std::mutex m_AvailableMutex;
226 std::mutex m_ReadableMutex;
227 std::condition_variable m_ReadDataAvailable;
228
229 // The size of the buffer that can be read
230 unsigned int m_ReadableSize;
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100231
232 // The size of the buffer that has been committed for reading
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100233 unsigned int m_CommittedSize;
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100234
235 // The size of the buffer that has already been read
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100236 unsigned int m_ReadSize;
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100237};
238
Ferran Balaguer1b941722019-08-28 16:57:18 +0100239class MockSendCounterPacket : public ISendCounterPacket
240{
241public:
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100242 MockSendCounterPacket(IBufferManager& sendBuffer) : m_BufferManager(sendBuffer) {}
Ferran Balaguer1b941722019-08-28 16:57:18 +0100243
244 void SendStreamMetaDataPacket() override
245 {
246 std::string message("SendStreamMetaDataPacket");
247 unsigned int reserved = 0;
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100248 std::unique_ptr<IPacketBuffer> buffer = m_BufferManager.Reserve(1024, reserved);
249 memcpy(buffer->GetWritableData(), message.c_str(), static_cast<unsigned int>(message.size()) + 1);
250 m_BufferManager.Commit(buffer, reserved);
Ferran Balaguer1b941722019-08-28 16:57:18 +0100251 }
252
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100253 void SendCounterDirectoryPacket(const ICounterDirectory& counterDirectory) override
Ferran Balaguer1b941722019-08-28 16:57:18 +0100254 {
255 std::string message("SendCounterDirectoryPacket");
256 unsigned int reserved = 0;
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100257 std::unique_ptr<IPacketBuffer> buffer = m_BufferManager.Reserve(1024, reserved);
258 memcpy(buffer->GetWritableData(), message.c_str(), static_cast<unsigned int>(message.size()) + 1);
259 m_BufferManager.Commit(buffer, reserved);
Ferran Balaguer1b941722019-08-28 16:57:18 +0100260 }
261
262 void SendPeriodicCounterCapturePacket(uint64_t timestamp,
263 const std::vector<std::pair<uint16_t, uint32_t>>& values) override
264 {
265 std::string message("SendPeriodicCounterCapturePacket");
266 unsigned int reserved = 0;
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100267 std::unique_ptr<IPacketBuffer> buffer = m_BufferManager.Reserve(1024, reserved);
268 memcpy(buffer->GetWritableData(), message.c_str(), static_cast<unsigned int>(message.size()) + 1);
269 m_BufferManager.Commit(buffer, reserved);
Ferran Balaguer1b941722019-08-28 16:57:18 +0100270 }
271
272 void SendPeriodicCounterSelectionPacket(uint32_t capturePeriod,
273 const std::vector<uint16_t>& selectedCounterIds) override
274 {
275 std::string message("SendPeriodicCounterSelectionPacket");
276 unsigned int reserved = 0;
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100277 std::unique_ptr<IPacketBuffer> buffer = m_BufferManager.Reserve(1024, reserved);
278 memcpy(buffer->GetWritableData(), message.c_str(), static_cast<unsigned int>(message.size()) + 1);
279 m_BufferManager.Commit(buffer, reserved);
Ferran Balaguer1b941722019-08-28 16:57:18 +0100280 }
281
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100282 void SetReadyToRead() override {}
Ferran Balaguer1b941722019-08-28 16:57:18 +0100283
284private:
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100285 IBufferManager& m_BufferManager;
Ferran Balaguer1b941722019-08-28 16:57:18 +0100286};
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100287
288class MockCounterDirectory : public ICounterDirectory
289{
290public:
291 MockCounterDirectory() = default;
292 ~MockCounterDirectory() = default;
293
294 // Register profiling objects
295 const Category* RegisterCategory(const std::string& categoryName,
296 const armnn::Optional<uint16_t>& deviceUid = armnn::EmptyOptional(),
297 const armnn::Optional<uint16_t>& counterSetUid = armnn::EmptyOptional())
298 {
299 // Get the device UID
300 uint16_t deviceUidValue = deviceUid.has_value() ? deviceUid.value() : 0;
301
302 // Get the counter set UID
303 uint16_t counterSetUidValue = counterSetUid.has_value() ? counterSetUid.value() : 0;
304
305 // Create the category
306 CategoryPtr category = std::make_unique<Category>(categoryName, deviceUidValue, counterSetUidValue);
307 BOOST_ASSERT(category);
308
309 // Get the raw category pointer
310 const Category* categoryPtr = category.get();
311 BOOST_ASSERT(categoryPtr);
312
313 // Register the category
314 m_Categories.insert(std::move(category));
315
316 return categoryPtr;
317 }
318
319 const Device* RegisterDevice(const std::string& deviceName,
320 uint16_t cores = 0,
321 const armnn::Optional<std::string>& parentCategoryName = armnn::EmptyOptional())
322 {
323 // Get the device UID
324 uint16_t deviceUid = GetNextUid();
325
326 // Create the device
327 DevicePtr device = std::make_unique<Device>(deviceUid, deviceName, cores);
328 BOOST_ASSERT(device);
329
330 // Get the raw device pointer
331 const Device* devicePtr = device.get();
332 BOOST_ASSERT(devicePtr);
333
334 // Register the device
335 m_Devices.insert(std::make_pair(deviceUid, std::move(device)));
336
337 // Connect the counter set to the parent category, if required
338 if (parentCategoryName.has_value())
339 {
340 // Set the counter set UID in the parent category
341 Category* parentCategory = const_cast<Category*>(GetCategory(parentCategoryName.value()));
342 BOOST_ASSERT(parentCategory);
343 parentCategory->m_DeviceUid = deviceUid;
344 }
345
346 return devicePtr;
347 }
348
349 const CounterSet* RegisterCounterSet(
350 const std::string& counterSetName,
351 uint16_t count = 0,
352 const armnn::Optional<std::string>& parentCategoryName = armnn::EmptyOptional())
353 {
354 // Get the counter set UID
355 uint16_t counterSetUid = GetNextUid();
356
357 // Create the counter set
358 CounterSetPtr counterSet = std::make_unique<CounterSet>(counterSetUid, counterSetName, count);
359 BOOST_ASSERT(counterSet);
360
361 // Get the raw counter set pointer
362 const CounterSet* counterSetPtr = counterSet.get();
363 BOOST_ASSERT(counterSetPtr);
364
365 // Register the counter set
366 m_CounterSets.insert(std::make_pair(counterSetUid, std::move(counterSet)));
367
368 // Connect the counter set to the parent category, if required
369 if (parentCategoryName.has_value())
370 {
371 // Set the counter set UID in the parent category
372 Category* parentCategory = const_cast<Category*>(GetCategory(parentCategoryName.value()));
373 BOOST_ASSERT(parentCategory);
374 parentCategory->m_CounterSetUid = counterSetUid;
375 }
376
377 return counterSetPtr;
378 }
379
380 const Counter* RegisterCounter(const std::string& parentCategoryName,
381 uint16_t counterClass,
382 uint16_t interpolation,
383 double multiplier,
384 const std::string& name,
385 const std::string& description,
386 const armnn::Optional<std::string>& units = armnn::EmptyOptional(),
387 const armnn::Optional<uint16_t>& numberOfCores = armnn::EmptyOptional(),
388 const armnn::Optional<uint16_t>& deviceUid = armnn::EmptyOptional(),
389 const armnn::Optional<uint16_t>& counterSetUid = armnn::EmptyOptional())
390 {
391 // Get the number of cores from the argument only
392 uint16_t deviceCores = numberOfCores.has_value() ? numberOfCores.value() : 0;
393
394 // Get the device UID
395 uint16_t deviceUidValue = deviceUid.has_value() ? deviceUid.value() : 0;
396
397 // Get the counter set UID
398 uint16_t counterSetUidValue = counterSetUid.has_value() ? counterSetUid.value() : 0;
399
400 // Get the counter UIDs and calculate the max counter UID
401 std::vector<uint16_t> counterUids = GetNextCounterUids(deviceCores);
402 BOOST_ASSERT(!counterUids.empty());
403 uint16_t maxCounterUid = deviceCores <= 1 ? counterUids.front() : counterUids.back();
404
405 // Get the counter units
406 const std::string unitsValue = units.has_value() ? units.value() : "";
407
408 // Create the counter
409 CounterPtr counter = std::make_shared<Counter>(counterUids.front(),
410 maxCounterUid,
411 counterClass,
412 interpolation,
413 multiplier,
414 name,
415 description,
416 unitsValue,
417 deviceUidValue,
418 counterSetUidValue);
419 BOOST_ASSERT(counter);
420
421 // Get the raw counter pointer
422 const Counter* counterPtr = counter.get();
423 BOOST_ASSERT(counterPtr);
424
425 // Process multiple counters if necessary
426 for (uint16_t counterUid : counterUids)
427 {
428 // Connect the counter to the parent category
429 Category* parentCategory = const_cast<Category*>(GetCategory(parentCategoryName));
430 BOOST_ASSERT(parentCategory);
431 parentCategory->m_Counters.push_back(counterUid);
432
433 // Register the counter
434 m_Counters.insert(std::make_pair(counterUid, counter));
435 }
436
437 return counterPtr;
438 }
439
440 // Getters for counts
441 uint16_t GetCategoryCount() const override { return boost::numeric_cast<uint16_t>(m_Categories.size()); }
442 uint16_t GetDeviceCount() const override { return boost::numeric_cast<uint16_t>(m_Devices.size()); }
443 uint16_t GetCounterSetCount() const override { return boost::numeric_cast<uint16_t>(m_CounterSets.size()); }
444 uint16_t GetCounterCount() const override { return boost::numeric_cast<uint16_t>(m_Counters.size()); }
445
446 // Getters for collections
447 const Categories& GetCategories() const override { return m_Categories; }
448 const Devices& GetDevices() const override { return m_Devices; }
449 const CounterSets& GetCounterSets() const override { return m_CounterSets; }
450 const Counters& GetCounters() const override { return m_Counters; }
451
452 // Getters for profiling objects
453 const Category* GetCategory(const std::string& name) const override
454 {
455 auto it = std::find_if(m_Categories.begin(), m_Categories.end(), [&name](const CategoryPtr& category)
456 {
457 BOOST_ASSERT(category);
458
459 return category->m_Name == name;
460 });
461
462 if (it == m_Categories.end())
463 {
464 return nullptr;
465 }
466
467 return it->get();
468 }
469
470 const Device* GetDevice(uint16_t uid) const override
471 {
472 return nullptr; // Not used by the unit tests
473 }
474
475 const CounterSet* GetCounterSet(uint16_t uid) const override
476 {
477 return nullptr; // Not used by the unit tests
478 }
479
480 const Counter* GetCounter(uint16_t uid) const override
481 {
482 return nullptr; // Not used by the unit tests
483 }
484
485private:
486 Categories m_Categories;
487 Devices m_Devices;
488 CounterSets m_CounterSets;
489 Counters m_Counters;
490};
491
492class SendCounterPacketTest : public SendCounterPacket
493{
494public:
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100495 SendCounterPacketTest(IProfilingConnection& profilingconnection, IBufferManager& buffer)
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100496 : SendCounterPacket(profilingconnection, buffer)
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100497 {}
498
499 bool CreateDeviceRecordTest(const DevicePtr& device,
500 DeviceRecord& deviceRecord,
501 std::string& errorMessage)
502 {
503 return CreateDeviceRecord(device, deviceRecord, errorMessage);
504 }
505
506 bool CreateCounterSetRecordTest(const CounterSetPtr& counterSet,
507 CounterSetRecord& counterSetRecord,
508 std::string& errorMessage)
509 {
510 return CreateCounterSetRecord(counterSet, counterSetRecord, errorMessage);
511 }
512
513 bool CreateEventRecordTest(const CounterPtr& counter,
514 EventRecord& eventRecord,
515 std::string& errorMessage)
516 {
517 return CreateEventRecord(counter, eventRecord, errorMessage);
518 }
519
520 bool CreateCategoryRecordTest(const CategoryPtr& category,
521 const Counters& counters,
522 CategoryRecord& categoryRecord,
523 std::string& errorMessage)
524 {
525 return CreateCategoryRecord(category, counters, categoryRecord, errorMessage);
526 }
527};
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100528
529} // namespace profiling
530
531} // namespace armnn