Files
2026-07-13 13:33:03 +08:00

221 lines
8.8 KiB
C++

//
// QNNCommonExecution.cpp
// MNN
//
// Created by MNN on 2025/02/11.
// Copyright © 2018, Alibaba Group Holding Limited
//
#include "QNNCommonExecution.hpp"
namespace MNN {
namespace QNN {
#ifdef ENABLE_QNN_ONLINE_FINALIZE
// #define QNN_VERBOSE
QNNCommonExecution::QNNCommonExecution(Backend *backend, const Op *op) : Execution(backend), mOp(op) {
mBackend = (QnnBackend *)backend;
}
ErrorCode QNNCommonExecution::onResize(const std::vector<Tensor *> &inputs, const std::vector<Tensor *> &outputs) {
this->setNodeName(mOp, inputs, outputs);
std::string nodeNameBase = MNN::EnumNameOpType(mOp->type());
#ifdef QNN_VERBOSE
MNN_PRINT("%s encoding start\n", nodeNameBase.c_str());
#endif
ErrorCode result = this->onEncode(inputs, outputs);
if (result != NO_ERROR) {
MNN_ERROR("Error %s encoding\n", nodeNameBase.c_str());
return result;
}
#ifdef QNN_VERBOSE
MNN_PRINT("%s encoding end\n", nodeNameBase.c_str());
#endif
this->clean();
return NO_ERROR;
}
ErrorCode QNNCommonExecution::onEncode(const std::vector<Tensor *> &inputs, const std::vector<Tensor *> &outputs) {
return NO_ERROR;
}
ErrorCode QNNCommonExecution::onExecute(const std::vector<Tensor *> &inputs, const std::vector<Tensor *> &outputs) {
return NO_ERROR;
}
void QNNCommonExecution::setNodeName(const Op * op, const std::vector<Tensor *> &inputs, const std::vector<Tensor *> &outputs) {
if (nullptr != op->name()) {
mNodeName = op->name()->str();
for (int i=0; i<mNodeName.size(); ++i) {
if (mNodeName[i] == '.' || mNodeName[i] == '/' || mNodeName[i] == ':') {
mNodeName[i] = '_';
}
}
return;
}
std::string nodeNameBase = MNN::EnumNameOpType(mOp->type());
nodeNameBase += "_";
std::string inputTag = "I_";
std::string outputTag = "O_";
for (int i = 0; i < inputs.size(); i++) {
inputTag += std::to_string(mBackend->getTensorIdx(inputs[i]));
inputTag += "_";
}
for (int j = 0; j < outputs.size() - 1; j++) {
outputTag += std::to_string(mBackend->getTensorIdx(outputs[j]));
outputTag += "_";
}
outputTag += std::to_string(mBackend->getTensorIdx(outputs[outputs.size() - 1]));
mNodeName = nodeNameBase + inputTag + outputTag;
}
std::shared_ptr<QNNTensorWrapper> QNNCommonExecution::createStaticTensor(const std::string & name, Qnn_DataType_t dataType, const std::vector<uint32_t> & dimensions, const void * buffer, Qnn_QuantizeParams_t quantizeParam) {
std::string tensorName = mNodeName + "_" + name;
std::shared_ptr<QNNTensorWrapper> tensorWrapper = QNNTensorWrapper::createStaticTensor(tensorName, dataType, dimensions, buffer, quantizeParam);
mBackend->addTensor(tensorWrapper->getNativeTensor());
mTempTensorWrappers.push_back(tensorWrapper);
return tensorWrapper;
}
std::shared_ptr<QNNTensorWrapper> QNNCommonExecution::createStaticFloatTensor(const std::string & name, Qnn_DataType_t dataType, const std::vector<uint32_t> & dimensions, const float * buffer, Qnn_QuantizeParams_t quantize) {
std::string tensorName = mNodeName + "_" + name;
std::shared_ptr<QNNTensorWrapper> tensorWrapper = QNNTensorWrapper::createStaticFloatTensor(tensorName, dataType, dimensions, buffer, quantize);
mBackend->addTensor(tensorWrapper->getNativeTensor());
mTempTensorWrappers.push_back(tensorWrapper);
return tensorWrapper;
}
std::shared_ptr<QNNTensorWrapper> QNNCommonExecution::createStageTensor(const std::string & name, Qnn_DataType_t dataType, const std::vector<int> & dimensions, const Tensor* tensor) {
std::vector<uint32_t> vec(dimensions.size());
for (int i = 0; i < dimensions.size(); i++) {
vec[i] = (uint32_t)dimensions[i];
}
return this->createStageTensor(name, dataType, vec, tensor);
}
std::shared_ptr<QNNTensorWrapper> QNNCommonExecution::createStageTensor(const std::string & name, Qnn_DataType_t dataType, const std::vector<uint32_t> & dimensions, const Tensor* tensor) {
std::string tensorName = mNodeName + "_" + name;
Qnn_QuantizeParams_t quantize = DEFAULT_QUANTIZE_PARAMS;
Qnn_ScaleOffset_t tScaleOffsetEncoding;
if(tensor != nullptr && TensorUtils::getDescribe(tensor)->applyQuant){
quantize.encodingDefinition = QNN_DEFINITION_DEFINED;
quantize.quantizationEncoding = QNN_QUANTIZATION_ENCODING_SCALE_OFFSET;
tScaleOffsetEncoding.scale = mBackend->getNativeTensor(tensor)->v1.quantizeParams.scaleOffsetEncoding.scale;
tScaleOffsetEncoding.offset = mBackend->getNativeTensor(tensor)->v1.quantizeParams.scaleOffsetEncoding.offset;
quantize.scaleOffsetEncoding = tScaleOffsetEncoding;
}
std::shared_ptr<QNNTensorWrapper> tensorWrapper = QNNTensorWrapper::create(tensorName, QNN_TENSOR_TYPE_NATIVE, dataType, dimensions, quantize);
mBackend->addTensor(tensorWrapper->getNativeTensor());
mTempTensorWrappers.push_back(tensorWrapper);
return tensorWrapper;
}
std::shared_ptr<QNNParamTensorWrapper> QNNCommonExecution::createParamTensor(const std::string & paramName, Qnn_DataType_t dataType, const std::vector<uint32_t> & dims, void * data, std::string postName) {
MNN_ASSERT(!mNodeName.empty());
std::string tensorName;
if (postName.empty()) {
tensorName = mNodeName + "_" + paramName + "_PARAM";
} else {
tensorName = mNodeName + "_" + paramName + "_" + postName + "_PARAM";
}
std::shared_ptr<QNNParamTensorWrapper> result = QNNParamTensorWrapper::create(paramName, tensorName, dataType, dims);
void * dst = result->alloc();
::memcpy(dst, data, result->getNativeTensor()->v1.clientBuf.dataSize);
mBackend->addTensor(result->getNativeTensor());
mParamTensorWrappers.push_back(result);
return mParamTensorWrappers.back();
}
std::shared_ptr<QNNParamScalarWrapper> QNNCommonExecution::createParamScalar(const std::string & name, bool data) {
mParamScalarWrappers.push_back(QNNParamScalarWrapper::create(name, data));
return mParamScalarWrappers.back();
}
std::shared_ptr<QNNParamScalarWrapper> QNNCommonExecution::createParamScalar(const std::string & name, uint32_t data) {
mParamScalarWrappers.push_back(QNNParamScalarWrapper::create(name, data));
return mParamScalarWrappers.back();
}
std::shared_ptr<QNNParamScalarWrapper> QNNCommonExecution::createParamScalar(const std::string & name, int data) {
mParamScalarWrappers.push_back(QNNParamScalarWrapper::create(name, data));
return mParamScalarWrappers.back();
}
std::shared_ptr<QNNParamScalarWrapper> QNNCommonExecution::createParamScalar(const std::string & name, float data) {
mParamScalarWrappers.push_back(QNNParamScalarWrapper::create(name, data));
return mParamScalarWrappers.back();
}
void QNNCommonExecution::addNodeCommon(const std::vector<Tensor *> &inputs, const std::vector<Tensor *> &outputs, int inputSize, int outputSize) {
for (int i = 0; i < mParamTensorWrappers.size(); i++) {
mParams.push_back(*(mParamTensorWrappers[i]->getNativeParam()));
}
for (int j = 0; j < mParamScalarWrappers.size(); j++) {
mParams.push_back(*(mParamScalarWrappers[j]->getNativeParam()));
}
if (0 == inputSize) {
inputSize = inputs.size();
}
if (0 == outputSize) {
outputSize = outputs.size();
}
for (int k = 0; k < inputSize; k++) {
mInputs.push_back(*(mBackend->getNativeTensor(inputs[k])));
}
for (int l = 0; l < outputSize; l++) {
mOutputs.push_back(*(mBackend->getNativeTensor(outputs[l])));
}
mBackend->addNodeToGraph(mOpConfigVersion, mNodeName.c_str(), mPackageName.c_str(), mNodeType.c_str(), mParams, mInputs, mOutputs);
}
void QNNCommonExecution::addNodeCommonPermute(const std::string & nodeNamePostfix, const Qnn_Tensor_t & input, const Qnn_Param_t & paramPerm, const Qnn_Tensor_t & output) {
CLEAR_BEFORE_ADDING_NODE;
std::string name = mNodeName + "_" + nodeNamePostfix;
mNodeType = "Transpose";
mInputs.push_back(input);
mParams.push_back(paramPerm);
mOutputs.push_back(output);
mBackend->addNodeToGraph(mOpConfigVersion, name.c_str(), mPackageName.c_str(), mNodeType.c_str(), mParams, mInputs, mOutputs);
return;
}
void QNNCommonExecution::addNodeCommonReshape(const std::string & nodeNamePostfix, const Qnn_Tensor_t & input, const Qnn_Tensor_t & output) {
CLEAR_BEFORE_ADDING_NODE;
std::string name = mNodeName + "_" + nodeNamePostfix;
mNodeType = "Reshape";
mInputs.push_back(input);
mOutputs.push_back(output);
mBackend->addNodeToGraph(mOpConfigVersion, name.c_str(), mPackageName.c_str(), mNodeType.c_str(), mParams, mInputs, mOutputs);
return;
}
void QNNCommonExecution::clean() {
mTempTensorWrappers.clear();
mParamTensorWrappers.clear();
mParamScalarWrappers.clear();
mNodeName.clear();
mNodeType.clear();
mParams.clear();
mInputs.clear();
mOutputs.clear();
}
#endif
} // end namespace QNN
} // end namespace MNN