MNN 执行推理(九)

2024-03-23 14:12
文章标签 推理 执行 mnn

本文主要是介绍MNN 执行推理(九),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述

系列文章目录


MNN createFromBuffer(一)
MNN createRuntime(二)
MNN createSession 之 Schedule(三)
MNN createSession 之创建流水线后端(四)
MNN Session 之维度计算(五)
MNN Session 之几何计算(六)
MNN Session 之 CPU 算子(七)
MNN Session 之 Vulkan 算子(八)
MNN 执行推理(九)


文章目录

  • 系列文章目录
  • 1、Interpreter::runSession
    • 1.1 Session::run
    • 1.1.1 Pipeline::execute
    • 1.1.1.1 VulkanBackend::onExecuteBegin
    • 1.1.1.2 Execution::onExecute
    • 1.1.1.3 Backend::onExecuteEnd
    • 1.1.1.3.1 _finish


1、Interpreter::runSession

在这里插入图片描述

// source/core/Interpreter.cpp
ErrorCode Interpreter::runSession(Session* session) const {std::unique_lock<std::mutex> _l(mNet->lock);
#ifdef MNN_INTERNAL_ENABLEDTimer timer;
#endifErrorCode errorcode = session->run();#ifdef MNN_INTERNAL_ENABLEDif (shouldLog(FREQ_LOW)) {waitSessionFinish(session);float costTime = (float)timer.durationInUs() / (float)1000;logForRunSession(session, costTime, "Interpreter::runSession");}
#endif // MNN_INTERNAL_ENABLEDreturn errorcode;
}

1.1 Session::run

Pipeline

// source/core/Session.cpp
ErrorCode Session::run() const {if (mNeedResize) {MNN_ERROR("Can't run session because not resized\n");return COMPUTE_SIZE_ERROR;}// mPipelines 类型为 std::vector<std::shared_ptr<Pipeline>>for (auto& iter : mPipelines) {auto error = iter->execute();if (NO_ERROR != error) {return error;}}return NO_ERROR;
}

1.1.1 Pipeline::execute

OpCacheInfo 、BackendCache、Command、CommandBuffer

// source/core/Pipeline.cpp
// typedef std::pair<BackendCache, std::vector<OpCacheInfo>> PipelineInfo
ErrorCode Pipeline::execute() {_copyInputs();auto& mBackend = mInfo.first.cache.first;auto& mBackupBackend = mInfo.first.cache.second;mBackend->onExecuteBegin();// mInfo 类型为 std::pair<BackendCache, std::vector<OpCacheInfo>>for (auto& info : mInfo.second) {auto& buffer = info.executeBuffer;
//#define LOG_VERPOSE
#ifdef LOG_VERPOSEFUNC_PRINT_ALL(info.op->name()->c_str(), s);
#endiffor (auto& cmdP : buffer.command) {auto& cmd = *cmdP;auto code = cmd.execution->onExecute(cmd.workInputs, cmd.workOutputs);
// #define LOG_VERPOSE
#ifdef LOG_VERPOSEauto dumpT = [](Tensor* t) {auto size = TensorUtils::getRawSize(t);size = size > 10 ? 10 : size;if (t->getType() == halide_type_of<float>()) {for (int i=0; i<size; ++i) {MNN_PRINT("%f, ", t->host<float>()[i]);}} else {for (int i=0; i<size; ++i) {MNN_PRINT("%d, ", t->host<int>()[i]);}}MNN_PRINT("\n");};if (/* cmd.op->name() && cmd.op->name()->str() == "/embed/embed_/Gather_output_0"*/cmd.op->type() == OpType_Convolution) {MNN_PRINT("%s Input begin:\n", EnumNameOpType(cmd.op->type()));for (auto t : cmd.workInputs) {dumpT(t);}MNN_PRINT("%s Output begin:\n", EnumNameOpType(cmd.op->type()));for (auto t : cmd.workOutputs) {dumpT(t);}}
#endifif (NO_ERROR != code) {mBackend->onExecuteEnd();return code;}}}mBackend->onExecuteEnd();return NO_ERROR;
}

