Add basic gna2 model dump function (#4034)
* [GNA] Add gna model dumping * [GNA] Modify debug layout, add timestamp, fix compound bias dump * [GNA] Move data dump to another file * [GNA] Create model data dump file only when needed
This commit is contained in:
parent
0d0f06a2e4
commit
38d16e24e9
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2018-2020 Intel Corporation
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
@ -18,9 +18,10 @@
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
|
||||
std::string getLayerType(Gna2OperationType kind) {
|
||||
switch (kind) {
|
||||
std::string GetLayerType(Gna2OperationType type) {
|
||||
switch (type) {
|
||||
case Gna2OperationTypeFullyConnectedAffine: return "Gna2OperationTypeFullyConnectedAffine";
|
||||
case Gna2OperationTypeElementWiseAffine: return "Gna2OperationTypeElementWiseAffine";
|
||||
case Gna2OperationTypeRecurrent: return "Gna2OperationTypeRecurrent";
|
||||
@ -49,6 +50,7 @@ std::string GetSimpleString(Gna2Shape shape) {
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool NextElement(T & elementIndex, const Gna2Shape& total) {
|
||||
if (total.NumberOfDimensions == 0) return false;
|
||||
@ -85,6 +87,8 @@ int32_t GetValue(const Gna2Tensor& tensor, const T & elementIndex) {
|
||||
intValue = (reinterpret_cast<int32_t *>(tensor.Data)[linearIndex]);
|
||||
} else if (tensor.Type == Gna2DataTypeInt16) {
|
||||
intValue = reinterpret_cast<int16_t *>(tensor.Data)[linearIndex];
|
||||
} else {
|
||||
intValue = reinterpret_cast<int8_t*>(tensor.Data)[linearIndex];
|
||||
}
|
||||
return intValue;
|
||||
}
|
||||
@ -97,7 +101,7 @@ void WriteInputAndOutputTextGNAImpl(const Gna2Model & gnaModel, const std::strin
|
||||
const auto & intputTensor = *operation.Operands[InOpIdx];
|
||||
|
||||
out_file_name << std::setfill('0') << std::setw(2) << i << "_"
|
||||
<< getLayerType(operation.Type)
|
||||
<< GetLayerType(operation.Type)
|
||||
<< "-" << GetSimpleString(intputTensor.Shape)
|
||||
<< "-" << GetSimpleString(outputTensor.Shape);
|
||||
|
||||
@ -158,4 +162,242 @@ void WriteInputAndOutputTextGNAImpl(const Gna2Model & gnaModel, const std::strin
|
||||
}
|
||||
}
|
||||
|
||||
static std::string GetOperandType(Gna2DataType type) {
|
||||
const std::map<Gna2DataType, std::string> operandTypeMap = {
|
||||
{Gna2DataTypeNone, "Gna2DataTypeNone"},
|
||||
{Gna2DataTypeBoolean, "Gna2DataTypeBoolean"},
|
||||
{Gna2DataTypeInt4, "Gna2DataTypeInt4"},
|
||||
{Gna2DataTypeInt8, "Gna2DataTypeInt8"},
|
||||
{Gna2DataTypeInt16, "Gna2DataTypeInt16"},
|
||||
{Gna2DataTypeInt32, "Gna2DataTypeInt32"},
|
||||
{Gna2DataTypeUint4, "Gna2DataTypeUint4"},
|
||||
{Gna2DataTypeUint8, "Gna2DataTypeUint8"},
|
||||
{Gna2DataTypeUint16, "Gna2DataTypeUint16"},
|
||||
{Gna2DataTypeUint32, "Gna2DataTypeUint32"},
|
||||
{Gna2DataTypeUint64, "Gna2DataTypeUint64"},
|
||||
{Gna2DataTypeCompoundBias, "Gna2DataTypeCompoundBias"},
|
||||
{Gna2DataTypePwlSegment, "Gna2DataTypePwlSegment"},
|
||||
{Gna2DataTypeWeightScaleFactor, "Gna2DataTypeWeightScaleFactor"}
|
||||
};
|
||||
return operandTypeMap.find(type)->second;
|
||||
}
|
||||
|
||||
static std::vector<std::string> GetOperandNames(Gna2OperationType type) {
|
||||
const std::map<Gna2OperationType, std::vector<std::string>> operationOperandNamesMap = {
|
||||
{Gna2OperationTypeConvolution, {"inputs", "outputs", "filters", "biases", "activationFunction"}},
|
||||
{Gna2OperationTypeCopy, {"inputs", "outputs"}},
|
||||
{Gna2OperationTypeFullyConnectedAffine, {"inputs", "outputs", "weights", "biases", "activationFunction", "weightScaleFactors"}},
|
||||
{Gna2OperationTypeElementWiseAffine, {"inputs", "outputs", "weights", "biases", "activationFunction"}},
|
||||
{Gna2OperationTypeGmm, {"inputs", "outputs", "means/interleaved", "inverseCovariances", "constants"}},
|
||||
{Gna2OperationTypeRecurrent, {"inputs", "outputs", "weights", "biases", "activationFunction"}},
|
||||
{Gna2OperationTypeTransposition, {"inputs", "outputs"}}
|
||||
};
|
||||
return operationOperandNamesMap.find(type)->second;
|
||||
}
|
||||
|
||||
static std::vector<std::string> GetParamaterNames(Gna2OperationType type) {
|
||||
const std::map<Gna2OperationType, std::vector<std::string>> operationParamaterNamesMap = {
|
||||
{Gna2OperationTypeConvolution, {"convolutionStride", "biasMode", "poolingMode", "poolingWindow", "poolingStride", "zeroPadding"}},
|
||||
{Gna2OperationTypeCopy, {"shape (sub-tensor shape)"}},
|
||||
{Gna2OperationTypeFullyConnectedAffine, {"biasMode", "biasVectorIndex"}},
|
||||
{Gna2OperationTypeGmm, {"maximumScore"}},
|
||||
{Gna2OperationTypeRecurrent, {"delay"}}
|
||||
};
|
||||
return operationParamaterNamesMap.find(type)->second;
|
||||
}
|
||||
|
||||
static std::string GetBiasMode(Gna2BiasMode mode) {
|
||||
const std::map<Gna2BiasMode, std::string> biasModeMap = {
|
||||
{Gna2BiasModeDefault, "Gna2BiasModeDefault"},
|
||||
{Gna2BiasModePerStride, "Gna2BiasModePerStride"},
|
||||
{Gna2BiasModeGrouping, "Gna2BiasModeGrouping"}
|
||||
};
|
||||
return biasModeMap.find(mode)->second;
|
||||
}
|
||||
|
||||
static std::string GetPoolingMode(Gna2PoolingMode mode) {
|
||||
const std::map<Gna2PoolingMode, std::string> poolingModeMap = {
|
||||
{Gna2PoolingModeDisabled, "Gna2PoolingModeDisabled"},
|
||||
{Gna2PoolingModeMax, "Gna2PoolingModeMax"},
|
||||
{Gna2PoolingModeSum, "Gna2PoolingModeSum"}
|
||||
};
|
||||
return poolingModeMap.find(mode)->second;
|
||||
}
|
||||
|
||||
static void DumpShape(std::ostream& dumpFile, Gna2Shape* shape, const std::string paramName) {
|
||||
dumpFile << "\tParameter name: " << paramName << ", ";
|
||||
dumpFile << "parameter type: Gna2Shape\n";
|
||||
dumpFile << "\t\tNumber of dimensions: " << shape->NumberOfDimensions;
|
||||
dumpFile << "\n\t\tDimensions: [";
|
||||
for (uint32_t i = 0; i < shape->NumberOfDimensions; i++) {
|
||||
dumpFile << std::setw(8) << shape->Dimensions[i];
|
||||
}
|
||||
dumpFile << "]\n";
|
||||
}
|
||||
|
||||
static void DumpConvolutionParameters(std::ostream& dumpFile, void** parameters, size_t knownParamCount, const std::vector<std::string> paramNames) {
|
||||
size_t i = 0;
|
||||
|
||||
while (i < knownParamCount) {
|
||||
if (i == ConvStrideParamIdx || i == PoolWinParamIdx || i == PoolStrideParamIdx || i == ZeroPaddingParamIdx) {
|
||||
Gna2Shape* shape = reinterpret_cast<Gna2Shape*>(parameters[i]);
|
||||
if (shape != nullptr)
|
||||
DumpShape(dumpFile, shape, paramNames[i]);
|
||||
} else if (i == BiasModeCnnParamIdx) {
|
||||
Gna2BiasMode* biasMode = reinterpret_cast<Gna2BiasMode*>(parameters[i]);
|
||||
if (biasMode != nullptr)
|
||||
dumpFile << "\tParameter name: " << paramNames[i] << ", value: " << GetBiasMode(*biasMode) << "\n";
|
||||
} else {
|
||||
Gna2PoolingMode* poolingMode = reinterpret_cast<Gna2PoolingMode*>(parameters[i]);
|
||||
if (poolingMode != nullptr)
|
||||
dumpFile << "\tParameter name: " << paramNames[i] << ", value: " << GetPoolingMode(*poolingMode) << "\n";
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpCopyParameters(std::ostream& dumpFile, void** parameters, size_t knownParamCount, const std::vector<std::string> paramNames) {
|
||||
Gna2Shape* subTensorShape = reinterpret_cast<Gna2Shape*>(parameters[CopyShapeParamIdx]);
|
||||
DumpShape(dumpFile, subTensorShape, paramNames[CopyShapeParamIdx]);
|
||||
}
|
||||
|
||||
static void DumpFCAffineParameters(std::ostream& dumpFile, void** parameters, size_t knownParamCount, const std::vector<std::string> paramNames) {
|
||||
size_t i = 0;
|
||||
|
||||
while (i < knownParamCount) {
|
||||
if (i == BiasModeFCAffineParamIdx) {
|
||||
Gna2BiasMode* biasMode = reinterpret_cast<Gna2BiasMode*>(parameters[BiasModeFCAffineParamIdx]);
|
||||
if (biasMode != nullptr)
|
||||
dumpFile << "\tParameter name: " << paramNames[i] << ", value: " << GetBiasMode(*biasMode) << "\n";
|
||||
} else {
|
||||
uint32_t* biasVectorIndex = reinterpret_cast<uint32_t*>(parameters[BiasModeFCAffineParamIdx]);
|
||||
if (biasVectorIndex != nullptr)
|
||||
dumpFile << "\tParameter name: " << paramNames[i] << ", value: " << *biasVectorIndex << "\n";
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpIntParameter(std::ostream& dumpFile, void** parameters, size_t knownParamCount, const std::vector<std::string> paramNames) {
|
||||
uint32_t* param = reinterpret_cast<uint32_t*>(parameters[0]);
|
||||
if (param != nullptr)
|
||||
dumpFile << "\tParameter name: " << paramNames[0] << ", value: " << *param << "\n";
|
||||
}
|
||||
|
||||
typedef void (*dumpParamaters) (std::ostream&, void**, size_t, const std::vector<std::string>);
|
||||
|
||||
static dumpParamaters GetParamDumpFunc(Gna2OperationType type) {
|
||||
static const std::map<Gna2OperationType, dumpParamaters> dumpParamMap = {
|
||||
{Gna2OperationTypeConvolution, DumpConvolutionParameters},
|
||||
{Gna2OperationTypeCopy, DumpCopyParameters},
|
||||
{Gna2OperationTypeFullyConnectedAffine, DumpFCAffineParameters},
|
||||
{Gna2OperationTypeGmm, DumpIntParameter},
|
||||
{Gna2OperationTypeRecurrent, DumpIntParameter}
|
||||
};
|
||||
return dumpParamMap.find(type) != dumpParamMap.end() ? dumpParamMap.find(type)->second : nullptr;
|
||||
}
|
||||
|
||||
static void DumpPwl(std::ostream& dumpFile, const Gna2Tensor& activation) {
|
||||
const Gna2PwlSegment* const segments = static_cast<Gna2PwlSegment*>(activation.Data);
|
||||
const uint32_t numberOfSegments = activation.Shape.Dimensions[0];
|
||||
|
||||
for (uint32_t k = 0; k < numberOfSegments; k++) {
|
||||
uint32_t scale = ((segments[k].xBase & 3) + 1) * 8;
|
||||
uint64_t factor = 1ULL << scale;
|
||||
int32_t B = segments[k].xBase & 0xfffffffc;
|
||||
double a = static_cast<double>(segments[k].Slope) / factor;
|
||||
double b = static_cast<double>(segments[k].yBase) - ((static_cast<double>(B) * segments[k].Slope) / factor);
|
||||
|
||||
dumpFile << "\t\tBase value for input (B) : " << B << "\n";
|
||||
dumpFile << "\t\tBase value for output (b) : " << segments[k].yBase << "\n";
|
||||
dumpFile << "\t\tSegment slope (S): " << segments[k].Slope << "\n";
|
||||
dumpFile << "\t\tShift (scale) : " << scale << "\n";
|
||||
dumpFile << "\t\ty = ax + b: a = " << a << ", b = " << b;
|
||||
if (segments[k].Slope != 0) {
|
||||
double x0 = static_cast<double>(B) - ((static_cast<double>(segments[k].yBase) * factor) / segments[k].Slope);
|
||||
dumpFile << ", x0 = " << x0;
|
||||
}
|
||||
dumpFile << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpCompoundBias(std::ostream& dumpFile, const Gna2Tensor& tensor) {
|
||||
auto i = 0;
|
||||
|
||||
while (i < tensor.Shape.Dimensions[0]) {
|
||||
const Gna2CompoundBias* const bias = static_cast<Gna2CompoundBias*>(tensor.Data) + i;
|
||||
dumpFile << "\t\tBias for row " << i << " : " << bias->Bias << ", multiplier: " << unsigned(bias->Multiplier) << "\n";
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpCharArray(std::ostream& dumpFile, const char *carray, size_t count) {
|
||||
auto i = 0;
|
||||
while (*(carray + i) != 0 && i < count) {
|
||||
dumpFile << *(carray + i) << " ";
|
||||
i++;
|
||||
}
|
||||
dumpFile << "\n";
|
||||
}
|
||||
|
||||
void DumpGna2Model(const Gna2Model& gnaModel, const std::string dumpFolderNameGNA, bool dumpData) {
|
||||
std::stringstream dumpFileName;
|
||||
uint32_t opsNo = gnaModel.NumberOfOperations;
|
||||
std::time_t currTime = std::time(nullptr);
|
||||
|
||||
dumpFileName << dumpFolderNameGNA << "Gna2ModelDebugDump_" << opsNo << "_layer_" << std::put_time(std::localtime(&currTime), "%Y%m%d%H%M%S");
|
||||
|
||||
std::ofstream dumpFile(dumpFileName.str() + ".txt", std::ios::out);
|
||||
|
||||
dumpFile << "Layers (operations) count: " << opsNo << "\n";
|
||||
|
||||
for (uint32_t i = 0; i < opsNo; i++) {
|
||||
const auto& operation = gnaModel.Operations[i];
|
||||
|
||||
dumpFile << "------------------------------------------------------------------------\n\n";
|
||||
|
||||
dumpFile << "Layer (operation): " << i << "\n";
|
||||
dumpFile << "Layer (operation) type: " << GetLayerType(operation.Type) << "\n";
|
||||
dumpFile << "Number of possible operands: " << operation.NumberOfOperands << "\n";
|
||||
|
||||
for (uint32_t j = 0; j < operation.NumberOfOperands; j++) {
|
||||
if (operation.Operands[j] == nullptr) {
|
||||
dumpFile << "\tOperand " << j << " == nullptr\n";
|
||||
continue;
|
||||
}
|
||||
const auto& operand = *operation.Operands[j];
|
||||
dumpFile << "\tOperand " << j << " (" << GetOperandNames(operation.Type)[j] << ")"
|
||||
<< " type: " << GetOperandType(operand.Type) <<
|
||||
" shape: " << GetSimpleString(operand.Shape) <<
|
||||
" layout: ";
|
||||
|
||||
DumpCharArray(dumpFile, operand.Layout, GNA2_SHAPE_MAXIMUM_NUMBER_OF_DIMENSIONS);
|
||||
|
||||
if (operand.Type == Gna2DataTypePwlSegment) {
|
||||
DumpPwl(dumpFile, operand);
|
||||
} else if (operand.Type == Gna2DataTypeCompoundBias) {
|
||||
DumpCompoundBias(dumpFile, operand);
|
||||
} else if (dumpData) {
|
||||
std::ofstream datFile(dumpFileName.str() + ".dat", std::ios::out);
|
||||
std::vector<uint32_t> elementIndex(operand.Shape.NumberOfDimensions);
|
||||
|
||||
datFile << "Layer " << i << ", type " << GetLayerType(operation.Type) <<
|
||||
", operand " << j << " - " << GetOperandNames(operation.Type)[j] << "\n";
|
||||
|
||||
do {
|
||||
int32_t value = GetValue(operand, elementIndex);
|
||||
datFile << value << "\n";
|
||||
} while (NextElement(elementIndex, operand.Shape));
|
||||
}
|
||||
}
|
||||
|
||||
dumpFile << "Parameters: \n";
|
||||
|
||||
if (operation.NumberOfParameters > 0 && GetParamDumpFunc(operation.Type) != nullptr) {
|
||||
std::vector<std::string> paramNames = GetParamaterNames(operation.Type);
|
||||
size_t knownParamCount = operation.NumberOfParameters <= paramNames.size() ? operation.NumberOfParameters : paramNames.size();
|
||||
GetParamDumpFunc(operation.Type)(dumpFile, operation.Parameters, knownParamCount, paramNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2018-2020 Intel Corporation
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
@ -11,5 +11,6 @@
|
||||
#include "gna2-model-api.h"
|
||||
|
||||
void WriteInputAndOutputTextGNAImpl(const Gna2Model & gnaModel, const std::string dumpFolderNameGNA, const std::string refFolderName);
|
||||
void DumpGna2Model(const Gna2Model& gnaModel, const std::string dumpFolderNameGNA, bool dumpData);
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2018-2020 Intel Corporation
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
@ -28,6 +28,7 @@ constexpr uint32_t PoolModeParamIdx = 2;
|
||||
constexpr uint32_t PoolWinParamIdx = 3;
|
||||
constexpr uint32_t PoolStrideParamIdx = 4;
|
||||
constexpr uint32_t ZeroPaddingParamIdx = 5;
|
||||
constexpr uint32_t MaximumScoreParamIdx = 0;
|
||||
|
||||
#define GNA_MAX_OP_PARAM 10
|
||||
typedef void (*GnaUserFree)(void*);
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2018-2020 Intel Corporation
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include "gna2-instrumentation-api.h"
|
||||
#include "gna2-memory-api.h"
|
||||
#include "gna2_model_export_helper.hpp"
|
||||
#include "gna2_model_debug_log.hpp"
|
||||
#else
|
||||
#include "gna-api-status.h"
|
||||
#include "gna-api.h"
|
||||
@ -26,6 +27,8 @@
|
||||
#include "details/ie_exception.hpp"
|
||||
#include "gna_plugin_log.hpp"
|
||||
|
||||
//#define MODEL_DUMP
|
||||
|
||||
std::mutex GNADeviceHelper::acrossPluginsSync{};
|
||||
|
||||
uint8_t* GNADeviceHelper::alloc(uint32_t size_requested, uint32_t *size_granted) {
|
||||
@ -131,6 +134,15 @@ uint32_t GNADeviceHelper::createModel(Gna2Model& gnaModel) const {
|
||||
if (isUpTo20GnaHwDevice() && isGnaLibVersion2_1) {
|
||||
enforceLegacyCnns(gnaModel);
|
||||
}
|
||||
#if GNA_LIB_VER == 2 && defined MODEL_DUMP
|
||||
std::string path =
|
||||
#ifdef _WIN32
|
||||
".\\";
|
||||
#else
|
||||
"./";
|
||||
#endif
|
||||
DumpGna2Model(gnaModel, path, false);
|
||||
#endif
|
||||
const auto status = Gna2ModelCreate(nGnaDeviceIndex, &gnaModel, &modelId);
|
||||
|
||||
checkGna2Status(status, gnaModel);
|
||||
|
Loading…
Reference in New Issue
Block a user