
ONNX Runtime WebGPU EP ABI 适配器插件式动态执行提供者的设计与实现解析【免费下载链接】onnxruntimeONNX Runtime: cross-platform, high performance ML inferencing and training accelerator项目地址: https://gitcode.com/GitHub_Trending/on/onnxruntime本文以 onnxruntime/core/providers/webgpu/ep/README.md 为核心深入剖析 ONNX Runtime WebGPU 执行提供者EP在“EP ABI 适配器”架构下的设计取舍与源码实现静态库构建如何保持零改动、动态库构建如何仅依赖 EP ABI 并通过桥接类连接内部实现、导出符号与版本脚本如何收敛 DLL 接口以及构建系统中版本号的注入方式。读完本文你将掌握 WebGPU EP 插件化Plugin EP的完整机制包括设备枚举、内存分配器、数据布局协商、图捕获Graph Capture等关键 API 的实现路径并能理解 README 中列出的“缺失部分”当前在源码中的落地状态。一、定位ep文件夹是 WebGPU 的 EP ABI 适配层onnxruntime/core/providers/webgpu/ep/ 目录下的 README 开门见山地说明了该目录的职责The current folder contains the implementation of EP ABI adapter for WebGPU.也就是说整个 WebGPU EP 的推理内核program_manager、buffer_manager、wgsl 着色器模板等见 onnxruntime/core/providers/webgpu/在静态库构建下直接链接进onnxruntime主库而在插件化场景下同一套内核被封装为一个独立的动态库Windows 下为onnxruntime_providers_webgpu.dll通过 ONNX Runtime 定义的EP ABIExecution Provider ABI即OrtEpFactory/OrtEp函数表结构与主运行时解耦通信。目录结构如下各文件职责清晰文件职责ep.h / ep.ccEp桥接类实现OrtEp函数表连接 EP ABI 与内部WebGpuExecutionProviderfactory.h / factory.ccFactory类实现OrtEpFactory函数表负责设备枚举、创建 EP 实例、共享分配器与数据搬运api.cc动态库仅有的两个导出符号CreateEpFactories/ReleaseEpFactory的实现symbols.defWindows 导出定义文件.defversion_script.ldsLinux/Unix 链接器版本脚本限定导出符号versioninfo.rcWindows DLL 资源版本信息二、README 的核心设计约束静态库零改动动态库“只用 EP ABI”README 的 “Design considerations” 一节给出了三条设计决策这些决策直接决定了源码的组织方式静态库构建不做任何改动“No changes to static library build. It should still work as before.”。WebGPU 在静态构建下仍是内置 EP原有的GetProvider路径继续工作。动态库只使用、且仅使用 EP ABI“use and only use the EP ABI. (no support forGetProvider)”。插件库不再依赖主库的内部 C 符号发现机制避免 ABI 耦合。动态库仍然依赖 onnxruntime 各构建目标“still depends on onnxruntime targets”并通过桥接类bridge把 EP ABI 的内部类连接起来。这第 3 点在 cmake/onnxruntime_providers_webgpu.cmake 中有直接印证动态库目标onnxruntime_providers_webgpu链接了onnxruntime_optimizer、onnxruntime_providers、onnxruntime_lora、onnxruntime_framework、onnxruntime_graph、onnxruntime_util、onnxruntime_common、onnxruntime_flatbuffers等内部目标——插件 EP 复用了大量主库代码只是对外接口收敛到 EP ABI。构建方式上还有两条硬约束cmake/onnxruntime_providers_webgpu.cmake共享库构建不支持 build cache且Emscripten 平台不支持共享库构建WASM 场景请使用静态库否则 CMake 会直接报错终止。三、导出面整个动态库只有两个 C 符号无论 Windows 还是 Linux插件库的导出符号都被严格限定为两个symbols.defWindowsLIBRARY onnxruntime_providers_webgpu.dll EXPORTS CreateEpFactories 1 ReleaseEpFactory 2version_script.ldsLinuxVERS_1.0.0 { global: CreateEpFactories; ReleaseEpFactory; local: *; };这两个符号正是 README 所说“use and only use the EP ABI”的落地点。cmake/onnxruntime_providers_webgpu.cmake 中按平台分别挂上链接选项Linux 使用--version-script.../ep/version_script.lds、--gc-sections与-rpath$ORIGINWindows 使用-DEF:.../ep/symbols.defmacOS 则仅附加-dead_strip符号导出依赖 api.cc 中的EXPORT_SYMBOLvisibility 属性。3.1CreateEpFactories插件入口api.cc 中的CreateEpFactories由 ORT 主库在加载插件动态库时调用其执行流程为手动初始化 C API 层以ORT_API_MANUAL_INIT模式包含onnxruntime_cxx_api.h并调用onnxruntime::ep::ApiInit(ort_api_base, ORT_PLUGIN_EP_MIN_ORT_VERSION)。这里传入的最小 ORT 版本宏在初始化失败时如宿主 ORT 版本过低会经由一个保守的report_errorlambda 创建OrtStatus——由于此时OrtApi尚未完成初始化代码用static_assert断言OrtApi::CreateStatus在 v1 API 中的偏移为 0保证即使只能拿到 v1 表也能安全创建错误对象。读取环境变量决定 Factory 行为见 factory.h 的Config结构环境配置项kOrtEnvAllowVirtualDevices值为1时允许注册一个虚拟 GPU 设备用于“无设备、仅编译”device-free compile-only会话典型场景是 Win32k-lockdown 沙箱等枚举不到 GPU 的主机环境变量ORT_WEBGPU_EP_ALLOW_SOFTWARE_ADAPTER设为1时允许在没有 GPU 硬件设备的情况下把 WebGPU EP 挂到CPU 硬件设备上使 EP 设备变得可选Dawn 独立选择软件适配器开启时还会打印 WARNING 日志。初始化全局默认 loggerLoggingManager::CreateDefaultLogger并构造唯一的Factory实例返回给宿主。3.2ReleaseEpFactory清理顺序即“缺失部分”的答案README 的 “Missing parts” 第一条提到“需要一种方式做 WebGPU 清理OrtEnv::~OrtEnv()目前在静态库构建下调用webgpu::CleanupWebGpuContexts()”。从当前源码看动态库构建中这个职责已经落在 api.cc 的ReleaseEpFactory中其清理链条为固定五步delete掉Factory实例其析构函数会释放虚拟硬件设备webgpu::CleanupKernelRegistries()清理缓存的 kernel 注册表webgpu::CleanupWebGpuContexts()清理 WebGPU 上下文LoggingManager::DestroyDefaultLogger()销毁默认日志包装google::protobuf::ShutdownProtobufLibrary()关闭 protobuf 库。这与静态库构建下OrtEnv析构时的清理形成了互补静态库由OrtEnv生命周期驱动动态库由插件工厂生命周期驱动。四、Factory设备枚举、EP 实例与共享分配器Factory继承自OrtEpFactory见 factory.h构造函数factory.cc完成三件事初始化OrtEpFactory函数表、预构造两组OrtMemoryInfodefault_memory_info_为OrtDeviceAllocatorreadonly_memory_info_为OrtReadOnlyAllocatorallocator name 均为WEBGPU_BUFFER、在allow_virtual_devices开启时通过Api().ep.CreateHardwareDevice注册带IsVirtual1元数据的虚拟 GPU 硬件设备。工厂自报身份为名字kWebGpuExecutionProvider、厂商Microsoft、vendor id0、版本ORT_PLUGIN_EP_VERSION。4.1GetSupportedDevices三层设备暴露策略factory.cc 按顺序做三件事真实 GPU遍历宿主传入的OrtHardwareDevice数组凡类型为OrtHardwareDeviceType_GPU的设备都包装成一个OrtEpDevice并挂上默认与只读两组 allocator info软件适配器回退allow_software_adapter开启且没有任何 GPU 设备时找到 CPU 硬件设备把 WebGPU EP 暴露在其上使 EP 在纯 CPU 主机上仍可选实际由 Dawn 选择软件适配器虚拟设备allow_virtual_devices开启时额外暴露虚拟 GPU EP 设备且不携带 allocator info——源码注释解释了原因虚拟设备仅支撑“停止在会话最终化之前的 compile-only 会话”从不分配内存若设置内存信息反而会让 ORT 尝试创建没有底层设备的共享 WebGPU 分配器。4.2CreateEp把内部WebGpuExecutionProvider包进Epfactory.cc 的CreateEpImpl是桥接发生的地方目前只支持一次一个设备num_devices ! 1直接报ORT_INVALID_ARGUMENT从OrtSessionOptions取出全部 session config entries 并灌入ConfigOptions再经WebGpuProviderFactoryCreator::Create(config_options)CreateProvider构造出真正的内部 EPWebGpuExecutionProvider——可以看到插件路径下session 配置项如webgpu_*选项的解析逻辑与静态构建完全复用虚拟设备 非 compile-only 组合会被前置拒绝若选中的设备元数据标记为虚拟但session.compile_only ! 1直接返回清晰的错误信息避免 Dawn 后续创建设备时的晦涩失败分配器策略若上下文HasDevice()为 false即无设备的 compile-only 会话CreateWebGpuAllocator会构造一个 no-op 分配器否则构造真正的GpuBufferAllocator。最终Ep::Config持有三个分配器CPU 分配器CPUAllocator::DefaultInstance()、设备分配器、以及 initializer 只读设备分配器指向InitializerBufferManager。4.3 共享分配器与数据搬运CreateAllocatorImplfactory.cc只接受allocator_type OrtDeviceAllocator、device_id 0、allocator name 为WEBGPU_BUFFER的OrtMemoryInfo底层包装成webgpu::GpuBufferAllocator绑定到默认 WebGPU 上下文的BufferManagerCreateDataTransferImplfactory.cc直接调用OrtWebGpuCreateDataTransfer()复用 WebGPU EP 的 host↔device 数据搬运实现IsStreamAware恒为falseCreateSyncStreamForDevice返回ORT_NOT_IMPLEMENTED——WebGPU EP 不是 stream-aware 的 EP。五、Ep桥接类EP ABI 函数表的逐项映射Ep继承自onnxruntime::ep::adapter::Ep见 ep.h构造函数ep.cc把OrtEp的每个函数表槽位绑定到对应的静态实现并显式地把不适用的槽位置空Compile nullptr、ReleaseNodeComputeInfos nullptrper-kernel 型 EP 不使用图级编译SetDynamicOptions nullptr未实现CreateSyncStreamForDevice nullptr非 stream-awareGetCompiledModelCompatibilityInfo nullptr不是 compiled EP。有实现的槽位逐一映射到内部WebGpuExecutionProvider的方法形成“EP ABI → 内部类”的一对一桥接EP ABI 函数桥接目标行为说明GetNameFactory::GetName返回kWebGpuExecutionProviderGetCapability见 5.1 节决定哪些节点交给 WebGPUGetKernelRegistryWebGpuExecutionProvider::GetKernelRegistryImpl()委托内部注册表ep.ccGetPreferredDataLayout/ShouldConvertDataLayoutForOpGetPreferredLayout()/ShouldConvertDataLayoutForOp()内部DataLayout枚举与OrtEpDataLayout一一对应NCHW0NHWC1未知 op 返回-1表示未表态OnRunStart/OnRunEndWebGpuExecutionProvider::OnRunStart/OnRunEndOnRunStart目前只透传kOrtRunOptionsConfigCudaGraphAnnotationgpu_graph_id这一条 run optionep.ccIsConcurrentRunSupported恒false不支持并发运行IsGraphCaptureEnabled/IsGraphCaptured/ReplayGraph/ReleaseCapturedGraph/GetGraphCaptureNodeAssignmentPolicy同名内部方法直通内部 WebGPU 图捕获实现ep.ccCreateAllocatoradapter::Allocator包装OrtReadOnlyAllocator映射到 initializer 分配器其余映射到设备分配器ep.cc5.1GetCapability节点分配与 CPU 回退逻辑GetCapabilityImplep.cc是插件路径下的图分区入口其判定流程为取图中全部节点EP 名已标注为 WebGPU 的节点直接进入候选集已标注为其他非 CPU EP的节点跳过拒绝重分配对未标注或标注 CPU 的节点先用EpGraphSupportInfo_LookUpKernel查询 kernel 注册表——查不到 kernel 即回退 CPU并打 INFO 日志webgpu kernel not found in registries for Op type: ...命中ForceCpuNodeNames强制 CPU 名单的节点回退 CPU针对com.microsoft域的Attention算子做细粒度能力检查不支持mask_indexinput[3]、pastinput[4]、past_seq_leninput[6]输入不支持presentoutput[1]输出且past_present_share_buffer属性非 0 时一律回退 CPU借助FALLBACK_TO_CPU_IF_EXIST_INPUT/OUTPUT宏实现ep.cc最后调用onnxruntime::ep::GetCpuPreferredNodes头文件ep/get_capability_utils.h做 CPU 偏好节点判定只有不在cpu_preferred_nodes中的候选节点才通过EpGraphSupportInfo_AddSingleNode正式划归 WebGPU。这套逻辑保证了插件路径与静态路径的节点分配语义一致注册表查不到 kernel 或能力不满足时节点自然留在 CPU 上执行而不是让整个会话失败。六、构建与版本治理版本号如何进入插件 DLL插件 EP 的版本信息有两条注入链均在 cmake/onnxruntime_providers_webgpu.cmake 中完成插件自身版本若未显式定义onnxruntime_PLUGIN_EP_VERSION默认取${ORT_VERSION}-dev编译为ORT_PLUGIN_EP_VERSION宏供Factory::GetVersionImpl返回最小兼容 ORT 版本以 plugin-ep-webgpu/MIN_ONNXRUNTIME_VERSION 文件当前内容为1.24.4格式要求严格的MAJOR.MINOR.PATCH为唯一事实来源读入并编译为ORT_PLUGIN_EP_MIN_ORT_VERSION宏——该宏在CreateEpFactories中传给ApiInit从而在插件加载期就强制校验宿主 ORT 版本是否足够新文件缺失或为空时 CMake 直接FATAL_ERROR。这与 plugin-ep-webgpu/ 目录下的打包工程VERSION_NUMBER、MIN_ONNXRUNTIME_VERSION、Python/C# 插件包构成同一套版本治理体系DLL 内自报的版本和最低宿主版本与发布物元数据保持一致。七、README “Missing parts” 的现状盘点README 最后列出了两项尚未完成的能力结合当前源码可以做如下对照WebGPU 清理的入口静态库下依赖OrtEnv::~OrtEnv()调用webgpu::CleanupWebGpuContexts()动态库下该职责已由ReleaseEpFactory的五步清理链承接见 3.2 节。从源码结构看动态库路径的清理问题已基本闭环README 该条目反映的是插件化早期状态。WebGPU “默认配置”的设置途径README 希望在 ORT C API 上提供类似SetCurrentGpuDeviceId的全局状态入口并进一步泛化为ORT_API2_STATUS(SetEpDefaultConfig, _In_ const char* ep_name, _In_ const char* key, _In_ const char* value);该 API 截至目前未在仓库中出现。当前的替代手段是通过 session options 配置项在CreateEpImpl中从OrtSessionOptions读取并灌入ConfigOptions以及环境变量ORT_WEBGPU_EP_ALLOW_SOFTWARE_ADAPTER、环境配置项allow_virtual_devices来控制插件行为。换言之面向“进程级默认配置”的通用 API 仍是 WebGPU EP ABI 适配层待补齐的一块。八、小结onnxruntime/core/providers/webgpu/ep/ 这套 EP ABI 适配器用极小的对外接口面CreateEpFactories/ReleaseEpFactory两个符号 ep.cc、factory.cc 两层桥接类实现了 WebGPU EP 的插件化静态库构建零改动继续走内置 EP 路径动态库构建下设备枚举含软件适配器回退与虚拟设备、内存分配、数据布局协商、运行生命周期与图捕获全部经由 EP ABI 函数表转发到既有的WebGuExecutionProvider内部实现WebGpuExecutionProvider。版本兼容性由MIN_ONNXRUNTIME_VERSION单一事实来源 编译期宏注入在加载期强制校验。对需要自行构建或排查 WebGPU 插件行为的开发者建议按“README 设计约束 →api.cc入口 →factory.cc设备/分配器 →ep.cc函数表映射”的顺序阅读源码即可完整还原插件从加载到执行的全链路。【免费下载链接】onnxruntimeONNX Runtime: cross-platform, high performance ML inferencing and training accelerator项目地址: https://gitcode.com/GitHub_Trending/on/onnxruntime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考