MNN 执行推理(九)

简介: MNN 执行推理(九)

1、Interpreter::runSession

// source/core/Interpreter.cpp
ErrorCode Interpreter::runSession(Session* session) const {
    std::unique_lock<std::mutex> _l(mNet->lock);
#ifdef MNN_INTERNAL_ENABLED
    Timer timer;
#endif
    ErrorCode errorcode = session->run();

#ifdef MNN_INTERNAL_ENABLED
    if (shouldLog(FREQ_LOW)) {
        waitSessionFinish(session);
        float costTime = (float)timer.durationInUs() / (float)1000;
        logForRunSession(session, costTime, "Interpreter::runSession");
    }
#endif // MNN_INTERNAL_ENABLED

    return 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 BackendCacheCommandCommandBuffer

// 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_VERPOSE
        FUNC_PRINT_ALL(info.op->name()->c_str(), s);
#endif
        for (auto& cmdP : buffer.command) {
            auto& cmd = *cmdP;
            auto code = cmd.execution->onExecute(cmd.workInputs, cmd.workOutputs);
// #define LOG_VERPOSE
#ifdef LOG_VERPOSE
            auto 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);
                }
            }
#endif
            if (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);
}


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());
    // 把算子中录制的指令加入到 VulkanBackend 的 mCmdBuffers 中
    extra->pushCommand(mCmdBuffer->get());
    return NO_ERROR;
}


1.1.1.2.1 VulkanBackend::pushCommand

// source/backend/vulkan/image/backend/VulkanBackend.cpp
void VulkanBackend::pushCommand(VkCommandBuffer buffer) const {
    mCmdBuffers.emplace_back(buffer);
//    _finish();
}

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();
}

  提交各个算子中的指令缓存,开始推理。


目录
相关文章
|
7月前
|
机器学习/深度学习 并行计算 PyTorch
TensorRT部署系列 | 如何将模型从 PyTorch 转换为 TensorRT 并加速推理?
TensorRT部署系列 | 如何将模型从 PyTorch 转换为 TensorRT 并加速推理?
1025 0
|
7月前
|
机器学习/深度学习 Java TensorFlow
模型推理脚本
模型推理脚本可以使用各种编程语言编写,如Python、C++、Java等。在机器学习和深度学习领域中,Python是最常用的编程语言之一,因为它有许多流行的深度学习框架,如TensorFlow、PyTorch和Keras,这些框架都提供了简单易用的API来加载模型和进行模型推理。
159 5
|
机器学习/深度学习 人工智能 API
使用TensorRT-LLM进行高性能推理
LLM的火爆之后,英伟达(NVIDIA)也发布了其相关的推理加速引擎TensorRT-LLM。TensorRT是nvidia家的一款高性能深度学习推理SDK。此SDK包含深度学习推理优化器和运行环境,可为深度学习推理应用提供低延迟和高吞吐量。而TensorRT-LLM是在TensorRT基础上针对大模型进一步优化的加速推理库,它号称可以增加4倍的推理速度。
548 0
|
运维 并行计算 C语言
TensorRT-LLM在CodeFuse-CodeLlama-34B上的int4量化实践
Codefuse是由蚂蚁集团开发的专门用于支持整个软件开发生命周期的大型代码语言模型(Code LLMs),涵盖设计、需求、编码、测试、部署、运维等关键阶段。致力于打造创新的解决方案,让软件开发者们在研发的过程中如丝般顺滑。
427 0
|
15天前
基于VisualGLM-6B大模型的本地部署与推理
本文是基于清华开源的VisualGLM-6B 支持图像中英文的多模态对话语言模型,进行了一系列本地的简单部署,包括环境配置、模型部署、演示推理、模型微调(官方提供的代码),由于个人电脑显存不足,最后是在阿里云服务器交互式平台DSW终端进行微调和训练操作的。
56 17
|
1天前
|
存储 缓存 物联网
MNN推理框架将大模型放进移动端设备,并达到SOTA推理性能!
随着移动端(手机/平板等)算力、内存、磁盘空间的不断增长,在移动端部署大模型逐渐成为可能。在端侧运行大模型,可以有一系列好处:去除网络延迟,加快响应速度;降低算力成本,便于大规模应用;不需数据上传,保护用户稳私。
MNN推理框架将大模型放进移动端设备,并达到SOTA推理性能!
|
7月前
|
机器学习/深度学习 人工智能 Cloud Native
大语言模型推理提速,TensorRT-LLM 高性能推理实践
大型语言模型(Large language models,LLM)是基于大量数据进行预训练的超大型深度学习模型,本文主要讲述TensorRT-LLM利用量化、In-Flight Batching、Attention、Graph Rewriting提升 LLM 模型推理效率。
101754 2
|
7月前
|
物联网 Shell Swift
NPU推理&微调大模型实战
本文为魔搭社区轻量级训练推理工具SWIFT微调实战教程系列
|
4月前
|
机器学习/深度学习 并行计算 PyTorch
ONNX 优化技巧:加速模型推理
【8月更文第27天】ONNX (Open Neural Network Exchange) 是一个开放格式,用于表示机器学习模型,使模型能够在多种框架之间进行转换。ONNX Runtime (ORT) 是一个高效的推理引擎,旨在加速模型的部署。本文将介绍如何使用 ONNX Runtime 和相关工具来优化模型的推理速度和资源消耗。
2016 4
|
5月前
|
并行计算 PyTorch 算法框架/工具
LLM推理引擎怎么选?TensorRT vs vLLM vs LMDeploy vs MLC-LLM
有很多个框架和包可以优化LLM推理和服务,所以在本文中我将整理一些常用的推理引擎并进行比较。
566 2