尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

模型优化器实战:从量化剪枝到算子融合的推理加速指南

发布时间:2026/9/28 16:25:36

资讯中心
01
ARTICLE

模型优化器实战:从量化剪枝到算子融合的推理加速指南

模型优化器实战:从量化剪枝到算子融合的推理加速指南
1. 模型优化器到底在优化什么第一次看到 Model-Optimizer 这个词很多人会下意识觉得它又是一个“调参工具”或者“训练加速库”。但真正在模型部署和推理这条链路上摸爬滚打过的人会明白模型优化器解决的是一个非常具体且极其昂贵的问题如何让一个已经训练好的模型在保持精度的前提下跑得更快、占得更少、适配得更广。我最早接触这类工具是在做一个移动端图像分类项目的时候。当时训练出来的模型在服务器上跑得好好的一放到手机端就卡得没法看推理一帧要等三四秒。那时候我才意识到训练和部署之间隔着一道巨大的鸿沟而模型优化器就是填这道鸿沟的那把铲子。它做的事情包括但不限于量化、剪枝、算子融合、图优化、内存复用、内核自动调优。每一项单独拿出来都能写一篇长文而一个成熟的模型优化器会把这些能力串成一条流水线让你用相对统一的接口完成从原始模型到高效推理模型的转换。这篇文章适合谁看如果你正在做模型部署、推理加速、端侧 AI 应用或者你训练完模型之后发现推理成本高得离谱那这篇内容就是写给你的。我会从整体设计思路讲到具体实操细节把我在实际项目中踩过的坑和总结出来的经验都摊开来说。不管你是刚接触模型优化的新手还是已经用过几款优化工具的老手应该都能从中找到一些可以直接拿走用的东西。2. 整体设计思路与方案选型拆解2.1 为什么需要专门的模型优化器很多人会问我直接用推理框架不就行了吗为什么还要单独搞一个优化器这个问题问得好因为它涉及到职责划分的问题。推理框架的核心任务是“执行”模型它关心的是怎么把算子调度到硬件上、怎么管理内存、怎么处理并发请求。而模型优化器的核心任务是“改造”模型它关心的是怎么把模型的计算图变得更简洁、更高效、更适合目标硬件。打个比方推理框架像是一条生产线模型优化器像是生产线前面的预处理车间。原材料进来之后预处理车间会把它切割、打磨、重新组装让它更适合生产线的加工方式。如果你跳过预处理直接上生产线当然也能跑但效率可能只有优化后的三分之一甚至更低。从技术角度看模型优化器存在的理由有三个。第一训练框架产出的计算图通常包含大量冗余操作比如恒等映射、冗余的转置、可以合并的连续算子等这些在训练时无所谓但在推理时就是白白浪费算力。第二不同硬件的指令集和内存层次结构差异巨大同一个模型在 GPU 和 NPU 上的最优执行方式完全不同需要针对性地做算子替换和内存布局调整。第三量化、剪枝这类压缩手段需要在模型层面做结构性修改推理框架本身并不负责这些。2.2 主流技术路线的取舍逻辑模型优化器的技术路线大致可以分成三条基于计算图的静态优化、基于运行时反馈的动态优化、以及两者结合的混合方案。静态优化是在模型加载之前就把计算图改好典型的操作包括常量折叠、算子融合、死代码消除、布局转换等。这条路线的优势是确定性强、可预测性好优化后的模型可以直接序列化保存部署时不需要额外的优化开销。缺点是它依赖对目标硬件的先验知识如果硬件特性发生变化优化策略可能就不再最优。动态优化则是在运行时根据实际执行情况做调整比如自动选择最优的 kernel 实现、动态调整 batch size、根据内存压力决定是否启用某些优化等。这条路线的优势是适应性强能应对多变的运行环境。缺点是引入了运行时开销而且优化效果受限于运行时的观测窗口。混合方案是我个人最推荐的路线。它的思路是在编译期做那些确定性的、与运行时无关的优化把模型的计算图精简到最简形式然后在运行时做那些依赖具体硬件状态和负载情况的决策。这样既保证了基础性能又保留了应对变化的灵活性。目前主流的模型优化器基本都走这条路区别只在于静态和动态的边界划在哪里。2.3 优化流水线的阶段划分一个完整的模型优化流水线通常包含四个阶段图获取、图变换、算子选择与代码生成、以及验证与回退。图获取阶段负责从训练框架中导出计算图。这里的关键是保证导出的图是完整的、语义正确的。不同训练框架的导出机制差异很大有的导出的是静态图有的导出的是带有控制流的动态图有的还会保留训练专用的节点。优化器需要能够处理这些差异把图规范化成内部表示。图变换阶段是优化的核心包含一系列 pass每个 pass 负责一种或一类优化。这些 pass 通常按照固定顺序执行因为某些优化会为后续优化创造条件。比如先做常量折叠可以减少图中的节点数量让后续的算子融合更容易识别出可融合的模式。算子选择与代码生成阶段负责把优化后的图映射到目标硬件上。这里涉及到算子库的匹配、kernel 的选择、内存分配策略的确定等。对于不支持的算子还需要有回退机制比如拆解成多个支持的算子或者回退到通用实现。验证与回退阶段经常被忽视但它极其重要。优化后的模型必须经过数值验证确保输出和原始模型在可接受的误差范围内一致。如果验证不通过需要有机制回退到未优化的版本或者降低优化强度。我在实际项目中见过太多次因为跳过验证而导致线上事故的案例这个环节绝对不能省。3. 核心细节解析与实操要点3.1 计算图导出的关键细节计算图导出是整条流水线的起点也是最容易出问题的环节。不同框架的导出方式差异很大我分别说一下常见的坑。对于基于静态图的框架导出相对简单但要注意控制流和动态 shape 的处理。很多模型在训练时使用了动态 shape导出时如果固定成静态 shape可能会导致某些分支无法正确执行。我的建议是如果目标场景允许尽量在导出时保留动态 shape 的能力哪怕这会增加一些优化难度。对于基于动态图的框架导出时通常需要做一次 trace 或者 script。Trace 的问题是它只能捕获实际执行到的路径条件分支中未执行的分支会丢失。Script 虽然能保留完整逻辑但对代码写法有要求不是所有模型都能顺利转换。我一般的做法是先用 trace 试如果发现控制流丢失再改用 script 或者手动标注。还有一个容易被忽视的点是算子版本。同一个算子在不同版本的框架中可能有不同的语义或属性导出时需要确保优化器支持的算子版本和导出时的版本匹配。我遇到过因为版本不匹配导致数值偏差的案例排查了很久才发现是某个算子的默认属性变了。3.2 量化策略的选择与参数计算量化是模型优化中收益最直接的手段之一但它也是最容易翻车的环节。量化的本质是用低精度数据类型如 int8来近似表示高精度数据如 float32从而减少内存占用和计算量。但量化会引入误差误差控制不好就会导致精度大幅下降。量化的核心参数是 scale 和 zero_point。Scale 决定了浮点数的动态范围如何映射到整数范围zero_point 决定了浮点零对应哪个整数值。这两个参数的计算方式直接影响了量化误差的大小。以对称量化为例假设我们要把 float32 的权重映射到 int8计算过程是这样的首先统计权重的绝对值最大值记为 abs_max。然后计算 scale abs_max / 127因为 int8 的正数范围是 0 到 127。量化时quantized_value round(float_value / scale)反量化时float_value quantized_value * scale。这里的 127 就是量化范围的一半因为对称量化把浮点范围对称地映射到整数范围。非对称量化则更复杂一些它需要分别统计最小值和最大值然后计算 scale (max - min) / 255zero_point round(-min / scale)。非对称量化能更好地利用整数范围但计算量稍大。在实际操作中我通常会对权重使用对称量化对激活值使用非对称量化。原因是权重的分布通常比较对称对称量化足够而激活值的分布往往有偏非对称量化能减少截断误差。这个策略在大多数视觉模型和 NLP 模型上都表现不错。注意量化校准集的选取非常关键。校准集应该能代表实际推理时的数据分布否则计算出的 scale 和 zero_point 会偏离实际需求。我一般会从验证集中随机抽取 100 到 500 个样本作为校准集太少会导致统计不稳定太多则浪费时间。3.3 算子融合的模式识别与实现算子融合是提升推理效率最有效的手段之一它的核心思想是把多个小算子合并成一个大的算子减少 kernel 启动开销和中间结果的读写。常见的融合模式包括Conv BN ReLU、MatMul Add、Transpose Reshape 等。以 Conv BN ReLU 为例这个融合之所以可行是因为 BN 在推理阶段是一个线性变换可以把它吸收到 Conv 的权重和偏置中。具体来说BN 的推理公式是 y gamma * (x - mean) / sqrt(var eps) beta其中 gamma、beta、mean、var 是 BN 的参数eps 是防止除零的小量。把 Conv 的输出代入 x可以得到一个新的卷积其权重为 W W * gamma / sqrt(var eps)偏置为 b (b - mean) * gamma / sqrt(var eps) beta。这样 Conv 和 BN 就合并成了一个卷积ReLU 则作为激活函数附加在后面。这个融合的收益非常明显。原本需要三个 kernel 完成的计算现在只需要一个 kernel中间结果不需要写回内存再读出来带宽节省了延迟也降低了。在移动端设备上这种融合带来的加速比通常能达到 1.5 到 2 倍。但融合不是无条件的。有些融合会改变数值精度比如把多个小算子融合成一个大算子后中间结果的精度可能降低。有些融合会限制后续优化的空间比如融合后可能无法再做某些算子替换。所以融合策略需要根据具体场景权衡不能一味追求融合数量。3.4 内存复用与生命周期分析内存复用是另一个容易被忽视但收益可观的优化点。在推理过程中很多中间张量的生命周期并不重叠理论上可以复用同一块内存。但如果没有显式的内存复用机制框架通常会为每个张量分配独立的内存导致峰值内存占用远高于实际需求。内存复用的核心是生命周期分析。优化器需要分析每个张量的定义点和使用点确定它的活跃区间。如果两个张量的活跃区间不重叠它们就可以共享同一块内存。这个分析在静态图中比较容易做因为执行顺序是确定的在动态图中则复杂一些需要做保守估计。我在一个目标检测项目上做过测试开启内存复用后峰值内存占用从 1.2GB 降到了 680MB降幅超过 40%。这对于内存受限的端侧设备来说意义重大意味着可以跑更大的模型或者处理更高分辨率的输入。提示内存复用和原地操作in-place operation要配合使用。原地操作是指算子的输出直接覆盖输入的内存这能进一步减少内存占用但要求输入在算子执行后不再被使用。优化器需要仔细分析依赖关系确保原地操作不会破坏后续计算。4. 实操过程与核心环节实现4.1 环境搭建与依赖管理动手之前先把环境理清楚这一步偷懒后面会加倍还回来。模型优化器通常依赖特定版本的训练框架、推理框架和算子库版本不匹配是导致各种诡异问题的头号原因。我的习惯是用虚拟环境隔离每个项目然后用一个 requirements 文件锁定所有依赖的精确版本。不要用 latest不要用范围版本就写死。比如 torch2.1.0、onnx1.14.0、onnxruntime1.16.0 这样。看起来笨但能省掉大量排查时间。python -m venv model_opt_env source model_opt_env/bin/activate pip install torch2.1.0 onnx1.14.0 onnxruntime1.16.0 numpy1.24.0如果你要用 GPU 做优化和验证还需要确保 CUDA 版本和框架版本匹配。我一般会先用一个小模型跑通全流程确认环境没问题之后再上真正的大模型。这个“小模型探路”的习惯帮我省了很多时间。4.2 模型导出与图规范化导出这一步的目标是得到一个干净的计算图。以 PyTorch 导出 ONNX 为例基本命令是这样的import torch import torch.onnx model MyModel() model.eval() dummy_input torch.randn(1, 3, 224, 224) torch.onnx.export( model, dummy_input, model.onnx, opset_version13, input_names[input], output_names[output], dynamic_axes{input: {0: batch_size}, output: {0: batch_size}} )这里有几个关键点。opset_version 决定了可用的算子集合版本越高支持的算子越多但兼容性可能越差。我一般选 13 或 14这两个版本在功能和兼容性之间比较平衡。dynamic_axes 用来标记动态维度如果你的模型需要支持变长输入或者可变 batch size这个必须设置。导出之后我强烈建议用 ONNX 的检查工具过一遍import onnx model onnx.load(model.onnx) onnx.checker.check_model(model) print(fIR version: {model.ir_version}) print(fOpset version: {model.opset_import[0].version})检查通过之后还要做一次数值验证确保导出的模型和原始模型的输出一致。这一步很多人会跳过但它是发现导出问题的最后一道防线。import onnxruntime as ort import numpy as np sess ort.InferenceSession(model.onnx) onnx_output sess.run(None, {input: dummy_input.numpy()}) torch_output model(dummy_input).detach().numpy() np.testing.assert_allclose(onnx_output[0], torch_output, rtol1e-3, atol1e-5)如果数值对不上先检查是不是有算子不支持或者语义不一致再检查输入预处理是否一致。我遇到过因为模型里有自定义算子导致导出后行为不同的情况这种就需要手动实现对应的 ONNX 算子或者替换成标准算子。4.3 量化校准与精度验证量化校准的实操流程分为三步准备校准数据、运行校准、验证精度。准备校准数据时我一般会写一个 DataLoader从验证集里随机抽取样本做和推理时一致的预处理。注意不要做数据增强校准需要的是真实分布的数据。calibration_data [] for i, (image, _) in enumerate(val_loader): if i 200: break calibration_data.append(image.numpy())然后调用量化工具做校准。以 ONNX Runtime 的静态量化为例from onnxruntime.quantization import quantize_static, CalibrationDataReader class DataReader(CalibrationDataReader): def __init__(self, data): self.data data self.index 0 def get_next(self): if self.index len(self.data): return None input_dict {input: self.data[self.index]} self.index 1 return input_dict reader DataReader(calibration_data) quantize_static( model_inputmodel.onnx, model_outputmodel_quantized.onnx, calibration_data_readerreader, quant_formatQuantFormat.QDQ, per_channelTrue )per_channelTrue 表示对每个通道单独计算 scale 和 zero_point这通常能带来更好的精度但模型体积会稍大一些。如果对体积极度敏感可以设为 False 使用 per_tensor 量化。量化完成后必须做精度验证。我会在完整的验证集上跑一遍对比量化前后的精度指标。如果精度下降超过 1 个百分点就需要调整量化策略比如把某些敏感层排除在量化之外或者改用混合精度量化。def evaluate(model_path, val_loader): sess ort.InferenceSession(model_path) correct 0 total 0 for images, labels in val_loader: outputs sess.run(None, {input: images.numpy()}) preds np.argmax(outputs[0], axis1) correct (preds labels.numpy()).sum() total len(labels) return correct / total fp32_acc evaluate(model.onnx, val_loader) int8_acc evaluate(model_quantized.onnx, val_loader) print(fFP32 accuracy: {fp32_acc:.4f}) print(fINT8 accuracy: {int8_acc:.4f}) print(fAccuracy drop: {fp32_acc - int8_acc:.4f})4.4 性能基准测试与瓶颈定位优化做完之后必须做性能基准测试否则你不知道优化到底有没有效果。基准测试要关注三个指标延迟、吞吐量、内存占用。延迟测试我一般用 onnxruntime 的 profiling 功能sess_options ort.SessionOptions() sess_options.enable_profiling True sess ort.InferenceSession(model_quantized.onnx, sess_options) for _ in range(100): sess.run(None, {input: dummy_input.numpy()}) prof_file sess.end_profiling() print(fProfile saved to: {prof_file})然后用工具分析 profile 文件找出耗时最长的算子。如果某个算子的耗时占比异常高可能是它没有被正确优化或者目标硬件上缺少高效的实现。内存占用可以用 psutil 或者框架自带的内存统计工具来测。我一般会记录推理过程中的峰值内存对比优化前后的差异。import psutil import os process psutil.Process(os.getpid()) mem_before process.memory_info().rss / 1024 / 1024 sess.run(None, {input: dummy_input.numpy()}) mem_after process.memory_info().rss / 1024 / 1024 print(fMemory increase: {mem_after - mem_before:.2f} MB)如果优化后延迟没有明显下降先检查优化是否真的生效了。有时候优化器会因为某些原因跳过优化比如遇到了不支持的算子或者图结构不符合优化条件。打开优化器的日志输出确认每个 pass 是否执行成功。5. 常见问题与排查技巧实录5.1 精度下降问题的排查路径量化后精度下降是最常见的问题排查起来需要系统性地逐层定位。我的做法是逐层对比量化前后的输出找出误差最大的层。具体操作是用同一个输入分别跑原始模型和量化模型在每一层输出处做对比。ONNX Runtime 支持在指定节点处获取中间输出可以通过修改模型的输出列表来实现。import onnx model onnx.load(model_quantized.onnx) for node in model.graph.node: if node.op_type Conv: # 把这一层的输出也加到模型输出中 model.graph.output.extend([onnx.ValueInfoProto(namenode.output[0])])然后对比每一层的输出差异找出误差突增的层。通常问题出在以下几种情况该层的权重分布范围过大导致量化精度不足该层的激活值有极端离群点导致大部分数值被压缩到很小的范围该层对精度特别敏感比如检测头的最后一层。针对第一种情况可以对该层使用 per_channel 量化或者提高量化位宽。针对第二种情况可以做激活值的截断把极端值裁掉。针对第三种情况可以把该层排除在量化之外保持浮点精度。5.2 算子不支持的回退策略目标硬件或推理框架不支持某些算子是家常便饭。遇到这种情况有几种回退策略可以选。第一种是算子拆解把不支持的算子拆成多个支持的算子。比如某些框架不支持 GroupConv可以拆成多个普通 Conv 再拼接。这种方式的优点是保持全硬件加速缺点是可能引入额外的内存拷贝和计算开销。第二种是回退到 CPU 执行。大多数推理框架都支持把不支持的算子放到 CPU 上跑虽然慢但至少能跑通。这种方式适合那些执行频率低、耗时占比小的算子。第三种是自定义算子实现。如果某个算子对性能影响很大又找不到替代方案就只能自己写一个。这需要了解目标硬件的编程模型和框架的算子注册机制门槛较高但收益也最大。我一般的优先级是先试算子拆解不行再回退 CPU最后才考虑自定义实现。因为自定义实现的维护成本很高框架升级或者硬件更换时可能需要重写。5.3 内存溢出与显存不足的应对内存溢出在优化大模型时经常遇到。除了前面提到的内存复用还有几个实用的技巧。第一个是分阶段执行。把模型切成几段每段执行完后释放中间结果再执行下一段。这能显著降低峰值内存但会增加一些调度开销。第二个是动态 batch size。如果显存不够就减小 batch size用时间换空间。这个策略在服务端推理中很常用可以根据当前显存占用动态调整 batch size。第三个是使用内存池。预先分配一块大内存所有张量都从这块内存中分配避免频繁的 malloc/free 导致的内存碎片。大多数推理框架都内置了内存池但需要正确配置池的大小。注意显存不足和内存不足的排查方法不同。显存不足通常会在分配张量时直接报错而内存不足可能表现为系统变慢、swap 频繁。用 nvidia-smi 监控显存用 free 或 top 监控内存能快速定位是哪种不足。5.4 常见问题速查表问题现象可能原因排查方法解决方案量化后精度大幅下降校准集分布不匹配对比校准集和验证集的分布重新选取校准集推理延迟没有改善优化 pass 未生效查看优化器日志检查图结构是否满足优化条件导出模型输出不一致算子语义差异逐层对比输出替换为语义一致的算子显存溢出峰值内存过高用 profiling 工具分析开启内存复用或减小 batch算子不支持硬件或框架限制查看错误信息拆解算子或回退 CPU多线程推理结果异常线程安全问题单线程对比测试加锁或使用线程安全版本6. 优化效果的度量与持续迭代6.1 建立可量化的评估体系优化不是一次性的工作而是一个持续迭代的过程。要迭代就必须有可量化的评估体系。我一般会从四个维度来度量优化效果精度、延迟、吞吐量、资源占用。精度用任务相关的指标来衡量分类用准确率检测用 mAP分割用 IoU。延迟用 P50 和 P99 分位数不要只看平均值因为尾部延迟往往更能反映用户体验。吞吐量用 QPS 或 FPS资源占用包括内存峰值、显存峰值、CPU 利用率。这些指标需要在一个固定的测试集和固定的硬件环境下测量否则数据没有可比性。我会把每次优化的结果记录在一个表格里方便对比不同策略的效果。优化阶段精度P50延迟P99延迟内存峰值模型体积原始模型76.5%45ms68ms1.2GB98MB图优化后76.5%38ms55ms1.1GB98MB量化后75.8%18ms26ms680MB25MB量化融合75.8%14ms21ms650MB25MB这张表能直观地看出每一步优化的收益和代价。精度下降 0.7 个百分点换来了延迟降低 69%、内存降低 46%、体积降低 74%这个 trade-off 在大多数场景下都是划算的。6.2 不同硬件平台的适配经验同一个优化策略在不同硬件上的效果可能天差地别。我在 GPU、CPU、移动端 NPU 上都做过模型优化分别说一下各自的特点。GPU 平台对量化最敏感。FP16 量化在 GPU 上通常能带来接近 2 倍的加速而且精度损失极小基本可以无脑开。INT8 量化的加速比更高但需要硬件支持 INT8 指令集老一些的 GPU 可能没有。算子融合在 GPU 上收益也很大因为 GPU 的 kernel 启动开销相对较高。CPU 平台对内存布局最敏感。把 NHWC 转成 NCHW 或者反过来性能可能差好几倍。量化在 CPU 上收益也很明显因为 CPU 的浮点算力通常不如整数算力。另外 CPU 上要特别注意线程数的配置线程太多会导致上下文切换开销线程太少又跑不满。移动端 NPU 的优化空间最大但限制也最多。NPU 通常只支持特定的算子集合和数据类型不支持的算子会回退到 CPU导致性能断崖式下降。所以在移动端做优化第一件事是确认模型的算子是否都在 NPU 的支持列表里。如果不在要么替换算子要么接受回退。6.3 自动化优化流水线的搭建手动做优化效率太低而且容易出错。我建议把优化流程自动化用脚本串起来每次模型更新后自动跑一遍优化和验证。一个典型的自动化流水线包含这些步骤模型导出、图检查、数值验证、量化校准、精度验证、性能测试、结果记录。每一步的输出作为下一步的输入任何一步失败就中断并报警。def optimize_pipeline(model, val_loader, config): # Step 1: Export export_onnx(model, model.onnx, config) # Step 2: Check check_model(model.onnx) # Step 3: Validate validate_numerical(model, model.onnx, config) # Step 4: Quantize quantize(model.onnx, model_quantized.onnx, val_loader, config) # Step 5: Evaluate accuracy acc evaluate(model_quantized.onnx, val_loader) assert acc config.min_accuracy, fAccuracy {acc} below threshold # Step 6: Benchmark latency benchmark(model_quantized.onnx, config) assert latency config.max_latency, fLatency {latency} exceeds limit # Step 7: Record record_results(config, acc, latency) return model_quantized.onnx这个流水线跑通之后每次模型迭代只需要触发一次几分钟就能拿到优化结果和评估报告。我在团队里推行这套流程之后模型上线的周期从原来的两三天缩短到了半天。6.4 版本管理与回滚机制优化后的模型必须做版本管理每个版本要记录对应的原始模型、优化配置、评估结果。这样当线上出现问题需要回滚时能快速定位到上一个稳定版本。我一般会用模型注册表来管理每个模型版本有一个唯一的 ID包含模型文件、配置文件、评估报告。部署时指定版本 ID回滚时切换到上一个版本 ID 即可。提示优化配置也要纳入版本管理。同一个模型用不同的优化配置可能产生完全不同的结果如果只记录模型文件不记录配置复现和回滚都会很困难。7. 我在实际项目中的几点体会做模型优化这些年最大的感受是没有银弹只有权衡。每一个优化手段都有它的代价量化牺牲精度换速度剪枝牺牲容量换体积融合牺牲灵活性换效率。关键是要清楚你的场景最在意什么然后围绕这个目标去组合优化策略。另一个体会是验证比优化本身更重要。我见过太多团队花大量时间调优化参数却在验证环节草草了事结果上线后精度不达标或者延迟不稳定。优化做得再好验证不过关就是白做。所以我现在会把至少一半的精力放在验证体系的建设上确保每一个优化结果都是可信的。还有一点是关于工具的选择。市面上的模型优化工具很多各有各的优缺点。我的建议是不要盲目追新选一个社区活跃、文档完善、和你技术栈匹配的工具深入用透。工具之间的差异其实没有想象中那么大真正拉开差距的是你对模型和硬件的理解深度。最后分享一个小技巧在做任何优化之前先建立一个性能基线。没有基线你就不知道优化有没有效果也不知道优化空间还有多大。基线不需要很精确但必须可复现。我一般会用原始模型在目标硬件上跑 100 次推理取 P50 和 P99 作为基线后续所有优化都跟这个基线对比。这个习惯让我避免了很多“感觉快了但实际没快”的错觉。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。