用"先定义、再分析、后总结"的三段式结构,把每道技术题答出深度和条理。
通用答题方法论
三段式答题框架
每一道技术题都按以下三段式回答:
用数据支撑回答
回答中尽量带入具体数字,以下是一组参考基准值:
FDE 面试高频技术问题 Top 15
Q1:解释 vLLM 的 PagedAttention 机制
定义:把 KV Cache 按固定大小的 block 分页管理,借鉴操作系统虚拟内存思想。 分析: - 问题:传统推理引擎的 KV Cache 连续分配,导致显存碎片化(浪费 30-40%) - 方案:将 KV Cache 切分为固定大小的 block(如 16 tokens/block),按需分配 - 核心机制:block table 动态映射、非连续存储、自动 GC 回收 - 效果:显存碎片率从 40% 降到接近 0,整体利用率从 60% 提升到 95% 总结:在我的实践中,开启 PagedAttention 后,同样一张 A100 能服务的并发请求数提升了 2.5 倍。
Q2:Continuous Batching 解决了什么问题?
定义:在批次级别动态替换已完成的序列,而不是等整个 batch 都完成再出下一批。 分析: - 传统 Static Batching 的问题:短序列等长序列,GPU 空转 - Continuous Batching 的做法:一个序列生成完毕立即从 batch 中移除,新序列补充进来 - 实现依赖:PagedAttention 提供的非连续 KV Cache 存储 - 效果:吞吐提升 2-4 倍,尤其在请求长度差异大的场景下效果显著 总结:生产环境中请求长度方差通常很大(CV 约 0.6-0.8),Continuous Batching 的价值更加突出。
Q3:INT8 量化和 FP8 量化怎么选?
定义:INT8 使用 8bit 整数表示权重/激活,FP8 使用 8bit 浮点数(E4M3/E5M2 格式)。 分析: - 精度:FP8 优于 INT8(因为浮点有动态范围) - 速度:两者接近,都依赖硬件支持(Hopper 架构原生支持 FP8) - 兼容性:INT8 更广泛,FP8 需要 H100 或更新 GPU - 实践建议: - 有 H100 则优先 FP8,精度更好 - 有 A100 则 INT8 是唯一选择 - 70B 以上大模型则更推荐 FP8,精度损失更可控 总结:我们在 A100 上用 INT8 量化 70B 模型,精度损失 小于0.5%,显存降低约 50%。
Q4:70B 模型如何在有限 GPU 下部署?
定义:通过量化 + 分布式并行 + 推理优化的组合方案,在资源约束下部署大模型。 分析: - 方案一:INT8 量化 + Tensor Parallel(2-4 卡),显存从 140GB 降到 70GB - 方案二:INT4 量化 + 单卡,显存降到 35GB,但精度损失更大 - 方案三:CPU offload(推理慢,适合离线场景) - 推荐方案:如果有多卡,TP2 + INT8 是性价比最高的选择 - 额外优化:启用 Prefix Caching(相同前缀只计算一次) 总结:我们采用 TP2 + INT8 部署 70B 模型,2 张 A100-80G, P99 延迟约 400ms,GPU 利用率 75%。
Q5:如何优化推理延迟?
定义:从 prefill(首 token 延迟)和 decode(逐 token 生成延迟)两个阶段分别优化。 分析: - Prefill 阶段优化: - Flash Attention 2(减少 IO 复杂度) - 增大 prefill batch size(提高并行度) - Decode 阶段优化: - Continuous Batching(减少空闲等待) - 量化(降低计算量) - KV Cache 优化(PagedAttention、Prefix Caching) - 系统级优化: - 模型并行度(TP/PP)选择 - GPU 通信优化(NCCL 调参) 总结:我们的综合优化路径是 FlashAttention2 + Continuous Batching + INT8, TTFT 从 600ms 降到 200ms,解码吞吐提升 3 倍。
Q6:流量翻 10 倍怎么扛?
定义:从垂直扩展、水平扩展、架构优化三个层次应对流量激增。 分析: - 第一层(立即生效): - 调大 batch size,提升单实例吞吐 - 开启所有优化开关(Continuous Batching、Prefix Caching) - 第二层(短期,小时级): - 水平扩展:K8s HPA 自动加实例 - 负载均衡:根据模型/请求类型分流 - 第三层(中期,天级): - 架构优化:换更高效的推理引擎 - 模型蒸馏:用 7B 蒸馏模型替代 13B - 引入缓存:高频问题直接返回缓存结果 - 第四层(降级策略): - 限流:保护核心业务 - 优雅降级:降低生成长度或切换到更小模型 总结:关键是提前做好容量规划,建立 auto-scaling 体系, 而不是临时手忙脚乱。
Q7:线上 P99 延迟突然升高怎么排查?
定义:按"监控 → 定位 → 分析 → 解决"四步法进行线上延迟排查。 分析: - 第一步:看监控大盘 - 是单个实例问题还是全局问题? - 延迟升高发生在 prefill 还是 decode? - 是否有请求量突增? - 第二步:定位瓶颈 - GPU 利用率:如果低于预期,说明有瓶颈 - KV Cache 使用率:接近 100% 说明显存是瓶颈 - 网络 IO:是否有数据传输瓶颈 - 第三步:profiling 分析 - 用 nsight / py-spy 做 profile - 定位 hotspot(计算还是 IO) - 第四步:解决 - 如果是请求量突增,则触发扩容 - 如果是显存瓶颈,则降低 batch size 或启用量化 - 如果是长尾请求,则检查是否有超长输入 总结:我们遇到过一次线上延迟升高,最终定位到是某个业务线 突然发了大量超长 prompt,通过启用 prompt 长度限制和前缀缓存解决。
Q8:Transformer 中 Self-Attention 的时间复杂度和空间复杂度?
定义:Attention 的计算复杂度是 O(n²d),其中 n 是序列长度,d 是隐藏层维度。 分析: - 时间复杂度: - Q·K^T 矩阵乘法:O(n²d) - softmax:O(n²) - attention·V:O(n²d) - 总体 O(n²d),序列长度是主导因素 - 空间复杂度: - attention score 矩阵:O(n²) - KV Cache:O(n·d),每生成一个 token 需要缓存 - 优化方向: - Flash Attention:IO 感知算法,将复杂度从 O(n²d) 优化到更高效的实现 - 稀疏 Attention:减少 n² 计算 - MQA / GQA:减少 KV head 数量,降低 KV Cache 压力 总结:GQA 是近期最实用的优化,Llama 3 从 MHA 改成了 GQA, KV Cache 内存减少了 8 倍(head 从 32 降到 4)。
Q9:解释 Flash Attention 的核心思想
定义:一种 IO 感知的 Attention 算法,通过分块计算(tiling)和重计算(recomputation) 减少 HBM 和 SRAM 之间的数据搬运。 分析: - 传统 Attention 的瓶颈:中间矩阵 O(n²) 需要反复读写 HBM - Flash Attention 的做法: 1. Tiling:把 Q、K、V 切分为 block,在 SRAM 内完成计算 2. Recomputation:不存储完整的 attention score 矩阵,需要时重算 3. 在线 softmax:避免额外的归一化 pass - 效果:理论复杂度仍是 O(n²d),但常数项大幅降低,实际加速 2-4 倍 总结:Flash Attention 2 进一步优化了计算顺序, 在我们的 70B 模型上,TTFT 缩短了约 30%。
Q10:Speculative Decoding 是什么?
定义:用一个小模型(或草稿模型)预生成多个 token,然后用大模型并行验证的加速方法。 分析: - 原理:小模型生成 N 个草稿 token,大模型一次验证 N 个 token - 加速条件:小模型的猜测准确率越高,加速效果越好 - 典型配置:1B 草稿 + 70B 验证,加速 1.5-2.5 倍 - 适用场景:生成式任务中,当输出有一定可预测性时效果最好 总结:在我们的代码生成场景中(输出模式相对固定), Speculative Decoding 带来了约 1.8 倍的吞吐提升。
Q11:Tensor Parallel 和 Pipeline Parallel 的区别?
定义:两种不同的模型分布式并行策略。 分析: - Tensor Parallel(TP): - 方式:把每一层的权重矩阵切分到多卡上 - 通信:每层都需要 all-reduce,通信量大 - 延迟:单层延迟低,但通信开销随卡数增加 - 适用:小模型多卡部署(如 70B 在 2-4 卡) - Pipeline Parallel(PP): - 方式:把模型按层切分到不同卡上 - 通信:只在层间传递激活,通信量小 - 延迟:存在 bubble(空闲时间),需要 micro-batching 优化 - 适用:超大模型部署(如 175B 以上) 总结:我们部署 70B 模型时用 TP2,通信开销在可接受范围内; 如果模型更大,会考虑 TP + PP 混合并行。
Q12:如何评估量化后的模型精度?
定义:通过 benchmark 测试量化前后模型在目标任务上的表现差异。 分析: - 通用评估: - Perplexity(PPL):在 WikiText / C4 等数据集上计算 - PPL 增长 小于5% 通常可接受 - 任务评估: - 用具体任务(如代码生成、问答)对比 FP16 和量化的输出 - 可以用 LLM-as-judge 做自动评估 - 实践方法: - 先选一小部分代表性数据做快速评估 - 确认精度后再全量部署 - 线上持续监控用户反馈 总结:我们量化 70B 模型时,PPL 从 6.2 升到 6.5(增长 4.8%), 线上 AB 测试显示用户满意度无显著差异。
Q13:vLLM 的 Scheduler 是怎么工作的?
定义:vLLM 的调度器负责在 prefill 和 decode 之间分配 GPU 资源。 分析: - 核心策略: - 优先调度 prefill(减少 TTFT) - 但当显存不足时,优先保证 decode 完成(避免中断已开始的生成) - 调度算法: - 基于 block 的显存管理 - 支持 chunked prefill(大 prompt 分段处理) - 动态调整 batch 组成 - 关键参数: - max_num_seqs:最大并发序列数 - max_num_batched_tokens:最大批处理 token 数 总结:理解 Scheduler 的工作机制对线上调参非常关键, 我们调整 max_num_seqs 参数后,在高并发场景下吞吐提升了 30%。
Q14:Prefix Caching 的原理和适用场景?
定义:对相同或相似前缀的 prompt 共享 KV Cache 计算结果,避免重复计算。 分析: - 原理: - 计算 prompt 的 KV Cache 并缓存 - 新请求到来时,匹配前缀,复用已计算的 KV Cache - 只需计算新增部分 - 适用场景: - System prompt 很长且重复(如 role-playing 场景) - Multi-turn 对话(历史对话可复用) - 相同 prompt 不同后缀的场景 - 效果: - 在 multi-turn 场景下,TTFT 可降低 50-80% 总结:我们的客服场景中,system prompt 有 2000+ token, 开启 Prefix Caching 后 TTFT 从 800ms 降到 150ms。
Q15:MoE 模型部署的挑战和应对方案?
定义:MoE(Mixture of Experts)模型通过激活部分 expert 实现高效推理,但部署有特殊挑战。 分析: - 挑战一:显存占用大(expert 数量多,如 Mixtral 8x7B 总参数量 47B) - 应对:只加载激活的 expert,但需要 expert 级别的调度 - 挑战二:负载不均衡(不同 expert 的计算量不同) - 应对:动态路由 + 负载均衡策略 - 挑战三:通信开销(expert 分布在多卡上时) - 应对:expert 级别的 TP + 合理的 expert 放置策略 总结:MoE 已在 2025-2026 年大规模生产部署(DeepSeek V3、Kimi K2 1T 参数), 核心挑战从"能不能部署"转向"如何高效部署",Expert 通信优化和负载均衡是关键。
不会的问题怎么回答
"坦诚 + 分析思路"框架
遇到不会的问题,不要用以下方式应对:
正确的做法:
1. 坦诚边界:"这个问题我没有深入研究过" 2. 展示思路:"但如果让我来分析,我会从这几个角度考虑..." 3. 关联已知:"这和我熟悉的 [某个相关领域] 有相似之处..." 4. 表达学习意愿:"面试结束后我会去深入了解这个方向"
示例
面试官:"你对 Triton 的 kernel 优化有了解吗?"
回答:"Triton 的 kernel 编程我没有亲手写过,但我知道它的核心思想是用 Python 级别的 DSL 描述 GPU kernel,编译器自动处理 block 切分和内存优化。如果让我来优化一个 Attention kernel,我会先从 Flash Attention 的分块策略入手,用 Triton 重写出来对比性能。这个方向我一直想实践,面试结束后我会深入研究。"
技术深度追问的应对策略
防御性回答策略
面试官经常会对你的回答进行追问("为什么选 INT8 而不是 FP8?"),这是好事——说明对你感兴趣。应对策略:
被问住后的补救
如果某个问题确实没答好:
"这个问题我刚才回答得不够深入。实际上在 [项目] 中我遇到过类似场景, 当时的做法是 [简述]。从这个经验来看,我认为关键点在于 [总结]。"
面试视角:回答的加分项