【Bug已解决】[Web] DB-style detection model returns all-zero output on Apple M-series above ~2048px inpu…
【Bug已解决】[Web] DB-style detection model returns all-zero output on Apple M-series above ~2048px input - likely fp16 overflow in ReduceMean 解决方案一、现象长什么样一个 DB 风格Differentiable Binarization文字检测的 ORT 模型在 Apple M 系列芯片上通过 WebGPU / CoreML EP 跑推理。输入图片小的时候比如 1024x1024输出正常但一旦边长超过约 2048px输出整体变成全零概率图、阈值图全 0检测彻底失效// Web 端ONNX Runtime Web加载 const session await ort.InferenceSession.create(db_detect.onnx, { executionProviders: [webgpu], // Apple M 系列走 Metal }); const out await session.run(feed); // input 2048x2048 - out 全 0input 1024x1024 - 正常最小复现信号输入边长 2048px : 输出正常有非零概率 输入边长 2048px : 输出全 0 阈值恰好在 2048 附近像“数值溢出后归零”注意模型能跑、不报错只是大图时数值溢出导致结果归零。这不是逻辑错是数值精度问题。二、背景DB 检测模型的头部有一个概率图生成步骤对特征图做ReduceMean或ReduceSum/Softmax前的求和把通道维聚合成单通道概率。整个过程在 Apple M 系列上走的是 fp16半精度路径 - WebGPU/Metal 的f16是原生类型ORT 在 Apple 上为了性能默认用 fp16 执行。fp16 的表示范围大约是 /-65504相对精度约 3 位十进制。问题在于ReduceMean的实现如果它在 fp16 下逐个元素累加再除以个数大图2048x2048 的特征图像素数约 4M累加时部分和会远超 65504 然后上溢成 infinf 参与后续Sigmoid/exp运算变成 nan / 0最终概率图被钳到 0表现为全零输出。而 1024x1024约 1M 像素时累加和还没超 65504所以正常。阈值约 2048px 恰好对应累加和突破 fp16 上限的临界点。这就是 “likely fp16 overflow in ReduceMean”。三、根因根因是 Apple M 系列 fp16 路径下的ReduceMean用 fp16 累加大图特征部分和溢出 fp16 上限/-65504变成 inf/nan 后结果归零fp16 累加溢出ReduceMean在 fp16 精度下逐元素求和特征图元素多2048 的平方量级时部分和轻松破 65504直接 inf。溢出传染inf 进Sigmoid/exp变成 nan 或 0再经Clip/Cast被钳成 0输出全零。只在 Applefp16 原生明显x86 上 ORT 可能用 fp32 跑、或 Metal 的 fp16 累加更易触发CPU fp32 路径完全不受影响所以小图正常、大图归零、只在 M 系列。不是模型结构错同样的 ONNX 在 CPU fp32 上大图也正常说明是 EP 的数值实现问题。所以这不是逻辑错而是 fp16 归约缺乏数值稳定性没用 fp32 累加器 / Kahan 补偿大图溢出归零。四、最小可运行复现下面用 NumPy 模拟 “fp16 ReduceMean 大图溢出归零”用float16累加复现import numpy as np def reduce_mean_fp16_naive(x): 有 bug 的实现在 fp16 下逐元素累加Apple M 的 fp16 路径。 acc np.float16(0.0) for v in x.flatten(): acc acc np.float16(v) # fp16 累加大数组溢出 return float(acc) / x.size def reduce_mean_fp32(x): 正确实现用 fp32 累加最后再转回。 return float(np.mean(x.astype(np.float32))) if __name__ __main__: # 模拟 2048x2048 特征图元素均值约 1.0如激活值 big np.ones(2048 * 2048, dtypenp.float32) naive reduce_mean_fp16_naive(big) correct reduce_mean_fp32(big) print(fp16 朴素累加:, naive, inf/nan 即为溢出) print(fp32 累加 :, correct) # 朴素 fp16 累加 4M 个 1.0 - 远超 65504 - inf assert (not np.isfinite(naive)) or naive ! correct print(复现大图 fp16 累加溢出 - 归约结果 inf - 输出归零)跑出来朴素 fp16 累加得到inf或不稳定值fp32 得到正确的1.0。这正好复现大图 fp16 ReduceMean 溢出归零的机制。五、解决方案第一层最小直接修复最小修复让ReduceMean及相关归约在 fp16 路径下用 fp32 累加器或干脆对这个模型用 fp32 执行。Web 侧可以这样// 方案 A对归约相关节点强制 fp32若 ORT Web 暴露该选项 const session await ort.InferenceSession.create(db_detect.onnx, { executionProviders: [{ name: webgpu }], graphOptimizationLevel: all, }); // 或在导出时把 ReduceMean 之后的头部数据类型固定为 fp32 // 方案 B导出时把特征图头部的 ReduceMean 输入限制在 fp32 精度 // 用 onnx 修改工具把对应节点的 dtype 标成 fp32对 ORT 仓库侧修复是改 Apple/Metal 的ReduceMean内核归约累加用 fp32或float2双缓冲做部分和最后再转 fp16 输出。这一层立刻让大图输出正常。六、解决方案第二层结构性改进把 “哪些算子在 fp16 路径下必须用 fp32 累加” 收口成唯一的配置对象OrtWebReduceMeanFp16PolicyWeb 加载与内核选择读它from dataclasses import dataclass, field from typing import Tuple dataclass(frozenTrue) class OrtWebReduceMeanFp16Policy: Apple M 系列 fp16 归约数值稳定的单一事实来源。 # 必须在 fp16 路径下用 fp32 累加的算子 fp32_accum_ops: Tuple[str, ...] (ReduceMean, ReduceSum, ReduceL2, Softmax) # 触发 fp32 累加的“大图阈值”特征图元素数超过此值必用 fp32 累加 overflow_pixel_threshold: int 2048 * 2048 # 是否全局强制这些算子 fp32 执行最稳略慢 force_fp32_for_these_ops: bool False # 平台限定Apple M 系列 Metal fp16 原生易溢出 affected_platforms: Tuple[str, ...] (apple, m-series, metal, webgpu) def needs_fp32_accum(self, op_type: str, num_pixels: int) - bool: if op_type not in self.fp32_accum_ops: return False if self.force_fp32_for_these_ops: return True return num_pixels self.overflow_pixel_threshold def describe(self) - str: return 大图 ReduceMean 等在 fp16 路径用 fp32 累加防溢出归零 POLICY OrtWebReduceMeanFp16Policy() def plan_reduce(op_type: str, num_pixels: int, policy: OrtWebReduceMeanFp16Policy POLICY) - str: return fp32_accum if policy.needs_fp32_accum(op_type, num_pixels) else fp16所有 Web 加载与内核选择读同一份POLICY大图归约自动用 fp32 累加避免溢出。七、解决方案第三层断言 / CI 守护把 “大图 ReduceMean 不溢出、数值稳定” 做成断言。下面用 pytest 风格守护复用第四节逻辑import numpy as np def test_large_image_mean_finite(): big np.ones(2048 * 2048, dtypenp.float32) assert np.isfinite(reduce_mean_fp32(big)) assert abs(reduce_mean_fp32(big) - 1.0) 1e-3 def test_fp32_accum_for_large_reduce(policy): assert policy.needs_fp32_accum(ReduceMean, 2048 * 2048 1) is True assert policy.needs_fp32_accum(ReduceMean, 1024 * 1024) is False def test_affected_platform_covers_apple(policy): assert apple in policy.affected_platforms def test_reduce_ops_listed(policy): assert ReduceMean in policy.fp32_accum_ops这四组断言锁住(1) 大图均值有限且正确(2) 大图 ReduceMean 触发 fp32 累加、小图不触发(3) 平台覆盖 Apple(4) 归约算子已列入名单。CI 跑通即代表大图不会溢出归零。八、排查清单遇到 Apple M 系列上大图 DB 检测输出全零先换 EP / 精度验证用 CPU fp32 跑大图若正常 - 锁定 fp16 数值问题。看阈值是否在 2048px 附近是的话高度怀疑 fp16 累加溢出。查 ReduceMean 内核Apple/Metal 的 fp16 归约是不是用 fp16 累加应改 fp32 累加。临时规避对该模型强制 fp32 执行或导出时把归约头部标 fp32。根本修复改 Metal ReduceMean 内核用 fp32 部分和最后转 fp16。统一策略对象用OrtWebReduceMeanFp16Policy固化大图阈值与算子名单。CI 守护断言大图 ReduceMean 数值有限、触发 fp32 累加。九、小结[Web] DB-style detection model returns all-zero output on Apple M-series above ~2048px input - likely fp16 overflow in ReduceMean的根因是Apple M 系列 fp16 路径下的ReduceMean在 fp16 精度下逐元素累加大图特征部分和超过 fp16 上限 /-65504 后变成 inf/nan经 Sigmoid/exp 传染后概率图被钳成 0表现为大图2048px输出全零小图累加和未超上限所以正常CPU fp32 路径不受影响。最小修复是让 ReduceMean 在 fp16 路径用 fp32 累加器或对该模型强制 fp32结构性改进是用唯一的OrtWebReduceMeanFp16Policy固化“大图阈值 必须用 fp32 累加的算子名单”CI 用四组断言守护“大图均值有限、触发 fp32 累加、平台覆盖 Apple、算子已列入”。记住fp16 归约一定要用 fp32 累加器大图累加必溢出否则结果悄悄归零。

