当前位置:首页 > 文章列表 > 科技周边 > 人工智能 > ONNX Runtime 量化怎样比较动态量化与静态量化的部署差异怎样完成一个可复用的最小示例

ONNX Runtime 量化怎样比较动态量化与静态量化的部署差异怎样完成一个可复用的最小示例

来源:17golang原创 2026-11-10 02:33:01 0浏览 收藏

ONNX Runtime 动态量化在推理时计算激活量化参数,静态量化则用校准数据预先确定这些参数。比较部署差异时,要固定原模型、执行提供器、线程与输入,再分开记录产物大小、输出误差和推理延迟。动态量化不需要同样的离线激活校准,但有运行时计算开销;静态量化依赖校准数据的代表性,二者都不保证一定更快或完全保留精度。

ONNX Runtime 官方地址:https://onnxruntime.ai/

先把输入模型、校准数据和比较数据分开

保护的资产有三类:可回退的 fp32.onnx、用于校准的 calibration,以及独立比较集 evaluation。Reader 负责把 calibration 交给静态量化;dynamic.onnx 与 static.onnx 都来自同一份浮点模型。若把比较集混入校准,或者替换了输入预处理,部署决策就失去可比性。

区分静态校准依赖与共同输入
图1:区分静态校准依赖与共同输入。静态结构说明图,非截图或运行结果。

本例主动生成一个小 MatMul 模型,不下载模型、不接触生产数据。真实部署需把模型来源与运行资源限制纳入边界:不可信模型或超大输入可能消耗资源,校准数据还可能携带业务信息。量化转换不是模型内容安全检查,也不应把原始敏感样本打进部署包。

用最小 MatMul 模型生成两种量化产物

在独立 Python 环境安装依赖,保存下方脚本为 compare_quant.py 再运行。下面是供读者执行的示例,本文没有运行量化、代码或基准测试。

# 在隔离环境安装示例所需的模型工具与 CPU 运行时
python -m pip install numpy onnx onnxruntime
# 正式复现时应记录并固定实际安装的依赖版本
python compare_quant.py
from pathlib import Path
import json
import time
import numpy as np
import onnx
from onnx import helper, TensorProto, numpy_helper
import onnxruntime as ort
from onnxruntime.quantization import (
    CalibrationDataReader, QuantFormat, QuantType,
    quantize_dynamic, quantize_static,
)

# 只生成教学模型,不加载来源不明的模型或真实用户数据
rng = np.random.default_rng(7)
out = Path("quant-demo")
out.mkdir(exist_ok=True)
weight = rng.normal(size=(8, 4)).astype(np.float32)
graph = helper.make_graph(
    [helper.make_node("MatMul", ["x", "w"], ["y"])],
    "demo",
    [helper.make_tensor_value_info("x", TensorProto.FLOAT, [1, 8])],
    [helper.make_tensor_value_info("y", TensorProto.FLOAT, [1, 4])],
    [numpy_helper.from_array(weight, name="w")],
)
model = helper.make_model(
    graph, opset_imports=[helper.make_opsetid("", 13)], ir_version=8
)
fp = out / "fp32.onnx"
onnx.save(model, str(fp))

# 校准集与比较集分开生成;随机校准只适用于此教学模型
calibration = [rng.normal(size=(1, 8)).astype(np.float32) for _ in range(32)]
evaluation = [rng.normal(size=(1, 8)).astype(np.float32) for _ in range(16)]

class Reader(CalibrationDataReader):
    def __init__(self, values):
        self.values = values
        self.rewind()

    def get_next(self):
        return next(self.items, None)

    def rewind(self):
        self.items = iter({"x": x} for x in self.values)

dynamic = out / "dynamic.onnx"
static = out / "static.onnx"
quantize_dynamic(str(fp), str(dynamic), weight_type=QuantType.QInt8,
                 op_types_to_quantize=["MatMul"])
quantize_static(str(fp), str(static), Reader(calibration),
                quant_format=QuantFormat.QDQ,
                activation_type=QuantType.QInt8, weight_type=QuantType.QInt8,
                op_types_to_quantize=["MatMul"])

def session(path):
    # 固定线程和执行提供器,避免把配置差异误当量化收益
    options = ort.SessionOptions()
    options.intra_op_num_threads = 1
    options.inter_op_num_threads = 1
    return ort.InferenceSession(str(path), options,
                               providers=["CPUExecutionProvider"])