1.1.1.1 VulkanBackend::onExecuteBegin

    在函数 Pipeline::execute 中调用 Backend::onExecuteBegin 函数的代码如下:

	mBackend->onExecuteBegin();

    onExecuteBegin 函数是个虚函数, mBackend->onExecuteBegin 调用是个多态,其基类为 Backend,此处 mBackendVulkanBackend,其具体实现代码如下:

// source/backend/vulkan/image/backend/VulkanBackend.cpp
void VulkanBackend::onExecuteBegin() const {if (!mDirect) {mCmdBuffers.push_back(mCmdBuffer->get());}// FUNC_PRINT_ALL(mDynamicMemoryPool->computeSize(), f);
}

VulkanBasicExecutionDirect::onExecute

1.1.1.2 Execution::onExecute

    在函数 Pipeline::execute 中调用 Execution::onExecute 函数的代码如下:

            auto code = cmd.execution->onExecute(cmd.workInputs, cmd.workOutputs);

    Execution::onExecute 函数是个虚函数,对于 Vulkan 来说,主要有 VulkanBasicExecutionDirect 和 VulkanBasicExecutionInDirect,我们以 VulkanBasicExecutionDirect 进行分析:

// source/backend/vulkan/image/execution/VulkanBasicExecution.cpp
ErrorCode VulkanBasicExecutionDirect::onExecute(const std::vector<Tensor *> &inputs, const std::vector<Tensor *> &outputs) {auto extra = static_cast<VulkanBackend *>(backend());extra->pushCommand(mCmdBuffer->get());return NO_ERROR;
}

1.1.1.3 Backend::onExecuteEnd

    在函数 Pipeline::execute 中调用 Backend::onExecuteEnd 函数的代码如下:

	mBackend->onExecuteEnd();

    Backend::onExecuteEnd 函数是个虚函数,对于 Vulkan 来说为 VulkanBackend ,以下为其代码:

// source/backend/vulkan/image/backend/VulkanBackend.cpp
void VulkanBackend::onExecuteEnd() const {_finish();
}

1.1.1.3.1 _finish

// source/backend/vulkan/image/backend/VulkanBackend.cpp
void VulkanBackend::_finish() const {if (mCmdBuffers.empty()) {return;}VkSubmitInfo submit_info = {/* .sType                = */ VK_STRUCTURE_TYPE_SUBMIT_INFO,/* .pNext                = */ nullptr,/* .waitSemaphoreCount   = */ 0,/* .pWaitSemaphores      = */ nullptr,/* .pWaitDstStageMask    = */ nullptr,/* .commandBufferCount   = */ (uint32_t)mCmdBuffers.size(),/* .pCommandBuffers      = */ mCmdBuffers.data(),/* .signalSemaphoreCount = */ 0,/* .pSignalSemaphores    = */ nullptr};auto fenceReal           = mFence->get();mFence->reset();CALL_VK(vkQueueSubmit(device().acquireDefaultDevQueue(), 1, &submit_info, fenceReal));auto res = mFence->wait();MNN_VK_CHECK(res);mCmdBuffers.clear();
}

   

这篇关于MNN 执行推理(九)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/838545

相关文章

maven 编译构建可以执行的jar包

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」👈,「stormsha的知识库」👈持续学习,不断总结,共同进步,为了踏实,做好当下事儿~ 专栏导航 Python系列: Python面试题合集,剑指大厂Git系列: Git操作技巧GO

jenkins 插件执行shell命令时,提示“Command not found”处理方法

首先提示找不到“Command not found,可能我们第一反应是查看目标机器是否已支持该命令,不过如果相信能找到这里来的朋友估计遇到的跟我一样,其实目标机器是没有问题的通过一些远程工具执行shell命令是可以执行。奇怪的就是通过jenkinsSSH插件无法执行,经一番折腾各种搜索发现是jenkins没有加载/etc/profile导致。 【解决办法】: 需要在jenkins调用shell脚

