xref: /aosp_15_r20/external/armnn/shim/sl/canonical/CanonicalUtils.cpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
1*89c4ff92SAndroid Build Coastguard Worker //
2*89c4ff92SAndroid Build Coastguard Worker // Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
3*89c4ff92SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
4*89c4ff92SAndroid Build Coastguard Worker //
5*89c4ff92SAndroid Build Coastguard Worker 
6*89c4ff92SAndroid Build Coastguard Worker #define LOG_TAG "arm-armnn-sl"
7*89c4ff92SAndroid Build Coastguard Worker 
8*89c4ff92SAndroid Build Coastguard Worker #include "CanonicalUtils.hpp"
9*89c4ff92SAndroid Build Coastguard Worker 
10*89c4ff92SAndroid Build Coastguard Worker #include <armnn/Utils.hpp>
11*89c4ff92SAndroid Build Coastguard Worker #include <armnn/utility/Assert.hpp>
12*89c4ff92SAndroid Build Coastguard Worker #include <armnnSerializer/ISerializer.hpp>
13*89c4ff92SAndroid Build Coastguard Worker #include <armnnUtils/Permute.hpp>
14*89c4ff92SAndroid Build Coastguard Worker 
15*89c4ff92SAndroid Build Coastguard Worker #include <ghc/filesystem.hpp>
16*89c4ff92SAndroid Build Coastguard Worker namespace fs = ghc::filesystem;
17*89c4ff92SAndroid Build Coastguard Worker #include <half/half.hpp>
18*89c4ff92SAndroid Build Coastguard Worker #include <log/log.h>
19*89c4ff92SAndroid Build Coastguard Worker 
20*89c4ff92SAndroid Build Coastguard Worker #include <cassert>
21*89c4ff92SAndroid Build Coastguard Worker #include <cerrno>
22*89c4ff92SAndroid Build Coastguard Worker #include <cinttypes>
23*89c4ff92SAndroid Build Coastguard Worker #include <cstdio>
24*89c4ff92SAndroid Build Coastguard Worker #include <sstream>
25*89c4ff92SAndroid Build Coastguard Worker #include <time.h>
26*89c4ff92SAndroid Build Coastguard Worker #include <variant>
27*89c4ff92SAndroid Build Coastguard Worker 
28*89c4ff92SAndroid Build Coastguard Worker namespace armnn
29*89c4ff92SAndroid Build Coastguard Worker {
30*89c4ff92SAndroid Build Coastguard Worker using Half = half_float::half; //import half float implementation
31*89c4ff92SAndroid Build Coastguard Worker } //namespace armnn
32*89c4ff92SAndroid Build Coastguard Worker 
33*89c4ff92SAndroid Build Coastguard Worker using namespace android;
34*89c4ff92SAndroid Build Coastguard Worker using namespace android::nn;
35*89c4ff92SAndroid Build Coastguard Worker 
36*89c4ff92SAndroid Build Coastguard Worker namespace armnn_driver
37*89c4ff92SAndroid Build Coastguard Worker {
38*89c4ff92SAndroid Build Coastguard Worker const armnn::PermutationVector g_DontPermute{};
39*89c4ff92SAndroid Build Coastguard Worker 
SwizzleAndroidNn4dTensorToArmNn(armnn::TensorInfo & tensorInfo,const void * input,void * output,const armnn::PermutationVector & mappings)40*89c4ff92SAndroid Build Coastguard Worker void SwizzleAndroidNn4dTensorToArmNn(armnn::TensorInfo& tensorInfo,
41*89c4ff92SAndroid Build Coastguard Worker                                      const void* input,
42*89c4ff92SAndroid Build Coastguard Worker                                      void* output,
43*89c4ff92SAndroid Build Coastguard Worker                                      const armnn::PermutationVector& mappings)
44*89c4ff92SAndroid Build Coastguard Worker {
45*89c4ff92SAndroid Build Coastguard Worker     assert(tensorInfo.GetNumDimensions() == 4U);
46*89c4ff92SAndroid Build Coastguard Worker 
47*89c4ff92SAndroid Build Coastguard Worker     armnn::DataType dataType = tensorInfo.GetDataType();
48*89c4ff92SAndroid Build Coastguard Worker     switch (dataType)
49*89c4ff92SAndroid Build Coastguard Worker     {
50*89c4ff92SAndroid Build Coastguard Worker     case armnn::DataType::Float16:
51*89c4ff92SAndroid Build Coastguard Worker     case armnn::DataType::Float32:
52*89c4ff92SAndroid Build Coastguard Worker     case armnn::DataType::QAsymmU8:
53*89c4ff92SAndroid Build Coastguard Worker     case armnn::DataType::QSymmS8:
54*89c4ff92SAndroid Build Coastguard Worker     case armnn::DataType::QAsymmS8:
55*89c4ff92SAndroid Build Coastguard Worker         // First swizzle tensor info
56*89c4ff92SAndroid Build Coastguard Worker         tensorInfo = armnnUtils::Permuted(tensorInfo, mappings);
57*89c4ff92SAndroid Build Coastguard Worker         // Then swizzle tensor data
58*89c4ff92SAndroid Build Coastguard Worker         armnnUtils::Permute(tensorInfo.GetShape(), mappings, input, output, armnn::GetDataTypeSize(dataType));
59*89c4ff92SAndroid Build Coastguard Worker         break;
60*89c4ff92SAndroid Build Coastguard Worker     default:
61*89c4ff92SAndroid Build Coastguard Worker         VLOG(DRIVER) << "Unknown armnn::DataType for swizzling";
62*89c4ff92SAndroid Build Coastguard Worker         assert(0);
63*89c4ff92SAndroid Build Coastguard Worker     }
64*89c4ff92SAndroid Build Coastguard Worker }
65*89c4ff92SAndroid Build Coastguard Worker 
GetMemoryFromPool(DataLocation location,const std::vector<android::nn::RunTimePoolInfo> & memPools)66*89c4ff92SAndroid Build Coastguard Worker void* GetMemoryFromPool(DataLocation location, const std::vector<android::nn::RunTimePoolInfo>& memPools)
67*89c4ff92SAndroid Build Coastguard Worker {
68*89c4ff92SAndroid Build Coastguard Worker     // find the location within the pool
69*89c4ff92SAndroid Build Coastguard Worker     assert(location.poolIndex < memPools.size());
70*89c4ff92SAndroid Build Coastguard Worker 
71*89c4ff92SAndroid Build Coastguard Worker     const android::nn::RunTimePoolInfo& memPool = memPools[location.poolIndex];
72*89c4ff92SAndroid Build Coastguard Worker     uint8_t* memPoolBuffer = memPool.getBuffer();
73*89c4ff92SAndroid Build Coastguard Worker     uint8_t* memory = memPoolBuffer + location.offset;
74*89c4ff92SAndroid Build Coastguard Worker     return memory;
75*89c4ff92SAndroid Build Coastguard Worker }
76*89c4ff92SAndroid Build Coastguard Worker 
GetMemoryFromPointer(const Request::Argument & requestArg)77*89c4ff92SAndroid Build Coastguard Worker void* GetMemoryFromPointer(const Request::Argument& requestArg)
78*89c4ff92SAndroid Build Coastguard Worker {
79*89c4ff92SAndroid Build Coastguard Worker     // get the pointer memory
80*89c4ff92SAndroid Build Coastguard Worker     auto ptrMemory = std::visit([](std::variant<const void*, void*>&& memory)
81*89c4ff92SAndroid Build Coastguard Worker                                 {
82*89c4ff92SAndroid Build Coastguard Worker                                     if (std::holds_alternative<const void*>(memory))
83*89c4ff92SAndroid Build Coastguard Worker                                     {
84*89c4ff92SAndroid Build Coastguard Worker                                         auto ptr = std::get<const void*>(memory);
85*89c4ff92SAndroid Build Coastguard Worker                                         auto ptrMemory = static_cast<const uint8_t*>(ptr);
86*89c4ff92SAndroid Build Coastguard Worker                                         return const_cast<uint8_t*>(ptrMemory);
87*89c4ff92SAndroid Build Coastguard Worker                                     }
88*89c4ff92SAndroid Build Coastguard Worker                                     else
89*89c4ff92SAndroid Build Coastguard Worker                                     {
90*89c4ff92SAndroid Build Coastguard Worker                                         auto ptr = std::get<void*>(memory);
91*89c4ff92SAndroid Build Coastguard Worker                                         return static_cast<uint8_t*>(ptr);
92*89c4ff92SAndroid Build Coastguard Worker                                     }
93*89c4ff92SAndroid Build Coastguard Worker                                 }, requestArg.location.pointer);
94*89c4ff92SAndroid Build Coastguard Worker     return ptrMemory;
95*89c4ff92SAndroid Build Coastguard Worker }
96*89c4ff92SAndroid Build Coastguard Worker 
GetTensorInfoForOperand(const Operand & operand)97*89c4ff92SAndroid Build Coastguard Worker armnn::TensorInfo GetTensorInfoForOperand(const Operand& operand)
98*89c4ff92SAndroid Build Coastguard Worker {
99*89c4ff92SAndroid Build Coastguard Worker     using namespace armnn;
100*89c4ff92SAndroid Build Coastguard Worker     bool perChannel = false;
101*89c4ff92SAndroid Build Coastguard Worker     bool isScalar   = false;
102*89c4ff92SAndroid Build Coastguard Worker 
103*89c4ff92SAndroid Build Coastguard Worker     DataType type;
104*89c4ff92SAndroid Build Coastguard Worker     switch (operand.type)
105*89c4ff92SAndroid Build Coastguard Worker     {
106*89c4ff92SAndroid Build Coastguard Worker         case OperandType::TENSOR_BOOL8:
107*89c4ff92SAndroid Build Coastguard Worker             type = armnn::DataType::Boolean;
108*89c4ff92SAndroid Build Coastguard Worker             break;
109*89c4ff92SAndroid Build Coastguard Worker         case OperandType::TENSOR_FLOAT32:
110*89c4ff92SAndroid Build Coastguard Worker             type = armnn::DataType::Float32;
111*89c4ff92SAndroid Build Coastguard Worker             break;
112*89c4ff92SAndroid Build Coastguard Worker         case OperandType::TENSOR_FLOAT16:
113*89c4ff92SAndroid Build Coastguard Worker             type = armnn::DataType::Float16;
114*89c4ff92SAndroid Build Coastguard Worker             break;
115*89c4ff92SAndroid Build Coastguard Worker         case OperandType::TENSOR_QUANT8_ASYMM:
116*89c4ff92SAndroid Build Coastguard Worker             type = armnn::DataType::QAsymmU8;
117*89c4ff92SAndroid Build Coastguard Worker             break;
118*89c4ff92SAndroid Build Coastguard Worker         case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
119*89c4ff92SAndroid Build Coastguard Worker             perChannel=true;
120*89c4ff92SAndroid Build Coastguard Worker             ARMNN_FALLTHROUGH;
121*89c4ff92SAndroid Build Coastguard Worker         case OperandType::TENSOR_QUANT8_SYMM:
122*89c4ff92SAndroid Build Coastguard Worker             type = armnn::DataType::QSymmS8;
123*89c4ff92SAndroid Build Coastguard Worker             break;
124*89c4ff92SAndroid Build Coastguard Worker         case OperandType::TENSOR_QUANT16_SYMM:
125*89c4ff92SAndroid Build Coastguard Worker             type = armnn::DataType::QSymmS16;
126*89c4ff92SAndroid Build Coastguard Worker             break;
127*89c4ff92SAndroid Build Coastguard Worker         case OperandType::TENSOR_INT32:
128*89c4ff92SAndroid Build Coastguard Worker             type = armnn::DataType::Signed32;
129*89c4ff92SAndroid Build Coastguard Worker             break;
130*89c4ff92SAndroid Build Coastguard Worker         case OperandType::INT32:
131*89c4ff92SAndroid Build Coastguard Worker             type = armnn::DataType::Signed32;
132*89c4ff92SAndroid Build Coastguard Worker             isScalar = true;
133*89c4ff92SAndroid Build Coastguard Worker             break;
134*89c4ff92SAndroid Build Coastguard Worker         case OperandType::TENSOR_QUANT8_ASYMM_SIGNED:
135*89c4ff92SAndroid Build Coastguard Worker             type = armnn::DataType::QAsymmS8;
136*89c4ff92SAndroid Build Coastguard Worker             break;
137*89c4ff92SAndroid Build Coastguard Worker         default:
138*89c4ff92SAndroid Build Coastguard Worker             throw UnsupportedOperand<OperandType>(operand.type);
139*89c4ff92SAndroid Build Coastguard Worker     }
140*89c4ff92SAndroid Build Coastguard Worker 
141*89c4ff92SAndroid Build Coastguard Worker     TensorInfo ret;
142*89c4ff92SAndroid Build Coastguard Worker     if (isScalar)
143*89c4ff92SAndroid Build Coastguard Worker     {
144*89c4ff92SAndroid Build Coastguard Worker         ret = TensorInfo(TensorShape(armnn::Dimensionality::Scalar), type);
145*89c4ff92SAndroid Build Coastguard Worker     }
146*89c4ff92SAndroid Build Coastguard Worker     else
147*89c4ff92SAndroid Build Coastguard Worker     {
148*89c4ff92SAndroid Build Coastguard Worker         if (operand.dimensions.size() == 0)
149*89c4ff92SAndroid Build Coastguard Worker         {
150*89c4ff92SAndroid Build Coastguard Worker             TensorShape tensorShape(Dimensionality::NotSpecified);
151*89c4ff92SAndroid Build Coastguard Worker             ret = TensorInfo(tensorShape, type);
152*89c4ff92SAndroid Build Coastguard Worker         }
153*89c4ff92SAndroid Build Coastguard Worker         else
154*89c4ff92SAndroid Build Coastguard Worker         {
155*89c4ff92SAndroid Build Coastguard Worker             bool dimensionsSpecificity[5] = { true, true, true, true, true };
156*89c4ff92SAndroid Build Coastguard Worker             int count = 0;
157*89c4ff92SAndroid Build Coastguard Worker             std::for_each(operand.dimensions.data(),
158*89c4ff92SAndroid Build Coastguard Worker                           operand.dimensions.data() +  operand.dimensions.size(),
159*89c4ff92SAndroid Build Coastguard Worker                           [&](const unsigned int val)
160*89c4ff92SAndroid Build Coastguard Worker                           {
161*89c4ff92SAndroid Build Coastguard Worker                               if (val == 0)
162*89c4ff92SAndroid Build Coastguard Worker                               {
163*89c4ff92SAndroid Build Coastguard Worker                                   dimensionsSpecificity[count] = false;
164*89c4ff92SAndroid Build Coastguard Worker                               }
165*89c4ff92SAndroid Build Coastguard Worker                               count++;
166*89c4ff92SAndroid Build Coastguard Worker                           });
167*89c4ff92SAndroid Build Coastguard Worker 
168*89c4ff92SAndroid Build Coastguard Worker             TensorShape tensorShape(operand.dimensions.size(), operand.dimensions.data(), dimensionsSpecificity);
169*89c4ff92SAndroid Build Coastguard Worker             ret = TensorInfo(tensorShape, type);
170*89c4ff92SAndroid Build Coastguard Worker         }
171*89c4ff92SAndroid Build Coastguard Worker     }
172*89c4ff92SAndroid Build Coastguard Worker 
173*89c4ff92SAndroid Build Coastguard Worker     if (perChannel)
174*89c4ff92SAndroid Build Coastguard Worker     {
175*89c4ff92SAndroid Build Coastguard Worker         // ExtraParams is expected to be of type channelQuant
176*89c4ff92SAndroid Build Coastguard Worker         const auto& perAxisQuantParams = std::get<Operand::SymmPerChannelQuantParams>(operand.extraParams);
177*89c4ff92SAndroid Build Coastguard Worker 
178*89c4ff92SAndroid Build Coastguard Worker         ret.SetQuantizationScales(perAxisQuantParams.scales);
179*89c4ff92SAndroid Build Coastguard Worker         ret.SetQuantizationDim(MakeOptional<unsigned int>(perAxisQuantParams.channelDim));
180*89c4ff92SAndroid Build Coastguard Worker     }
181*89c4ff92SAndroid Build Coastguard Worker     else
182*89c4ff92SAndroid Build Coastguard Worker     {
183*89c4ff92SAndroid Build Coastguard Worker         ret.SetQuantizationScale(operand.scale);
184*89c4ff92SAndroid Build Coastguard Worker         ret.SetQuantizationOffset(operand.zeroPoint);
185*89c4ff92SAndroid Build Coastguard Worker     }
186*89c4ff92SAndroid Build Coastguard Worker     return ret;
187*89c4ff92SAndroid Build Coastguard Worker }
188*89c4ff92SAndroid Build Coastguard Worker 
GetOperandSummary(const Operand & operand)189*89c4ff92SAndroid Build Coastguard Worker std::string GetOperandSummary(const Operand& operand)
190*89c4ff92SAndroid Build Coastguard Worker {
191*89c4ff92SAndroid Build Coastguard Worker     std::stringstream ss;
192*89c4ff92SAndroid Build Coastguard Worker     ss << "operand dimensions: [ ";
193*89c4ff92SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < operand.dimensions.size(); ++i)
194*89c4ff92SAndroid Build Coastguard Worker     {
195*89c4ff92SAndroid Build Coastguard Worker         ss << operand.dimensions[i] << " ";
196*89c4ff92SAndroid Build Coastguard Worker     }
197*89c4ff92SAndroid Build Coastguard Worker     ss << "] operand type: " << operand.type;
198*89c4ff92SAndroid Build Coastguard Worker     return ss.str();
199*89c4ff92SAndroid Build Coastguard Worker }
200*89c4ff92SAndroid Build Coastguard Worker 
201*89c4ff92SAndroid Build Coastguard Worker template <typename TensorType>
202*89c4ff92SAndroid Build Coastguard Worker using DumpElementFunction = void (*)(const TensorType& tensor,
203*89c4ff92SAndroid Build Coastguard Worker                                      unsigned int elementIndex,
204*89c4ff92SAndroid Build Coastguard Worker                                      std::ofstream& fileStream);
205*89c4ff92SAndroid Build Coastguard Worker 
206*89c4ff92SAndroid Build Coastguard Worker namespace
207*89c4ff92SAndroid Build Coastguard Worker {
208*89c4ff92SAndroid Build Coastguard Worker template <typename TensorType, typename ElementType, typename PrintableType = ElementType>
DumpTensorElement(const TensorType & tensor,unsigned int elementIndex,std::ofstream & fileStream)209*89c4ff92SAndroid Build Coastguard Worker void DumpTensorElement(const TensorType& tensor, unsigned int elementIndex, std::ofstream& fileStream)
210*89c4ff92SAndroid Build Coastguard Worker {
211*89c4ff92SAndroid Build Coastguard Worker     const ElementType* elements = reinterpret_cast<const ElementType*>(tensor.GetMemoryArea());
212*89c4ff92SAndroid Build Coastguard Worker     fileStream << static_cast<PrintableType>(elements[elementIndex]) << " ";
213*89c4ff92SAndroid Build Coastguard Worker }
214*89c4ff92SAndroid Build Coastguard Worker 
215*89c4ff92SAndroid Build Coastguard Worker } // namespace
216*89c4ff92SAndroid Build Coastguard Worker template <typename TensorType>
DumpTensor(const std::string & dumpDir,const std::string & requestName,const std::string & tensorName,const TensorType & tensor)217*89c4ff92SAndroid Build Coastguard Worker void DumpTensor(const std::string& dumpDir,
218*89c4ff92SAndroid Build Coastguard Worker                 const std::string& requestName,
219*89c4ff92SAndroid Build Coastguard Worker                 const std::string& tensorName,
220*89c4ff92SAndroid Build Coastguard Worker                 const TensorType& tensor)
221*89c4ff92SAndroid Build Coastguard Worker {
222*89c4ff92SAndroid Build Coastguard Worker     // The dump directory must exist in advance.
223*89c4ff92SAndroid Build Coastguard Worker     fs::path dumpPath = dumpDir;
224*89c4ff92SAndroid Build Coastguard Worker     const fs::path fileName = dumpPath / (requestName + "_" + tensorName + ".dump");
225*89c4ff92SAndroid Build Coastguard Worker 
226*89c4ff92SAndroid Build Coastguard Worker     std::ofstream fileStream;
227*89c4ff92SAndroid Build Coastguard Worker     fileStream.open(fileName.c_str(), std::ofstream::out | std::ofstream::trunc);
228*89c4ff92SAndroid Build Coastguard Worker 
229*89c4ff92SAndroid Build Coastguard Worker     if (!fileStream.good())
230*89c4ff92SAndroid Build Coastguard Worker     {
231*89c4ff92SAndroid Build Coastguard Worker         VLOG(DRIVER) << "Could not open file %s for writing" << fileName.c_str();
232*89c4ff92SAndroid Build Coastguard Worker         return;
233*89c4ff92SAndroid Build Coastguard Worker     }
234*89c4ff92SAndroid Build Coastguard Worker 
235*89c4ff92SAndroid Build Coastguard Worker     DumpElementFunction<TensorType> dumpElementFunction = nullptr;
236*89c4ff92SAndroid Build Coastguard Worker 
237*89c4ff92SAndroid Build Coastguard Worker     switch (tensor.GetDataType())
238*89c4ff92SAndroid Build Coastguard Worker     {
239*89c4ff92SAndroid Build Coastguard Worker         case armnn::DataType::Float32:
240*89c4ff92SAndroid Build Coastguard Worker         {
241*89c4ff92SAndroid Build Coastguard Worker             dumpElementFunction = &DumpTensorElement<TensorType, float>;
242*89c4ff92SAndroid Build Coastguard Worker             break;
243*89c4ff92SAndroid Build Coastguard Worker         }
244*89c4ff92SAndroid Build Coastguard Worker         case armnn::DataType::QAsymmU8:
245*89c4ff92SAndroid Build Coastguard Worker         {
246*89c4ff92SAndroid Build Coastguard Worker             dumpElementFunction = &DumpTensorElement<TensorType, uint8_t, uint32_t>;
247*89c4ff92SAndroid Build Coastguard Worker             break;
248*89c4ff92SAndroid Build Coastguard Worker         }
249*89c4ff92SAndroid Build Coastguard Worker         case armnn::DataType::Signed32:
250*89c4ff92SAndroid Build Coastguard Worker         {
251*89c4ff92SAndroid Build Coastguard Worker             dumpElementFunction = &DumpTensorElement<TensorType, int32_t>;
252*89c4ff92SAndroid Build Coastguard Worker             break;
253*89c4ff92SAndroid Build Coastguard Worker         }
254*89c4ff92SAndroid Build Coastguard Worker         case armnn::DataType::Float16:
255*89c4ff92SAndroid Build Coastguard Worker         {
256*89c4ff92SAndroid Build Coastguard Worker             dumpElementFunction = &DumpTensorElement<TensorType, armnn::Half>;
257*89c4ff92SAndroid Build Coastguard Worker             break;
258*89c4ff92SAndroid Build Coastguard Worker         }
259*89c4ff92SAndroid Build Coastguard Worker         case armnn::DataType::QAsymmS8:
260*89c4ff92SAndroid Build Coastguard Worker         {
261*89c4ff92SAndroid Build Coastguard Worker             dumpElementFunction = &DumpTensorElement<TensorType, int8_t, int32_t>;
262*89c4ff92SAndroid Build Coastguard Worker             break;
263*89c4ff92SAndroid Build Coastguard Worker         }
264*89c4ff92SAndroid Build Coastguard Worker         case armnn::DataType::Boolean:
265*89c4ff92SAndroid Build Coastguard Worker         {
266*89c4ff92SAndroid Build Coastguard Worker             dumpElementFunction = &DumpTensorElement<TensorType, bool>;
267*89c4ff92SAndroid Build Coastguard Worker             break;
268*89c4ff92SAndroid Build Coastguard Worker         }
269*89c4ff92SAndroid Build Coastguard Worker         default:
270*89c4ff92SAndroid Build Coastguard Worker         {
271*89c4ff92SAndroid Build Coastguard Worker             dumpElementFunction = nullptr;
272*89c4ff92SAndroid Build Coastguard Worker         }
273*89c4ff92SAndroid Build Coastguard Worker     }
274*89c4ff92SAndroid Build Coastguard Worker 
275*89c4ff92SAndroid Build Coastguard Worker     if (dumpElementFunction != nullptr)
276*89c4ff92SAndroid Build Coastguard Worker     {
277*89c4ff92SAndroid Build Coastguard Worker         const unsigned int numDimensions = tensor.GetNumDimensions();
278*89c4ff92SAndroid Build Coastguard Worker         const armnn::TensorShape shape = tensor.GetShape();
279*89c4ff92SAndroid Build Coastguard Worker 
280*89c4ff92SAndroid Build Coastguard Worker         if (!shape.AreAllDimensionsSpecified())
281*89c4ff92SAndroid Build Coastguard Worker         {
282*89c4ff92SAndroid Build Coastguard Worker             fileStream << "Cannot dump tensor elements: not all dimensions are specified" << std::endl;
283*89c4ff92SAndroid Build Coastguard Worker             return;
284*89c4ff92SAndroid Build Coastguard Worker         }
285*89c4ff92SAndroid Build Coastguard Worker         fileStream << "# Number of elements " << tensor.GetNumElements() << std::endl;
286*89c4ff92SAndroid Build Coastguard Worker 
287*89c4ff92SAndroid Build Coastguard Worker         if (numDimensions == 0)
288*89c4ff92SAndroid Build Coastguard Worker         {
289*89c4ff92SAndroid Build Coastguard Worker             fileStream << "# Shape []" << std::endl;
290*89c4ff92SAndroid Build Coastguard Worker             return;
291*89c4ff92SAndroid Build Coastguard Worker         }
292*89c4ff92SAndroid Build Coastguard Worker         fileStream << "# Shape [" << shape[0];
293*89c4ff92SAndroid Build Coastguard Worker         for (unsigned int d = 1; d < numDimensions; ++d)
294*89c4ff92SAndroid Build Coastguard Worker         {
295*89c4ff92SAndroid Build Coastguard Worker             fileStream << "," << shape[d];
296*89c4ff92SAndroid Build Coastguard Worker         }
297*89c4ff92SAndroid Build Coastguard Worker         fileStream << "]" << std::endl;
298*89c4ff92SAndroid Build Coastguard Worker         fileStream << "Each line contains the data of each of the elements of dimension0. In NCHW and NHWC, each line"
299*89c4ff92SAndroid Build Coastguard Worker                       " will be a batch" << std::endl << std::endl;
300*89c4ff92SAndroid Build Coastguard Worker 
301*89c4ff92SAndroid Build Coastguard Worker         // Split will create a new line after all elements of the first dimension
302*89c4ff92SAndroid Build Coastguard Worker         // (in a 4, 3, 2, 3 tensor, there will be 4 lines of 18 elements)
303*89c4ff92SAndroid Build Coastguard Worker         unsigned int split = 1;
304*89c4ff92SAndroid Build Coastguard Worker         if (numDimensions == 1)
305*89c4ff92SAndroid Build Coastguard Worker         {
306*89c4ff92SAndroid Build Coastguard Worker             split = shape[0];
307*89c4ff92SAndroid Build Coastguard Worker         }
308*89c4ff92SAndroid Build Coastguard Worker         else
309*89c4ff92SAndroid Build Coastguard Worker         {
310*89c4ff92SAndroid Build Coastguard Worker             for (unsigned int i = 1; i < numDimensions; ++i)
311*89c4ff92SAndroid Build Coastguard Worker             {
312*89c4ff92SAndroid Build Coastguard Worker                 split *= shape[i];
313*89c4ff92SAndroid Build Coastguard Worker             }
314*89c4ff92SAndroid Build Coastguard Worker         }
315*89c4ff92SAndroid Build Coastguard Worker 
316*89c4ff92SAndroid Build Coastguard Worker         // Print all elements in the tensor
317*89c4ff92SAndroid Build Coastguard Worker         for (unsigned int elementIndex = 0; elementIndex < tensor.GetNumElements(); ++elementIndex)
318*89c4ff92SAndroid Build Coastguard Worker         {
319*89c4ff92SAndroid Build Coastguard Worker             (*dumpElementFunction)(tensor, elementIndex, fileStream);
320*89c4ff92SAndroid Build Coastguard Worker 
321*89c4ff92SAndroid Build Coastguard Worker             if ( (elementIndex + 1) % split == 0 )
322*89c4ff92SAndroid Build Coastguard Worker             {
323*89c4ff92SAndroid Build Coastguard Worker                 fileStream << std::endl;
324*89c4ff92SAndroid Build Coastguard Worker             }
325*89c4ff92SAndroid Build Coastguard Worker         }
326*89c4ff92SAndroid Build Coastguard Worker         fileStream << std::endl;
327*89c4ff92SAndroid Build Coastguard Worker     }
328*89c4ff92SAndroid Build Coastguard Worker     else
329*89c4ff92SAndroid Build Coastguard Worker     {
330*89c4ff92SAndroid Build Coastguard Worker         fileStream << "Cannot dump tensor elements: Unsupported data type "
331*89c4ff92SAndroid Build Coastguard Worker             << static_cast<unsigned int>(tensor.GetDataType()) << std::endl;
332*89c4ff92SAndroid Build Coastguard Worker     }
333*89c4ff92SAndroid Build Coastguard Worker 
334*89c4ff92SAndroid Build Coastguard Worker     if (!fileStream.good())
335*89c4ff92SAndroid Build Coastguard Worker     {
336*89c4ff92SAndroid Build Coastguard Worker         VLOG(DRIVER) << "An error occurred when writing to file %s" << fileName.c_str();
337*89c4ff92SAndroid Build Coastguard Worker     }
338*89c4ff92SAndroid Build Coastguard Worker }
339*89c4ff92SAndroid Build Coastguard Worker 
340*89c4ff92SAndroid Build Coastguard Worker template void DumpTensor<armnn::ConstTensor>(const std::string& dumpDir,
341*89c4ff92SAndroid Build Coastguard Worker                                              const std::string& requestName,
342*89c4ff92SAndroid Build Coastguard Worker                                              const std::string& tensorName,
343*89c4ff92SAndroid Build Coastguard Worker                                              const armnn::ConstTensor& tensor);
344*89c4ff92SAndroid Build Coastguard Worker 
345*89c4ff92SAndroid Build Coastguard Worker template void DumpTensor<armnn::Tensor>(const std::string& dumpDir,
346*89c4ff92SAndroid Build Coastguard Worker                                         const std::string& requestName,
347*89c4ff92SAndroid Build Coastguard Worker                                         const std::string& tensorName,
348*89c4ff92SAndroid Build Coastguard Worker                                         const armnn::Tensor& tensor);
349*89c4ff92SAndroid Build Coastguard Worker 
DumpJsonProfilingIfRequired(bool gpuProfilingEnabled,const std::string & dumpDir,armnn::NetworkId networkId,const armnn::IProfiler * profiler)350*89c4ff92SAndroid Build Coastguard Worker void DumpJsonProfilingIfRequired(bool gpuProfilingEnabled,
351*89c4ff92SAndroid Build Coastguard Worker                                  const std::string& dumpDir,
352*89c4ff92SAndroid Build Coastguard Worker                                  armnn::NetworkId networkId,
353*89c4ff92SAndroid Build Coastguard Worker                                  const armnn::IProfiler* profiler)
354*89c4ff92SAndroid Build Coastguard Worker {
355*89c4ff92SAndroid Build Coastguard Worker     // Check if profiling is required.
356*89c4ff92SAndroid Build Coastguard Worker     if (!gpuProfilingEnabled)
357*89c4ff92SAndroid Build Coastguard Worker     {
358*89c4ff92SAndroid Build Coastguard Worker         return;
359*89c4ff92SAndroid Build Coastguard Worker     }
360*89c4ff92SAndroid Build Coastguard Worker 
361*89c4ff92SAndroid Build Coastguard Worker     // The dump directory must exist in advance.
362*89c4ff92SAndroid Build Coastguard Worker     if (dumpDir.empty())
363*89c4ff92SAndroid Build Coastguard Worker     {
364*89c4ff92SAndroid Build Coastguard Worker         return;
365*89c4ff92SAndroid Build Coastguard Worker     }
366*89c4ff92SAndroid Build Coastguard Worker 
367*89c4ff92SAndroid Build Coastguard Worker     ARMNN_ASSERT(profiler);
368*89c4ff92SAndroid Build Coastguard Worker 
369*89c4ff92SAndroid Build Coastguard Worker     // Set the name of the output profiling file.
370*89c4ff92SAndroid Build Coastguard Worker     fs::path dumpPath = dumpDir;
371*89c4ff92SAndroid Build Coastguard Worker     const fs::path fileName = dumpPath / (std::to_string(networkId) + "_profiling.json");
372*89c4ff92SAndroid Build Coastguard Worker 
373*89c4ff92SAndroid Build Coastguard Worker     // Open the ouput file for writing.
374*89c4ff92SAndroid Build Coastguard Worker     std::ofstream fileStream;
375*89c4ff92SAndroid Build Coastguard Worker     fileStream.open(fileName.c_str(), std::ofstream::out | std::ofstream::trunc);
376*89c4ff92SAndroid Build Coastguard Worker 
377*89c4ff92SAndroid Build Coastguard Worker     if (!fileStream.good())
378*89c4ff92SAndroid Build Coastguard Worker     {
379*89c4ff92SAndroid Build Coastguard Worker         VLOG(DRIVER) << "Could not open file %s for writing" << fileName.c_str();
380*89c4ff92SAndroid Build Coastguard Worker         return;
381*89c4ff92SAndroid Build Coastguard Worker     }
382*89c4ff92SAndroid Build Coastguard Worker 
383*89c4ff92SAndroid Build Coastguard Worker     // Write the profiling info to a JSON file.
384*89c4ff92SAndroid Build Coastguard Worker     profiler->Print(fileStream);
385*89c4ff92SAndroid Build Coastguard Worker }
386*89c4ff92SAndroid Build Coastguard Worker 
ExportNetworkGraphToDotFile(const armnn::IOptimizedNetwork & optimizedNetwork,const std::string & dumpDir)387*89c4ff92SAndroid Build Coastguard Worker std::string ExportNetworkGraphToDotFile(const armnn::IOptimizedNetwork& optimizedNetwork,
388*89c4ff92SAndroid Build Coastguard Worker                                         const std::string& dumpDir)
389*89c4ff92SAndroid Build Coastguard Worker {
390*89c4ff92SAndroid Build Coastguard Worker     std::string fileName;
391*89c4ff92SAndroid Build Coastguard Worker     // The dump directory must exist in advance.
392*89c4ff92SAndroid Build Coastguard Worker     if (dumpDir.empty())
393*89c4ff92SAndroid Build Coastguard Worker     {
394*89c4ff92SAndroid Build Coastguard Worker         return fileName;
395*89c4ff92SAndroid Build Coastguard Worker     }
396*89c4ff92SAndroid Build Coastguard Worker 
397*89c4ff92SAndroid Build Coastguard Worker     std::string timestamp = GetFileTimestamp();
398*89c4ff92SAndroid Build Coastguard Worker     if (timestamp.empty())
399*89c4ff92SAndroid Build Coastguard Worker     {
400*89c4ff92SAndroid Build Coastguard Worker         return fileName;
401*89c4ff92SAndroid Build Coastguard Worker     }
402*89c4ff92SAndroid Build Coastguard Worker 
403*89c4ff92SAndroid Build Coastguard Worker     // Set the name of the output .dot file.
404*89c4ff92SAndroid Build Coastguard Worker     fs::path dumpPath = dumpDir;
405*89c4ff92SAndroid Build Coastguard Worker     fs::path tempFilePath = dumpPath / (timestamp + "_networkgraph.dot");
406*89c4ff92SAndroid Build Coastguard Worker     fileName = tempFilePath.string();
407*89c4ff92SAndroid Build Coastguard Worker 
408*89c4ff92SAndroid Build Coastguard Worker     VLOG(DRIVER) << "Exporting the optimized network graph to file: %s" << fileName.c_str();
409*89c4ff92SAndroid Build Coastguard Worker 
410*89c4ff92SAndroid Build Coastguard Worker     // Write the network graph to a dot file.
411*89c4ff92SAndroid Build Coastguard Worker     std::ofstream fileStream;
412*89c4ff92SAndroid Build Coastguard Worker     fileStream.open(fileName, std::ofstream::out | std::ofstream::trunc);
413*89c4ff92SAndroid Build Coastguard Worker 
414*89c4ff92SAndroid Build Coastguard Worker     if (!fileStream.good())
415*89c4ff92SAndroid Build Coastguard Worker     {
416*89c4ff92SAndroid Build Coastguard Worker         VLOG(DRIVER) << "Could not open file %s for writing" << fileName.c_str();
417*89c4ff92SAndroid Build Coastguard Worker         return fileName;
418*89c4ff92SAndroid Build Coastguard Worker     }
419*89c4ff92SAndroid Build Coastguard Worker 
420*89c4ff92SAndroid Build Coastguard Worker     if (optimizedNetwork.SerializeToDot(fileStream) != armnn::Status::Success)
421*89c4ff92SAndroid Build Coastguard Worker     {
422*89c4ff92SAndroid Build Coastguard Worker         VLOG(DRIVER) << "An error occurred when writing to file %s" << fileName.c_str();
423*89c4ff92SAndroid Build Coastguard Worker     }
424*89c4ff92SAndroid Build Coastguard Worker     return fileName;
425*89c4ff92SAndroid Build Coastguard Worker }
426*89c4ff92SAndroid Build Coastguard Worker 
SerializeNetwork(const armnn::INetwork & network,const std::string & dumpDir,std::vector<uint8_t> & dataCacheData,bool dataCachingActive)427*89c4ff92SAndroid Build Coastguard Worker std::string SerializeNetwork(const armnn::INetwork& network,
428*89c4ff92SAndroid Build Coastguard Worker                              const std::string& dumpDir,
429*89c4ff92SAndroid Build Coastguard Worker                              std::vector<uint8_t>& dataCacheData,
430*89c4ff92SAndroid Build Coastguard Worker                              bool dataCachingActive)
431*89c4ff92SAndroid Build Coastguard Worker {
432*89c4ff92SAndroid Build Coastguard Worker     std::string fileName;
433*89c4ff92SAndroid Build Coastguard Worker     bool bSerializeToFile = true;
434*89c4ff92SAndroid Build Coastguard Worker     if (dumpDir.empty())
435*89c4ff92SAndroid Build Coastguard Worker     {
436*89c4ff92SAndroid Build Coastguard Worker         bSerializeToFile = false;
437*89c4ff92SAndroid Build Coastguard Worker     }
438*89c4ff92SAndroid Build Coastguard Worker     else
439*89c4ff92SAndroid Build Coastguard Worker     {
440*89c4ff92SAndroid Build Coastguard Worker         std::string timestamp = GetFileTimestamp();
441*89c4ff92SAndroid Build Coastguard Worker         if (timestamp.empty())
442*89c4ff92SAndroid Build Coastguard Worker         {
443*89c4ff92SAndroid Build Coastguard Worker             bSerializeToFile = false;
444*89c4ff92SAndroid Build Coastguard Worker         }
445*89c4ff92SAndroid Build Coastguard Worker     }
446*89c4ff92SAndroid Build Coastguard Worker     if (!bSerializeToFile && !dataCachingActive)
447*89c4ff92SAndroid Build Coastguard Worker     {
448*89c4ff92SAndroid Build Coastguard Worker         return fileName;
449*89c4ff92SAndroid Build Coastguard Worker     }
450*89c4ff92SAndroid Build Coastguard Worker 
451*89c4ff92SAndroid Build Coastguard Worker     auto serializer(armnnSerializer::ISerializer::Create());
452*89c4ff92SAndroid Build Coastguard Worker     // Serialize the Network
453*89c4ff92SAndroid Build Coastguard Worker     serializer->Serialize(network);
454*89c4ff92SAndroid Build Coastguard Worker     if (dataCachingActive)
455*89c4ff92SAndroid Build Coastguard Worker     {
456*89c4ff92SAndroid Build Coastguard Worker         std::stringstream stream;
457*89c4ff92SAndroid Build Coastguard Worker         auto serialized = serializer->SaveSerializedToStream(stream);
458*89c4ff92SAndroid Build Coastguard Worker         if (serialized)
459*89c4ff92SAndroid Build Coastguard Worker         {
460*89c4ff92SAndroid Build Coastguard Worker             std::string const serializedString{stream.str()};
461*89c4ff92SAndroid Build Coastguard Worker             std::copy(serializedString.begin(),
462*89c4ff92SAndroid Build Coastguard Worker                       serializedString.end(),
463*89c4ff92SAndroid Build Coastguard Worker                       std::back_inserter(dataCacheData));
464*89c4ff92SAndroid Build Coastguard Worker         }
465*89c4ff92SAndroid Build Coastguard Worker     }
466*89c4ff92SAndroid Build Coastguard Worker 
467*89c4ff92SAndroid Build Coastguard Worker     if (bSerializeToFile)
468*89c4ff92SAndroid Build Coastguard Worker     {
469*89c4ff92SAndroid Build Coastguard Worker         // Set the name of the output .armnn file.
470*89c4ff92SAndroid Build Coastguard Worker         fs::path dumpPath = dumpDir;
471*89c4ff92SAndroid Build Coastguard Worker         std::string timestamp = GetFileTimestamp();
472*89c4ff92SAndroid Build Coastguard Worker         fs::path tempFilePath = dumpPath / (timestamp + "_network.armnn");
473*89c4ff92SAndroid Build Coastguard Worker         fileName = tempFilePath.string();
474*89c4ff92SAndroid Build Coastguard Worker 
475*89c4ff92SAndroid Build Coastguard Worker         // Save serialized network to a file
476*89c4ff92SAndroid Build Coastguard Worker         std::ofstream serializedFile(fileName, std::ios::out | std::ios::binary);
477*89c4ff92SAndroid Build Coastguard Worker         auto serialized = serializer->SaveSerializedToStream(serializedFile);
478*89c4ff92SAndroid Build Coastguard Worker         if (!serialized)
479*89c4ff92SAndroid Build Coastguard Worker         {
480*89c4ff92SAndroid Build Coastguard Worker             VLOG(DRIVER) << "An error occurred when serializing to file %s" << fileName.c_str();
481*89c4ff92SAndroid Build Coastguard Worker         }
482*89c4ff92SAndroid Build Coastguard Worker     }
483*89c4ff92SAndroid Build Coastguard Worker     return fileName;
484*89c4ff92SAndroid Build Coastguard Worker }
485*89c4ff92SAndroid Build Coastguard Worker 
IsDynamicTensor(const armnn::TensorInfo & tensorInfo)486*89c4ff92SAndroid Build Coastguard Worker bool IsDynamicTensor(const armnn::TensorInfo& tensorInfo)
487*89c4ff92SAndroid Build Coastguard Worker {
488*89c4ff92SAndroid Build Coastguard Worker     if (tensorInfo.GetShape().GetDimensionality() == armnn::Dimensionality::NotSpecified)
489*89c4ff92SAndroid Build Coastguard Worker     {
490*89c4ff92SAndroid Build Coastguard Worker         return true;
491*89c4ff92SAndroid Build Coastguard Worker     }
492*89c4ff92SAndroid Build Coastguard Worker     // Account for the usage of the TensorShape empty constructor
493*89c4ff92SAndroid Build Coastguard Worker     if (tensorInfo.GetNumDimensions() == 0)
494*89c4ff92SAndroid Build Coastguard Worker     {
495*89c4ff92SAndroid Build Coastguard Worker         return true;
496*89c4ff92SAndroid Build Coastguard Worker     }
497*89c4ff92SAndroid Build Coastguard Worker     return !tensorInfo.GetShape().AreAllDimensionsSpecified();
498*89c4ff92SAndroid Build Coastguard Worker }
499*89c4ff92SAndroid Build Coastguard Worker 
AreDynamicTensorsSupported()500*89c4ff92SAndroid Build Coastguard Worker bool AreDynamicTensorsSupported() //TODO
501*89c4ff92SAndroid Build Coastguard Worker {
502*89c4ff92SAndroid Build Coastguard Worker     return true;
503*89c4ff92SAndroid Build Coastguard Worker }
504*89c4ff92SAndroid Build Coastguard Worker 
isQuantizedOperand(const OperandType & operandType)505*89c4ff92SAndroid Build Coastguard Worker bool isQuantizedOperand(const OperandType& operandType)
506*89c4ff92SAndroid Build Coastguard Worker {
507*89c4ff92SAndroid Build Coastguard Worker     if (operandType == OperandType::TENSOR_QUANT8_ASYMM ||
508*89c4ff92SAndroid Build Coastguard Worker         operandType == OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL ||
509*89c4ff92SAndroid Build Coastguard Worker         operandType == OperandType::TENSOR_QUANT8_SYMM ||
510*89c4ff92SAndroid Build Coastguard Worker         operandType == OperandType::TENSOR_QUANT16_SYMM ||
511*89c4ff92SAndroid Build Coastguard Worker         operandType == OperandType::TENSOR_QUANT8_ASYMM_SIGNED)
512*89c4ff92SAndroid Build Coastguard Worker     {
513*89c4ff92SAndroid Build Coastguard Worker         return true;
514*89c4ff92SAndroid Build Coastguard Worker     }
515*89c4ff92SAndroid Build Coastguard Worker     else
516*89c4ff92SAndroid Build Coastguard Worker     {
517*89c4ff92SAndroid Build Coastguard Worker         return false;
518*89c4ff92SAndroid Build Coastguard Worker     }
519*89c4ff92SAndroid Build Coastguard Worker }
520*89c4ff92SAndroid Build Coastguard Worker 
GetModelSummary(const Model & model)521*89c4ff92SAndroid Build Coastguard Worker std::string GetModelSummary(const Model& model)
522*89c4ff92SAndroid Build Coastguard Worker {
523*89c4ff92SAndroid Build Coastguard Worker     std::stringstream result;
524*89c4ff92SAndroid Build Coastguard Worker 
525*89c4ff92SAndroid Build Coastguard Worker     result << model.main.inputIndexes.size() << " input(s), "
526*89c4ff92SAndroid Build Coastguard Worker            << model.main.operations.size() << " operation(s), "
527*89c4ff92SAndroid Build Coastguard Worker            << model.main.outputIndexes.size() << " output(s), "
528*89c4ff92SAndroid Build Coastguard Worker            << model.main.operands.size() << " operand(s) "
529*89c4ff92SAndroid Build Coastguard Worker            << std::endl;
530*89c4ff92SAndroid Build Coastguard Worker 
531*89c4ff92SAndroid Build Coastguard Worker     result << "Inputs: ";
532*89c4ff92SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < model.main.inputIndexes.size(); i++)
533*89c4ff92SAndroid Build Coastguard Worker     {
534*89c4ff92SAndroid Build Coastguard Worker         result << GetOperandSummary(model.main.operands[model.main.inputIndexes[i]]) << ", ";
535*89c4ff92SAndroid Build Coastguard Worker     }
536*89c4ff92SAndroid Build Coastguard Worker     result << std::endl;
537*89c4ff92SAndroid Build Coastguard Worker 
538*89c4ff92SAndroid Build Coastguard Worker     result << "Operations: ";
539*89c4ff92SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < model.main.operations.size(); i++)
540*89c4ff92SAndroid Build Coastguard Worker     {
541*89c4ff92SAndroid Build Coastguard Worker         result << model.main.operations[i].type << ", ";
542*89c4ff92SAndroid Build Coastguard Worker     }
543*89c4ff92SAndroid Build Coastguard Worker     result << std::endl;
544*89c4ff92SAndroid Build Coastguard Worker 
545*89c4ff92SAndroid Build Coastguard Worker     result << "Outputs: ";
546*89c4ff92SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < model.main.outputIndexes.size(); i++)
547*89c4ff92SAndroid Build Coastguard Worker     {
548*89c4ff92SAndroid Build Coastguard Worker         result << GetOperandSummary(model.main.operands[model.main.outputIndexes[i]]) << ", ";
549*89c4ff92SAndroid Build Coastguard Worker     }
550*89c4ff92SAndroid Build Coastguard Worker     result << std::endl;
551*89c4ff92SAndroid Build Coastguard Worker 
552*89c4ff92SAndroid Build Coastguard Worker     return result.str();
553*89c4ff92SAndroid Build Coastguard Worker }
554*89c4ff92SAndroid Build Coastguard Worker 
GetFileTimestamp()555*89c4ff92SAndroid Build Coastguard Worker std::string GetFileTimestamp()
556*89c4ff92SAndroid Build Coastguard Worker {
557*89c4ff92SAndroid Build Coastguard Worker     // used to get a timestamp to name diagnostic files (the ArmNN serialized graph
558*89c4ff92SAndroid Build Coastguard Worker     // and getSupportedOperations.txt files)
559*89c4ff92SAndroid Build Coastguard Worker     timespec ts;
560*89c4ff92SAndroid Build Coastguard Worker     int iRet = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
561*89c4ff92SAndroid Build Coastguard Worker     std::stringstream ss;
562*89c4ff92SAndroid Build Coastguard Worker     if (iRet == 0)
563*89c4ff92SAndroid Build Coastguard Worker     {
564*89c4ff92SAndroid Build Coastguard Worker         ss << std::to_string(ts.tv_sec) << "_" << std::to_string(ts.tv_nsec);
565*89c4ff92SAndroid Build Coastguard Worker     }
566*89c4ff92SAndroid Build Coastguard Worker     else
567*89c4ff92SAndroid Build Coastguard Worker     {
568*89c4ff92SAndroid Build Coastguard Worker         VLOG(DRIVER) << "clock_gettime failed with errno " <<
569*89c4ff92SAndroid Build Coastguard Worker             std::to_string(errno).c_str() << " : " <<
570*89c4ff92SAndroid Build Coastguard Worker             std::strerror(errno);
571*89c4ff92SAndroid Build Coastguard Worker     }
572*89c4ff92SAndroid Build Coastguard Worker     return ss.str();
573*89c4ff92SAndroid Build Coastguard Worker }
574*89c4ff92SAndroid Build Coastguard Worker 
RenameExportedFiles(const std::string & existingSerializedFileName,const std::string & existingDotFileName,const std::string & dumpDir,const armnn::NetworkId networkId)575*89c4ff92SAndroid Build Coastguard Worker void RenameExportedFiles(const std::string& existingSerializedFileName,
576*89c4ff92SAndroid Build Coastguard Worker                          const std::string& existingDotFileName,
577*89c4ff92SAndroid Build Coastguard Worker                          const std::string& dumpDir,
578*89c4ff92SAndroid Build Coastguard Worker                          const armnn::NetworkId networkId)
579*89c4ff92SAndroid Build Coastguard Worker {
580*89c4ff92SAndroid Build Coastguard Worker     if (dumpDir.empty())
581*89c4ff92SAndroid Build Coastguard Worker     {
582*89c4ff92SAndroid Build Coastguard Worker         return;
583*89c4ff92SAndroid Build Coastguard Worker     }
584*89c4ff92SAndroid Build Coastguard Worker     RenameFile(existingSerializedFileName, std::string("_network.armnn"), dumpDir, networkId);
585*89c4ff92SAndroid Build Coastguard Worker     RenameFile(existingDotFileName, std::string("_networkgraph.dot"), dumpDir, networkId);
586*89c4ff92SAndroid Build Coastguard Worker }
587*89c4ff92SAndroid Build Coastguard Worker 
RenameFile(const std::string & existingName,const std::string & extension,const std::string & dumpDir,const armnn::NetworkId networkId)588*89c4ff92SAndroid Build Coastguard Worker void RenameFile(const std::string& existingName,
589*89c4ff92SAndroid Build Coastguard Worker                 const std::string& extension,
590*89c4ff92SAndroid Build Coastguard Worker                 const std::string& dumpDir,
591*89c4ff92SAndroid Build Coastguard Worker                 const armnn::NetworkId networkId)
592*89c4ff92SAndroid Build Coastguard Worker {
593*89c4ff92SAndroid Build Coastguard Worker     if (existingName.empty() || dumpDir.empty())
594*89c4ff92SAndroid Build Coastguard Worker     {
595*89c4ff92SAndroid Build Coastguard Worker         return;
596*89c4ff92SAndroid Build Coastguard Worker     }
597*89c4ff92SAndroid Build Coastguard Worker 
598*89c4ff92SAndroid Build Coastguard Worker     fs::path dumpPath = dumpDir;
599*89c4ff92SAndroid Build Coastguard Worker     const fs::path newFileName = dumpPath / (std::to_string(networkId) + extension);
600*89c4ff92SAndroid Build Coastguard Worker     int iRet = rename(existingName.c_str(), newFileName.c_str());
601*89c4ff92SAndroid Build Coastguard Worker     if (iRet != 0)
602*89c4ff92SAndroid Build Coastguard Worker     {
603*89c4ff92SAndroid Build Coastguard Worker         std::stringstream ss;
604*89c4ff92SAndroid Build Coastguard Worker         ss << "rename of [" << existingName << "] to [" << newFileName << "] failed with errno "
605*89c4ff92SAndroid Build Coastguard Worker            << std::to_string(errno) << " : " << std::strerror(errno);
606*89c4ff92SAndroid Build Coastguard Worker         VLOG(DRIVER) << ss.str().c_str();
607*89c4ff92SAndroid Build Coastguard Worker     }
608*89c4ff92SAndroid Build Coastguard Worker }
609*89c4ff92SAndroid Build Coastguard Worker 
CommitPools(std::vector<::android::nn::RunTimePoolInfo> & memPools)610*89c4ff92SAndroid Build Coastguard Worker void CommitPools(std::vector<::android::nn::RunTimePoolInfo>& memPools)
611*89c4ff92SAndroid Build Coastguard Worker {
612*89c4ff92SAndroid Build Coastguard Worker     // Commit output buffers.
613*89c4ff92SAndroid Build Coastguard Worker     // Note that we update *all* pools, even if they aren't actually used as outputs -
614*89c4ff92SAndroid Build Coastguard Worker     // this is simpler and is what the CpuExecutor does.
615*89c4ff92SAndroid Build Coastguard Worker     for (auto& pool : memPools)
616*89c4ff92SAndroid Build Coastguard Worker     {
617*89c4ff92SAndroid Build Coastguard Worker         // Type android::nn::RunTimePoolInfo has changed between Android P & Q and Android R, where
618*89c4ff92SAndroid Build Coastguard Worker         // update() has been removed and flush() added.
619*89c4ff92SAndroid Build Coastguard Worker         pool.flush();
620*89c4ff92SAndroid Build Coastguard Worker     }
621*89c4ff92SAndroid Build Coastguard Worker }
622*89c4ff92SAndroid Build Coastguard Worker } // namespace armnn_driver
623