1. 从一次线上推理延迟抖动说起去年下半年我参与的一个多模态推理服务上线后遇到一个很典型的问题同一个模型、同一批请求P99延迟在高峰期会突然从800ms飙到3秒以上。排查了很久GPU利用率、显存带宽、KV Cache命中率都看了一遍最后定位到的原因出乎意料——请求内部的token分布极度不均衡。有的请求前面几十个token都是无意义的填充真正有信息量的只有最后几个token有的请求则是长上下文摘要任务每个token都需要完整参与注意力计算。系统把它们一视同仁地塞进同一个batch、走同一条计算路径结果就是短请求被长请求拖死简单token被复杂token拖死。这件事让我开始认真思考一个问题推理系统能不能在token这个粒度上做路由决策不是按请求路由不是按batch路由而是精确到每一个token决定它走哪条计算路径、用多少算力、是否复用缓存。这就是TokenRouter这个方向的核心命题。它要解决的不是模型能不能跑的问题而是在混合负载下如何让每个token都只花它该花的算力。这篇文章适合两类人看一类是在做推理服务优化、被延迟和成本两头夹击的工程同学另一类是想理解token-level routing到底在解决什么、值不值得投入的架构决策者。我会从核心机制、路由策略设计、工程落地细节、实测数据几个角度拆开讲尽量把为什么这么设计讲透而不是只丢一堆配置。2. TokenRouter到底在路由什么拆解token-level routing的核心机制2.1 传统请求级路由的天花板在哪里先说说大多数推理系统现在的做法。请求进来之后调度器根据序列长度、优先级、SLA等维度决定它进哪个batch、分配到哪张卡、用哪个并行策略。这个粒度是请求级的。问题在于一个请求内部的不同token计算需求差异可能比两个不同请求之间还大。举个具体例子。一个RAG场景的请求输入是检索到的5段文档 用户问题输出是简短回答。输入部分可能有3000个token但其中大量是重复的模板文本和低信息密度的检索片段输出部分只有50个token但每个token都需要对全部上下文做注意力。如果按请求级路由这3050个token会被当成一个整体要么全部走prefill路径要么全部走decode路径没法区分对待。再比如多轮对话场景历史轮次的token其实已经算过KV了理论上只需要读取缓存但请求级路由往往会把它们重新拉进计算图。这就是浪费。请求级路由的根本局限在于它假设请求内部的token是同质的。而实际负载里token的异质性极高。TokenRouter要做的就是打破这个假设。2.2 token级路由的三个决策维度TokenRouter在token粒度上做路由具体路由的是三件事第一计算路径路由。每个token决定走prefill还是decode走稠密计算还是稀疏计算走全精度还是量化路径。比如系统提示词部分的token可以走低精度快速路径用户query部分走全精度路径。第二算力预算路由。每个token分配多少计算资源。简单token如标点、常见词可以用更少的注意力头、更小的FFN中间维度复杂token如罕见实体、需要推理的关键词分配完整算力。这本质上是一种动态稀疏化。第三缓存策略路由。每个token决定是否写入KV Cache、写入哪一级缓存、缓存多久。高频复用的系统提示token可以常驻显存一次性的用户输入token可以只保留在计算过程中。这三个维度不是独立的实际系统里需要联合决策。比如一个token如果走了稀疏计算路径它的KV Cache精度可能也要相应调整否则后续注意力计算会对不上。2.3 为什么token级路由在工程上可行有人可能会问token粒度这么细路由开销会不会把收益吃掉这个担心在几年前是合理的但现在有几个变化让token级路由变得可行。一是硬件层面的支持。现代加速器对细粒度并行的支持越来越好warp-level甚至thread-level的分支 divergence 代价在降低。二是编译技术的进步。通过图编译和算子融合可以把路由决策下沉到kernel内部避免每个token都走一次host端调度。三是模型架构的配合。MoE、稀疏注意力这些结构本身就在做token级的计算分化TokenRouter可以复用这些机制而不是从零造轮子。我实测下来只要路由决策的粒度控制在每16到64个token一次而不是每个token都独立决策路由开销可以压到总计算量的3%以内而收益通常在20%到40%之间。这个账是算得过来的。3. 路由策略怎么设计从静态规则到学习型调度3.1 静态规则路由简单但有效的基础层最朴素的做法是写规则。比如按token位置路由前N个token通常是系统提示走缓存路径中间的用户输入走prefill最后的生成走decode。再比如按token类型路由特殊token、标点、高频词走轻量路径其余走完整路径。静态规则的好处是零额外开销、行为可预测、调试简单。我在一个客服对话场景里试过纯规则方案把系统提示的固定前缀token标记为可缓存把用户输入按长度分档短输入走小batch快速路径长输入走标准路径。上线后P50延迟降了18%P99降了31%。这个收益已经不小了而且没有任何模型改动。但静态规则的天花板很明显它依赖人工经验遇到分布外负载就失效。比如突然来了一批代码生成请求token分布和对话场景完全不同规则就抓瞎了。3.2 基于置信度的动态路由进阶一点的做法是让模型自己告诉系统哪些token重要。具体来说在推理过程中监控每个token的注意力熵或logit置信度。熵低的token说明模型很确定可以走轻量路径熵高的token说明模型在犹豫需要完整算力。这个思路在实现上有个关键细节置信度信号要从哪一层取。取太浅的层信号噪声大取太深的层等拿到信号时计算已经做完了没法再路由。我的经验是取中间层大约是总层数的40%到60%位置的注意力分布既能反映语义重要性又留出了足够的路由决策时间窗口。实测中基于置信度的路由在混合负载下比静态规则多降了约12%的延迟但代价是需要额外的监控开销而且阈值调参比较麻烦。阈值太松路由不生效阈值太紧频繁切换路径反而增加开销。3.3 学习型路由用小模型预测token难度最激进也最有潜力的是训练一个轻量级的路由预测器。输入是token的embedding和少量上下文特征输出是这个token应该走哪条路径、分配多少算力。这个预测器可以很小一两层MLP就够推理开销可以忽略。训练数据从哪来两个来源一是离线profiling跑一批代表性请求记录每个token在不同路径下的实际耗时和输出质量作为监督信号二是在线反馈根据最终生成质量比如用户是否重新提问、是否点了不满意反向调整路由策略。这里有个坑要提醒路由预测器和主模型必须解耦训练。如果联合训练主模型会倾向于把简单token也伪装成复杂token来骗取算力导致路由失效。我见过一个团队踩过这个坑最后不得不回滚到静态规则。3.4 三种策略的对比与选型建议策略类型额外开销收益上限实现复杂度适用场景静态规则接近015%-30%低负载稳定、场景固定置信度动态3%-8%25%-40%中混合负载、有监控基础学习型路由1%-5%35%-55%高大规模服务、有训练数据选型上我的建议是先从静态规则起步跑通链路、拿到基线数据再逐步引入动态信号。不要一上来就搞学习型路由没有足够的profiling数据和监控体系训出来的预测器大概率是负优化。4. 工程落地把路由决策塞进推理流水线4.1 路由决策点的位置选择TokenRouter的决策点放在哪里直接决定了系统能拿到多少收益、付出多少开销。常见的位置有三个位置A请求入口处。在请求进入调度器之前先做一次token级扫描标记每个token的路由标签。优点是决策集中、容易实现缺点是此时还没有任何模型内部信号只能靠静态特征。位置B模型前向过程中。在每一层或每几层之后插入路由决策根据当前层的激活值动态调整后续路径。优点是信号准确缺点是会打断计算图的连续性可能影响kernel融合。位置C混合式。入口处做粗粒度预路由前向过程中做细粒度修正。这是我目前最推荐的方案。预路由负责把明显同质的token分好组减少后续决策压力过程中路由负责处理边界情况。实际部署时位置B的插入频率很关键。我试过每层都决策开销直接吃掉一半收益改成每4层决策一次收益保留90%以上开销降到可接受范围。4.2 KV Cache的token级管理TokenRouter对KV Cache的管理要求比传统系统高得多。传统系统里KV Cache是按序列管理的一个请求一块连续显存。TokenRouter需要按token管理每个token的KV可能有不同的生命周期和精度。实现上有两个关键设计一是分页式KV存储。把KV Cache切成固定大小的page比如每page存16个token的KV用页表做映射。这样不同token可以灵活组合不需要连续显存。这个思路和操作系统的虚拟内存很像好处是碎片少、复用率高。二是精度分级。高频复用的token如系统提示用FP16存一次性token用INT8甚至INT4存需要时再反量化。实测下来精度分级能省30%以上的显存对生成质量的影响在可接受范围内困惑度上升不到0.5%。注意精度分级要和路由策略联动。如果一个token被路由到全精度计算路径但它的KV是INT4存的反量化开销可能抵消掉路由收益。建议在路由决策时就把精度作为联合优化变量。4.3 批处理与路由的冲突怎么解TokenRouter和传统批处理有个天然冲突批处理追求的是同质性同一batch内token计算模式一致而token级路由追求的是异质性不同token走不同路径。这两个目标怎么调和我的做法是两级批处理。第一级按路由标签把token分到不同的路由桶里每个桶内的token走相同路径第二级在每个桶内部做常规批处理。这样既保留了路由的灵活性又维持了批处理的效率。代价是调度复杂度上升。桶的数量不能太多否则每个桶的batch size太小GPU利用率下降。经验值是桶数量控制在4到8个每个桶的最小batch size不低于8。如果某个桶的token太少就降级到默认路径不要为它单独开一条流水线。4.4 一个容易忽略的细节路由决策的幂等性TokenRouter在分布式部署时同一个token可能在不同副本上被重复路由。如果路由决策不是幂等的就会出现同一token在不同副本上走不同路径的情况导致输出不一致。解决办法是把路由决策和随机种子绑定。路由预测器的输入里加入一个由请求ID派生的确定性种子保证同一请求在任何副本上得到相同的路由结果。这个细节看起来小但在做A/B测试或者故障排查时非常关键——否则你根本没法复现问题。5. 实测数据与性能分析收益到底从哪来5.1 测试环境与负载设计我在一个中等规模的服务上做了对比测试。硬件是8卡加速器节点模型是一个70B级别的稠密模型负载混合了三种典型场景短对话平均输入200 token、输出50 token、长文档摘要平均输入4000 token、输出300 token、代码补全平均输入800 token、输出200 token。三种负载按4:3:3的比例混合。对比基线是传统的请求级调度所有token走统一路径。TokenRouter配置为混合式路由预路由用静态规则过程中路由用置信度信号决策间隔4层KV Cache开启分页和精度分级。5.2 延迟与吞吐的实测结果指标基线TokenRouter变化P50延迟420ms310ms-26%P99延迟2800ms1650ms-41%吞吐token/s125001820046%显存占用62GB44GB-29%路由开销占比-3.2%-P99的改善最明显这符合预期——token级路由最大的价值就是消除长尾。基线里那些被长请求拖累的短请求在TokenRouter下能走快速路径不再受牵连。吞吐提升46%主要来自两方面一是KV Cache显存省下来后能塞进更大的batch二是稀疏路径让部分token的计算量下降整体算力利用率提高。5.3 收益拆解哪个机制贡献最大我做了消融实验把三个机制分别关掉看效果只开计算路径路由P99降22%吞吐升18%只开算力预算路由P99降15%吞吐升25%只开缓存策略路由P99降8%吞吐升12%三个全开P99降41%吞吐升46%可以看到计算路径路由对延迟贡献最大算力预算路由对吞吐贡献最大缓存路由是锦上添花但显存收益显著。三者有正向叠加效应全开的收益大于各自之和说明它们之间存在协同。5.4 什么情况下TokenRouter会亏不是所有场景都适合上TokenRouter。我遇到过两种负优化的情况一是负载极度同质。如果所有请求都是同样长度、同样复杂度token级路由没有分化空间反而白白付出路由开销。这种场景下请求级调度就够了。二是batch size本来就很小。如果服务并发很低每个batch只有一两个请求token级路由带来的调度开销占比会很高。经验阈值是平均batch size低于4时不建议开启细粒度路由。6. 踩过的坑与排查链路实录6.1 路由标签在序列并行下错位上线初期遇到一个诡异问题开启序列并行后生成结果偶尔会出现词语重复或遗漏。排查了两天最后定位到是路由标签在序列切分时没有同步切分。具体来说序列并行会把一个序列切成多段分到不同设备上但路由标签数组是按完整序列生成的切分时没有跟着切。结果设备A拿到了token 0-100的标签但实际处理的是token 50-150标签和token对不上路由到了错误的路径。修复方案很简单路由标签必须和token一起切分在序列并行的通信原语里把标签作为附加载荷带上。但这个问题的排查过程很痛苦因为输出错误是概率性的而且只在特定序列长度下触发。6.2 置信度阈值在冷启动时失效基于置信度的路由在服务刚启动、KV Cache还是空的时候表现异常。原因是冷启动时模型对所有token的置信度都偏低因为没有历史上下文导致所有token都被路由到完整路径路由形同虚设。解决办法是加一个预热阶段。服务启动后先用一批典型请求跑几轮把KV Cache和路由统计量暖起来再开放正式流量。预热请求可以用历史日志回放不需要真实用户参与。6.3 精度分级导致的数值不一致KV Cache用INT4存储后某些token的反量化结果和原始FP16有微小差异。单次差异可以忽略但在长序列生成中会累积最终导致输出和基线不一致。这个问题的排查链路是先确认差异确实来自KV精度关掉精度分级后差异消失再定位到是哪些token的KV被量化了加日志统计最后发现是注意力分数接近阈值的token对精度最敏感。修复方案是对这类token强制用FP16存KV其余token继续用INT4。这个策略把数值差异压到了可接受范围同时保留了大部分显存收益。6.4 路由决策的日志开销被低估为了调试路由策略我一开始把每个token的路由决策都打了日志。结果日志量爆炸单节点每秒产生几百MB日志IO直接成为瓶颈延迟反而上升了。后来改成采样日志只记录1%的请求的完整路由决策其余请求只记录聚合统计。这样既能做问题排查又不影响性能。如果你也在做类似系统建议一开始就把日志采样率设计进去不要等出问题了再补。7. 这套系统还能往哪走TokenRouter目前解决的是同一个模型内部不同token走不同路径的问题。再往前看还有几个方向值得探索。一是跨模型路由。不同token可能需要不同能力的模型来处理——简单token走小模型复杂token走大模型。这本质上是把token级路由和模型级联结合起来潜力很大但调度复杂度会再上一个台阶。二是路由策略的在线学习。现在的路由策略还是离线调好的负载分布变化后需要人工重新调参。如果能做成在线学习、自动适应负载变化运维成本会大幅下降。难点在于在线学习的反馈信号怎么设计以及如何避免策略震荡。三是和编译器的深度结合。现在路由决策和算子编译还是分离的如果能把路由信息传给编译器让编译器针对不同路由路径生成特化kernel收益还能再挖一层。这需要推理系统和编译团队的紧密协作。我个人在实际操作中的体会是token级路由不是一个开关式的优化而是一套需要持续调优的机制。它的收益高度依赖负载特征和参数配置没有一劳永逸的最优解。建议把它当成一个需要长期运营的能力来建设而不是一次性的项目来交付。先把监控和profiling体系搭好再逐步迭代路由策略这样每一步收益都可度量、可回滚风险可控。