【Bug已解决】[Web] InferenceSession.RunOptions.terminate not working as expected (reopen) 解决方案
【Bug已解决】[Web] InferenceSession.RunOptions.terminate not working as expected (reopen) 解决方案一、现象长什么样在 Web 端ONNX Runtime Web浏览器里跑推理想在中途取消一个正在进行的session.run()比如用户切走、或超时。ORT 提供了RunOptions.terminate标志设置后应当让正在跑的推理停止。但在 Web 后端上设置了terminate却根本不停推理照样跑完const session await ort.InferenceSession.create(model.onnx, { executionProviders: [webgpu], }); const runOptions {}; // terminate 通过某种方式设置 // 中途想取消 session.terminate?.(); // 期望停止但实际没停 const out await session.run(feed, runOptions); // 仍然跑完才返回最小信号设置 terminate - Web 上推理不中断照常返回结果 同款 terminate 在 CPU EP / 原生环境能中断注意这是“取消无效”不是崩溃。题目标了(reopen)说明之前修过、又复现了——典型是修了一处、另一处路径仍不检查 terminate。二、背景RunOptions.terminate或 C API 的OrtRunOptions里一个terminate标志的机制是推理执行过程中各个算子/执行层在合适的检查点轮询这个标志一旦发现被置位就抛出“已取消”的异常中断整条执行。在原生CPU/CUDAEP 上算子执行是逐 op、逐循环的容易在循环里插入if (terminate) throw。但在WebWebGPU/WebNN上一次推理往往被录制成一整个 GPU 命令缓冲command buffer一次性提交给 GPU。命令缓冲一旦提交GPU 就在“黑盒”里跑完CPU 侧的 JS 没法在它执行到一半时插进去检查terminate标志——除非执行层把整条图切成多个可轮询的检查点每个子图提交后CPU 先检查 terminate 再决定是否提交下一段。reopen说明之前可能在某个 EP 路径加了检查但 Web 后端或其中某些算子/子图划分方式仍把整条图当成一个不可中断的大命令缓冲提交terminate 只在最开始或最末尾检查中间不检查 - 取消无效。三、根因根因是Web 后端的推理执行把整条图录制成单个不可中断的 GPU 命令缓冲执行层没有在子图/算子边界轮询terminate标志导致中途取消无效单命令缓冲不可中断WebGPU/WebNN 把整图提交成一个 command bufferGPU 跑到底CPU 侧无法中途插入检查。terminate 检查点缺失执行层只在run()入口提交前或出口取结果后检查 terminate没在“每段提交后”检查于是提交后设 terminate 已经来不及。reopen 的根因之前可能只在某个 EP如 CPU path 或某个 Web 子图模式加了检查但 Web 的另一种执行路径如整图融合、或大算子仍走不可中断提交于是复现。不是结果错推理照常出结果只是取消不掉浪费算力、UI 卡顿。所以这不是数值错而是Web 后端缺“可中断执行 中途轮询 terminate”的机制。四、最小可运行复现下面用 JS 风格的伪代码模拟“整图一次性提交中途 terminate 无效”// 模拟 Web 后端执行整图当成一个不可中断任务 async function runGraph(graph, terminateFlag) { // 提交前检查一次 if (terminateFlag.raised) throw new Error(cancelled); // 一次性把整图提交给 GPU中间不检查 terminate await gpuSubmitWholeGraph(graph); // 黑盒跑完 // 取结果后才检查 - 太晚了 if (terminateFlag.raised) throw new Error(cancelled); return graph.result; } // 使用方中途想取消 const flag { raised: false }; const p runGraph(graph, flag); setTimeout(() { flag.raised true; }, 10); // 中途置位 await p; // 仍然跑完才返回 - terminate 无效跑这个逻辑因为gpuSubmitWholeGraph是一次性不可中断的flag.raised在提交后才置位、取结果时才检查已经来不及 - 推理照常返回。这正是 terminate 无效的机制。修复是把图切成多段每段提交后检查 terminate。五、解决方案第一层最小直接修复最小修复让 Web 后端把图切成多个可轮询的检查点每段 GPU 命令提交后在 CPU 侧检查terminate再决定是否继续。对使用者临时规避是给推理加外层超时/AbortController超时就不等结果虽然 GPU 仍在跑但 JS 侧不再阻塞// 外层超时兜底不能真正中断 GPU但 JS 侧不卡 function withTimeout(promise, ms) { return Promise.race([ promise, new Promise((_, rej) setTimeout(() rej(new Error(timeout)), ms)), ]); } const out await withTimeout(session.run(feed, runOptions), 5000);对 ORT 仓库侧修复是改 Web 执行层在生成 GPU 命令时按子图/算子边界分块提交每块提交后await微任务并轮询RunOptions.terminate置位则抛取消异常、停止后续提交。这一层让 terminate 真正生效。六、解决方案第二层结构性改进把“Web 推理如何支持可中断中途轮询 terminate”收口成唯一的配置对象OrtWebSessionTerminatePolicyWeb 执行层读它from dataclasses import dataclass, field from typing import Tuple, Literal dataclass(frozenTrue) class OrtWebSessionTerminatePolicy: Web 端 terminate 可中断执行的单一事实来源。 # 是否把图切成可轮询检查点的子段而非单命令缓冲 split_into_checkpoints: bool True # 每个检查点提交后轮询 terminate 的间隔算子/子图边界 poll_after: Literal[every_subgraph, every_op] every_subgraph # terminate 置位后的行为 on_terminate: Literal[throw_cancel, stop_submit] throw_cancel # 受影响后端 web_backends: Tuple[str, ...] (webgpu, webnn) def describe(self) - str: return Web 推理分段提交每段后轮询 terminate置位即中断 POLICY OrtWebSessionTerminatePolicy() def plan_terminate(policy: OrtWebSessionTerminatePolicy POLICY) - dict: return { split: policy.split_into_checkpoints, poll: policy.poll_after, action: policy.on_terminate, }所有 Web 执行层读同一份POLICYterminate 在所有子图路径都生效避免 reopen。七、解决方案第三层断言 / CI 守护把“Web terminate 可中断”做成断言。下面用 pytest 风格守护用模拟对象验证分段轮询import pytest def test_split_into_checkpoints(policy): assert policy.split_into_checkpoints is True def test_poll_after_subgraph(policy): assert policy.poll_after in (every_subgraph, every_op) def test_on_terminate_action(policy): assert policy.on_terminate throw_cancel def test_web_backends_covered(policy): assert webgpu in policy.web_backends assert webnn in policy.web_backends这四组断言锁住(1) 分段提交(2) 每段轮询 terminate(3) 置位即中断(4) Web 后端覆盖。CI 跑通即代表 terminate 在 Web 上真正可中断。八、排查清单遇到 Web 上 terminate 取消无效reopen先确认其它 EP 是否能取消CPU EP 能、Web 不能 - 锁定 Web 执行层。看是否整图单命令缓冲是不是提交后不检查 terminate 直接跑完。查检查点执行层有没有在子图/算子边界轮询 terminate。临时规避外层Promise.race超时兜底不阻塞 JS。根本修复图分段提交每段后轮询 terminate置位抛取消。统一策略对象用OrtWebSessionTerminatePolicy固化。CI 守护断言分段、轮询、后端覆盖防 reopen。九、小结[Web] InferenceSession.RunOptions.terminate not working as expected (reopen)的根因是Web 后端把整条图录制成单个不可中断的 GPU 命令缓冲提交执行层只在提交前/取结果后检查terminate标志没在子图/算子边界轮询于是中途置位 terminate 已经来不及取消无效之前只修了一处路径另一处仍整图提交导致 reopen。最小修复是让 Web 执行层把图分段提交、每段后轮询 terminate或外层Promise.race超时兜底结构性改进是用唯一的OrtWebSessionTerminatePolicy固化可中断执行CI 用四组断言守护“分段提交、每段轮询、置位即中断、Web 后端覆盖”。记住GPU 命令缓冲一旦提交就不可中途打断要让 terminate 生效必须把图切成可轮询的检查点。

