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 std::vector<unsigned char> dimensionsSpecificity(operand.dimensions.size(),
true);
157 std::for_each(operand.dimensions.data(),
158 operand.dimensions.data() + operand.dimensions.size(),
159 [&](
const unsigned int val)
163 dimensionsSpecificity[count] = false;
169 operand.dimensions.data(),
170 reinterpret_cast<const bool *
>(dimensionsSpecificity.data()));
178 const auto& perAxisQuantParams = std::get<Operand::SymmPerChannelQuantParams>(operand.extraParams);
180 ret.SetQuantizationScales(perAxisQuantParams.scales);
181 ret.SetQuantizationDim(MakeOptional<unsigned int>(perAxisQuantParams.channelDim));
185 ret.SetQuantizationScale(operand.scale);
186 ret.SetQuantizationOffset(operand.zeroPoint);
193 std::stringstream ss;
194 ss <<
"operand dimensions: [ ";
195 for (
unsigned int i = 0; i < operand.dimensions.size(); ++i)
197 ss << operand.dimensions[i] <<
" ";
199 ss <<
"] operand type: " << operand.type;
203 template <
typename TensorType>
205 unsigned int elementIndex,
206 std::ofstream& fileStream);
210 template <
typename TensorType,
typename ElementType,
typename Pr
intableType = ElementType>
211 void DumpTensorElement(
const TensorType& tensor,
unsigned int elementIndex, std::ofstream& fileStream)
213 const ElementType* elements =
reinterpret_cast<const ElementType*
>(tensor.GetMemoryArea());
214 fileStream << static_cast<PrintableType>(elements[elementIndex]) <<
" ";
218 template <
typename TensorType>
220 const std::string& requestName,
221 const std::string& tensorName,
222 const TensorType& tensor)
225 fs::path dumpPath = dumpDir;
226 const fs::path fileName = dumpPath / (requestName +
"_" + tensorName +
".dump");
228 std::ofstream fileStream;
229 fileStream.open(fileName.c_str(), std::ofstream::out | std::ofstream::trunc);
231 if (!fileStream.good())
233 VLOG(DRIVER) <<
"Could not open file %s for writing" << fileName.c_str();
239 switch (tensor.GetDataType())
243 dumpElementFunction = &DumpTensorElement<TensorType, float>;
248 dumpElementFunction = &DumpTensorElement<TensorType, uint8_t, uint32_t>;
253 dumpElementFunction = &DumpTensorElement<TensorType, int32_t>;
258 dumpElementFunction = &DumpTensorElement<TensorType, armnn::Half>;
263 dumpElementFunction = &DumpTensorElement<TensorType, int8_t, int32_t>;
268 dumpElementFunction = &DumpTensorElement<TensorType, bool>;
273 dumpElementFunction =
nullptr;
277 if (dumpElementFunction !=
nullptr)
279 const unsigned int numDimensions = tensor.GetNumDimensions();
284 fileStream <<
"Cannot dump tensor elements: not all dimensions are specified" << std::endl;
287 fileStream <<
"# Number of elements " << tensor.
GetNumElements() << std::endl;
289 if (numDimensions == 0)
291 fileStream <<
"# Shape []" << std::endl;
294 fileStream <<
"# Shape [" << shape[0];
295 for (
unsigned int d = 1; d < numDimensions; ++d)
297 fileStream <<
"," << shape[d];
299 fileStream <<
"]" << std::endl;
300 fileStream <<
"Each line contains the data of each of the elements of dimension0. In NCHW and NHWC, each line"
301 " will be a batch" << std::endl << std::endl;
305 unsigned int split = 1;
306 if (numDimensions == 1)
312 for (
unsigned int i = 1; i < numDimensions; ++i)
319 for (
unsigned int elementIndex = 0; elementIndex < tensor.GetNumElements(); ++elementIndex)
321 (*dumpElementFunction)(tensor, elementIndex, fileStream);
323 if ( (elementIndex + 1) % split == 0 )
325 fileStream << std::endl;
328 fileStream << std::endl;
332 fileStream <<
"Cannot dump tensor elements: Unsupported data type "
333 <<
static_cast<unsigned int>(tensor.GetDataType()) << std::endl;
336 if (!fileStream.good())
338 VLOG(DRIVER) <<
"An error occurred when writing to file %s" << fileName.c_str();
342 template void DumpTensor<armnn::ConstTensor>(
const std::string& dumpDir,
343 const std::string& requestName,
344 const std::string& tensorName,
347 template void DumpTensor<armnn::Tensor>(
const std::string& dumpDir,
348 const std::string& requestName,
349 const std::string& tensorName,
353 const std::string& dumpDir,
358 if (!gpuProfilingEnabled)
369 if (profiler ==
nullptr)
375 fs::path dumpPath = dumpDir;
376 const fs::path fileName = dumpPath / (std::to_string(networkId) +
"_profiling.json");
379 std::ofstream fileStream;
380 fileStream.open(fileName.c_str(), std::ofstream::out | std::ofstream::trunc);
382 if (!fileStream.good())
384 VLOG(DRIVER) <<
"Could not open file %s for writing" << fileName.c_str();
389 profiler->
Print(fileStream);
393 const std::string& dumpDir)
395 std::string fileName;
403 if (timestamp.empty())
409 fs::path dumpPath = dumpDir;
410 fs::path tempFilePath = dumpPath / (timestamp +
"_networkgraph.dot");
411 fileName = tempFilePath.string();
413 VLOG(DRIVER) <<
"Exporting the optimized network graph to file: %s" << fileName.c_str();
416 std::ofstream fileStream;
417 fileStream.open(fileName, std::ofstream::out | std::ofstream::trunc);
419 if (!fileStream.good())
421 VLOG(DRIVER) <<
"Could not open file %s for writing" << fileName.c_str();
427 VLOG(DRIVER) <<
"An error occurred when writing to file %s" << fileName.c_str();
433 const std::string& dumpDir,
434 std::vector<uint8_t>& dataCacheData,
435 bool dataCachingActive)
437 std::string fileName;
438 bool bSerializeToFile =
true;
441 bSerializeToFile =
false;
446 if (timestamp.empty())
448 bSerializeToFile =
false;
451 if (!bSerializeToFile && !dataCachingActive)
459 if (dataCachingActive)
461 std::stringstream stream;
462 auto serialized =
serializer->SaveSerializedToStream(stream);
465 std::string
const serializedString{stream.str()};
466 std::copy(serializedString.begin(),
467 serializedString.end(),
468 std::back_inserter(dataCacheData));
472 if (bSerializeToFile)
475 fs::path dumpPath = dumpDir;
477 fs::path tempFilePath = dumpPath / (timestamp +
"_network.armnn");
478 fileName = tempFilePath.string();
481 std::ofstream serializedFile(fileName, std::ios::out | std::ios::binary);
482 auto serialized =
serializer->SaveSerializedToStream(serializedFile);
485 VLOG(DRIVER) <<
"An error occurred when serializing to file %s" << fileName.c_str();
512 if (operandType == OperandType::TENSOR_QUANT8_ASYMM ||
513 operandType == OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL ||
514 operandType == OperandType::TENSOR_QUANT8_SYMM ||
515 operandType == OperandType::TENSOR_QUANT16_SYMM ||
516 operandType == OperandType::TENSOR_QUANT8_ASYMM_SIGNED)
528 std::stringstream result;
530 result << model.main.inputIndexes.size() <<
" input(s), "
531 << model.main.operations.size() <<
" operation(s), "
532 << model.main.outputIndexes.size() <<
" output(s), "
533 << model.main.operands.size() <<
" operand(s) "
536 result <<
"Inputs: ";
537 for (uint32_t i = 0; i < model.main.inputIndexes.size(); i++)
539 result <<
GetOperandSummary(model.main.operands[model.main.inputIndexes[i]]) <<
", ";
543 result <<
"Operations: ";
544 for (uint32_t i = 0; i < model.main.operations.size(); i++)
546 result << model.main.operations[i].type <<
", ";
550 result <<
"Outputs: ";
551 for (uint32_t i = 0; i < model.main.outputIndexes.size(); i++)
553 result <<
GetOperandSummary(model.main.operands[model.main.outputIndexes[i]]) <<
", ";
565 int iRet = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
566 std::stringstream ss;
569 ss << std::to_string(ts.tv_sec) <<
"_" << std::to_string(ts.tv_nsec);
573 VLOG(DRIVER) <<
"clock_gettime failed with errno " <<
574 std::to_string(errno).c_str() <<
" : " <<
575 std::strerror(errno);
581 const std::string& existingDotFileName,
582 const std::string& dumpDir,
589 RenameFile(existingSerializedFileName, std::string(
"_network.armnn"), dumpDir, networkId);
590 RenameFile(existingDotFileName, std::string(
"_networkgraph.dot"), dumpDir, networkId);
594 const std::string& extension,
595 const std::string& dumpDir,
598 if (existingName.empty() || dumpDir.empty())
603 fs::path dumpPath = dumpDir;
604 const fs::path newFileName = dumpPath / (std::to_string(networkId) + extension);
605 int iRet = rename(existingName.c_str(), newFileName.c_str());
608 std::stringstream ss;
609 ss <<
"rename of [" << existingName <<
"] to [" << newFileName <<
"] failed with errno "
610 << std::to_string(errno) <<
" : " << std::strerror(errno);
611 VLOG(DRIVER) << ss.str().c_str();
615 void CommitPools(std::vector<::android::nn::RunTimePoolInfo>& memPools)
620 for (
auto& pool : memPools)