onnx转mnn模型mingw32编译的使用

目的:手上有onnx模型文件,想用mingw32编译来推理,但onnx不支持mingw32,所以转为mnn模型来实现。

mingw32编译也可以参考这篇。

61、Window11+Clion+MinGW32编译MNN使用_mnn win11 编译-CSDN博客

下载安装

1. MNN下载,GitHub给的是源文件,可以按需要选择对应的编译器进行编译,本文只介绍mingw32编译。下载解压得到一个MNN-master文件夹。

GitHub - alibaba/MNN: MNN is a blazing fast, lightweight deep learning framework, battle-tested by business-critical use cases in Alibaba

下载Cmake,下载最近版本的.msi安装包,安装时将其加入到环境变量。

CMake - Upgrade Your Software Build System

安装ninja,参考这篇。

问题描述:在Windows下没有预装ninja工具_windows安装ninja-CSDN博客

模型转换

2.mnn提供了从onnx生成mnn的模型转换工具MNNConvert,可以用Visual Studio来用MNN-master文件夹的代码来生成MNNConvert。也可以直接用别人生成好的,就不用安装Visual Studio。

下面演示用Visual Studio生成这两个工具文件,用现成的可以跳过。

Visual Studio下载地址:Visual Studio: 面向软件开发人员和 Teams 的 IDE 和代码编辑器

这里用的是vs2022,勾选C++开发工具,安装。

PS:VS盗版可能出现问题,慎用。

vs2022安装好后,按照mnn文档给的流程生成可执行文件。

转换工具Windows编译 · 语雀

打开VS编译x64架构程序的虚拟环境

跳转到MNN-master文件夹下,执行以下指令。

mkdir build
cd build
cmake -G "Ninja" -DMNN_BUILD_SHARED_LIBS=OFF -DMNN_BUILD_CONVERTER=ON -DCMAKE_BUILD_TYPE=Release -DMNN_WIN_RUNTIME_MT=ON ..

构建后,编译。

ninja

完成后会在MNN-master\build下生成MNNConvert.exe工具和MNNConvert.pdb库

有了工具就可以进行下面的模型转换。将上面两个工具文件,和onnx模型放进来。

然后用下面的命令行将xxxxxxxxx.onnx的模型转换为xxxxxxxxx.mnn模型,文件名自己定义

命令行

MNNConvert -f ONNX --modelFile xxxxxxxxx.onnx --MNNModel xxxxxxxxx.mnn

 模型转换完成

编译生成库文件

3.下面是编译mnn生成推理需要的库文件。

这里用的编译器是QT5.9.9自带的mingw32,根据安装QT的位置,先配置一下编译器路径到环境变量

qt下载地址

Index of /new_archive/qt/5.9/5.9.9

到MNN-master文件夹内,修改CMakeLists.txt配置,配置选项根据自己环境和需求来自定义配置

这里给出我的配置,做为参考:

# build options
option(MNN_USE_SYSTEM_LIB "For opencl and vulkan, use system lib or use dlopen" OFF)
option(MNN_BUILD_HARD "Build -mfloat-abi=hard or not" OFF)
option(MNN_BUILD_SHARED_LIBS "MNN build shared or static lib" ON)
option(MNN_WIN_RUNTIME_MT "MNN use /MT on Windows dll" OFF)
option(MNN_FORBID_MULTI_THREAD "Disable Multi Thread" OFF)
option(MNN_OPENMP "Use OpenMP's thread pool implementation. Does not work on iOS or Mac OS" OFF)
option(MNN_USE_THREAD_POOL "Use MNN's own thread pool implementation" ON)
option(MNN_BUILD_TRAIN "Build MNN's training framework" OFF)
option(MNN_BUILD_DEMO "Build demo/exec or not" OFF)
option(MNN_BUILD_TOOLS "Build tools/cpp or not" ON)
option(MNN_BUILD_QUANTOOLS "Build Quantized Tools or not" OFF)
option(MNN_EVALUATION "Build Evaluation Tools or not" OFF)
option(MNN_BUILD_CONVERTER "Build Converter" OFF)
option(MNN_SUPPORT_DEPRECATED_OP "Enable MNN's tflite quantized op" OFF)
option(MNN_DEBUG_MEMORY "MNN Debug Memory Access" OFF)
option(MNN_DEBUG_TENSOR_SIZE "Enable Tensor Size" OFF)
option(MNN_GPU_TRACE "Enable MNN Gpu Debug" OFF)
option(MNN_SUPPORT_RENDER "Enable MNN Render Ops" OFF)
option(MNN_SUPPORT_TRANSFORMER_FUSE "Enable MNN transformer Fuse Ops" OFF)
option(MNN_PORTABLE_BUILD "Link the static version of third party libraries where possible to improve the portability of built executables" OFF)
option(MNN_SEP_BUILD "Build MNN Backends and expression separately. Only works with MNN_BUILD_SHARED_LIBS=ON" OFF)
option(NATIVE_LIBRARY_OUTPUT "Native Library Path" OFF)
option(NATIVE_INCLUDE_OUTPUT "Native Include Path" OFF)
option(MNN_AAPL_FMWK "Build MNN.framework instead of traditional .a/.dylib" OFF)
option(MNN_WITH_PLUGIN "Build with plugin op support." OFF)
option(MNN_BUILD_MINI "Build MNN-MINI that just supports fixed shape models." OFF)
option(MNN_USE_SSE "Use SSE optimization for x86 if possiable" OFF)
option(MNN_BUILD_CODEGEN "Build with codegen" OFF)
option(MNN_ENABLE_COVERAGE "Build with coverage enable" OFF)
option(MNN_BUILD_PROTOBUFFER "Build with protobuffer in MNN" ON)
option(MNN_BUILD_OPENCV "Build OpenCV api in MNN." OFF)
option(MNN_BUILD_LLM "Build llm library based MNN." OFF)
option(MNN_BUILD_DIFFUSION "Build diffusion demo based MNN." OFF)
option(MNN_INTERNAL "Build with MNN internal features, such as model authentication, metrics logging" OFF)
option(MNN_JNI "Build MNN Jni for java to use" OFF)