相关新闻

【Bug已解决】QMoE per-channel quantization produces garbage results on CUDA EP, correct on CPU EP 解决方案

【Bug已解决】QMoE per-channel quantization produces garbage results on CUDA EP, correct on CPU EP 解决方案

【Bug已解决】QMoE per-channel quantization produces garbage results on CUDA EP, correct on CPU EP 解决方案 一、现象长什么样 用 ONNX Runtime 的 QMoE(量化 MoE)跑一个做了 per-channel 量化 的专家权重模型。同一个 ONNX,CPUExecuti…

2026/10/14 0:18:41 阅读更多 →
3步搞定M3U8视频下载:告别命令行恐惧的图形化解决方案

3步搞定M3U8视频下载:告别命令行恐惧的图形化解决方案

3步搞定M3U8视频下载:告别命令行恐惧的图形化解决方案 【免费下载链接】N_m3u8DL-CLI-SimpleG N_m3u8DL-CLIs simple GUI 项目地址: https://gitcode.com/gh_mirrors/nm3/N_m3u8DL-CLI-SimpleG 你是否曾遇到心仪的网络视频却无法保存的困扰?&…

2026/10/7 23:24:52 阅读更多 →
Python键盘监听与自动化脚本:从pynput入门到热键管理器实战

Python键盘监听与自动化脚本:从pynput入门到热键管理器实战

