
1. 从一个被问烂了的问题说起如果你在AI Infra、高性能计算或者芯片行业待过一阵子大概率会遇到这样一个场景有人在群里发了一张GPU规格表上面写着“FP16算力 312 TFLOPS”然后另一个人问“那这个模型训练一次要多少FLOPs”接着就有人开始算算着算着两边吵起来了——因为一个人把FLOPS当成了FLOPs另一个人把FLOPs当成了FLOPS。这不是段子这是几乎每个月都会在技术社区里重演的真实画面。我见过工作三四年的工程师在技术评审会上把这两个词混着用也见过面试候选人在白板上推导模型计算量时单位写错了导致整个估算差了三个数量级。更麻烦的是很多技术文档自己也没写清楚一会儿FLOPS一会儿FLOPs读者根本分不清作者到底在说算力还是在说计算量。所以这篇内容就是要把这件事彻底讲透。FLOPS和FLOPs一个字母大小写的差别背后是两套完全不同的概念体系一个是衡量硬件“跑得多快”的算力指标一个是衡量模型或算法“要跑多少步”的计算量指标。搞混它们轻则算错训练成本重则选错硬件方案、定错优化方向。这篇文章适合谁看如果你是刚入行的算法工程师、正在做模型部署的工程同学、需要评估训练成本的团队负责人或者只是单纯被这两个词搞晕过的技术从业者那接下来的内容应该能帮你把这块知识补扎实。我会从概念定义、单位体系、计算逻辑、实际估算方法、常见踩坑场景几个维度展开尽量用从业者之间聊天的口吻把这件事说清楚。2. 概念拆解两个词到底在说什么2.1 FLOPS硬件的“极限速度表”FLOPS的全称是Floating-point Operations Per Second注意最后的“Per Second”它描述的是单位时间内能完成多少次浮点运算。这是一个速度指标衡量的是硬件的能力上限。你可以把它理解成汽车的“最高时速”。一辆车标称最高时速240公里意思是它在理想条件下每小时最多能跑240公里。至于你实际开的时候是不是一直踩到底、路上有没有堵车那是另一回事。FLOPS也一样它标的是理论峰值实际能跑到多少取决于你的代码、内存带宽、并行度等一系列因素。FLOPS的常见量级单位是这样的单位含义典型场景MFLOPS每秒百万次浮点运算早期CPU、嵌入式芯片GFLOPS每秒十亿次浮点运算现代CPU、入门级GPUTFLOPS每秒万亿次浮点运算主流数据中心GPUPFLOPS每秒千万亿次浮点运算高端加速卡、超算节点EFLOPS每秒百亿亿次浮点运算顶级超算系统这里有个细节值得注意FLOPS前面通常会带精度标识比如FP64 FLOPS、FP32 FLOPS、FP16 FLOPS、TF32 FLOPS。同一块芯片在不同精度下的FLOPS可以差几十倍。比如某款数据中心GPUFP64可能只有几十TFLOPS但FP16 Tensor Core能到上千TFLOPS。所以看到“这块卡有XXX TFLOPS”的时候第一反应应该是问一句什么精度下的2.2 FLOPs模型的“工作量清单”FLOPs的全称是Floating-point Operations注意这里没有“Per Second”它描述的是完成一次特定任务需要多少次浮点运算。这是一个总量指标衡量的是工作量。继续用汽车类比如果FLOPS是最高时速那FLOPs就是从北京开到上海总共需要跑多少公里。这个数字跟车没关系跟路线有关系。换一辆更快的车总里程不会变但跑完需要的时间会缩短。FLOPs通常出现在这些场景里论文里说“我们的模型只有4.5 GFLOPs”意思是推理一次需要45亿次浮点运算训练框架日志里写“Total FLOPs: 3.2e18”意思是整个训练过程累计做了3.2×10¹⁸次浮点运算部署工程师说“这个模型FLOPs太高了端侧跑不动”意思是单次推理的计算量超出了目标设备的处理能力FLOPs的量级单位跟FLOPS长得一样也是M/G/T/P但含义完全不同。1 GFLOPs是十亿次浮点运算是一个“次数”不是一个“速率”。2.3 为什么这两个词这么容易混混用的根源有三个。第一拼写太像了。就差一个字母的大小写在快速阅读或者打字的时候极容易搞错。而且很多字体里大写I和小写l看起来也差不多视觉上更难区分。第二中文翻译都差不多。很多资料把FLOPS翻译成“浮点运算能力”或“浮点算力”把FLOPs翻译成“浮点运算量”或“浮点计算量”。但在口语里大家经常都说“算力”于是“这个模型算力多大”和“这块卡算力多大”就混在一起了。第三量级单位重叠。两者都用M/G/T/P做前缀如果不看上下文看到“1.2 TFLOPs”根本不知道是在说速度还是在说总量。我自己的经验是看单位后面有没有“/s”或者“Per Second”。有就是FLOPS速度没有就是FLOPs总量。这个判断规则简单但极其有效建议你从现在开始就养成这个习惯。3. 单位体系与换算别在数量级上栽跟头3.1 两套单位体系的对照虽然FLOPS和FLOPs的前缀一样但它们描述的东西不同所以在实际使用中你需要建立两套独立的直觉。对于FLOPS速度你需要知道一块主流数据中心GPU的FP16 Tensor Core算力大概在几百到上千TFLOPS一块高端消费级显卡的FP32算力大概在几十TFLOPS一颗服务器CPU的FP64算力大概在几百GFLOPS到几TFLOPS手机SoC的NPU算力通常在几TOPS到几十TOPS注意这里是TOPS整数运算后面会讲对于FLOPs总量你需要知道一个ResNet-50推理一次大约4 GFLOPs一个BERT-Base推理一次大约22 GFLOPs一个GPT-3规模模型推理一次大约350 GFLOPs取决于序列长度训练一个GPT-3规模模型总计算量在3×10²³ FLOPs量级把这两组数字放在一起你就能做一些有意义的估算了。比如用一块312 TFLOPS的卡去推理BERT-Base理论最短时间是多少计算过程是这样的22 GFLOPs ÷ 312 TFLOPS 22×10⁹ ÷ 312×10¹² ≈ 7×10⁻⁵秒也就是大约0.07毫秒。当然这是理论峰值实际因为内存带宽、kernel启动开销、batch size等因素真实延迟会高不少但至少你有了一个数量级上的参考。3.2 精度对FLOPS的影响前面提到同一块芯片在不同精度下的FLOPS差异巨大。这里展开说一下为什么。浮点运算的精度决定了每次运算需要多少位宽。FP64用64位表示一个数FP32用32位FP16用16位INT8用8位。位宽越窄同样面积的电路能塞下的计算单元就越多或者同样的计算单元能在更短时间内完成一次运算。以某代数据中心GPU为例粗略的算力比例大概是FP641×FP322×TF328×FP16/BF1616×INT832×这个比例不是固定的不同架构差异很大但趋势是一致的精度越低标称FLOPS越高。这也是为什么AI训练和推理越来越倾向于用低精度——不是因为它更准而是因为它更快。但这里有个坑低精度FLOPS高不代表实际任务就能等比例加速。因为很多操作的瓶颈不在计算而在内存带宽。比如LayerNorm、Softmax这类操作计算量不大但需要频繁读写内存这时候FP16的高FLOPS根本发挥不出来。所以看到“FP16算力是FP32的16倍”时不要天真地以为所有任务都能快16倍。3.3 FLOPs的计算口径问题FLOPs的统计口径比FLOPS更乱因为“一次浮点运算”的定义本身就有歧义。最常见的分歧是乘加运算算一次还是两次一个矩阵乘法里的核心操作是a×bc这包含一次乘法和一次加法。有的统计工具把它算作2次浮点运算1次乘法1次加法有的算作1次因为硬件通常有FMA指令一个周期完成乘加。这两种口径算出来的FLOPs能差一倍。主流的约定是学术论文和大多数分析工具如fvcore、thop默认乘加算2次硬件规格书里的FLOPS通常按FMA算1次运算来标称这就导致一个尴尬的局面你用工具算出来模型有10 GFLOPs除以硬件标称的100 TFLOPS得到0.1毫秒但实际可能跑出来0.2毫秒甚至更多。不一定全是口径问题但口径至少是原因之一。我的建议是在做任何严肃估算之前先确认两边的口径是否一致。如果不一致要么统一口径要么在结果上留出足够的余量。4. 实际估算从模型到硬件的完整计算链4.1 怎么估算一个模型的FLOPs对于常见的神经网络层FLOPs有比较成熟的经验公式。全连接层输入维度D_in输出维度D_out则FLOPs ≈ 2 × D_in × D_out乘加各算一次。如果带batch size B再乘B。卷积层输出特征图尺寸H_out × W_out卷积核尺寸K × K输入通道C_in输出通道C_out则FLOPs ≈ 2 × H_out × W_out × K × K × C_in × C_out。注意力层这是Transformer的核心。对于序列长度L、隐藏维度D、注意力头数H粗略估算FLOPs ≈ 2 × L² × D × 2 2 × L × D² × 4。第一项是注意力矩阵的计算第二项是QKV投影和输出投影。当L很大时第一项会主导。这些公式看起来简单但实际用的时候有几个注意点激活函数、归一化层的FLOPs通常可以忽略不计因为它们只占总量很小一部分残差连接不产生额外的浮点运算只是加法Embedding层本身不算FLOPs但后续的投影要算如果你不想手算可以用工具。PyTorch生态里有fvcore和thop两个库用法很简单import torch from thop import profile model MyModel() input_tensor torch.randn(1, 3, 224, 224) flops, params profile(model, inputs(input_tensor,)) print(fFLOPs: {flops / 1e9:.2f} GFLOPs) print(fParams: {params / 1e6:.2f} M)但要注意这些工具对某些自定义算子可能统计不准尤其是动态控制流、条件分支、循环结构。所以工具结果只能作为参考关键场景还是得结合理论分析。4.2 从FLOPs和FLOPS推算时间有了模型的FLOPs和硬件的FLOPS理论上就能算时间理论最短时间 FLOPs ÷ FLOPS但这个公式的实际可用性取决于一个关键概念MFUModel FLOPs Utilization模型计算利用率。MFU 实际达到的FLOPS ÷ 理论峰值FLOPS在真实训练场景中MFU通常在30%到60%之间。做得好的框架和模型能到50%以上做得差的可能只有20%出头。推理场景的MFU通常更低因为batch size小、kernel启动开销占比高。所以更实际的估算公式是实际时间 ≈ FLOPs ÷ (FLOPS × MFU)举个例子训练一个总计算量3×10²³ FLOPs的模型用1000块标称312 TFLOPS的卡假设MFU是40%那么总可用FLOPS 1000 × 312×10¹² × 0.4 1.248×10¹⁷ FLOPS 训练时间 3×10²³ ÷ 1.248×10¹⁷ ≈ 2.4×10⁶秒 ≈ 28天这个估算跟业界公开的一些训练时长数据是能对上的说明方法本身是靠谱的。4.3 一个完整的估算实例假设你要训练一个类似LLaMA-7B的模型想估算需要多少卡、跑多久。第一步估算单次前向传播的FLOPs对于Transformer类模型前向FLOPs ≈ 2 × N × L × D其中N是参数量L是序列长度D是隐藏维度。但更准确的公式要考虑注意力部分的二次项。LLaMA-7B大约有6.7B参数隐藏维度4096序列长度2048。粗略估算前向FLOPs ≈ 2 × 6.7×10⁹ × 2048 ≈ 2.7×10¹³ FLOPs 27 TFLOPs第二步估算训练总FLOPs训练时前向反向大约需要3倍前向的计算量反向传播的FLOPs约为前向的2倍。再乘以训练token总数。假设训练1T token 总FLOPs ≈ 3 × 2.7×10¹³ × 1×10¹² ≈ 8.1×10²⁵ FLOPs第三步估算训练时间用1024块卡每块标称312 TFLOPSMFU取40%可用FLOPS 1024 × 312×10¹² × 0.4 ≈ 1.28×10¹⁷ FLOPS 训练时间 8.1×10²⁵ ÷ 1.28×10¹⁷ ≈ 6.3×10⁸秒 ≈ 7300天这个数字明显不对说明我的估算哪里出了问题。检查一下1T token的训练量对于7B模型来说总FLOPs应该是6 × N × token数 6 × 6.7×10⁹ × 1×10¹² 4×10²² FLOPs而不是8.1×10²⁵。我前面多乘了三个数量级。修正后 训练时间 4×10²² ÷ 1.28×10¹⁷ ≈ 3.1×10⁵秒 ≈ 3.6天这个结果就合理多了。业界训练7B模型在1T token上用千卡级别跑几天是符合实际的。这个例子说明一个很重要的事FLOPs估算里最容易出错的就是数量级。一个不小心多乘或少乘10³结果就完全失去参考价值。所以每次算完都要用直觉检查一下——这个时间/成本合理吗5. 常见混淆场景与避坑指南5.1 硬件规格书里的文字游戏很多硬件规格书在写FLOPS的时候会标注“峰值”或者“理论最大值”。这个数字是在最理想条件下测出来的所有计算单元满载、数据全部在寄存器里、没有内存访问延迟、没有指令调度开销。实际能跑到多少在训练场景MFU 40%-50%算不错在推理场景尤其是小batchMFU可能只有10%-20%。所以看到规格书上的FLOPS先打个对折甚至打两折再用来做估算。另一个坑是稀疏算力。有些规格书会标“稀疏FLOPS是稠密的2倍”但这个2倍只有在模型本身有50%结构化稀疏且硬件支持稀疏加速时才能拿到。大多数模型没有这种稀疏性所以那个数字看看就好。5.2 论文里的FLOPs口径不一致读论文的时候经常看到“我们的模型只有XX GFLOPs”然后跟另一个论文的模型对比。但两篇论文的FLOPs统计口径可能不一样一个算乘加为2次一个算1次一个算输入分辨率224一个算320一个包含后处理一个不包含。所以跨论文比较FLOPs时要格外小心。如果论文没有明确说明统计口径最好自己用统一工具重新算一遍或者至少确认输入尺寸、是否包含特定层等关键条件。5.3 训练和推理的FLOPs不是一回事训练时的FLOPs通常是推理的3倍左右前向反向但这只是计算量。训练还涉及优化器状态更新、梯度同步、数据加载等额外开销这些不直接体现在FLOPs里但会显著影响实际耗时。推理场景则更复杂batch size1时FLOPs利用率极低因为很多计算单元在等数据batch size增大后利用率提升但延迟也会增加。所以推理优化往往是在FLOPs、延迟、吞吐量之间做权衡不是单纯看FLOPs数字。5.4 整数运算的TOPS是另一套体系在端侧和边缘计算场景你更常看到的是TOPSTera Operations Per Second而不是FLOPS。TOPS统计的是整数运算通常用于量化后的模型。TOPS和FLOPS之间没有简单的换算关系因为整数运算和浮点运算的硬件实现不同。一个标称10 TOPS的NPU跑浮点模型可能只有1-2 TFLOPS的有效算力。所以端侧选型时不要拿TOPS直接跟FLOPS比要看实际模型在目标硬件上的benchmark。6. 实操中的经验与技巧6.1 快速判断该用哪个词我自己的判断流程是这样的如果描述的对象是硬件GPU、CPU、NPU、加速卡用FLOPS如果描述的对象是模型、算法、任务用FLOPs如果是在说“跑得多快”用FLOPS如果是在说“要跑多少”用FLOPs如果拿不准看单位后面有没有“/s”或“Per Second”这个规则覆盖了90%以上的场景。6.2 估算时留足余量不管是估算训练时间还是推理延迟我都会在理论值基础上留2-3倍的余量。原因很简单理论值假设了完美的并行、零开销的通信、100%的MFU这些在现实中都不存在。具体来说训练场景理论时间 × 2.5 作为保守估计推理场景理论延迟 × 3 作为保守估计成本估算在时间估算基础上再上浮20%作为buffer这样算出来的数字虽然不够“精确”但至少不会让你在项目排期时过于乐观。6.3 工具推荐与使用注意除了前面提到的thop和fvcore还有一些工具可以用PyTorch Profiler不仅能看FLOPs还能看实际kernel耗时、内存占用Nsight Systems / Nsight ComputeNVIDIA生态下的性能分析工具能看到实际FLOPS利用率rocProfilerAMD生态的对应工具使用这些工具时要注意它们统计的FLOPs通常是“理论计算量”不是“实际执行的指令数”。有些框架会做算子融合把多个小算子合并成一个大kernel这时候工具统计的FLOPs可能跟实际执行的浮点运算次数有出入。6.4 一个容易被忽略的细节Batch Size的影响FLOPs本身不随batch size变化因为它是单样本的计算量但实际FLOPS利用率跟batch size关系极大。小batch时GPU的并行度利用不充分很多计算单元闲置实际FLOPS远低于峰值。大batch时利用率提升但可能遇到内存瓶颈或者梯度同步开销。所以在做推理优化时一个常见的策略是在延迟允许的范围内尽量增大batch size把FLOPS利用率拉上去。这也是为什么很多推理服务会做动态batching——把多个请求攒在一起跑提高硬件利用率。7. 回到最初的问题现在再回头看“FLOPS和FLOPs的区别”其实一句话就能说清楚FLOPS是速度FLOPs是总量。但这一句话背后涉及的是从硬件规格到模型设计、从训练成本到推理优化的完整知识链。我在实际工作中见过太多因为混淆这两个词而导致的错误决策有人拿模型的FLOPs去跟硬件的FLOPS直接比得出“这个模型跑不了”的结论其实只是单位搞错了有人在选卡时只看FLOPS数字忽略了精度和实际利用率结果买回来的卡跑自己模型还不如另一款便宜的。这些坑我都踩过所以现在每次做估算我都会先把单位写清楚把口径对齐把余量留足。这三个习惯看起来简单但能避免绝大多数低级错误。如果你只记住一件事那就记住这个看到FLOPS想“多快”看到FLOPs想“多少”。剩下的就是在实际项目中不断积累对数量级的直觉——这个没有捷径只能靠多算、多验证、多跟实际benchmark对照。算得多了你看到一组数字大概就能感觉到它靠不靠谱。这种直觉比任何公式都值钱。