资讯动态

大模型计算指标全解析:从FLOPS到显存带宽的优化实战

发布时间:2026/10/13 23:47:42 来源:尧图企业网站定制
1. 大模型计算指标到底在算什么第一次接触“大模型计算指标”这个概念很多人会以为它只是几张性能跑分表或者某个框架里自带的监控面板。实际干过一轮训练和推理优化之后你会发现这套指标体系更像是给模型做体检的化验单——它不告诉你模型聪不聪明但能告诉你它“跑得累不累、喘得凶不凶、吃得多不多”。我最初做推理服务压测的时候就是因为只看吞吐量不看显存占用曲线结果上线第二天就被OOM打脸从那以后才老老实实把计算指标当成一等公民来对待。所谓大模型计算指标核心是围绕算力消耗、内存占用、通信开销、时间延迟这四个维度展开的一组量化数据。它解决的是一个非常实际的问题同样一个模型为什么在A卡上能跑出每秒三千token换到B卡就只剩八百为什么训练loss正常下降但GPU利用率始终卡在40%上不去这些问题的答案全都藏在计算指标里。适合阅读这篇内容的人包括正在做模型训练调优的工程师、负责推理服务部署的后端开发、需要做硬件选型和成本估算的技术决策者以及任何想搞清楚“大模型到底吃多少资源”的从业者。哪怕你只是刚接触这个领域只要跟着把每个指标的含义和测量方法过一遍也能建立起一套可复用的分析框架。我写这篇东西的出发点很简单网上讲大模型原理的文章铺天盖地但真正把计算指标拆开揉碎、告诉你每个数字怎么来的、怎么测的、怎么用的内容少得可怜。很多团队在汇报时列一堆FLOPS和显存数字但被问到“这个数字是怎么算出来的”就支支吾吾。所以下面我会从设计思路讲到实操细节把踩过的坑和总结的技巧都摊开来说。2. 核心指标体系的设计逻辑与选型考量2.1 为什么是这四个维度而不是别的大模型的计算指标不是拍脑袋定的它对应的是硬件资源的四种瓶颈类型。算力对应计算单元比如GPU的CUDA核心或Tensor Core内存对应显存和内存带宽通信对应卡间互联和网络带宽时间则是前三者综合作用的外在表现。这四个维度基本覆盖了从单卡到集群的所有资源约束场景。我见过一些团队只盯着FLOPS看觉得算力越大越好结果买了一批高算力卡回来发现显存不够模型根本放不下。也见过只关注显存的选了超大显存的卡但互联带宽拉胯做张量并行时通信成了瓶颈多卡加速比惨不忍睹。所以这四个维度必须放在一起看缺一个都会导致选型或优化方向跑偏。从测量角度来说这四个维度也有层次关系。时间指标延迟、吞吐是最外层、最容易观测的但它的波动受太多因素影响单独看容易误判。算力和内存指标是中间层能解释时间指标为什么好或不好。通信指标则是在分布式场景下才会凸显出来。我的习惯是先看时间指标定位问题再往下钻到算力、内存、通信去找根因。2.2 训练指标和推理指标的差异训练和推理虽然都跑在同样的硬件上但计算指标的侧重点完全不同。训练阶段最关心的是吞吐量每秒处理多少样本或token和算力利用率MFUModel FLOPS Utilization因为训练时间直接等于成本。推理阶段则更关注首token延迟TTFT和每token延迟TPOT因为这直接影响用户体验。这里有个很容易混淆的点训练时的MFU和推理时的算力利用率不是一回事。训练是计算密集型MFU能到40%以上就算不错了推理是内存带宽密集型decode阶段算力利用率往往只有个位数百分比这时候盯着算力利用率看毫无意义应该看的是内存带宽利用率。注意不要拿训练阶段的指标基准去衡量推理性能两者的瓶颈根本不在一个地方。我见过有人用训练时的MFU来评估推理优化效果结果优化了半天发现指标纹丝不动因为瓶颈压根不在算力上。2.3 指标采集的粒度选择采集粒度是个容易被忽视但很关键的设计决策。粒度太粗比如只看整个训练任务的平均值会掩盖掉很多瞬时的异常粒度太细比如每毫秒采一次数据量爆炸不说采集本身还会影响性能。我的经验是分三层采集宏观层按训练步或推理请求统计用于看整体趋势中观层按算子或层统计用于定位瓶颈在哪个模块微观层按CUDA kernel统计用于做极致的kernel级优化。大部分场景下中观层就够用了只有需要做深度优化时才下钻到微观层。采集工具方面训练场景常用的是框架自带的profiler比如PyTorch的torch.profiler推理场景则更多依赖服务框架的metrics接口加上硬件厂商提供的监控工具。不管用什么工具核心原则是采集开销要控制在总计算时间的5%以内否则测出来的数据本身就失真了。3. 核心指标详解与计算方法3.1 算力指标FLOPS与MFUFLOPSFloating Point Operations Per Second是衡量算力的基础单位但要注意区分理论峰值FLOPS和实际达成FLOPS。理论峰值是硬件规格书上写的数字实际达成则取决于你的模型和优化水平。计算一个模型的理论计算量有个常用公式。对于Transformer类模型前向传播的计算量大约是FLOPs ≈ 2 × 参数量 × token数训练时因为包含前向和反向大约是前向的3倍训练FLOPs ≈ 6 × 参数量 × token数这个公式是估算值实际会因为注意力机制的平方复杂度、激活重计算等因素有偏差但用来做量级估算足够了。MFU的计算就是实际达成的FLOPS除以硬件理论峰值MFU 实际FLOPS / 理论峰值FLOPS举个例子某张卡的理论峰值是300 TFLOPS这里指特定精度下的数值你训练时实测每秒处理了1000个token模型参数量是70B那么实际FLOPS大约是6 × 70e9 × 1000 4.2e14 420 TFLOPSMFU就是420/300超过1了说明我的举例数字有问题——这正好说明一个常见坑理论峰值要按实际使用的精度来算。如果用FP16训练就要用FP16的峰值如果用BF16就用BF16的峰值。不同精度的峰值可能差一倍甚至更多。实操心得算MFU之前先确认三件事——模型实际参数量不是配置文件里写的是实际参与计算的、实际使用的计算精度、硬件的对应精度峰值。这三个有一个搞错算出来的MFU就没有参考价值。3.2 内存指标显存占用与带宽利用率显存占用是很多人最关心的指标因为它直接决定模型能不能跑起来。显存占用主要分四块模型参数、梯度、优化器状态、激活值。模型参数占用很好算参数量乘以每个参数的字节数。FP16是2字节FP32是4字节INT8是1字节。一个70B参数的模型FP16下光参数就要140GB单卡根本放不下所以必须做模型并行或量化。梯度占用和参数一样大训练时优化器状态如果是Adam需要存储一阶矩和二阶矩又是参数量的两倍。所以训练一个70B模型光参数梯度优化器状态就要140140280560GB这还没算激活值。这就是为什么大模型训练必须用分布式。激活值占用和batch size、序列长度强相关而且不同层的激活值大小不一样。有个粗略估算方法激活值占用大约是 batch_size × seq_len × hidden_size × 层数 × 精度字节数 × 系数。这个系数取决于具体实现一般在2到10之间。内存带宽利用率是推理场景的核心指标。decode阶段每生成一个token都需要把整个模型参数从显存读一遍所以理论上的token生成速度上限是最大token/s 显存带宽 / 模型参数字节数比如显存带宽是2TB/s模型是FP16的7B14GB那么理论上限就是2000/14 ≈ 143 token/s。实际能达到60%到80%就算优化得很好了。3.3 通信指标带宽与通信量分布式训练和推理中通信开销往往是隐藏的杀手。通信指标主要看两个通信量传了多少数据和通信带宽传得多快。数据并行的通信量相对好算每步需要同步梯度通信量等于模型参数量乘以精度字节数。70B模型FP16下每步要同步140GB的梯度如果卡间带宽是100GB/s光通信就要1.4秒这还没算计算时间。张量并行的通信量更大因为每层的前向和反向都需要做all-reduce或all-gather。通信量和层数、hidden_size都相关具体计算比较复杂但有个经验规律张量并行的通信量通常是数据并行的数倍。流水线并行的通信量最小只在阶段之间传递激活值通信量大约是 batch_size × seq_len × hidden_size × 精度字节数。但流水线并行有气泡问题需要配合微批次来缓解。注意通信指标不能只看带宽还要看通信效率。同样传140GB数据用NVLink和用普通网络实际耗时可能差十倍。选型时一定要确认卡间互联的实际带宽不要只看标称值。3.4 时间指标延迟与吞吐时间指标是最直观的但也是最容易误读的。吞吐量throughput和延迟latency往往是一对矛盾体增大batch size能提升吞吐但会增加延迟减小batch size能降低延迟但吞吐上不去。推理场景下延迟要拆成首token延迟TTFT和每token延迟TPOT。TTFT主要受prefill阶段影响和输入长度强相关TPOT主要受decode阶段影响和模型大小、显存带宽相关。这两个指标要分开优化因为瓶颈不同。训练场景下主要看每步耗时step time和每秒样本数samples/s。每步耗时又可以分为计算时间、通信时间、数据加载时间。优化时要先定位哪部分占比最大再针对性处理。有个容易被忽视的指标是时间抖动jitter。平均延迟看起来很好但P99延迟很高说明存在长尾问题。在线上服务中P99延迟往往比平均延迟更重要因为用户对卡顿的感知是看最差的那几次。4. 实操测量与优化流程4.1 训练场景的指标采集实操训练场景我习惯用PyTorch的profiler配合自定义的metrics hook。具体做法是在训练循环里插入计时点和显存查询import torch import time # 记录开始时间和显存 torch.cuda.synchronize() start_time time.time() start_mem torch.cuda.memory_allocated() # 训练步 output model(input_ids) loss criterion(output, labels) loss.backward() optimizer.step() optimizer.zero_grad() # 记录结束时间和显存 torch.cuda.synchronize() end_time time.time() end_mem torch.cuda.memory_allocated() step_time end_time - start_time peak_mem torch.cuda.max_memory_allocated()这里有个关键点一定要在计时前后调用torch.cuda.synchronize()。因为CUDA操作是异步的不同步的话计时结果完全不准。我早期就犯过这个错误测出来的step time比实际少了一半还以为是优化见效了。采集到的数据要按训练步记录下来画成曲线看趋势。正常情况下step time应该在一个小范围内波动如果出现周期性的大幅波动可能是数据加载或通信出了问题。显存占用应该是稳定的如果持续增长大概率是内存泄漏。4.2 推理场景的压测方法推理压测比训练复杂因为要模拟真实的请求模式。我一般分三步走单请求基准测试、固定并发压测、变并发压测。单请求基准测试是发一个请求测TTFT和TPOT这是最理想情况下的性能。固定并发压测是同时发N个请求看吞吐量和延迟的变化。变并发压测是模拟真实流量并发数随时间变化看系统的稳定性。压测工具可以用开源的负载测试框架也可以自己写脚本。关键是要控制变量输入长度、输出长度、并发数、请求间隔都要明确记录。我见过有人压测时不记录输入输出长度结果两次测试结果差了一倍排查半天才发现是输入长度不同导致的。压测时还要监控显存碎片。长时间运行后显存碎片会导致明明有足够空闲显存却分配不出连续空间。监控方法是定期查询显存的分配和保留情况如果保留显存远大于分配显存说明碎片严重。4.3 基于指标的优化决策树拿到指标数据后怎么决定优化方向我总结了一个简单的决策流程现象可能瓶颈优化方向算力利用率低显存带宽利用率高内存带宽量化、减少访存、算子融合算力利用率高显存带宽利用率低算力增加并行度、使用更快精度通信时间占比高通信调整并行策略、梯度压缩、通信重叠显存占用高但利用率低显存管理激活重计算、梯度累积、显存池化延迟抖动大调度或数据加载预取、批处理优化、异步加载这个表不是绝对的但能覆盖大部分常见场景。实际排查时先用profiler拿到各部分的耗时占比再对照这个表找方向。实操心得优化之前一定要先建立基线。没有基线的优化就像蒙眼开车你不知道自己是在前进还是在原地打转。基线要记录完整的指标数据包括硬件配置、软件版本、模型配置、输入输出规格否则后续对比没有意义。4.4 一个完整的优化案例拆解假设我们有一个7B模型的推理服务实测TPOT是50ms目标是降到20ms。先采集指标显存带宽利用率85%算力利用率5%显存占用14GBFP16。分析算力利用率极低显存带宽利用率很高典型的内存带宽瓶颈。TPOT的理论下限是模型大小除以显存带宽14GB除以2TB/s等于7ms所以还有优化空间。第一步优化做INT8量化。模型大小降到7GB理论TPOT下限降到3.5ms。实测TPOT降到30ms显存带宽利用率还是85%左右。说明量化生效了但还没达到理论上限。第二步优化做算子融合。把多个小算子合并成一个大算子减少kernel启动开销和中间结果的访存。实测TPOT降到22ms。第三步优化调整batch size和调度策略。发现当前batch size下GPU有等待时间增大batch size后TPOT降到18ms但TTFT略有上升。最终在延迟和吞吐之间取了个平衡点。这个案例说明优化是个迭代过程每步都要重新采集指标看瓶颈是否转移。不要指望一步到位也不要盲目套用别人的优化方案因为瓶颈可能完全不同。5. 常见问题与排查技巧实录5.1 指标数据不可信的几种情况情况一计时不同步。前面提过CUDA异步执行导致计时偏短。解决方法是在计时点前后加synchronize或者用CUDA event来计时。情况二profiler开销过大。有些profiler会记录每个kernel的详细信息开销可能达到20%以上。这时候测出来的性能不代表真实性能。解决方法是先用低开销的粗粒度采集定位大致范围再针对特定区域开高开销的细粒度采集。情况三预热不充分。第一次运行会因为各种初始化CUDA上下文、内存分配、kernel编译而特别慢。必须预热足够多的步数等指标稳定后再开始记录。我一般预热10到20步。情况四后台干扰。同一台机器上跑着其他任务或者有监控进程在采样都会影响指标。压测时尽量独占机器关掉不必要的后台服务。5.2 显存溢出但显示显存充足这是最让人头疼的问题之一。nvidia-smi显示还有空闲显存但程序就是报OOM。原因通常是显存碎片。PyTorch的缓存分配器会预留大块显存如果请求的连续空间比最大的空闲块大即使总空闲显存足够也会失败。解决方法有几个设置PYTORCH_CUDA_ALLOC_CONF环境变量调整分配策略在训练循环中定期调用torch.cuda.empty_cache()释放未使用的缓存或者改用更节省显存的实现方式比如激活重计算。注意empty_cache()会释放缓存但也会导致下次分配变慢。不要在每步都调用只在显存紧张时调用。5.3 多卡加速比不达预期多卡训练时理想情况下N卡应该带来N倍加速但实际往往只有60%到80%。原因通常是通信开销和负载不均衡。排查步骤先看通信时间占比如果超过20%说明通信是瓶颈。再看各卡的利用率是否均衡如果某张卡利用率明显偏低说明负载不均衡。最后看通信和计算是否重叠如果没有重叠通信时间就是纯开销。优化方向调整并行策略数据并行、张量并行、流水线并行的组合使用梯度累积减少通信频率开启通信和计算的重叠比如在反向传播时提前开始梯度同步。5.4 常见问题速查表问题现象可能原因排查方法解决方向算力利用率低内存带宽瓶颈或数据加载慢看显存带宽利用率和数据加载时间量化、算子融合、预取数据显存OOM但有空闲显存碎片查最大空闲块大小调整分配策略、定期清缓存多卡加速比低通信瓶颈或负载不均看通信时间占比和各卡利用率调整并行策略、通信重叠延迟抖动大调度问题或GC看P99和P50的差距优化调度、减少动态分配吞吐上不去batch size太小或调度开销大看GPU空闲时间增大batch、批处理请求训练loss异常数值精度问题看梯度范数和激活值范围调整精度、梯度裁剪5.5 几个容易被忽视的细节细节一精度对指标的影响。FP16和BF16的算力峰值可能不同显存占用相同但数值稳定性不同。做指标对比时一定要确认精度一致。细节二序列长度的影响。注意力机制的计算量随序列长度平方增长所以长序列场景的指标和短序列完全不同。压测时要覆盖实际业务中的序列长度分布。细节三冷启动和热启动的差异。推理服务刚启动时模型权重还在内存里没加载到显存第一次请求会特别慢。生产环境要考虑预热机制。细节四不同框架的指标口径不同。同样叫“吞吐量”有的框架算的是输入token数有的算的是输出token数有的算的是请求数。对比时要统一口径。6. 指标体系的落地与持续迭代6.1 建立指标看板零散的指标数据价值有限要把它变成持续可观测的看板。训练场景我一般记录step time、samples/s、MFU、显存占用、通信时间占比、loss曲线。推理场景记录QPS、TTFT、TPOT、P99延迟、显存占用、batch size分布。看板的作用是发现趋势和异常。比如step time突然变大可能是数据加载出了问题TPOT逐渐上升可能是显存碎片积累。有了看板就能在问题恶化之前介入。6.2 指标驱动的容量规划有了历史指标数据就能做容量规划。比如根据当前的QPS和TPOT推算需要多少张卡才能支撑目标流量。计算方法是目标QPS乘以每请求的计算量除以单卡的处理能力再留一定的冗余。容量规划时要注意峰值和均值的差异。按均值规划会导致高峰期过载按峰值规划会导致资源浪费。我一般按P95流量来规划再配合弹性伸缩应对突发流量。6.3 持续优化的节奏指标优化不是一次性的工作而是持续迭代的过程。我的节奏是每周看一次指标趋势每月做一次深度分析每季度做一次全面优化。深度分析时会用profiler做细粒度采集全面优化时会尝试新的量化方案、并行策略或硬件配置。每次优化后都要更新基线否则后续对比会混乱。基线数据要存档包括当时的软硬件配置和模型配置方便回溯。6.4 团队协作中的指标规范如果是团队协作指标的定义和采集方法要统一。我见过不同团队用不同的口径算MFU汇报时数字对不上扯了半天才发现是算法不同。所以最好在团队内建立指标规范文档明确每个指标的定义、计算公式、采集方法和正常范围。规范文档不用很复杂一张表就够指标名称、定义、公式、采集工具、正常范围、异常处理。新成员入职时先看这个文档能省很多沟通成本。7. 一些个人体会做指标优化这些年最大的感受是不要迷信任何单一指标。我见过MFU很高但实际训练很慢的因为通信时间没算进去也见过显存占用很低但推理很慢的因为频繁在CPU和GPU之间倒腾数据。指标要组合看要结合具体场景看。另一个体会是优化要有优先级。不是所有指标都值得优化要先搞清楚业务最关心什么。如果是离线训练吞吐量最重要如果是在线推理延迟最重要。把精力花在关键指标上比全面撒网效果好得多。最后说个实用的技巧遇到性能问题先别急着改代码先把指标数据完整采集一遍。很多时候数据一看问题就清楚了。盲目改代码往往是在治标不治本甚至引入新问题。指标是眼睛没有眼睛的优化就是瞎折腾。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