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

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


目录
相关文章
|
4月前
|
机器学习/深度学习 人工智能 负载均衡
基于 NVIDIA Megatron-Core 的 MoE LLM 实现和训练优化
本文将分享阿里云人工智能平台 PAI 团队与 NVIDIA Megatron-Core 团队在 MoE (Mixture of Experts) 大型语言模型(LLM)实现与训练优化上的创新工作。
|
4月前
|
机器学习/深度学习 并行计算 PyTorch
TensorRT部署系列 | 如何将模型从 PyTorch 转换为 TensorRT 并加速推理?
TensorRT部署系列 | 如何将模型从 PyTorch 转换为 TensorRT 并加速推理?
737 0
|
4月前
|
机器学习/深度学习 Java TensorFlow
模型推理脚本
模型推理脚本可以使用各种编程语言编写,如Python、C++、Java等。在机器学习和深度学习领域中,Python是最常用的编程语言之一,因为它有许多流行的深度学习框架,如TensorFlow、PyTorch和Keras,这些框架都提供了简单易用的API来加载模型和进行模型推理。
127 5
|
11月前
|
机器学习/深度学习 人工智能 API
使用TensorRT-LLM进行高性能推理
LLM的火爆之后,英伟达(NVIDIA)也发布了其相关的推理加速引擎TensorRT-LLM。TensorRT是nvidia家的一款高性能深度学习推理SDK。此SDK包含深度学习推理优化器和运行环境,可为深度学习推理应用提供低延迟和高吞吐量。而TensorRT-LLM是在TensorRT基础上针对大模型进一步优化的加速推理库,它号称可以增加4倍的推理速度。
514 0
|
11月前
|
运维 并行计算 C语言
TensorRT-LLM在CodeFuse-CodeLlama-34B上的int4量化实践
Codefuse是由蚂蚁集团开发的专门用于支持整个软件开发生命周期的大型代码语言模型(Code LLMs),涵盖设计、需求、编码、测试、部署、运维等关键阶段。致力于打造创新的解决方案,让软件开发者们在研发的过程中如丝般顺滑。
385 0
|
4月前
|
机器学习/深度学习 人工智能 Cloud Native
大语言模型推理提速,TensorRT-LLM 高性能推理实践
大型语言模型(Large language models,LLM)是基于大量数据进行预训练的超大型深度学习模型,本文主要讲述TensorRT-LLM利用量化、In-Flight Batching、Attention、Graph Rewriting提升 LLM 模型推理效率。
101261 2
|
23天前
|
机器学习/深度学习 并行计算 PyTorch
ONNX 优化技巧:加速模型推理
【8月更文第27天】ONNX (Open Neural Network Exchange) 是一个开放格式,用于表示机器学习模型,使模型能够在多种框架之间进行转换。ONNX Runtime (ORT) 是一个高效的推理引擎,旨在加速模型的部署。本文将介绍如何使用 ONNX Runtime 和相关工具来优化模型的推理速度和资源消耗。
187 4
|
2月前
|
并行计算 PyTorch 算法框架/工具
LLM推理引擎怎么选?TensorRT vs vLLM vs LMDeploy vs MLC-LLM
有很多个框架和包可以优化LLM推理和服务,所以在本文中我将整理一些常用的推理引擎并进行比较。
231 2
|
9月前
|
自然语言处理 测试技术 异构计算
使用Accelerate库在多GPU上进行LLM推理
大型语言模型(llm)已经彻底改变了自然语言处理领域。随着这些模型在规模和复杂性上的增长,推理的计算需求也显著增加。为了应对这一挑战利用多个gpu变得至关重要。
1437 0
|
4月前
|
机器学习/深度学习 并行计算 PyTorch
【多GPU炼丹-绝对有用】PyTorch多GPU并行训练:深度解析与实战代码指南
本文介绍了PyTorch中利用多GPU进行深度学习的三种策略:数据并行、模型并行和两者结合。通过`DataParallel`实现数据拆分、模型不拆分,将数据批次在不同GPU上处理;数据不拆分、模型拆分则将模型组件分配到不同GPU,适用于复杂模型;数据和模型都拆分,适合大型模型,使用`DistributedDataParallel`结合`torch.distributed`进行分布式训练。代码示例展示了如何在实践中应用这些策略。
1587 2
【多GPU炼丹-绝对有用】PyTorch多GPU并行训练:深度解析与实战代码指南