外观
面试题库
先记住本页的一句话:面试不是考知识,是考"你会不会用知识解决没做过的问题"。 单靠背题不可能通过推理部署岗的面试,但完全不看题就上考场是浪费机会——本文给的是两样东西:题目背后的考察逻辑,以及你回答时该走的框架。刷题的目的是把高频考点变成条件反射,而不是押中原文。
本页是 career 模块四步流水线的最后一步「证明自己」,前面三步(看清市场、能力地图、简历打磨)做完,再来这里。时间紧张时请按第九节 面试准备计划 的清单执行。
一、面试结构全景:一轮一轮在考什么
推理部署岗的面试大体由五到七轮组成,多数公司一天内完成 2–4 轮。每一轮有它自己的通过标准,不要用"我上一轮答得很好"来替代"这一轮该怎么答"。
推理部署岗典型面试流程(大厂 / 中厂通用)
┌─────────────┬─────────────────────────────┬──────────────────────────────┐
│ 轮次 │ 现场形式 │ 通过标准(面试官心里打分) │
├─────────────┼─────────────────────────────┼──────────────────────────────┤
│ ① 自我介绍 │ 3–5 分钟口头 │ 表达逻辑、定位清晰、和岗位匹配 │
│ ② 系统基础 │ Python/C++/Linux 问答 │ 工程底子扎实、能讲 GIL/RAII │
│ ③ 引擎与调度│ vLLM/TensorRT/PagedAttention │ 源码理解、能讲权衡、能定位瓶颈│
│ ④ 算子与量化│ CUDA/Triton/INT8/FP8 问答 │ 知道机制、能讲 bank conflict │
│ ⑤ 项目深挖 │ 围绕简历项目连环追问 │ 真实做过、有性能数字、能扛追问│
│ ⑥ 系统设计 │ 设计 1000 QPS LLM 服务 │ 有框架、有取舍、有边界意识 │
│ ⑦ 手撕代码 │ KV cache 草稿 / reduction │ 正确性 + 复杂度 + 沟通 │
│ ⑧ HR 面 │ 聊天式 │ 稳定性、动机、软素质 │
└─────────────┴─────────────────────────────┴──────────────────────────────┘各轮真正的考察点拆开说:
- ① 自我介绍:不是复述简历。面试官要的是**"你是谁 → 你做过什么 → 为什么适合这个岗位"三句话骨架**。30 秒讲背景,2 分钟讲 1–2 个有性能数字的项目,30 秒讲动机。结尾抛一个钩子("我最近在给 vLLM 提 PR 加 chunked prefill,正好对应你们 JD 里的长上下文优化"),把节奏引向你准备好的领域。
- ② 系统基础:考察工程底子是否扎实。Python GIL / asyncio、C++ RAII / 智能指针、Linux 性能分析是高频三连。这一轮不通过的话后面再亮也救不回来。
- ③ 引擎与调度:推理部署岗的"承重轮"。vLLM 的 Scheduler 怎么工作、PagedAttention 的 block table 长什么样、continuous batching 与 in-flight batching 的差异——这些问题考的是"你是看过文档还是读过源码"。
- ④ 算子与量化:考察能否下到 CUDA / Triton 层。FlashAttention 为什么快、bank conflict 怎么避免、INT8 vs FP8 选型——这一轮是引擎岗与系统岗的分水岭。
- ⑤ 项目深挖:面试官用连环追问检验项目真实性——"真的做过"和"看过别人的项目"在追问 3 层之后立刻暴露。细节问题包括 vLLM 的
--gpu-memory-utilization你设多少、为什么;Nsight 报告里你看到哪几个指标;benchmark 时 batch 与 seq_len 怎么选。详见第六节。 - ⑥ 系统设计:给开放问题("设计一个支持 1000 QPS 的 LLM 服务""设计一个多模型推理平台")。评分标准不是"标准答案",而是你是否有一套从需求 → 引擎选型 → 部署架构 → 监控告警 → 容量规划的思维框架,以及能否在延迟、成本、可用性约束下做取舍。
- ⑦ 手撕代码:通用算法题(排序 / 二分 / DP)+ 推理相关手写题(KV cache 草稿、reduction kernel)。通过标准是跑得对、复杂度说得清、过程中会沟通。不会做时先讲暴力解再说优化,比闷头写强得多。
- ⑧ HR 面:考察稳定性(为什么离职 / 为什么选我们)、动机、团队协作与抗压。核心原则:正面、具体、不抱怨前东家。薪资谈崩多发生在"我期望 X 万"给出绝对数字时,正确做法是报区间并反问对方预算。
一条贯穿所有轮次的原则:STAR 法
项目、行为、设计问题全部可以用 STAR 组织回答:Situation(背景)→ Task(任务)→ Action(你做了什么,突出你的决策)→ Result(数字化的结果)。面试官对"我们当时有个推理服务慢"的回答印象为零,对"vLLM --max-num-batched-tokens 从 2048 调到 4096,TTFT 从 1.8s 降到 0.6s、吞吐 +120%"的回答印象深刻。
二、性能与指标题(4 题)
1. TTFT 与 TPOT 的区别?分别受什么影响?
- 考察点:推理部署岗的元概念,必考题。
- 参考答案:
- TTFT(Time To First Token):从用户发送请求到收到第一个 token 的时间。受 prefill 阶段主导——计算量随 prompt 长度平方级增长,受 GPU 算力、KV cache 显存分配、batch 内调度策略影响。
- TPOT(Time Per Output Token):生成阶段每个 token 的平均时间。受 decode 阶段主导——每生成一个 token 都要做一次 forward,但 batch 内只有 1 个 token,是 memory-bound,受 HBM 带宽、KV cache 大小、batch size 影响最大。
- 优化方向不同:TTFT 优化靠 chunked prefill、prefix caching、更快的 attention kernel(FlashAttention);TPOT 优化靠 continuous batching 提高并行度、KV cache 量化减小访存、投机解码减少 forward 次数。
- 加分回答:
- "线上业务侧其实更关心 P99 而非均值,TTFT 与 TPOT 都要按 P50/P99 上报";
- "TTFT 与 TPOT 之间有'权衡':开 chunked prefill 会增加 TPOT 但降 TTFT,需要按业务侧权重调参"。
- 本站对应:延迟与吞吐、批处理与调度、基准测试。
2. memory-bound 与 compute-bound 怎么判断?
- 考察点:Roofline 模型的直觉理解。
- 参考答案:
- 用 Roofline 模型判断:横轴是算术强度(FLOPs / Byte),纵轴是吞吐(FLOP/s)。某算子的性能上限 = min(峰值算力,HBM 带宽 × 算术强度)。
- 如果算子落在"带宽斜线"上 → memory-bound,瓶颈是 HBM 带宽;
- 如果落在"算力水平线"上 → compute-bound,瓶颈是 Tensor Core 算力。
- LLM 推理的特征:decode 阶段几乎总是 memory-bound(每生成 1 token 只算 batch×hidden 维度的小矩阵乘,但要把整个权重从 HBM 读出来,算术强度极低);prefill 阶段在长 prompt 下趋于 compute-bound。
- 实测方法:用 Nsight Compute 看每个 kernel 的
Achieved Occupancy与DRAM Throughput,前者低且后者满 → memory-bound。
- 加分回答:"Llama-70B decode 的算术强度约 0.5 FLOP/Byte,A100 HBM 带宽 2TB/s × 0.5 = 1 TFLOP/s,远低于 312 TFLOP/s 的峰值算力,所以是 memory-bound。这就是为什么 weight-only 量化能线性加速 decode——降带宽 = 提速。"详见内存与带宽与Roofline 模型。
- 本站对应:Roofline 模型、内存与带宽、GPU 优化原理。
3. LLM 推理的延迟瓶颈通常在哪?怎么定位?
- 考察点:性能调优实战经验。
- 参考答案:按"调度 → prefill → decode → 通信"四层排查:
- ① 调度层:vLLM 的
Waiting/Running队列长度、是否因max_num_seqs卡住;Triton 的dynamic_batching队列; - ② prefill 层:长 prompt 触发 chunked prefill 不足、KV cache 显存分配失败;
- ③ decode 层:batch 不足导致 memory-bound 没填满 HBM 带宽、attention kernel 走了非 FlashAttention 路径;
- ④ 通信层:跨节点 TP 的 all-reduce 占 forward 时间 > 30%、NCCL 走 PCIe 而非 NVLink/RDMA。
- 定位工具链:Nsight Systems 看 forward 内部各阶段比例;PyTorch Profiler 看 forward 内每个 kernel 的开销;vLLM 的
--profile模式生成 trace。
- ① 调度层:vLLM 的
- 加分回答:"70B 跨 2 节点 TP=16 时,我曾定位到 NCCL all-reduce 占 forward 38%,调
NCCL_NET_GDR_LEVEL=5走 RDMA 后降到 15%。这个值在 nsys trace 上是nccl-allreduce这一段。" - 本站对应:延迟与吞吐、分布式推理、调优实践。
4. 为什么 LLM 推理的 batch size 不能无限大?
- 考察点:调度与显存的权衡理解。
- 参考答案:三个约束:
- ① 显存约束:KV cache 随 batch×seq 线性增长,
max_num_seqs × max_num_batched_tokens × 2 × num_layers × hidden_size × dtype_size ≤ 可用显存; - ② 延迟约束:batch 越大,每个 forward 算的算子越大,单次 forward 时间变长;decode 阶段 batch 越大 TPOT 越高(因为算术强度上升但延迟变长);
- ③ 调度约束:vLLM 的 continuous batching 会在 batch 中请求完成时立即换入新请求,batch 太大换入频次降低,反而吞吐下降。
- 最优 batch size 通常在 32–256 之间,需要按硬件 + 模型 + SLO 实测。
--max-num-seqs与--max-num-batched-tokens是 vLLM 调度的两个核心参数。
- ① 显存约束:KV cache 随 batch×seq 线性增长,
- 加分回答:"我做过一个实测:Llama-70B 在 A100 80G 上,batch 从 8 到 64 时吞吐线性上升,64 到 128 时吞吐基本持平,128+ 时因 KV cache 不足触发 evict,吞吐反而下降。"
- 本站对应:批处理与调度、内存与带宽、基准测试。
三、量化题(4 题)
1. GPTQ vs AWQ 区别?分别适合什么场景?
- 考察点:量化方法选型,推理优化岗必考。
- 参考答案:
- GPTQ:基于二阶 Hessian 信息的权重量化方法,逐列求解权重更新使输出误差最小。需要校准数据(128 条左右),量化后精度损失通常 < 1%。适合 精度敏感场景(如 chat 模型、指令跟随任务)。
- AWQ:基于"权重重要性"的量化——只对 outlier 通道(激活大的)保留高精度,其余 INT4 量化。不需要二阶信息,速度快、内存友好。适合 资源受限 / 快速量化场景。
- 机制差异:GPTQ 用反向传播式的方法最小化输出误差(用预激活值校准),AWQ 直接按激活幅值识别"重要权重"并保护。
- 实测对比:在 Llama-70B 上,GPTQ perplexity 上升 0.3%,AWQ 上升 0.4%,但 AWQ 量化速度快 3 倍。
- 加分回答:"SmoothQuant 是另一种思路——通过平滑激活的 outlier,让 weight 和 activation 都能量化到 INT8。LLM 推理主推 weight-only(GPTQ / AWQ),原因是 decode 阶段 memory-bound,weight 量化直接降带宽;activation 量化在 LLM 上掉点严重。"
- 本站对应:量化、权重-激活混合精度。
2. 权重量化为何在 LLM 推理上效果显著?
- 考察点:量化的"为什么",深入理解。
- 参考答案:两个原因:
- ① decode 阶段是 memory-bound:算术强度约 0.5 FLOP/Byte,瓶颈是 HBM 带宽。权重占显存大头(Llama-70B FP16 = 140GB),INT4 weight-only 把权重压到 35GB,直接 4× 减少 HBM 访问 → 线性加速 decode。
- ② 权重的"列方向 outlier"稀疏:LLM 权重存在少量 outlier 通道,但 outlier 是结构性的(同一通道在不同 token 上都是 outlier),可以用 group-wise 量化或 AWQ 的"重要通道保护"机制处理,整体精度损失小。
- 对比:activation 量化在 LLM 上掉点严重——激活的 outlier 是 token-level 的(不同 token outlier 位置不同),INT8 量化时被 outlier 主导,整体精度崩坏。这就是 LLM 主推 weight-only 的根本原因。
- 加分回答:"INT4 weight-only 把 Llama-70B 从 140GB 压到 35GB,单卡 H100 80G 就能跑——而 FP16 必须 2 卡 TP。这是量化解决'装不下'的硬件问题,不只是加速问题。"
- 本站对应:量化、权重-激活混合精度、内存与带宽。
3. INT4 量化的精度损失来源?
- 考察点:量化精度问题的深入理解。
- 参考答案:四个来源:
- ① outlier 通道量化饱和:少数 outlier 通道幅值远大于其他,4bit 范围只有 16 个值,outlier 被压到 max → 精度损失集中在 outlier 通道。AWQ 通过保留 outlier 通道 FP16 来缓解。
- ② group-wise 量化误差:group_size 越大,组内 outlier 与非 outlier 差异越大,量化误差越大;group_size=128 是经验平衡点。
- ③ 零点偏移不准:对称量化(zero_point=0)在权重分布偏移时误差大,非对称量化需要校准 zero_point。
- ④ KV cache 量化叠加:如果同时开 INT4 weight + INT8 KV cache,误差会累积,需要分别评估。
- 通常 INT4 group-wise 量化在 Llama 系列上 perplexity 上升 0.3–0.6%,业务侧盲测基本无感知差异。
- 加分回答:"我用 AWQ group_size=32 在 Llama-3-8B 上跑过:group_size=128 perplexity +0.4%,group_size=32 +0.2%,但 group_size=8 显存反而增加(scale 与 zero_point 元数据多)——32 是性价比甜点。"
- 本站对应:量化、权重-激活混合精度。
4. FP8 与 INT8 的区别?H100 上 FP8 为什么快?
- 考察点:新硬件与精度格式的结合。
- 参考答案:
- 格式差异:INT8 是 8bit 整数(-128 到 127),需要 scale 与 zero_point;FP8 有 E4M3(4 位指数 + 3 位尾数)与 E5M2(5 位指数 + 2 位尾数)两种格式,是浮点数,无需 scale 但有动态范围。
- 精度差异:FP8 在 LLM 上的精度损失通常 < INT8(因为权重与激活的 outlier 用浮点格式更安全);INT8 weight-only 在 LLM 上仍是主流,FP8 weight + activation 在 H100 上是新趋势。
- H100 上 FP8 为什么快:H100 引入 Transformer Engine + FP8 Tensor Core,FP8 矩阵乘吞吐相对 FP16 翻倍(1979 TFLOP/s vs 989 TFLOP/s)。同时 FP8 不需要量化 / 反量化的转换开销(与 INT8 的 dequantize kernel 对比),减少 kernel launch 与访存。
- 何时不用 FP8:A100 与之前硬件不支持 FP8 Tensor Core;精度敏感场景(如 RLHF 训练)仍主推 BF16;端侧与 CPU 推理 INT8 更通用。
- 加分回答:"FP8 在 H100 上不只是快,更重要的是 NVIDIA 把 Transformer Engine 与 FP8 深度集成——FP8 量化、scale 管理、loss scaling 都在硬件层做,软件栈(TransformerEngine、TensorRT-LLM、vLLM 0.8+)已经原生支持。"
- 本站对应:量化、GPU 优化原理、硬件入门。
四、KV cache 与 batching 题(4 题)
1. KV cache 大小怎么算?
考察点:基本功,几乎必考。
参考答案:公式:
KV cache (bytes) = 2 (K and V) × num_layers × batch_size × seq_len × head_dim × num_kv_heads × dtype_size- 2:K 与 V 两个 cache;
- num_layers:Transformer 层数;
- batch_size × seq_len:每个 token 都要存一对 K、V;
- head_dim × num_kv_heads:每个 KV head 的维度与 KV head 数量;
- dtype_size:FP16 = 2 bytes,INT8 = 1 byte。
例子:Llama-70B(80 layers, 64 heads, 8 KV heads, head_dim=128, FP16),batch=8, seq=2048:
2 × 80 × 8 × 2048 × 128 × 8 × 2 = 5.37GBMQA / GQA 的影响:num_kv_heads 从 num_heads 降到 1(MQA)或 num_heads/8(GQA),KV cache 直接降到 1/8 或 1/8。这是 GQA 在 LLM 上如此重要的原因。
加分回答:"算 KV cache 大小是调 vLLM
--gpu-memory-utilization的前提:可用显存 = 总显存 - 权重显存 - 临时 buffer - KV cache。我之前调 70B 在 A100 80G 单卡时,先算 FP16 权重 140GB 装不下 → INT4 权重 35GB → 剩 45GB 给 KV cache → 算出 batch×seq 上限。"
2. continuous batching 怎么工作?解决了什么问题?
- 考察点:vLLM 与 TensorRT-LLM 的核心机制。
- 参考答案:
- static batching 的问题:batch 内请求长度不同,短请求完成后要等长请求,GPU 空转;新请求要等整个 batch 完成才能进,延迟堆积。
- continuous batching:在每次 forward 的边界(一个 step),调度器检查哪些请求已完成,把它们换出,把队列里的新请求换入,开始下一 step。整个过程对未完成请求的 KV cache 透明。
- 关键数据结构:PagedAttention 的 block table——KV cache 不是连续分配的,而是按 block(如 16 个 token 一块)分页管理,请求可以共享空闲 block,避免显存碎片。
- 效果:吞吐相对 static batching 提升 2–10×,相对无 batching 提升 10×+。vLLM 的 continuous batching 与 TensorRT-LLM 的 in-flight batching 本质相同,实现细节不同。
- 加分回答:"continuous batching 限制:每 step 的 forward 是 batch 内所有 token 一起算,但短请求完成后换入新请求时,新请求的 prefill 计算与老请求的 decode 计算混在同一个 batch——这就是 chunked prefill 要解决的问题,把长 prompt 的 prefill 切块,避免它占用整个 forward 预算。"
- 本站对应:批处理与调度、vLLM、TensorRT-LLM。
3. PagedAttention 解决了什么问题?
- 考察点:vLLM 的招牌机制。
- 参考答案:
- 问题:传统 KV cache 按"请求连续分配"——请求一来就申请
max_seq_len大小的连续显存,导致两个问题:①显存碎片:短请求完成后留下小碎片,长请求装不下;②预留 max_seq_len 浪费:实际生成长度通常远小于 max_seq_len,预留部分浪费。 - PagedAttention 的解:借鉴 OS 的虚拟内存——KV cache 按 block(如 16 token / block)分页存储,逻辑上连续、物理上离散。block table 记录每个请求的逻辑 block → 物理 block 的映射。请求完成后 block 直接归还 free pool,无碎片。
- 关键机制:①block table:每个请求一个,记录 KV cache 的物理位置;②copy-on-write:beam search 等多分支场景共享 block,需要修改时再复制;③prefix sharing:相同 prefix 的请求(如相同 system prompt)共享 KV block,省重算。
- 效果:显存利用率从 30–50% 提升到 90%+;吞吐相对 static batching 提升 2–24×(vLLM 论文数据)。
- 问题:传统 KV cache 按"请求连续分配"——请求一来就申请
- 加分回答:"PagedAttention 的副作用是 attention kernel 要按 block table 索引访问 KV,相比连续访问有性能损失(cache miss)。vLLM 0.8 之前 block_size=16,0.8 后调到 16 仍是默认——这是性能与显存利用率的权衡。block_size 越大越接近连续访存,但显存利用率越低。"
- 本站对应:批处理与调度、vLLM、内存与带宽。
4. chunked prefill 是什么?为什么 vLLM 0.8 引入?
- 考察点:vLLM 演进的理解,区分用过与读过源码。
- 参考答案:
- 问题:continuous batching 在引入新请求时,新请求的 prefill 计算量随 prompt 长度平方级增长,长 prompt 会占满 forward 预算,老请求的 decode 等待时间飙长,TPOT 抖动。
- chunked prefill 的解:把长 prompt 的 prefill 切成多块(每块 N 个 token),每 step 只算一块,与老请求的 decode 混在同一个 forward。这样长 prompt 不会"霸占"forward 预算,老请求 decode 延迟稳定。
- 关键参数:
--max-num-batched-tokens控制每 step 总 token 数预算(如 4096)。设小了 → 长 prompt 切太细,prefill 阶段长;设大了 → 老 decode 等待久。需要按业务调。 - 何时该用:业务里有长 prompt(> 4k token)混合短 prompt 时必开;纯短 prompt 业务可以关掉省调度开销。
- 加分回答:"chunked prefill 与 TTFT / TPOT 的关系:开 chunked prefill → TTFT 升(prefill 切块后整体变慢)但 TPOT 降(老 decode 不被阻塞)。这是一个典型的延迟-延迟权衡。"
- 本站对应:批处理与调度、vLLM、延迟与吞吐。
五、算子题(3 题)
1. FlashAttention 为什么快?
- 考察点:算子优化必考,考察对机制而非名字的理解。
- 参考答案:三个机制贡献:
- ① Tiling:把 Q、K、V 切块到 SRAM(shared memory),避免 HBM 反复读写。原始 attention 的 S = QKᵀ 是 O(N²) 中间结果,要写回 HBM 再读回来算 softmax;FlashAttention 把整个 softmax 融合到 tiling 内,中间结果不落 HBM。
- ② Recompute:反向传播时不存中间 attention 矩阵,前向只存 Q、K、V 与 softmax 归一化系数,反向重算 attention。这是"用算力换显存"。
- ③ IO-aware:精确地不是减少 FLOPs(其实 FLOPs 略增),而是减少 HBM 访问—— Roofline 视角下 attention 是 memory-bound,减 HBM 访问 = 加速。
- 效果:FlashAttention-1 在 A100 上把 attention 速度从 2.3× 提升到 4×(小 seq)/ 7×(长 seq);FlashAttention-2 优化 GPU 线程调度,再快 2×;FlashAttention-3 在 H100 上用 TMA + FP8,再快 1.5–2×。
- 加分回答:"FlashAttention 的核心不是'算法快'而是'IO 少'。看 Nsight Compute 报告,原始 attention 的瓶颈是
DRAMthroughput 飙满;FlashAttention 后DRAM利用率降到 30%,瓶颈转到SM Compute。"详见算子融合与内存与带宽。 - 本站对应:算子融合、内存与带宽、GPU 优化原理。
2. 算子融合的边界在哪?什么时候不要融合?
- 考察点:算子优化的判断能力。
- 参考答案:融合的收益与边界:
- 收益:①减少 HBM 访问(中间结果在 SRAM 流转);②减少 kernel launch 开销(一次 launch 跑一组算子);③减少显存占用(中间 tensor 不分配)。
- 边界:
- ①算子形状差异大:Conv(N,C,H,W)与 MatMul(M,K,N)融合需要数据布局转换,转换成本可能超过融合收益;
- ②算子语义复杂:含 if/else 分支、动态 shape 的算子融合难度高(如 padding mask),编译器常放弃;
- ③reduction 跨 block:跨 block 的 reduction(如全 layer norm)需要 atomic op 或两阶段 kernel,融合反而慢;
- ④Shape 静态:动态 shape 时融合的 tile 大小无法预测,性能反而差。
- 什么时候不要融合:单个 kernel 已经接近峰值性能(如 cuBLAS GEMM 在大矩阵下已经 95% 峰值);融合需要写自定义 kernel 但维护成本高(PyTorch eager 直接调更稳定)。
- 加分回答:"Linear+ReLU+Linear 这种"邻接融合"是显然的;但 Transformer 里 attention 之所以要 FlashAttention 单独写,是因为融合需要算法级改造(recompute + tiling),不是简单的 kernel 串联。这就是为什么 fusion 的真正高阶形式需要"算法+硬件协同设计"。"
- 本站对应:算子融合、图优化、GPU 优化原理。
3. CUDA 里 bank conflict 是什么?怎么避免?
- 考察点:CUDA 基础,算子工程师必考。
- 参考答案:
- bank conflict:shared memory 被分成 32 个 bank(每 bank 4 字节宽,可独立访问)。一个 warp 内 32 个 thread 同时访问 shared memory,如果两个或以上 thread 访问同一 bank 的不同地址 → 串行化 → 性能下降。
- 类型:①2-way bank conflict:2 个 thread 同 bank → 2 倍延迟;②32-way bank conflict:32 个 thread 同 bank → 32 倍延迟(最严重);
- 避免方法:①padding:在数据布局上加一列 padding(如 33 列而非 32 列),错开 bank;②swizzle:调整 thread 到数据的映射(如把 thread (i,j) 映射到 (j, i ⊕ j) 的位置),让连续 thread 访问不同 bank;③用
__ldmatrix指令(Hopper):硬件层支持 ldmatrix 指令,自动避免 bank conflict; - 检测方法:Nsight Compute 的
L1/Histogram Shared Bank指标,看到 32-way conflict 就是 bug。
- 加分回答:"CUTLASS 里 GEMM kernel 的 swizzle 是经典案例——thread 到 tile 的映射用 XOR swizzle,让同一 warp 在不同迭代访问不同 bank。读懂 CUTLASS 的 swizzle 比写一个能跑的 GEMM 更难,是真正区分'会写 CUDA'与'懂 CUTLASS'的分水岭。"
- 本站对应:GPU 优化原理、算子融合。
六、项目深挖题(8 题)
项目轮是推理部署岗淘汰率最高的一轮,因为简历造假与"挂名项目"在这一轮无所遁形。策略只有一个:项目是自己真实做过的,然后按"背景 → 我的决策 → 性能数据 → 复盘"组织。下面是高频问题的回答框架。
1. 讲一个你最得意的推理优化项目
- 回答框架:用 STAR,且刻意突出**"我做的决策"而非"我们做的事"**。结构:一句话背景(业务问题 + 模型 + 硬件)→ 我的三步动作(引擎选型、参数调整、kernel 改写,为什么这么选)→ 硬指标结果(TTFT、TPOT、QPS、GPU 利用率前后对比数字)→ 一句复盘(如果再让我做一次,哪一步会不同)。控制在 2–3 分钟,留出让面试官追问的空间。
- 常见错误:全程讲团队不突出个人;只讲成功不讲权衡;无性能数字。
- 追问应对:准备三个"被深挖点"——①引擎源码细节(你改了哪个文件、哪一行);②性能数字口径(benchmark 怎么跑的、预热了吗、取 P50 还是 P99);③踩过的坑(什么参数调错了、什么版本升级出过 bug)。
2. 你为什么选 vLLM 而不是 TensorRT-LLM?不用别的?
- 回答框架:对比决策三件套——模型类型(开源 LLM 还是闭源)、业务约束(成本、可维护性、生态)、团队栈(Python 优先还是 C++ 优先)。例:"业务是内部 Llama-70B 助手 + Python 栈优先,选 vLLM 0.8 因为:①开源生态活跃,问题能社区求助;②Python 主导,团队上手快;③chunked prefill 与 prefix caching 是 0.8 后新加的,正好对应我们长 prompt 场景。TensorRT-LLM 性能确实强 10–15%,但 build 链路复杂、版本升级痛,团队 C++ 资源不足,权衡下来 vLLM 是更现实的选择。"
- 考察点:不是选得对,而是有明确的决策逻辑——能说出"为什么不选 X"比"为什么选 Y"更值钱。
3. 线上推理 P99 突然飙到 8 秒,你会怎么排查?
- 回答框架:按"流量 → 调度 → 引擎 → 算子 → 硬件"五层排查:
- ①流量层:QPS 是否突然上涨?长 prompt 比例是否飙升?看 Grafana 看板确认。
- ②调度层:vLLM
Waiting队列长度是否堆积?max_num_seqs是否达上限?max_num_batched_tokens是否过小? - ③引擎层:vLLM 版本是否最近升级?某条 prompt 触发了非 FlashAttention 路径?prefix caching 是否失效?
- ④算子层:Nsight Systems trace 看 forward 内哪个 kernel 时间飙长;NCCL all-reduce 是否占 forward > 30%?
- ⑤硬件层:GPU 利用率是否下降(说明 I/O 卡了)?显存是否快满(KV cache evict 严重)?跨节点 NVLink 是否断了?
- 考察点:工程排查思维,答出"先怀疑流量、再怀疑调度、再怀疑引擎、最后才怀疑硬件"的排序非常加分。
4. 上线后效果慢慢变差,怎么办?
- 回答框架:这是分布漂移与 KV cache 碎片的混合场景。动作清单:
- ①建立监控:TTFT、TPOT、queue length、GPU 利用率、KV cache evict 率五线监控,报警阈值提前定好;
- ②定位漂移类型:用户 prompt 长度分布是否变化(业务高峰期长 prompt 多)?模型是否切换了版本?
- ③对策:a) 定期重启实例清理 KV cache 碎片(vLLM 0.8 之后有
PrefixCaching缓解,但仍需定期重启);b) 调整max_num_seqs:业务变化后旧参数不再最优;c) 多副本灰度:新参数先在 10% 副本试。 - 同时回答"如何防":上线前就设计监控看板,TTFT P99 > 阈值自动告警。
- 考察点:是否理解"推理服务是易腐商品",以及监控 / 调度闭环的 MLOps 意识。详见模型服务与常见陷阱。
5. 你在这个项目里踩过最大的坑是什么?
- 回答框架:诚实 + 完整闭环:坑是什么 → 怎么发现的 → 怎么解决的 → 沉淀了什么。最好选技术坑而非甩锅给他人。经典优质素材:
- chunked prefill 参数踩坑:
max_num_batched_tokens设过大导致老 decode 等待; - NCCL 通信走 PCIe 而非 NVLink:跨节点 TP 慢得离谱,调
NCCL_NET_GDR_LEVEL解决; - vLLM 升级回归:0.6 → 0.8 prefix caching 行为变化,导致 cache 命中率从 80% 降到 30%;
- 量化精度掉点:INT4 group_size=128 在某业务场景 perplexity 暴涨,发现是 outlier 分布异常,改 group_size=32 解决。
- chunked prefill 参数踩坑:
- 考察点:真实性与复盘能力。面试官知道项目不会一帆风顺,"没踩过坑"本身才是危险信号。
6. 你的 benchmark 是怎么跑的?口径可信吗?
- 回答框架:把 benchmark 当成一个独立工程讲:
- ①预热:先跑 10 次预热,让 KV cache、CUDA 上下文稳定,再开始计时;
- ②采样:跑 1000 次取 P50/P90/P99,不要取平均(长尾分布会让平均无意义);
- ③固定变量:模型版本、batch、seq_len、硬件、并发数都要写死,只改一个变量才能归因;
- ④对照组:每次都要有对照(旧版本、另一引擎、另一参数),否则绝对数字无意义;
- ⑤复现性:脚本与 prompt 集发到 GitHub,让面试官能 clone 下来复现。
- 考察点:是否真的做过基准测试,还是临时拼了个数字。详见基准测试。
7. 你是怎么给 vLLM 提 PR 的?讲讲 review 过程
- 回答框架:讲三件事:
- ①动机:业务场景碰到什么问题 → 读源码发现什么 bug 或性能瓶颈 → 改了什么;
- ②方案:为什么这么改,对比过哪些方案,benchmark 证明多少提升;
- ③review 过程:maintainer 提了什么意见 → 你怎么改 → 最终怎么合并 → 后续版本有没有延续你的方案。
- 加分点:讲出"被要求加测试"或"被要求改 API 设计"等具体 review 反馈,证明你真的经历过开源协作。一个合并到主线的 PR 比五个项目经历都值钱。
8. 如果给你两个月,你打算怎么把这个项目重做一遍?
- 回答框架:展示反思与优先级:
- ①先复盘原项目最大的短板(性能数字口径不清 / 没有监控告警 / 未做跨节点 TP / 未做投机解码),用 30% 时间补;
- ②监控与基准先行(监控口径错了,后面全错);
- ③按"基线 → 增量"迭代,每个增量都有 benchmark 与灰度;
- ④预留 1–2 周做投机解码 / 量化 / 端侧适配的实验。
- 回答里出现"我会先做一次完整 benchmark 与监控基线,再谈优化"是高分信号。
- 考察点:项目复盘 + 工程方法论 + 时间规划能力。
七、系统设计与综合题(4 题)
1. 设计一个支持 1000 QPS 的 LLM 推理服务
- 考察点:综合能力,常见系统设计题。
- 参考答案框架:
- ①需求澄清:1000 QPS 是峰值还是平均?prompt 平均长度?生成长度?TTFT / TPOT 的 SLO?预算?
- ②容量估算:假设 prompt 1k tokens、生成 500 tokens,单请求消耗 1500 token 推理。1000 QPS × 1500 = 150 万 token/s。Llama-70B 在 H100 80G 上单卡吞吐约 2000 token/s(INT4 weight + continuous batching),需要 750 张 H100——这显然不可接受。要么换更小模型(8B 单卡 10000+ token/s)、要么量化更狠(INT4 group-wise)、要么 batch 更大。
- ③架构设计:
- 入口层:Nginx / Envoy + 限流(按 prompt 长度路由);
- 调度层:vLLM 副本池 + 动态路由(按 prompt 长度分到长上下文 / 短上下文副本组);
- 推理层:单副本 vLLM + chunked prefill + prefix caching;长上下文副本组开 chunked prefill,短上下文副本关掉省调度开销;
- 监控层:Prometheus + Grafana,TTFT / TPOT / queue / GPU 利用率五指标打点;
- 弹性层:K8s HPA + GPU 资源池;
- 故障层:副本健康检查 + 自动重启 + 流量切换。
- ④取舍:要不要做多模型调度(多模型副本占用 GPU 资源,但可按需路由)?要不要投机解码(吞吐 +30–50%,但代码复杂)?要不要跨节点 TP(单模型装不下时必选,否则不必)?
- ⑤反思:1000 QPS 的瓶颈通常不是算力而是 KV cache 显存——可以靠 INT8 KV cache 量化 + GQA 模型解决。这是面试官想听的关键洞察。
- 加分回答:"我会先做容量规划再谈架构:1000 QPS 在 70B 上不现实,在 8B 上完全可行。模型选择本身就是架构决策的一部分。"
- 本站对应:模型服务、批处理与调度、分布式推理、基准测试。
2. 设计一个多模型推理平台,支持 200+ 模型版本
- 考察点:MLOps 视角的系统设计。
- 参考答案框架:
- ①模型仓库:每个模型版本一份 metadata(路径、版本、SLO、依赖硬件、量化方案);
- ②路由层:按 model_id 路由到对应副本组,按 prompt 长度 / 用户优先级二次路由;
- ③部署策略:a) 长驻副本(高频模型);b) 按需加载(低频模型,用 vLLM
--load-format与权重缓存);c) Serverless(极少调用的模型,启动开销大但成本最低); - ④版本管理:灰度发布(5% 流量灰度 30 分钟,无回归才全量)、A/B 测试、回滚机制;
- ⑤成本与配额:按团队计费、按 token 配额、超额限流。
- 这是 ML Infra / MLOps 工程师的核心考察题。详见模型服务。
- 本站对应:模型服务、Triton 推理服务。
3. 投机解码为何无损?Medusa vs EAGLE 区别?
- 考察点:投机解码原理。
- 参考答案:
- 为何无损:投机解码用一个小模型(draft model)先生成 k 个候选 token,大模型一次 forward 验证这 k 个 token(因为验证比生成便宜——一次 forward 算 k 个 token 的 logit)。被接受的 token 按大模型的概率分布保留,被拒绝的从拒绝点重新采样。关键在于:接受 / 拒绝的判断按大模型概率分布,所以最终输出分布与大模型直接采样完全等价 → 无损。
- Medusa:在 LLM 的 hidden state 上接多个"medusa head",每个 head 预测下一个 token。优势是不需要单独的 draft model,缺点是接受率较短。
- EAGLE:用一个 autoregressive 的 draft model,输入是 LLM 的 hidden state + 上一 token,输出下一个 token。优势是接受率高(0.6+),延迟加速比 2–3×。
- 何时不用:①接受率低(draft 模型与 target 模型差异大);②prompt 极长(draft 也要跑完整 prompt,prefill 阶段无加速);③strict mode 业务(必须严格按 target 模型输出,draft 偏差不可接受)。
- 加分回答:"投机解码的实际加速比取决于接受率与 k 的乘积。EAGLE 在 Llama-70B 上接受率 0.6、k=4,实际加速 2.2× 左右。代价是显存与算力增加(draft model 也要装下)——资源紧张时不值。"
- 本站对应:投机解码、vLLM、延迟与吞吐。
4. Tensor Parallel vs Pipeline Parallel,通信代价?
- 考察点:分布式推理必考。
- 参考答案:
- TP(Tensor Parallel):把单层的权重切到多卡,每次 forward 都要 all-reduce。通信量 = batch × seq × hidden × 2 bytes(FP16)。在机内 NVLink 上(NVSwitch 900GB/s)通信开销小,跨节点(IB 200GB/s)通信占比可达 30%+。
- PP(Pipeline Parallel):把不同层切到不同卡,只在层边界传 activation。通信量 = batch × seq × hidden × 2 bytes(每次只传一次)。但 PP 有 bubble 问题——前面的卡在等后面的卡完成才能进下一 micro-batch,bubble 比例 = (N-1) / (N+M-1),N 是 stage 数、M 是 micro-batch 数。
- 何时选:①单层装不下(70B 单层权重 > 单卡显存)→ 必选 TP;②整模型装不下但单层能装下 → PP;③通常 TP+PP 组合,机内 TP=8,跨节点 PP。
- MoE 推理:用 EP(Expert Parallel),把不同专家切到不同卡,token 按路由发到对应专家。EP 与 DP 的区别:DP 是每卡有完整模型副本,EP 是每卡只有部分专家。
- 加分回答:"跨节点 TP 慢的原因不是 NVLink vs IB 带宽差异(NVSwitch 900 vs IB 200),而是 NCCL 在跨节点时会 fall back 到 P2P 而非 RDMA,除非显式调
NCCL_NET_GDR_LEVEL。这是一个踩过坑才知道的细节。" - 本站对应:分布式推理、硬件入门。
八、手撕代码题(5 题)
推理部署岗的手撕分两类:通用算法(笔试 / 在线,见准备计划)与 推理相关手写题(现场问答 + 写核心代码)。这里给推理相关题的高频清单与参考实现。
1. 实现一个简单 KV cache 类
- 考察点:推理数据结构基本功。
- 参考实现:
python
import torch
class KVCache:
def __init__(self, num_layers, num_kv_heads, head_dim, max_batch, max_seq, dtype=torch.float16, device="cuda"):
self.num_layers = num_layers
self.num_kv_heads = num_kv_heads
self.head_dim = head_dim
self.max_batch = max_batch
self.max_seq = max_seq
# 预分配 (num_layers, max_batch, max_seq, num_kv_heads, head_dim)
self.k = torch.zeros(num_layers, max_batch, max_seq, num_kv_heads, head_dim, dtype=dtype, device=device)
self.v = torch.zeros_like(self.k)
# 当前每个 batch 已写入的长度
self.lengths = [0] * max_batch
def append(self, layer_idx, batch_idx, new_k, new_v):
# new_k, new_v: (new_seq, num_kv_heads, head_dim)
start = self.lengths[batch_idx]
end = start + new_k.shape[0]
self.k[layer_idx, batch_idx, start:end] = new_k
self.v[layer_idx, batch_idx, start:end] = new_v
self.lengths[batch_idx] = end
def get(self, layer_idx, batch_idx):
return self.k[layer_idx, batch_idx, :self.lengths[batch_idx]], \
self.v[layer_idx, batch_idx, :self.lengths[batch_idx]]- 追问:"这个实现有什么问题?"——①浪费显存(预分配 max_seq),实际用 PagedAttention 分块;②batch 维度无法动态扩缩(continuous batching 要换入换出请求);③无 prefix sharing。
- 本站对应:批处理与调度、vLLM。
2. PagedAttention 草稿:block table 与 block pool
- 考察点:PagedAttention 机制理解。
- 参考实现:
python
import torch
class PagedKVCache:
def __init__(self, num_layers, num_kv_heads, head_dim, block_size, num_blocks, dtype=torch.float16, device="cuda"):
self.block_size = block_size # 如 16 token / block
self.num_blocks = num_blocks
# 物理存储:(num_layers, num_blocks, block_size, num_kv_heads, head_dim)
self.k_blocks = torch.zeros(num_layers, num_blocks, block_size, num_kv_heads, head_dim, dtype=dtype, device=device)
self.v_blocks = torch.zeros_like(self.k_blocks)
# block pool:空闲物理 block 编号
self.free_blocks = list(range(num_blocks))
# 每个请求的逻辑 → 物理 block 映射
self.block_tables = {} # request_id -> list of physical block ids
def allocate(self, request_id, num_tokens_needed):
# 按需分配若干 block
n_blocks_needed = (num_tokens_needed + self.block_size - 1) // self.block_size
if n_blocks_needed > len(self.free_blocks):
raise RuntimeError("OOM: no free blocks")
blocks = [self.free_blocks.pop() for _ in range(n_blocks_needed)]
self.block_tables[request_id] = blocks
def free(self, request_id):
# 请求完成,归还 block
for b in self.block_tables[request_id]:
self.free_blocks.append(b)
del self.block_tables[request_id]- 追问:"这跟真实 vLLM 的实现差什么?"——①真实实现用 C++ 与自定义 allocator;②有 copy-on-write 支持 beam search;③有 prefix sharing(相同 prefix 共享 block,写时复制)。详见vLLM。
- 本站对应:批处理与调度、vLLM、内存与带宽。
3. 手写 reduction kernel(CUDA 草稿)
- 考察点:CUDA 基础。
- 参考实现:
cuda
__global__ void reduce_sum(const float* input, float* output, int n) {
__shared__ float sdata[256];
int tid = threadIdx.x;
int i = blockIdx.x * blockDim.x + tid;
// 每个线程取一个元素(更通用的版本要 strided 循环)
sdata[tid] = (i < n) ? input[i] : 0.0f;
__syncthreads();
// 树状 reduction
for (int s = blockDim.x / 2; s > 0; s >>= 1) {
if (tid < s) {
sdata[tid] += sdata[tid + s];
}
__syncthreads();
}
if (tid == 0) {
atomicAdd(output, sdata[0]);
}
}- 追问:"这个版本有什么 bank conflict?"——shared memory 访问
sdata[tid]与sdata[tid + s],s=128 时跨 128 个 float = 512 字节 = 128 bank,无 bank conflict;s=1 时是相邻访问,无冲突。但 stride 访问在某些 s 下会冲突,更优版本用 warp shuffle(__shfl_down_sync)。 - 本站对应:GPU 优化原理、算子融合。
4. 用 Triton 写一个简单 fused matmul + bias + relu kernel 草稿
- 考察点:Triton DSL 入门。
- 参考实现:
python
import triton
import triton.language as tl
@triton.jit
def matmul_bias_relu_kernel(
a_ptr, b_ptr, bias_ptr, c_ptr,
M, N, K,
stride_am, stride_ak,
stride_bk, stride_bn,
stride_cm, stride_cn,
BLOCK_M: tl.constexpr, BLOCK_N: tl.constexpr, BLOCK_K: tl.constexpr,
):
pid_m = tl.program_id(0)
pid_n = tl.program_id(1)
offs_m = pid_m * BLOCK_M + tl.arange(0, BLOCK_M)
offs_n = pid_n * BLOCK_N + tl.arange(0, BLOCK_N)
offs_k = tl.arange(0, BLOCK_K)
acc = tl.zeros((BLOCK_M, BLOCK_N), dtype=tl.float32)
for k in range(0, tl.cdiv(K, BLOCK_K)):
a = tl.load(a_ptr + offs_m[:, None] * stride_am + offs_k[None, :] * stride_ak,
mask=(offs_m[:, None] < M) & (offs_k[None, :] < K + k * BLOCK_K), other=0.0)
b = tl.load(b_ptr + offs_k[:, None] * stride_bk + offs_n[None, :] * stride_bn,
mask=(offs_k[:, None] < K) & (offs_n[None, :] < N), other=0.0)
acc += tl.dot(a, b)
bias = tl.load(bias_ptr + offs_n, mask=offs_n < N, other=0.0)
acc += bias[None, :]
acc = tl.maximum(acc, 0.0) # ReLU
tl.store(c_ptr + offs_m[:, None] * stride_cm + offs_n[None, :] * stride_cn,
acc, mask=(offs_m[:, None] < M) & (offs_n[None, :] < N))- 追问:"这个 kernel 的 TILE 大小怎么选?"——BLOCK_M / BLOCK_N / BLOCK_K 取决于 SRAM 大小,A100 上常用 128×128×32;过大会溢出 SRAM,过小会浪费并行度。
- 本站对应:算子融合、GPU 优化原理。
5. 通用算法手撕的练习范围
- 考察点:是否"刷得动题",高频范围比全刷重要。
- 参考清单:
- 二分查找与变种:在有序数组找第一个 >= target 的元素、找峰值;
- 排序:快排、归并、堆排;
- DP:最长上升子序列、背包问题、编辑距离;
- 图:BFS / DFS、拓扑排序、Dijkstra;
- 链表:反转、环检测、合并有序链表;
- 栈 / 队列:单调栈、滑动窗口最大值。
- 练习顺序:先暴力解能跑,再优化到面试官认可的最优复杂度;每题说清时间 / 空间复杂度,这是最重要的隐性评分项。常见坑与编码规范见常见陷阱。
九、如何回答"不知道"的题
被问住不可怕,答得难看才可怕。面试官也在观察你的临场反应——这本身就是一道软素质题。原则与话术:
- 原则 1:绝不装懂硬编。面试官问的深度通常远超你能覆盖的范围,编造的后果是被追问当场戳穿,评分直接崩盘,且失去"诚实"印象分。正确姿势是明确边界 + 展示思考路径。
- 原则 2:分层响应。不是所有"不知道"都值得直接承认,先判断层次:完全没听过(领域外)→ 听过不会推导(原理缺失)→ 会一部分(记忆模糊)。
- 原则 3:把"不知道"变成"会学习"的证据。
三套话术模板:
模板一(完全陌生,最诚实路线):
"这个概念我确实没系统学过。不过按我的理解,它可能和 X 相关(给出相邻知识),
如果是解决 Y 问题(从问题反推),我的初步思路是……。面试后我会去补一下这个方向。"
模板二(听过、不会推导):
"我在论文/博客里见过这个,能说出它大概解决什么问题(一两句),
但具体的推导细节我现在讲不完整。可以的话,你能提示一下它的前提假设吗?
或者我换成用例子描述我对它的理解——我判断它和 A、B 有关联……"
模板三(记忆模糊,引导式):
"我记得它和 PagedAttention 的关系,但具体 block table 的索引细节不确定。
我先把确定的部分讲清楚:……。不确定的部分我宁可直说,不想误导你。
如果你给我一个具体场景,我可以现场推理一下它的作用机制。"配套的三个加分层动作:
- 主动暴露学习路径:"我最近正在刷 FlashAttention-3 的源码,虽然今天没答好 TMA 的细节,但这个方向我下个月能讲清楚"——把"不会"变成"成长中"。
- 用类比兜底:听不懂术语时,用"我理解它大概是在做……,就像……"让面试官看到你的类比能力。
- 反客为主提问:在不熟悉的领域问一个具体且不冒犯的问题("这个机制在你们的推理服务里是 vLLM 实现的还是 TensorRT-LLM 实现的?"),既拖时间又展示参与度。不要问"能给我点提示吗"这种白嫖题。
一个必须避免的回答
"这个我没学过,能跳过吗"——直接消耗一题分数并暴露学习意愿差。 正确姿态永远是:承认边界 + 给出部分理解 + 表态会补。面试官不期待你全会,期待你"会的东西讲得透,不会的东西不丢分"。
十、面试准备计划(1 周与 1 个月清单)
按求职冲刺线的以终为始原则设计:先弄清目标岗位的 JD 考什么,再对着清单查漏。两个版本都默认你已经完成了能力地图的自评。
1 个月版(标准节奏,每天 2–3 小时)
| 周 | 主线任务 | 每天 30 分钟固定动作 |
|---|---|---|
| 第 1 周 | L1 基础 + 性能指标:Python GIL / C++ RAII / Nsight / TTFT-TPOT——配合延迟与吞吐、GPU 优化原理 | 手撕 1 道通用算法题 |
| 第 2 周 | L2 引擎 + 量化:vLLM 源码精读 / PagedAttention / continuous batching / GPTQ vs AWQ——配合vLLM、量化 | 口述 1 道概念题(录音回听) |
| 第 3 周 | L3 算子 + 分布式:FlashAttention / CUDA reduction / TP-PP-EP——配合算子融合、分布式推理 | 每天自问"我项目里这个决策为什么这么做" |
| 第 4 周 | 全真模拟:按第七节话术模拟"不知道"场景;预约 2 场模拟面试;整理错题本 | 复习前三周错题与口述录音 |
1 周版(紧急冲刺,每天 4–6 小时)
第 1–2 天 基础快扫:性能指标 4 题、量化 4 题(第二节)先自答再看答案,
不会的当天解决;配 latancy-throughput / quantization 两篇
第 3 天 引擎与调度:精读 vLLM Scheduler / PagedAttention 源码、
手推 KV cache 大小公式、写一遍 PagedAttention 草稿(第八节)
第 4 天 算子 + 分布式:FlashAttention 原理 / CUDA reduction 手写 / TP-PP 通信开销
第 5 天 项目深挖:STAR 重写简历项目,预演第六节 1、3、5、6 题;
把"不知道"话术背熟
第 6 天 模拟面试 2 场(找朋友/录像),重点练自我介绍与项目讲述
第 7 天 错题总复习 + 轻松复盘,不再学新内容三个贯穿全程的建议
- 录音回听自己的口头回答——90% 的"当时觉得很好"在回放时都暴露逻辑断裂,这是成本最低的提升手段。
- 建立"一句话定义"清单:每个高频概念能用一句话 + 一个数字讲清(如"TTFT 是 prefill 阶段的延迟、Llama-70B 在 H100 上 2k prompt 约 600ms"),这比能背长文有用得多。
- 术语统一:回答中主动使用规范术语(PagedAttention、continuous batching、TP、EP、TTFT、TPOT),并随时查术语表校准——术语使用是面试官判断"科班感"的隐形信号。
十一、延伸阅读
- 概念补课:延迟与吞吐 | 内存与带宽 | Roofline 模型 | GPU 优化原理 | 硬件入门
- 引擎与算子:vLLM | TensorRT-LLM | Triton 推理服务 | 算子融合 | 图优化
- 量化与压缩:量化 | 权重-激活混合精度 | 剪枝 | 蒸馏
- 调度与分布式:批处理与调度 | 模型服务 | 分布式推理 | 投机解码
- 端侧推理:llama.cpp | 移动端部署
- 实践:基准测试 | 调优实践 | 引擎对比 | 常见陷阱
- 求职配套:career 模块导读 | JD 清单 | 能力地图 | 简历分析 | 求职冲刺线
- 刷题平台:LeetCode(通用算法)、vLLM / SGLang / llama.cpp 源码(推理相关手写题参考实现)、Hugging Face 课程(LLM 方向)
参考资料
- Kwon et al. Efficient Memory Management for Large Language Model Serving with PagedAttention (SOSP 2023) —— vLLM/PagedAttention 原始论文
- Dao. FlashAttention-2: Fast Attention with Better Parallelism and Work Partitioning (2023) —— FlashAttention-2 原论文
- Shah et al. FlashAttention-3: Fast and Accurate Attention with Asynchrony and Low-precision (2024) —— FlashAttention-3 / H100 TMA / FP8
- Frantar et al. GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers (ICLR 2023) —— GPTQ 量化
- Lin et al. AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration (MLSys 2024) —— AWQ 量化
- Xiao et al. SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models (ICML 2023) —— SmoothQuant 激活量化
- Cai et al. Medusa: Simple Framework for Accelerating LLM Generation with Multiple Decoding Heads (ICML 2024) —— Medusa 投机解码
- Li et al. EAGLE: Speculative Sampling Requires Rethinking Feature Uncertainty (ICML 2024) —— EAGLE 投机解码
- Shoeybi et al. Megatron-LM: Training Multi-Billion Parameter Language Models Using Model Parallelism (2019) —— TP/PP 经典论文
- NVIDIA. H100 Transformer Engine Technical Brief (2022) —— H100 FP8 / TMA 官方说明
- NVIDIA. Nsight Systems Documentation —— 性能分析工具链官方文档
- NVIDIA. CUDA C++ Programming Guide —— bank conflict / reduction kernel 官方教材
- OpenAI Triton Language Tutorials —— Triton DSL 入门
- vLLM Project Source Code —— 引擎源码精读材料
- TensorRT-LLM Documentation —— in-flight batching / FP8 实现参考
- LeetCode 题库 —— 通用算法手撕的标准练习平台