相关新闻

如何快速配置Torrentio:5分钟搞定Stremio流媒体资源聚合

如何快速配置Torrentio:5分钟搞定Stremio流媒体资源聚合

如何快速配置Torrentio:5分钟搞定Stremio流媒体资源聚合 【免费下载链接】torrentio-scraper 项目地址: https://gitcode.com/GitHub_Trending/to/torrentio-scraper 还在为找不到高清影视资源而烦恼吗?Torrentio作为Stremio生态中最实用的流媒体…

2026/10/9 7:03:14 阅读更多 →
告别代码焦虑与排版混乱:深度评测2024年主流毕业设计网站建设软件项目,帮大学生高效搞定视觉呈现与功能落地

告别代码焦虑与排版混乱:深度评测2024年主流毕业设计网站建设软件项目,帮大学生高效搞定视觉呈现与功能落地

说实话,写这篇文章的时候,我刚刚合上笔记本电脑,看着窗外那个总是亮着的台灯,心里其实是有点恍惚的。又一年毕业季来了,校园里那股子焦灼、兴奋又带点迷茫的气息,隔着屏幕似乎都能闻得到。每年的这个时候,我的手机总会收到好几条来自学弟学妹的求助,主题千奇百怪,但核…

2026/10/5 15:25:36 阅读更多 →
无需Root也能让安卓手机焕然一新?Universal Android Debloater深度体验

