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

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


目录
相关文章
|
6月前
|
机器学习/深度学习 并行计算 PyTorch
TensorRT部署系列 | 如何将模型从 PyTorch 转换为 TensorRT 并加速推理?
TensorRT部署系列 | 如何将模型从 PyTorch 转换为 TensorRT 并加速推理?
931 0
|
6月前
|
机器学习/深度学习 Java TensorFlow
模型推理脚本
模型推理脚本可以使用各种编程语言编写,如Python、C++、Java等。在机器学习和深度学习领域中,Python是最常用的编程语言之一,因为它有许多流行的深度学习框架,如TensorFlow、PyTorch和Keras,这些框架都提供了简单易用的API来加载模型和进行模型推理。
143 5
|
机器学习/深度学习 人工智能 API
使用TensorRT-LLM进行高性能推理
LLM的火爆之后,英伟达(NVIDIA)也发布了其相关的推理加速引擎TensorRT-LLM。TensorRT是nvidia家的一款高性能深度学习推理SDK。此SDK包含深度学习推理优化器和运行环境,可为深度学习推理应用提供低延迟和高吞吐量。而TensorRT-LLM是在TensorRT基础上针对大模型进一步优化的加速推理库,它号称可以增加4倍的推理速度。
531 0
|
30天前
|
人工智能 监控
unsloth微调LLama3,指令遵循优化模型独家秘籍
【10月更文挑战第15天】在人工智能领域,LLama3是一款基于Transformer架构的先进语言模型,通过大量数据训练,学习了语言的模式和规律。然而,面对特定任务时,仍需微调以提升性能。unsloth工具为此提供了极大便利,通过数据增强、正则化、学习率调整等优化策略,有效提升了LLama3的指令遵循能力。本文将介绍如何利用unsloth对LLama3进行微调,包括数据准备、模型加载、微调过程及性能监控等步骤。
58 4
|
6月前
|
机器学习/深度学习 人工智能 Cloud Native
大语言模型推理提速,TensorRT-LLM 高性能推理实践
大型语言模型(Large language models,LLM)是基于大量数据进行预训练的超大型深度学习模型,本文主要讲述TensorRT-LLM利用量化、In-Flight Batching、Attention、Graph Rewriting提升 LLM 模型推理效率。
101664 2
|
3月前
|
机器学习/深度学习 并行计算 PyTorch
ONNX 优化技巧:加速模型推理
【8月更文第27天】ONNX (Open Neural Network Exchange) 是一个开放格式,用于表示机器学习模型,使模型能够在多种框架之间进行转换。ONNX Runtime (ORT) 是一个高效的推理引擎,旨在加速模型的部署。本文将介绍如何使用 ONNX Runtime 和相关工具来优化模型的推理速度和资源消耗。
1343 4
|
3月前
|
机器学习/深度学习 并行计算 PyTorch
PyTorch与CUDA:加速深度学习模型训练的最佳实践
【8月更文第27天】随着深度学习应用的广泛普及,高效利用GPU硬件成为提升模型训练速度的关键。PyTorch 是一个强大的深度学习框架,它支持动态计算图,易于使用且高度灵活。CUDA (Compute Unified Device Architecture) 则是 NVIDIA 开发的一种并行计算平台和编程模型,允许开发者直接访问 GPU 的并行计算能力。本文将详细介绍如何利用 PyTorch 与 CUDA 的集成来加速深度学习模型的训练过程,并提供具体的代码示例。
155 1
|
4月前
|
并行计算 PyTorch 算法框架/工具
LLM推理引擎怎么选?TensorRT vs vLLM vs LMDeploy vs MLC-LLM
有很多个框架和包可以优化LLM推理和服务,所以在本文中我将整理一些常用的推理引擎并进行比较。
394 2
|
3月前
|
算法 异构计算
自研分布式训练框架EPL问题之帮助加速Bert Large模型的训练如何解决
自研分布式训练框架EPL问题之帮助加速Bert Large模型的训练如何解决
|
11月前
|
自然语言处理 测试技术 异构计算
使用Accelerate库在多GPU上进行LLM推理
大型语言模型(llm)已经彻底改变了自然语言处理领域。随着这些模型在规模和复杂性上的增长,推理的计算需求也显著增加。为了应对这一挑战利用多个gpu变得至关重要。
1578 0