baseline = session(fp)
expected = [baseline.run(None, {"x": x})[0] for x in evaluation]
report = {"ort_version": ort.__version__, "provider": "CPUExecutionProvider",
          "calibration_n": len(calibration), "evaluation_n": len(evaluation),
          "variants": []}
for path in [fp, dynamic, static]:
    engine = session(path)
    # 会话初始化不计入热推理延迟;每个版本使用相同输入
    for _ in range(10):
        engine.run(None, {"x": evaluation[0]})
    costs, errors = [], []
    for x, target in zip(evaluation, expected):
        start = time.perf_counter()
        result = engine.run(None, {"x": x})[0]
        costs.append((time.perf_counter() - start) * 1000)
        errors.append(float(np.max(np.abs(result - target))))
    report["variants"].append({
        "file": path.name, "bytes": path.stat().st_size,
        "max_abs_error": max(errors),
        "median_ms": float(np.median(costs)),
    })
# 保存原始测量字段,不预填“加速倍数”或精度结论
(out / "report.json").write_text(json.dumps(report, indent=2), encoding="utf-8")

这里使用显式形状和单一 MatMul,省去复杂模型预处理。生产模型应把形状推导与适用的优化放在独立准备阶段,让两个分支读取相同预处理产物。QInt8 与 QDQ 是本例选项,不是对所有执行提供器、CPU 指令集和算子的统一推荐;若量化算子无法加载,应先检查支持范围和依赖版本,不要直接宣称另一种量化方式失败。

把文件大小、误差和延迟分列记录

脚本为每个模型创建相同 CPUExecutionProvider 会话,并记录 bytes、max_abs_error 和 median_ms。max_abs_error 是与 FP32 输出相比的最大绝对误差,不是分类准确率。median_ms 只统计热推理调用,不含模型加载时间,也混有 Python 调用开销。这个极小模型和少量输入适合检查比较方法,不能据此宣布业务加速。

解释统一部署环境与独立指标
图2:解释统一部署环境与独立指标。静态结构说明图,非截图或运行结果。
维度动态量化静态量化
离线激活校准本例不需要Reader 提供校准输入
激活参数来源推理时计算由校准确定并写入产物
部署包量化模型及运行依赖量化模型及运行依赖,不必附原始校准集
风险重点运行时开销与算子支持分布偏移与校准代表性
可否直接上线需目标环境业务评测需目标环境业务评测

让部署记录能够支持回退

report.json 记录运行时版本、执行提供器、校准与比较样本数。正式实验还应保存原模型与量化产物标识、转换参数、依赖版本、CPU 型号、线程、预处理版本及数据集合版本;原始校准内容放在受限存储,部署日志只保留必要标识。CPUExecutionProvider 的结果不能直接外推到 GPU、移动端或其他执行提供器。

保留 FP32 作为回退项。若业务指标下降超过预先约定的容忍范围,或算子支持、资源占用不满足约束,先回退原模型,再分析偏差层或量化配置。不要仅凭文件变小就替换线上模型。对小模型而言,量化元数据甚至可能使文件更大。

静态校准可否直接使用随机数

本例的随机数只服务于自造 MatMul 的可复用演示。真实图像、语音或文本模型需要与生产预处理和输入分布相符的代表性校准集,并使用独立数据评估任务指标。随机校准所得结论不能迁移到业务模型。

输出误差很小就能认为效果相同吗

不能。接近决策阈值的微小变化也可能改变分类、排序或生成行为;应同时比较业务任务指标和关键输入子集。静态与动态没有脱离模型、硬件、算子和数据的通用胜者。

官方量化参数与支持说明:https://onnxruntime.ai/docs/performance/model-optimizations/quantization.html。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
多模态模型评测怎样分别记录图像理解与文本生成指标怎样在批处理代码中减少额外分配多模态模型评测怎样分别记录图像理解与文本生成指标怎样在批处理代码中减少额外分配
上一篇
多模态模型评测怎样分别记录图像理解与文本生成指标怎样在批处理代码中减少额外分配
ONNX Runtime 量化怎样比较动态量化与静态量化的部署差异为什么结果为空或不符合预期
下一篇
ONNX Runtime 量化怎样比较动态量化与静态量化的部署差异为什么结果为空或不符合预期
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    965次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    966次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1077次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1056次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    888次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码