Lua 脚本在 Redis 中执行时的原子性以及与redis的事务的区别

在 Redis 中,Lua 脚本具有原子性是因为 Redis 保证在执行脚本时,脚本中的所有操作都会被当作一个不可分割的整体。具体来说,Redis 使用单线程的执行模型来处理命令,因此当 Lua 脚本在 Redis 中执行时,不会有其他命令打断脚本的执行过程。脚本中的所有操作都将连续执行,直到脚本执行完成后,Redis 才会继续处理其他客户端的请求。 Lua 脚本在 Redis 中原子性的原因

Smarty模板执行原理

为了实现程序的业务逻辑和内容表现页面的分离从而提高开发速度,php 引入了模板引擎的概念,php 模板引擎里面最流行的可以说是smarty了,smarty因其功能强大而且速度快而被广大php web开发者所认可。本文将记录一下smarty模板引擎的工作执行原理,算是加深一下理解。 其实所有的模板引擎的工作原理是差不多的,无非就是在php程序里面用正则匹配将模板里面的标签替换为php代码从而将两者

(function() {})();只执行一次

测试例子: var xx = (function() {     (function() { alert(9) })(); alert(10)     return "yyyy";  })(); 调用: alert(xx); 在调用的时候,你会发现只弹出"yyyy"信息,并不见弹出"10"的信息!这也就是说,这个匿名函数只在立即调用的时候执行一次,这时它已经赋予了给xx变量,也就是只是

Java程序到CPU上执行 的步骤

相信很多的小伙伴在最初学习编程的时候会容易产生一个疑惑❓,那就是编写的Java代码究竟是怎么一步一步到CPU上去执行的呢?CPU又是如何执行的呢?今天跟随小编的脚步去化解开这个疑惑❓。 在学习这个过程之前,我们需要先讲解一些与本内容相关的知识点 指令 指令是指导CPU运行的命令,主要由操作码+被操作数组成。 其中操作码用来表示要做什么动作,被操作数是本条指令要操作的数据,可能是内存地址,也

Android下执行linux命令

最近在开发过程中 使用了几个命令来对   手机的文件的权限进行修改;现在记录一下: 用到的方法: 1:判断是否有Root权限;  /**      * 判断当前手机是否有ROOT权限      * @return      */     public static boolean isRoot(){         boolean bool = false;         try{

PyInstaller问题解决 onnxruntime-gpu 使用GPU和CUDA加速模型推理

前言 在模型推理时,需要使用GPU加速,相关的CUDA和CUDNN安装好后,通过onnxruntime-gpu实现。 直接运行python程序是正常使用GPU的,如果使用PyInstaller将.py文件打包为.exe,发现只能使用CPU推理了。 本文分析这个问题和提供解决方案,供大家参考。 问题分析——找不到ONNX Runtime GPU 动态库 首先直接运行python程序

main函数执行前、后再执行的代码

一、main结束 不代表整个进程结束  (1)全局对象的构造函数会在main 函数之前执行,          全局对象的析构函数会在main函数之后执行;          用atexit注册的函数也会在main之后执行。  (2)一些全局变量、对象和静态变量、对象的空间分配和赋初值就是在执行main函数之前,而main函数执行完后,还要去执行一些诸如释放空间、释放资源使用权等操作   (3)

Java基础--基础类型及源码执行编译过程

数据类型 分为基本数据类型和引用数据类型 1、基本数据类型:8个 整型( byte short int long64) byte字节型–8个bit,敏感单元位,1byte=8bit,00000000,256种组合 用第一个bit位置来记录符号,0正数,1负数 数值的范围:-2的7次方2的7次方-1,-128127 其他的整数类型依次乘2 Short 2字节=16bit 65526种组合,-3276