6 #define LOG_TAG "arm-armnn-sl"
15 #include <ghc/filesystem.hpp>
16 namespace fs = ghc::filesystem;
17 #include <half/half.hpp>
30 using Half = half_float::half;
61 VLOG(DRIVER) <<
"Unknown armnn::DataType for swizzling";
66 void*
GetMemoryFromPool(DataLocation location,
const std::vector<android::nn::RunTimePoolInfo>& memPools)
69 assert(location.poolIndex < memPools.size());
71 const android::nn::RunTimePoolInfo& memPool = memPools[location.poolIndex];
72 uint8_t* memPoolBuffer = memPool.getBuffer();
73 uint8_t* memory = memPoolBuffer + location.offset;
80 auto ptrMemory = std::visit([](std::variant<const void*, void*>&& memory)
82 if (std::holds_alternative<const void*>(memory))
84 auto ptr = std::get<const void*>(memory);
85 auto ptrMemory =
static_cast<const uint8_t*
>(ptr);
86 return const_cast<uint8_t*
>(ptrMemory);
90 auto ptr = std::get<void*>(memory);
91 return static_cast<uint8_t*
>(ptr);
93 }, requestArg.location.pointer);
99 using namespace armnn;
100 bool perChannel =
false;
101 bool isScalar =
false;
104 switch (operand.type)
106 case OperandType::TENSOR_BOOL8:
109 case OperandType::TENSOR_FLOAT32:
112 case OperandType::TENSOR_FLOAT16:
115 case OperandType::TENSOR_QUANT8_ASYMM:
118 case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
121 case OperandType::TENSOR_QUANT8_SYMM:
124 case OperandType::TENSOR_QUANT16_SYMM:
127 case OperandType::TENSOR_INT32:
130 case OperandType::INT32:
134 case OperandType::TENSOR_QUANT8_ASYMM_SIGNED:
148 if (operand.dimensions.size() == 0)
150 TensorShape tensorShape(Dimensionality::NotSpecified);
155 bool dimensionsSpecificity[5] = {
true,
true,
true,
true,
true };
157 std::for_each(operand.dimensions.data(),
158 operand.dimensions.data() + operand.dimensions.size(),
159 [&](
const unsigned int val)
163 dimensionsSpecificity[count] = false;
168 TensorShape tensorShape(operand.dimensions.size(), operand.dimensions.data(), dimensionsSpecificity);
176 const auto& perAxisQuantParams = std::get<Operand::SymmPerChannelQuantParams>(operand.extraParams);
178 ret.SetQuantizationScales(perAxisQuantParams.scales);
179 ret.SetQuantizationDim(MakeOptional<unsigned int>(perAxisQuantParams.channelDim));
183 ret.SetQuantizationScale(operand.scale);
184 ret.SetQuantizationOffset(operand.zeroPoint);
191 std::stringstream ss;
192 ss <<
"operand dimensions: [ ";
193 for (
unsigned int i = 0; i < operand.dimensions.size(); ++i)
195 ss << operand.dimensions[i] <<
" ";
197 ss <<
"] operand type: " << operand.type;
201 template <
typename TensorType>
203 unsigned int elementIndex,
204 std::ofstream& fileStream);
208 template <
typename TensorType,
typename ElementType,
typename Pr
intableType = ElementType>
209 void DumpTensorElement(
const TensorType& tensor,
unsigned int elementIndex, std::ofstream& fileStream)
211 const ElementType* elements =
reinterpret_cast<const ElementType*
>(tensor.GetMemoryArea());
212 fileStream << static_cast<PrintableType>(elements[elementIndex]) <<
" ";
216 template <
typename TensorType>
218 const std::string& requestName,
219 const std::string& tensorName,
220 const TensorType& tensor)
223 fs::path dumpPath = dumpDir;
224 const fs::path fileName = dumpPath / (requestName +
"_" + tensorName +
".dump");
226 std::ofstream fileStream;
227 fileStream.open(fileName.c_str(), std::ofstream::out | std::ofstream::trunc);
229 if (!fileStream.good())
231 VLOG(DRIVER) <<
"Could not open file %s for writing" << fileName.c_str();
237 switch (tensor.GetDataType())
241 dumpElementFunction = &DumpTensorElement<TensorType, float>;
246 dumpElementFunction = &DumpTensorElement<TensorType, uint8_t, uint32_t>;
251 dumpElementFunction = &DumpTensorElement<TensorType, int32_t>;
256 dumpElementFunction = &DumpTensorElement<TensorType, armnn::Half>;
261 dumpElementFunction = &DumpTensorElement<TensorType, int8_t, int32_t>;
266 dumpElementFunction = &DumpTensorElement<TensorType, bool>;
271 dumpElementFunction =
nullptr;
275 if (dumpElementFunction !=
nullptr)
277 const unsigned int numDimensions = tensor.GetNumDimensions();
282 fileStream <<
"Cannot dump tensor elements: not all dimensions are specified" << std::endl;
285 fileStream <<
"# Number of elements " << tensor.
GetNumElements() << std::endl;
287 if (numDimensions == 0)
289 fileStream <<
"# Shape []" << std::endl;
292 fileStream <<
"# Shape [" << shape[0];
293 for (
unsigned int d = 1; d < numDimensions; ++d)
295 fileStream <<
"," << shape[d];
297 fileStream <<
"]" << std::endl;
298 fileStream <<
"Each line contains the data of each of the elements of dimension0. In NCHW and NHWC, each line"
299 " will be a batch" << std::endl << std::endl;
303 unsigned int split = 1;
304 if (numDimensions == 1)
310 for (
unsigned int i = 1; i < numDimensions; ++i)
317 for (
unsigned int elementIndex = 0; elementIndex < tensor.GetNumElements(); ++elementIndex)
319 (*dumpElementFunction)(tensor, elementIndex, fileStream);
321 if ( (elementIndex + 1) % split == 0 )
323 fileStream << std::endl;
326 fileStream << std::endl;
330 fileStream <<
"Cannot dump tensor elements: Unsupported data type "
331 <<
static_cast<unsigned int>(tensor.GetDataType()) << std::endl;
334 if (!fileStream.good())
336 VLOG(DRIVER) <<
"An error occurred when writing to file %s" << fileName.c_str();
340 template void DumpTensor<armnn::ConstTensor>(
const std::string& dumpDir,
341 const std::string& requestName,
342 const std::string& tensorName,
345 template void DumpTensor<armnn::Tensor>(
const std::string& dumpDir,
346 const std::string& requestName,
347 const std::string& tensorName,
351 const std::string& dumpDir,
356 if (!gpuProfilingEnabled)
370 fs::path dumpPath = dumpDir;
371 const fs::path fileName = dumpPath / (std::to_string(networkId) +
"_profiling.json");
374 std::ofstream fileStream;
375 fileStream.open(fileName.c_str(), std::ofstream::out | std::ofstream::trunc);
377 if (!fileStream.good())
379 VLOG(DRIVER) <<
"Could not open file %s for writing" << fileName.c_str();
384 profiler->
Print(fileStream);
388 const std::string& dumpDir)
390 std::string fileName;
398 if (timestamp.empty())
404 fs::path dumpPath = dumpDir;
405 fs::path tempFilePath = dumpPath / (timestamp +
"_networkgraph.dot");
406 fileName = tempFilePath.string();
408 VLOG(DRIVER) <<
"Exporting the optimized network graph to file: %s" << fileName.c_str();
411 std::ofstream fileStream;
412 fileStream.open(fileName, std::ofstream::out | std::ofstream::trunc);
414 if (!fileStream.good())
416 VLOG(DRIVER) <<
"Could not open file %s for writing" << fileName.c_str();
422 VLOG(DRIVER) <<
"An error occurred when writing to file %s" << fileName.c_str();
428 const std::string& dumpDir,
429 std::vector<uint8_t>& dataCacheData,
430 bool dataCachingActive)
432 std::string fileName;
433 bool bSerializeToFile =
true;
436 bSerializeToFile =
false;
441 if (timestamp.empty())
443 bSerializeToFile =
false;
446 if (!bSerializeToFile && !dataCachingActive)
454 if (dataCachingActive)
456 std::stringstream stream;
457 auto serialized =
serializer->SaveSerializedToStream(stream);
460 std::string
const serializedString{stream.str()};
461 std::copy(serializedString.begin(),
462 serializedString.end(),
463 std::back_inserter(dataCacheData));
467 if (bSerializeToFile)
470 fs::path dumpPath = dumpDir;
472 fs::path tempFilePath = dumpPath / (timestamp +
"_network.armnn");
473 fileName = tempFilePath.string();
476 std::ofstream serializedFile(fileName, std::ios::out | std::ios::binary);
477 auto serialized =
serializer->SaveSerializedToStream(serializedFile);
480 VLOG(DRIVER) <<
"An error occurred when serializing to file %s" << fileName.c_str();
507 if (operandType == OperandType::TENSOR_QUANT8_ASYMM ||
508 operandType == OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL ||
509 operandType == OperandType::TENSOR_QUANT8_SYMM ||
510 operandType == OperandType::TENSOR_QUANT16_SYMM ||
511 operandType == OperandType::TENSOR_QUANT8_ASYMM_SIGNED)
523 std::stringstream result;
525 result << model.main.inputIndexes.size() <<
" input(s), "
526 << model.main.operations.size() <<
" operation(s), "
527 << model.main.outputIndexes.size() <<
" output(s), "
528 << model.main.operands.size() <<
" operand(s) "
531 result <<
"Inputs: ";
532 for (uint32_t i = 0; i < model.main.inputIndexes.size(); i++)
534 result <<
GetOperandSummary(model.main.operands[model.main.inputIndexes[i]]) <<
", ";
538 result <<
"Operations: ";
539 for (uint32_t i = 0; i < model.main.operations.size(); i++)
541 result << model.main.operations[i].type <<
", ";
545 result <<
"Outputs: ";
546 for (uint32_t i = 0; i < model.main.outputIndexes.size(); i++)
548 result <<
GetOperandSummary(model.main.operands[model.main.outputIndexes[i]]) <<
", ";
560 int iRet = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
561 std::stringstream ss;
564 ss << std::to_string(ts.tv_sec) <<
"_" << std::to_string(ts.tv_nsec);
568 VLOG(DRIVER) <<
"clock_gettime failed with errno " <<
569 std::to_string(errno).c_str() <<
" : " <<
570 std::strerror(errno);
576 const std::string& existingDotFileName,
577 const std::string& dumpDir,
584 RenameFile(existingSerializedFileName, std::string(
"_network.armnn"), dumpDir, networkId);
585 RenameFile(existingDotFileName, std::string(
"_networkgraph.dot"), dumpDir, networkId);
589 const std::string& extension,
590 const std::string& dumpDir,
593 if (existingName.empty() || dumpDir.empty())
598 fs::path dumpPath = dumpDir;
599 const fs::path newFileName = dumpPath / (std::to_string(networkId) + extension);
600 int iRet = rename(existingName.c_str(), newFileName.c_str());
603 std::stringstream ss;
604 ss <<
"rename of [" << existingName <<
"] to [" << newFileName <<
"] failed with errno "
605 << std::to_string(errno) <<
" : " << std::strerror(errno);
606 VLOG(DRIVER) << ss.str().c_str();
610 void CommitPools(std::vector<::android::nn::RunTimePoolInfo>& memPools)
615 for (
auto& pool : memPools)