ORT:框架整体执行逻辑

如题所述

第1个回答  2024-04-05

ORT,作为微软主导的开源推理框架,其内部执行逻辑复杂而高效。它由总计约491,189行代码(C++和Python等)构建,提供强大的自定义编译选项,其编译脚本build.sh生成的可执行文件位于build/Linux/Debug目录下。


Python与C++的交互是ORT执行的核心桥梁。从Python 1.9版本起,创建InferenceSession需指定providers参数。通过get_available_providers接口,可以获取到可用的执行提供商,这个接口在core/providers/get_execution_providers.cc中有定义,它返回一个ProviderInfo数组,每个provider的启用可通过编译宏控制,其中CPUProvider默认启用。InferenceSession类的实现见于onnxruntime_inference_collection.py,初始化时,它会根据get_available_providers获取并存储可用providers。


Session.run()方法是推理的核心,它调用C++中的get_available_providers获取列表,并配置到_inference_session对象。onnxruntime.InferenceSession是Python对C++ InferenceSession类的封装,其Python接口包括initialize_session和run。关键接口背后,如`CreateInferencePybindStateModule`,负责定义接口,如初始化和运行操作,通过`addObjectMethods`来实现。


InferenceSession类的关键方法包括:构造函数负责初始化,Load负责模型加载,Initialize进行执行提供者注册和Session初始化,Run则执行模型推理。构造函数会执行一系列初始化步骤,如设置线程池和日志管理器,而Load函数则通过`LoadModelHelper`线程安全地调用`Model::Load`,负责从文件描述符解析ONNX模型。


在Load函数中,重要的是反序列化模型并创建Model对象,这被存储在InferenceSession的model_成员中。Initialize函数涉及一系列步骤,如加载模型表示、存储session信息、注册kernel信息,以及一系列图转换和优化操作。


特别是,执行计划的关键步骤包括:SequentialPlanner::CreatePlan的拓扑排序,用于确定节点运行顺序;CreateKernels为节点操作创建kernel实例;以及在InferenceSession::Run中,执行提供者自定义的初始化和结束操作。ExecuteGraph内部的OnRunStartOnRunEnd触发provider的定制动作,SequentialExecutor则负责按顺序执行Compute函数。


尽管本文未详尽阐述ORT的底层细节,但已经给出了一个概览,展示了其执行逻辑的概要结构。更多深入的技术剖析,如模型优化、provider管理和执行计划,可以参考官方代码:https://github.com/microsoft/onnxruntime