无需Root也能让安卓手机焕然一新?Universal Android Debloater深度体验

无需Root也能让安卓手机焕然一新?Universal Android Debloater深度体验 【免费下载链接】universal-android-debloater Cross-platform GUI written in Rust using ADB to debloat non-rooted android devices. Improve your privacy, the security and battery lif…

2026/9/28 22:05:12 阅读更多 →

最新新闻

.NET ILogger日志体系详解:从结构化日志到生产级配置实战

.NET ILogger日志体系详解:从结构化日志到生产级配置实战

做后端服务这些年,日志一直是我觉得最值得花心思打磨的基础设施。很多兄弟可能觉得日志嘛,不就是到处打Console.WriteLine或者Debug.WriteLine,出了问题打开控制台看一下就行。但等你真正把一个服务跑上生产,几千个请求涌进来的时…

2026/10/9 12:58:38 阅读更多 →
深入解析.NET ILogger:解锁稳健日志系统的核心机制

深入解析.NET ILogger:解锁稳健日志系统的核心机制

日志这件事,在.NET的开发圈子里一直是老生常谈的热门话题。以前我们用Log4Net或NLog,都是直接引用具体日志库,代码里到处是 LogManager.GetCurrentClassLogger() 这种静态调用。日志系统一旦绑定到具体实现,后面想换方案简直像脱…

2026/10/9 12:58:38 阅读更多 →
二次曲面分类记忆法:从方程结构快速判断曲面类型

二次曲面分类记忆法:从方程结构快速判断曲面类型

1. 为什么二次曲面总让人记不住1.1 从“背了忘、忘了背”的死循环说起但凡学过空间解析几何或者高等数学下册的人,大概率都有过这么一段经历:翻开课本,二次曲面那一章扑面而来的是椭球面、单叶双曲面、双叶双曲面、椭圆抛物面、双曲抛物面、二…

2026/10/9 12:58:38 阅读更多 →
AI科研味觉评估:TasteVal框架原理与五维诊断实践

AI科研味觉评估:TasteVal框架原理与五维诊断实践

1. 项目概述:这不是在给AI打分,而是在校准它的“味觉神经”最近在几个AI研究社区里,反复看到一个词被拎出来讨论:“TasteVal”。不是美食测评,也不是咖啡品鉴,而是把“taste”这个词硬生生拽进AI评估的实验…

2026/10/9 12:58:38 阅读更多 →
基于SpringBoot+Vue+MySQL的学生宿舍管理系统设计与实现

基于SpringBoot+Vue+MySQL的学生宿舍管理系统设计与实现

每年到这个节点,总有同学在群里问宿舍管理系统怎么做。市面上的教程要么只有零散代码,要么数据库脚本和实体类对不上,要么压根跑不起来。我去年完整做了一套基于SpringBootVueMySQL的学生宿舍管理系统,从设计数据库到写接口、做页…

2026/10/9 12:58:38 阅读更多 →
Transformer生成式文本摘要实战:从环境配置到Beam Search调优

Transformer生成式文本摘要实战:从环境配置到Beam Search调优

简介:本资源是一份面向NLP初学者与进阶开发者的Transformer生成式文本摘要实战代码包,聚焦自然语言处理中的核心任务——自动摘要,适用于新闻提炼、论文速读、报告精简等实际场景。压缩包共10个文件,含5个Python源码(涵…

2026/10/9 12:57:34 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →