Files
alibaba--mnn/source/backend/qnn/execution/QNNGather.cpp
T
2026-07-13 13:33:03 +08:00

148 lines
5.0 KiB
C++

#include "QNNGather.hpp"
namespace MNN {
namespace QNN {
#ifdef ENABLE_QNN_ONLINE_FINALIZE
ErrorCode QNNGather::onEncode(const std::vector<Tensor *> &inputs, const std::vector<Tensor *> &outputs) {
auto input = inputs[0];
auto indices = inputs[1];
auto axisTensor = inputs[2];
auto output = outputs[0];
// Create public resources.
mInputDim = input->dimensions();
mOutputDim = output->dimensions();
mDimType = TensorUtils::getDimType(input);
mRawAxis = axisTensor->host<int32_t>()[0];
mRawAxis = (mRawAxis >= 0) ? mRawAxis : (input->buffer().dimensions + mRawAxis);
mQnnDataType = mBackend->getNativeTensor(input)->v1.dataType;
mFlagScalarIndices = (indices->dimensions() == 0) ? true : false;
#ifdef QNN_VERBOSE
MNN_PRINT("QNN Gather inputs shape:\n");
for(int i = 0; i < inputs.size(); i++) {
auto shape = inputs[i]->shape();
for(int j = 0; j < shape.size(); j++) {
MNN_PRINT("%d ", shape[j]);
}
MNN_PRINT("\n");
}
MNN_PRINT("QNN Gather axis: %d %d\n", mRawAxis, mDimType);
MNN_PRINT("QNN Gather outputs shape:\n");
for(int i = 0; i < outputs.size(); i++) {
auto shape = outputs[i]->shape();
for(int j = 0; j < shape.size(); j++) {
MNN_PRINT("%d ", shape[j]);
}
MNN_PRINT("\n");
}
#endif
// Goto branches.
if (mFlagScalarIndices) {
return this->onEncodeScalar(inputs, outputs);
}else{
return this->onEncodeTensor(inputs, outputs);
}
return NO_ERROR;
}
ErrorCode QNNGather::onEncodeScalar(const std::vector<Tensor *> &inputs, const std::vector<Tensor *> &outputs) {
// Create resources.
this->createParamScalar("axis", mRawAxis);
std::vector<int> shapeStageOutput = inputs[0]->shape();
shapeStageOutput[mRawAxis] = 1;
this->createStageTensor("stageOutput", mQnnDataType, shapeStageOutput, outputs[0]);
// Add Nodes.
this->addNodeGather("Gather",
*(mBackend->getNativeTensor(inputs[0])),
*(mBackend->getNativeTensor(inputs[1])),
*(mParamScalarWrappers[0]->getNativeParam()),
*(mTempTensorWrappers[0]->getNativeTensor()));
this->addNodeReshape("Reshape",
*(mTempTensorWrappers[0]->getNativeTensor()),
*(mBackend->getNativeTensor(outputs[0])));
return NO_ERROR;
}
ErrorCode QNNGather::onEncodeTensor(const std::vector<Tensor *> &inputs, const std::vector<Tensor *> &outputs) {
// Create resources.
if(mOp->type() == OpType_GatherElements) {
this->createParamScalar("axis", (uint32_t)mRawAxis);
} else {
this->createParamScalar("axis", (int)mRawAxis);
}
// Add Node.
this->addNodeGather("Gather",
*(mBackend->getNativeTensor(inputs[0])),
*(mBackend->getNativeTensor(inputs[1])),
*(mParamScalarWrappers[0]->getNativeParam()),
*(mBackend->getNativeTensor(outputs[0])));
return NO_ERROR;
}
void QNNGather::addNodeGather(const std::string & nodeNamePostfix, const Qnn_Tensor_t & input0, const Qnn_Tensor_t & input1, const Qnn_Param_t & paramAxis, const Qnn_Tensor_t & output) {
CLEAR_BEFORE_ADDING_NODE;
std::string name = mNodeName + "_" + nodeNamePostfix;
mNodeType = "Gather";
if(mOp->type() == OpType_GatherElements) {
mNodeType = "GatherElements";
}
// MNN_PRINT("mNodeType: %s\n", mNodeType.c_str());
mInputs.push_back(input0);
mInputs.push_back(input1);
mParams.push_back(paramAxis);
mOutputs.push_back(output);
mBackend->addNodeToGraph(mOpConfigVersion, name.c_str(), mPackageName.c_str(), mNodeType.c_str(), mParams, mInputs, mOutputs);
return;
}
void QNNGather::addNodeReshape(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;
}
class QNNGatherCreator : public QnnBackend::Creator {
public:
virtual QNNCommonExecution * onCreate(const std::vector<Tensor*>& inputs, const std::vector<Tensor*>& outputs, const MNN::Op* op,
Backend* backend) const override {
if (op->main_type() == OpParameter_Axis) {
MNN_ERROR("QNN Gather type error fallback\n");
return nullptr;
}
if (inputs.size() < 2) {
MNN_ERROR("QNN Gather inputs size:%d error fallback\n", inputs.size());
return nullptr;
}
return new QNNGather(backend, op);
}
};
REGISTER_QNN_OP_CREATOR(QNNGatherCreator, OpType_GatherV2)
REGISTER_QNN_OP_CREATOR(QNNGatherCreator, OpType_GatherElements)
#endif
} // end namespace QNN
} // end namespace MNN