1. 从一次重复性操作说起:为什么我们需要键盘监听如果你和我一样,每天的工作都离不开电脑,那你一定遇到过这样的场景:需要反复执行某个固定的操作序列,比如在某个软件里点击一连串的菜单项,或者在不同的窗口…

2026/10/7 20:42:38 阅读更多 →

最新新闻

八字排盘四千年:节气计算与儒略日工程实践

八字排盘四千年:节气计算与儒略日工程实践

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

2026/10/14 1:09:04 阅读更多 →
ESMM如何解决推荐系统中的CVR预估偏差问题

ESMM如何解决推荐系统中的CVR预估偏差问题

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

2026/10/14 1:09:04 阅读更多 →
jQuery UI Layout插件:五区模型实现可拖拽后台布局

jQuery UI Layout插件:五区模型实现可拖拽后台布局

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

2026/10/14 1:09:04 阅读更多 →
硬件板上调试顺序:电源、时钟、复位与通信信号抓取指南

硬件板上调试顺序:电源、时钟、复位与通信信号抓取指南

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

2026/10/14 1:09:04 阅读更多 →
Zabbix 4.0 数据收集全链路解析:从 Agent 配置到大规模优化实践

Zabbix 4.0 数据收集全链路解析:从 Agent 配置到大规模优化实践

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

2026/10/14 1:09:04 阅读更多 →
算法概览图:用拓扑建模实现原理级动画可视化

算法概览图:用拓扑建模实现原理级动画可视化

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

2026/10/14 1:08:04 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/13 22:01:27 阅读更多 →
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/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →