【Bug已解决】CPU EP mis-loads packed `UINT2` Constant initializer (treats `UInt2x4` as unpacked storage;…
【Bug已解决】CPU EP mis-loads packedUINT2Constant initializer (treatsUInt2x4as unpacked storage;INT2unaffected) 解决方案一、现象长什么样模型里有一个被量化成2-bit的权重常量用 ONNX 的UINT2打包数据类型在每个字节里塞 4 个 2-bit 元素UInt2x4存成Constant初始化器。在 ONNX Runtime 的 CPU EP 上加载并推理结果全是垃圾值和预期差很远余弦相似度接近 0或分类输出全错 —— 但同一个模型在 GPU EP 上结果正确最小触发import onnxruntime as ort # 模型含一个 UINT2 打包的 Constant 初始化器 sess ort.InferenceSession(uint2_model.onnx, providers[CPUExecutionProvider]) out sess.run(None, feed)[0] # 结果错误换成 providers[CUDAExecutionProvider] 结果正确排查发现CPU EP 把UInt2x4当成了未打包的存储来读——也就是按“每字节一个元素”去解释那块 buffer而实际上每字节装了 4 个 2-bit 元素。偏偏INT22-bit 有符号是正确的只有UINT2错。这是典型的“打包数据类型反序列化漏了一种”。二、背景ONNX 从 opset 21 起支持 2-bit 和 4-bit 的“打包”数据类型UINT2/INT2每字节 4 个、UINT4/INT4每字节 2 个。打包后的常量在 proto 里表现为外层 tensor 的elem_type是UINT2dims描述的是打包后的形状比如原始 1024 个元素打包成 256 个字节dims[256]原始元素个数靠data_type 一个packed属性或约定推断。加载时运行时需要识别elem_type UINT2按“每字节 4 个元素”做位解包bit-unpack还原出 1024 个 0~3 的值把解包后的张量交给后续算子。CPU EP 的常量加载器tensor deserializer对INT2写了正确的解包路径但对UINT2走错了分支——直接把dims[256]的字节 buffer 当 256 个完整uint8元素用没解包。于是 256 个字节被当成 256 个值范围 0255而不是 1024 个 03 的值形状也对不上后续算子拿到完全错误的数据。三、根因根因是CPU EP 的常量加载器对UINT2和INT2的处理不对称解包分支漏了UINT2加载器里有一张elem_type - 加载函数的映射INT2指向了“位解包到 int8”的实现UINT2却错误地指向了“原样按 uint8 读”的默认实现或根本没在映射里fallback 到逐字节读。形状未还原因为没解包dims停留在打包后的[256]而下游算子期望[1024]读出来的元素个数和语义全错。INT2 正常对照INT2因为有正确的解包实现所以无影响——这进一步说明不是“打包机制整体坏了”而是UINT2这一支被漏掉。所以这不是模型算错而是CPU EP 反序列化 2-bit 数据时漏了对无符号UINT2的解包把它当成了未打包的 uint8。四、最小可运行复现下面用 Python NumPy 模拟“UINT2 打包数据被错误地当 uint8 读取”的偏差并给出正确的位解包import numpy as np def wrong_load(packed: np.ndarray) - np.ndarray: CPU EP 当前的错误做法把每字节当 1 个 uint8 元素。 return packed.astype(np.uint8) # 256 个值值域 0~255且未解包 def correct_unpack_uint2(packed: np.ndarray) - np.ndarray: 正确做法每字节拆出 4 个 2-bit 无符号元素低位在前。 packed packed.astype(np.uint8) out np.zeros(packed.shape[0] * 4, dtypenp.uint8) for i in range(4): out[i::4] (packed (2 * i)) 0x03 return out if __name__ __main__: # 打包前原始 4 个元素 [0,1,2,3] - 打包成 1 字节 0b11100100? 计算 raw np.array([0, 1, 2, 3], dtypenp.uint8) packed np.zeros(1, dtypenp.uint8) for i, v in enumerate(raw): packed[0] | (v 0x03) (2 * i) print(packed byte:, int(packed[0])) # 0b00001111 15 wrong wrong_load(packed) right correct_unpack_uint2(packed) print(错误加载:, wrong, 形状, wrong.shape) # [15] 错 print(正确解包:, right, 形状, right.shape) # [0 1 2 3] 对 assert np.array_equal(right, raw)跑出来错误加载得到[15]一个 uint8正确解包得到[0 1 2 3]四个 2-bit 元素。这正好复现了 CPU EP 把UInt2x4当未打包存储读错的现象。五、解决方案第一层最小直接修复最小修复在常量加载器里给UINT2补上和INT2对称的解包实现。对使用者来说临时规避是把模型里的UINT2常量在导出时改成UINT4或UINT8未打包绕开 CPU EP 的UINT2解包 bug或者干脆用 GPU EP 跑GPU EP 解包正确。对 ORT 仓库侧加载器映射应改成// 伪代码常量加载器的 elem_type 分支 switch (elem_type) { case ONNX_NAMESPACE::TensorProto::UINT2: return LoadPackeduint8_t, 2, /*signed*/false(tensor); // 补这一支 case ONNX_NAMESPACE::TensorProto::INT2: return LoadPackedint8_t, 2, /*signed*/true(tensor); case ONNX_NAMESPACE::TensorProto::UINT4: return LoadPackeduint8_t, 4, /*signed*/false(tensor); case ONNX_NAMESPACE::TensorProto::INT4: return LoadPackedint8_t, 4, /*signed*/true(tensor); default: return LoadPlain(tensor); }LoadPacked负责按 bits2 做位解包并把dims从打包形状还原成原始元素个数dim[0] * 4。这一层立刻让UINT2常量被正确解包。六、解决方案第二层结构性改进把“哪些打包类型需要解包、如何解包”收口成唯一的配置对象OrtCpuUint2ConstantPolicy加载器读它避免再漏类型from dataclasses import dataclass, field from typing import Dict, Tuple dataclass(frozenTrue) class OrtCpuUint2ConstantPolicy: CPU EP 打包常量加载的单一事实来源。 # 打包类型 - (每字节元素数, 是否有符号) packed_types: Tuple[str, ...] (UINT2, INT2, UINT4, INT4) bits_per_element: Dict[str, int] field(default_factorylambda: { UINT2: 2, INT2: 2, UINT4: 4, INT4: 4, }) signed: Dict[str, bool] field(default_factorylambda: { UINT2: False, INT2: True, UINT4: False, INT4: True, }) # 是否必须解包True 表示不能当 uint8 原样读 must_unpack: Tuple[str, ...] (UINT2, INT2, UINT4, INT4) # 字节内位序低位在前 lsb_first: bool True def needs_unpack(self, elem_type: str) - bool: return elem_type in self.must_unpack def unpack_shape_scale(self, elem_type: str) - int: return 8 // self.bits_per_element.get(elem_type, 8) def describe(self) - str: return UINT2/INT2/UINT4/INT4 全部走对称位解包无符号与有符号一致 POLICY OrtCpuUint2ConstantPolicy() def plan_load(elem_type: str, policy: OrtCpuUint2ConstantPolicy POLICY) - dict: return { unpack: policy.needs_unpack(elem_type), scale: policy.unpack_shape_scale(elem_type), signed: policy.signed.get(elem_type, False), }所有加载逻辑读同一份POLICY新增打包类型只要在packed_types里加一项就自动覆盖不会再出现“INT2 有、UINT2 漏”的不对称。七、解决方案第三层断言 / CI 守护把“UINT2 必须解包、结果与 GPU EP 一致”做成断言。下面用 pytest 风格守护复用第四节解包逻辑import numpy as np def test_uint2_must_unpack(policy): assert policy.needs_unpack(UINT2) is True assert policy.needs_unpack(INT2) is True def test_uint2_symmetrical_with_int2(policy): # UINT2 与 INT2 应走相同的解包机制仅符号不同 assert policy.bits_per_element[UINT2] policy.bits_per_element[INT2] assert policy.signed[UINT2] is False assert policy.signed[INT2] is True def test_unpack_recovers_values(): raw np.array([0, 1, 2, 3], dtypenp.uint8) packed np.zeros(1, dtypenp.uint8) for i, v in enumerate(raw): packed[0] | (v 0x03) (2 * i) assert np.array_equal(correct_unpack_uint2(packed), raw) def test_shape_restored_after_unpack(policy): scale policy.unpack_shape_scale(UINT2) assert scale 4 # 每字节 4 个元素这四组断言锁住(1)UINT2必须解包(2)UINT2/INT2对称仅符号差异(3) 解包还原正确值(4) 形状按 4 倍还原。CI 跑通即代表 CPU EP 的 2-bit 加载对称正确。八、排查清单遇到 CPU EP 上 2-bit 量化模型结果错、GPU EP 正常先换 EP 测GPU EP 结果对、CPU EP 错 → 多半是 CPU 反序列化问题。看常量 elem_type模型里是不是UINT2打包常量INT2正常可对照。检查加载器映射UINT2有没有指向位解包实现还是 fallback 到逐字节读。临时规避导出时把UINT2改UINT4/UINT8或暂用 GPU EP。根本修复给UINT2补对称解包并还原dims。统一策略对象用OrtCpuUint2ConstantPolicy固化新增打包类型自动覆盖。CI 守护断言UINT2解包正确、与INT2对称防止回归。九、小结CPU EP mis-loads packed UINT2 Constant initializer的根因是 CPU EP 的常量加载器对 2-bit 数据类型处理不对称INT2走了正确的位解包而UINT2漏了分支、被当成未打包的 uint8 逐字节读取导致值错误、形状未还原而 GPU EP 解包正确所以无影响。最小修复是给UINT2补上和INT2对称的解包实现并还原形状结构性改进是用唯一的OrtCpuUint2ConstantPolicy把打包类型的处理收口CI 用四组断言守护“UINT2 必须解包、与 INT2 对称、形状还原、值正确”。记住2-bit 打包数据在 CPU 反序列化时必须位解包无符号和有符号要走同一套机制、只差符号位。

相关新闻

从零开始搭建个人服务器 网站建设:一份写给独立开发者的真心话

从零开始搭建个人服务器 网站建设:一份写给独立开发者的真心话

在这个互联网巨头垄断流量、平台算法决定生死的大环境下,越来越多的技术人和内容创作者开始转向一种更底层、更本质,却也更具掌控力的生活方式——那就是通过个人服务器 网站建设 来实现数字空间的绝对自主。这不仅仅是一个技术项目的执行,更像是一场关于自由、隐私以及自我…

2026/8/13 22:56:31 阅读更多 →
从Softmax与交叉熵损失原理到NumPy实现:掌握分类任务核心梯度推导

从Softmax与交叉熵损失原理到NumPy实现:掌握分类任务核心梯度推导

1. 项目概述:从公式到代码的深度穿越 如果你正在入门深度学习,尤其是分类任务,那么“Softmax 交叉熵损失”这个组合对你来说,就像学开车必须先学会踩油门和刹车一样基础。但很多人可能只是调用了 torch.nn.CrossEntropyLoss() …

2026/8/13 22:56:31 阅读更多 →
搜索引擎爬虫触发LLM安全模糊测试:从Applebot现象看新型应用防御

搜索引擎爬虫触发LLM安全模糊测试:从Applebot现象看新型应用防御

最近在安全圈和AI圈的交界处,一个看似不起眼的变化正在发生:苹果的搜索引擎爬虫 Applebot,开始频繁地出现在一些大型语言模型(LLM)的访问日志里。这听起来可能只是技术栈里又多了一个用户代理字符串,但如果…

2026/8/13 22:56:31 阅读更多 →

最新新闻

storybook-addon-performance CLI工具详解:CI环境中的性能比较与分析

storybook-addon-performance CLI工具详解:CI环境中的性能比较与分析

storybook-addon-performance CLI工具详解:CI环境中的性能比较与分析 【免费下载链接】storybook-addon-performance 🚧 A storybook addon to help better understand and debug performance for React components. 项目地址: https://gitcode.com/gh…

2026/8/14 6:04:00 阅读更多 →
GEO 搜索优化的底层原理:大模型如何检索和采信企业信息

GEO 搜索优化的底层原理:大模型如何检索和采信企业信息

一、从 SEO 到 GEO:搜索范式的根本转变过去二十多年,企业线上获客的核心引擎一直是传统搜索引擎优化(SEO)。企业做关键词排名、外链建设、页面权重优化,目标明确——让网页出现在搜索结果第一页,用户点击进…

2026/8/14 6:04:00 阅读更多 →
Windows批处理FOR命令详解:从基础语法到自动化脚本实战

Windows批处理FOR命令详解:从基础语法到自动化脚本实战

1. 项目概述:从“黑框框”到自动化利器每次看到那个黑色的命令行窗口,很多人第一反应是“高手专用”或者“离我远点”。确实,对于大多数习惯了图形界面点点点的用户来说,CMD(命令提示符)就像一个神秘的黑匣…

2026/8/14 6:04:00 阅读更多 →
想象一下,在美容院体验逆龄语抗衰项目,究竟是一种怎样的功能与服务场景?

想象一下,在美容院体验逆龄语抗衰项目,究竟是一种怎样的功能与服务场景?

想象一下,你作为一位美容院经营者,正面临顾客对精细化抗衰日益增长的迫切需求,一位顾客指着眼角细纹询问:“有什么不开刀、不手术就能改善的项目?”此时,你能否从容拿出一套完整的专项解决方案?…

2026/8/14 6:04:00 阅读更多 →
十年老歌库一夜配齐歌词:163MusicLyrics 批量下载实战记录

十年老歌库一夜配齐歌词:163MusicLyrics 批量下载实战记录

十年老歌库一夜配齐歌词:163MusicLyrics 批量下载实战记录 【免费下载链接】163MusicLyrics 云音乐歌词获取处理工具【网易云、QQ音乐】 项目地址: https://gitcode.com/GitHub_Trending/16/163MusicLyrics 你是不是也这样:硬盘里躺着几百首当年下…

2026/8/14 6:04:00 阅读更多 →
DOM Distiller高级技巧:如何优化内容提取质量与性能

DOM Distiller高级技巧:如何优化内容提取质量与性能

DOM Distiller高级技巧:如何优化内容提取质量与性能 【免费下载链接】dom-distiller Distills the DOM 项目地址: https://gitcode.com/gh_mirrors/do/dom-distiller DOM Distiller是一款强大的内容提取工具,能够从网页中精准提取核心内容。本文将…

2026/8/14 6:03:00 阅读更多 →

日新闻

临沂网站建设铭镇:深耕本土数字生态,以匠心铸就企业品牌核心竞争力

临沂网站建设铭镇:深耕本土数字生态,以匠心铸就企业品牌核心竞争力

在这个流量为王、视觉至上的互联网时代,对于临沂乃至整个山东乃至全国的传统中小企业来说,拥有一张精美的“数字名片”早已不再是可选项,而是生存的必答题。每当夜幕降临,沂河两岸灯火辉煌,物流之都的喧嚣逐渐沉淀为对未来的思考。我们常常听到老板们在茶余饭后探讨:为什…

2026/8/14 0:00:26 阅读更多 →
Flutter与OpenHarmony实现剧本杀组队表单开发实战

Flutter与OpenHarmony实现剧本杀组队表单开发实战

1. 项目概述在移动应用开发领域,跨平台框架Flutter因其高效的开发体验和出色的性能表现,已经成为众多开发者的首选。而OpenHarmony作为新兴的操作系统平台,其开放性和灵活性为开发者提供了全新的可能性。本文将聚焦于一个实际应用场景——剧本…

2026/8/14 0:00:26 阅读更多 →
大连网站建设找简维科技:为您打造懂业务更懂用户的数字化转型引擎

大连网站建设找简维科技:为您打造懂业务更懂用户的数字化转型引擎

在这个数字化浪潮席卷全球的今天,企业想要在激烈的市场竞争中站稳脚跟,拥有一张好看的“数字名片”已经远远不够了。很多老板在刚开始接触互联网业务时,都有一个共同的困惑:为什么我花了钱建的网站,就像是在真空中自嗨?访客进来转了两圈就跑了,线索石沉大海,甚至连客服…

2026/8/14 0:01:27 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/13 2:38:34 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/13 10:41:52 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/13 10:41:51 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/13 10:41:50 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/13 10:41:49 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/13 10:41:49 阅读更多 →