在当前目录打开命令行,指定使用mingw32来进行编译

mkdir build_mingw32
cd build_mingw32
cmake -G "MinGW Makefiles" ..

等待Cmake完成,再执行编译命令

make -j8

PS:如果make命令不存在,把qt的mingw32-make.exe复制一个改成make.exe。

编译完成,生成的两个库文件libMNN.dll、libMNN.dll.a就是推理需要的库文件。

C++推理

4.C++推理

前面生成的两个库文件libMNN.dll、libMNN.dll.a,再加上include\MNN文件夹里面的头文件,可以用来模型推理。

官方给出了3种方法,session、Module和Expr的方式(参考官方文档)进行推理,

Session API使用 — MNN-Doc 2.1.1 documentation

Module API使用 — MNN-Doc 2.1.1 documentation

下面演示使用session


#include "MNN/Interpreter.hpp"
#include "MNN/Tensor.hpp"
#include "MNN/ImageProcess.hpp"


int main()
{
    // 加载模型
    std::string modelFilePath = "./xxxxxxxxx.mnn";
    auto net = std::shared_ptr<MNN::Interpreter>(MNN::Interpreter::createFromFile(modelFilePath.c_str()));

    MNN::ScheduleConfig config;
    config.type = MNN_FORWARD_AUTO;
    auto session = net->createSession(config);

    // 从txt中读取测试输入数据
    std::vector<float> inputData;

    // 赋值给inputData
    inputData[0] = 1;  // 根据具体数据修改

    // 网络输入数据
    auto inputTensor = net->getSessionInput(session, NULL);
    memcpy(inputTensor->host<float>(), inputData.data(), inputData.size() * sizeof(float));

    // 执行推理
    net->runSession(session);
    auto outputTensor = net->getSessionOutput(session, NULL);

    // 网络输出数据
    float* outputData = outputTensor->host<float>();
    return 0;
}

下面演示使用Module


#include "MNN/expr/ExprCreator.hpp"
#include "MNN/expr/Module.hpp"
using namespace MNN::Express;

int main() {

    // 从模型文件加载并创建新Module

    // 输入名:多个输入时按顺序填入,其顺序与后续 onForward 中的输入数组需要保持一致
    const std::vector<std::string> input_names{"input"};    
    // 输出名,多个输出按顺序填入,其顺序决定 onForward 的输出数组顺序
    const std::vector<std::string> output_names{"output"};

    MNN::ScheduleConfig sConfig;
    sConfig.type = MNN_FORWARD_OPENCL;
    std::shared_ptr<MNN::Express::Executor::RuntimeManager> rtmgr(MNN::Express::Executor::RuntimeManager::createRuntimeManager(sConfig), MNN::Express::Executor::RuntimeManager::destroy);
//    rtmgr->setCache(".cachefile");
    Module::Config mdconfig; // default module config
    std::unique_ptr<Module> module; // module
    // 若rtMgr为 nullptr ,Module会使用Executor的后端配置
    module.reset(Module::load(input_names, output_names, EncodermodelPath.c_str(), rtmgr, &mdconfig));

    
    std::vector<VARP> inputs(1);
    // 对于 tensoflow 转换过来的模型用NHWC,由 onnx 转换过来的模型用NCHW
    inputs[0] = MNN::Express::_Input({1, inlength}, NCHW, halide_type_of<float>());
    // 设置输入数据
    std::vector<float*> input_pointer = {inputs[0]->writeMap<float>()};
    for (int i = 0; i < inlength; ++i) {
        input_pointer[0][i] = data_norm[0][i];
    }
    // 执行推理
    std::vector<MNN::Express::VARP> outputs = module->onForward(inputs);
    // 获取输出
    auto output_ptr = outputs[0]->readMap<float>();

    return 1;

}

  • 21
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值