面灵AI→

快手 AI Infra 算法岗二面面经:分布式训练与推理、高并发系统设计

轮次
二面
时间
2026-09
来源
牛客网

《面试题目》

  1. 分布式训练解决了哪些问题?
  2. 请简述流水线并行(PP)的实现逻辑、核心作用与存在的短板。
  3. 分布式推理从根本上解决了哪些推理场景痛点?
  4. 离线推理主打高吞吐,有哪些具体优化手段可以提升整体吞吐?
  5. 时延降低为什么不等于吞吐一定提升?如何正确区分二者逻辑?
  6. 当前已有 Agent 自动化性能优化工具,你个人的核心竞争力是什么?
  7. 重构优化后,组 batch 逻辑是否会引入训练/推理随机性问题?如何规避?
  8. 是否了解 Java、MySQL 基础技术?
  9. 是否做过类似 12306 高并发系统的架构设计?
  10. 高并发系统设计需要重点考虑哪些核心维度?
  11. 手撕算法:链表两数相加。

《参考解析》

分布式训练解决的是「单卡装不下、也等不起」。 模型参数、梯度和优化器状态在 fp32 下大约是参数量的 16 倍字节,再叠加激活值,单卡显存很快见顶;同时训练时长与算力成正比,靠堆单卡算力不经济。分布式训练从三个方向切:数据并行解决吞吐(每卡放全量模型、分数据,用 AllReduce 或 ZeRO 切分优化器状态、梯度、参数,代价是通信量)、张量并行解决单层太大(把矩阵乘按列或按行切开,层内通信频繁,一般限制在单机 NVLink 内)、流水线并行解决层数太多(按层切到不同设备,用 micro-batch 填流水)。实际生产里常把三者组合成 3D 并行,再加序列并行、专家并行来安放超长序列和 MoE,核心矛盾始终是「算得多」与「通信少」之间的平衡。

流水线并行的实现逻辑与短板。 PP 把模型按层切成若干 stage 放到不同设备上,前向时依次传递激活、反向时依次回传梯度。问题在于朴素做法(GPipe 式的全批前向再全批反向)会产生大量空泡:设备在等上游的数据,利用率骤降。于是有了 micro-batch 切分与 1F1B(一个前向接一个反向)把空泡压到 (p-1)/(m+p-1) 量级(p 为 stage 数、m 为 micro-batch 数),进一步还有 interleaved 1F1B、zero-bubble 等把空泡再摊薄。短板也很明确:一是空泡无法彻底消除,stage 越多越明显;二是需要缓存多个 micro-batch 的激活,显存换利用率;三是负载均衡敏感,层切不匀时最慢的 stage 决定整体节奏;四是与前两者的组合复杂,通信与计算的重叠要做得好才有收益。

分布式推理的痛点与离线吞吐优化。 单卡推理的痛点是显存装不下长上下文和超大模型(KV Cache 随序列长度线性增长)、单卡算力不足导致首 token 时延(TTFT)和单 token 时延(TPOT)都不达标、以及无法弹性应对流量峰值。分布式推理用张量并行把模型摊开降单卡压力、用流水并行和多副本做横向扩容、用 PD 分离(prefill 与 decode 分池)避免长 prefill 阻塞 decode、用 KV Cache 的跨卡传输或分层缓存减少重复计算。离线场景主打吞吐,手段包括:连续批处理(continuous batching,不等整批结束就补新请求)、分页式 KV Cache 提升显存利用率、按长度分桶减少 padding 浪费、量化(W8A8、KV Cache 量化)提升单位显存吞吐、算子融合与 CUDA Graph 降低启动开销、prefix 复用与缓存命中、chunked prefill 平衡长短请求,以及投机解码在部分场景下用并行换串行。

时延与吞吐为什么不是一回事。 吞吐是单位时间完成的请求数,时延是单个请求从进入到返回的耗时,两者的桥梁是排队论:在资源不变的前提下,把批做大通常能提升吞吐,但会拉长单请求等待,所以时延变差;反过来,把时延压下去的手段(小批、抢占式调度、频繁切换)往往牺牲设备利用率,吞吐不升反降。可以补一句 Little 定律 L = λW:并发数、到达率与停留时间相互约束,单纯报「时延降了 30%」而不给并发与批大小,无法推出吞吐变化。真正能同时改善两者的手段是减少单位工作量(量化、算子优化、缓存复用、投机解码)或提升资源利用率(更好的调度与重叠),而「把批调大」只是在两者之间做取舍。

组 batch 重构会不会引入随机性。 会,而且这是分布式训练复现性问题的常见来源。批内样本组成改变会改变 padding 与 mask 的形状、影响梯度累加的浮点结合顺序,进而让数值结果出现微小差异;如果再加上按长度分桶、动态批、变长序列的注意力实现差异,同一个 step 在不同 rank 上可能取到不同的 batch,导致结果不可复现甚至影响收敛稳定性。规避办法:固定数据加载顺序与随机种子(含 sampler 的 seed 与 epoch 维度)、让所有 rank 拿到一致的 batch 划分与相同的样本数、对变长实现统一走同一条 kernel 路径、把梯度累加与归约顺序固定下来、给关键指标加「同种子两次运行结果一致」的回归校验;推理侧则要区分「可复现」与「可接受波动」,评测集上跑固定输入比对输出,别用随机采样结果下结论。

Agent 自动调优面前,个人的核心竞争力在哪。 面试官问这句通常是想确认你不是只会跑工具。可以这样答:工具擅长的是「给定目标做搜索」(调参、试 kernel、扫并行配置),它不擅长定义目标和判断代价——什么指标才代表真实业务收益、哪些优化会牺牲稳定性或可维护性、上线后如何回滚、边界条件在哪里,这些需要人给约束;而且性能问题的定位往往是跨层的(模型结构、框架、编译器、驱动、集群拓扑),需要能把现象拆成可验证的假设并设计实验,Agent 只能在你划定的空间里更快地试错。落到具体经历上,举一个你自己定位到瓶颈并量化收益的例子,比任何方法论都有说服力。

Java/MySQL 与 12306 这类高并发设计。 被问到语言基础时,Java 侧至少要能讲清集合与并发(HashMap 结构与扩容、ConcurrentHashMap 的分段或 CAS + synchronized、线程池参数与拒绝策略、JMM 与 volatile)、JVM 内存分区与常见 GC;MySQL 侧是索引(B+ 树、最左前缀、覆盖索引、回表)、事务隔离级别与 MVCC、锁(行锁与间隙锁)、慢查询与深分页优化。12306 的高并发设计可以按「隔离热点 + 削峰 + 幂等 + 兜底」四层讲:按车次与乘车日期做数据分片,把余票这种热点收敛到单点串行(Redis + Lua 原子扣减或本地队列),下单与支付走异步消息削峰、库存扣减与订单落库分阶段提交;所有写接口用幂等键(用户 + 车次 + 日期)防重复下单;读多写少的余票查询用多级缓存与读写分离,并在缓存击穿时用互斥重建;兜底要有排队与限流(令牌桶 / 漏桶)、灰度降级(关闭非核心功能)、容量水位与压测基线,以及售罄后的对账补偿。手撕「链表两数相加」按位遍历、处理进位与长度不等即可,注意头节点构造与最后的进位。