自定义graph
当网络使用转换工具转到一个平台时, 经常会遇到部分算子不支持的问题(比如一些网络的后处理部分), 这时可以考虑白剽MNN的算子. 这里以softmax为例.
假如你的分类网络(比如resent)的主要部分能够在gpu上推理,但是后面的softmax却不支持, 那么你可以使用MNN的expression库来实现, 使用cpu后端的话支持的算子当然多, 而且针对嵌入式平台也有优化. 实现代码如下:
#include <MNN/expr/Expr.hpp>
#include <MNN/expr/ExprCreator.hpp>
#include <MNN/expr/Executor.hpp>
//-------lyy
#include "MNN_generated.h"
#include <MNN/MNNForwardType.h>
#include <MNN/Interpreter.hpp>
#include <MNN/expr/Expr.hpp>
#include <MNN/MNNDefine.h>
void run_my_ops(){
MNN_PRINT("test my ops");
// define your graph
auto x1 = _Input({1, 2, 3, 4}, NCHW);
auto x = _Softmax(x1, -1);
// auto x2 = _Input({1, 2, 3, 4}, NCHW);
// auto x = _Add(x1, x2);
// x = _Softmax(x, -1);
std::unique_ptr<MNN::NetT> netTable(new MNN::NetT);
MNN::Express::Variable::save({x}, netTable.get());
flatbuffers::FlatBufferBuilder builder(1024);
auto offset = CreateNet(builder, netTable.get());
builder.Finish(offset);
const void* buf = builder.GetBufferPointer();
size_t size = builder.GetSize();
std::unique_ptr<MNN::Interpreter> net(MNN::Interpreter::createFromBuffer(buf, size));
net->setSessionMode(MNN::Interpreter::Session_Release);
MNN::ScheduleConfig config;
auto session = net->createSession(config);
net->releaseModel();
auto inputTensor = net->getSessionInput(session, NULL);
std::shared_ptr<MNN::Tensor> inputTensorHost(MNN::Tensor::createHostTensorFromDevice(inputTensor, false));
int eleSize = inputTensorHost->elementSize();
for (int i = 0; i < eleSize; ++i) {
inputTensorHost->host<float>()[i] = float(i);
}
MNN_PRINT("Input tensor:");
inputTensorHost->print();
auto outputTensor = net->getSessionOutput(session, NULL);
std::shared_ptr<MNN::Tensor> outputTensorHost(MNN::Tensor::createHostTensorFromDevice(outputTensor, false));
inputTensor->copyFromHostTensor(inputTensorHost.get());
net->runSession(session);
outputTensor->copyToHostTensor(outputTensorHost.get());
MNN_PRINT("output tensor:");
outputTensorHost->print();
}
参考资料:
MNN仓库:
benchmark/exprModels/SqueezeNetExpr.hpp
benchmark/benchmarkExprModels.cpp