1000道算法工程师面试题(大模型)—— 第35部分
摘要 本文探讨了大模型服务在生产环境中的稳定性保障与故障排查问题。主要内容包括:显存碎片化导致OOM的解决方案、僵尸进程处理、分层健康检查策略、KV Cache管理优化、GPU温度监控、共享GPU资源隔离、K8s调度问题排查、日志采样记录、共享内存配置、CUDA错误定位、客户端断开处理、降级预案设计、启动探针配置以及PyTorch版本兼容性问题。这些实践经验对于保障大模型服务的稳定运行具有重要参考
·
1000道大模型算法工程师面试题汇总(1-35部分 · 将持续更细)
- 第01部分:Python并发、GIL、多进程协程、内存管理与性能分析
- 第02部分:Linux排查、Docker瘦身、K8s资源调度与MLOps流水线
- 第03部分:深度学习基础、优化器、混合精度、分布式与Transformer结构
- 第04部分:指令微调、LoRA/QLoRA、DeepSpeed/Megatron并行与防遗忘
- 第05部分:推理加速、vLLM、PagedAttention、KV Cache与SGLang
- 第06部分:CUDA编程、Kernel优化、Warp Divergence与算子开发
- 第07部分:RAG基础入门、全链路架构、检索召回与Rerank策略
- 第08部分:在线服务架构、高并发、缓存体系、灰度发布与路由
- 第09部分:RAG向量检索、索引构建、混合检索与Embedding选型
- 第10部分:大模型评估体系、对齐安全、自动评测与红队测试
- 第11部分:推理性能优化、多租户调度、吞吐延迟与KV显存管理
- 第12部分:训练数据工程、MLOps流水线、数据清洗与质量控制
- 第13部分:国产算力适配、昇腾/海光/沐曦异构迁移与生态差异
- 第14部分:项目经验、STAR法则、RAG落地工程与简历面试技巧
- 第15部分:线上服务排障、推理QPS优化、Tracing与工程部署坑
- 第16部分:Code代码生成、Function Calling与Agent工程实战
- 第17部分:数据安全、隐私合规、敏感数据处理与私有化部署
- 第18部分:大模型评测基准、榜单解读、对齐评测与评估方法论
- 第19部分:架构演进、成本控制、FinOps与可观测性Observability
- 第20部分:企业级平台战略、自研vs采购、国产化迁移与技术蓝图
- 第21部分:参考答案:Python与深度学习框架基础(1-20题)
- 第22部分:参考答案:推理加速与框架实战(vLLM/MindIE/SGLang)
- 第23部分:参考答案:微调训练工程(DeepSpeed/ZeRO/显存优化)
- 第24部分:参考答案:CUDA编程、底层算子优化与硬件工程
- 第25部分:参考答案:综合混合题与面试总结收尾
- 第27部分:参考答案:对齐算法、RLHF、DPO/PPO与奖励模型
- 第28部分:参考答案:多模态模型、LLaVA/Qwen-VL与跨模态对齐
- 第29部分:参考答案:容器化、K8s资源调度、MLOps与GPU运维
- 第30部分:参考答案:Transformer底层原理、RoPE/GQA与算法细节
- 第31部分:参考答案:系统设计、企业级RAG、网关路由与降本增效
- 第32部分:参考答案:推理性能极限调优(参数调整/并发瓶颈)
- 第33部分:参考答案:国产算力踩坑(昇腾MindIE/HCCL/生态兼容)
- 第34部分:参考答案:RAG业务落地、分片/改写/混检与性能优化
- 第35部分:参考答案:SRE稳定性保障、故障排查、OOM与降级预案
这是第十四部分的详细参考答案。这部分考察的是 SRE(站点可靠性工程)和运维实战。对于生产环境的大模型服务,"跑起来"只是第一步,"稳得住"才是真正的本事。
第十四部分:稳定性保障与故障排查 (SRE/Ops) (276-300)
276. 线上服务突然 OOM,但是显存监控显示还有剩余,这通常是什么原因?(显存碎片?PyTorch 缓存未释放?)
答案:
- 原因: 显存碎片化 (Fragmentation)。
- PyTorch 的
CachingAllocator会申请大块显存并切分使用。如果程序中频繁申请不同大小的 Tensor(特别是动态 Shape 推理),会导致大块显存被切碎。 - 当需要一个连续的大块显存(比如 Prefill 阶段的 Attention 矩阵)时,虽然总剩余显存够,但没有一块足够大的连续空间,就会报 OOM。
- PyTorch 的
- 解决:
- 设置
PYTORCH_CUDA_ALLOC_CONF=max_split_size_mb:128来减少碎片。 - 在代码中适时调用
torch.cuda.empty_cache()(注意这会拖慢速度,仅在必要时用)。
- 设置
277. 遇到过“僵尸进程”吗?主进程挂了,但 GPU 显存还被子进程占着,导致重启失败。你的启动脚本里怎么处理这种情况?
答案:
- 现象: Docker 容器重启了,但 GPU 显存没释放,因为之前的 Worker 进程(子进程)变成了孤儿进程,被 Init 进程接管但没被杀掉。
- 处理:
- 使用
tini: 在 Dockerfile 中使用ENTRYPOINT ["/usr/bin/tini", "--", "python", "app.py"]。Tini 作为 PID 1 进程,负责正确回收所有僵尸子进程。 - 启动脚本 Trap: 在 shell 脚本里写
trap 'kill $(jobs -p)' EXIT,确保主进程退出时广播 Kill 信号给所有子进程。
- 使用
278. 你们的健康检查(Health Check)是只查 TCP 端口通不通,还是会真实地发一个推理请求进去测?
答案:
- 策略: 分层检查。
- Liveness Probe(存活检测): 查 TCP 端口或简单 HTTP Ping。只要进程还在,就不杀 Pod。
- Readiness Probe(就绪检测): 必须发真实的推理请求(通常是一个固定的、极短的 Prompt,如 “hi”)。
- 原因: 大模型服务经常出现“死锁”情况(Python GIL 锁死或 CUDA 挂起),端口是通的,但无法处理请求。只有真实推理才能判断服务是否可用,从而决定是否切断流量。
279. 服务运行几天后,推理速度越来越慢,重启就好了,这大概率是什么泄露了?(CPU 内存?文件句柄?还是 KV Cache 管理 Bug?)
答案:
- 概率最高: KV Cache 碎片化 或 Python 对象泄露。
- KV Cache: 如果是自己实现的 PagedAttention 逻辑,可能存在 Page 回收不彻底的问题,导致可用 Page 越来越少,Cache Miss 变高,速度变慢。
- Python 泄露: 比如在全局 List 里记录了每次请求的 Log 或 Latency 对象,几天下来积攒了几百万个对象,GC 扫描压力变大,导致 CPU 占用升高,拖慢整体调度。
280. 当 GPU 温度过高触发降频保护时,你们的监控系统能第一时间报警吗?是用 Prometheus 抓的哪个指标?
答案:
- 工具: DCGM Exporter (NVIDIA Data Center GPU Manager)。
- 指标:
DCGM_FI_DEV_GPU_TEMP:GPU 温度。DCGM_FI_DEV_CLOCK_THROTTLE_REASONS:最关键。这个值非 0 代表正在降频。
- 报警: 如果
Temp > 82°C或者Throttle > 0,立即触发 P1 报警给运维,检查机房空调或风扇。
281. 多个模型共享 GPU 显存时(比如一个 Embedding 一个 LLM),怎么防止一个把另一个挤挂?(CUDA MPS 用过吗?)
答案:
- 风险: 默认情况下,CUDA Context 之间没有内存隔离。Embedding 模型突然来个大 Batch,可能把 LLM 的显存挤爆。
- MPS (Multi-Process Service): 主要是解决计算资源的时间切片问题(提升小模型并发利用率),但不能强隔离显存。
- 最佳实践: 不要共享。
- 如果非要共享,必须在代码层面(TensorFlow 的
memory_fraction或 PyTorch 的max_split_size间接控制)严格限制每个进程的显存上限,或者使用 MIG (Multi-Instance GPU) 从硬件层面切分 A100。
- 如果非要共享,必须在代码层面(TensorFlow 的
282. 遇到过 K8s Pod 处于 Pending 状态,提示“没有足够的 GPU 资源”,但实际上有卡空闲,这是调度器哪里没配对?
答案:
- 原因: K8s 调度器看的是 Requests,不是实际利用率。
- 即使物理卡是空闲的,如果之前调度的 Pod 在 YAML 里申领了这张卡(
nvidia.com/gpu: 1),K8s 账本上这就已经没了。
- 即使物理卡是空闲的,如果之前调度的 Pod 在 YAML 里申领了这张卡(
- 特殊情况:
- Taints/Tolerations: 节点被打上了污点(如
NoSchedule),新 Pod 没有对应的容忍度。 - Device Plugin 问题: 某个 Pod 异常退出了,但 Device Plugin 没有向 Kubelet 汇报资源释放,导致 K8s 以为卡还在被占用(Ghost Pod)。重启 kubelet 或 device plugin pod 可解。
- Taints/Tolerations: 节点被打上了污点(如
283. 生产环境的日志量太大了(全量的 Input/Output),把磁盘写满了怎么办?你们有做采样记录(Sampling Logging)吗?
答案:
- 原则: 生产环境严禁全量打印 Input/Output Payload。
- 既有隐私合规风险,又会撑爆磁盘(JSON 很大)。
- 措施:
- Sampling: 只记录 1% 的请求详情用于抽检。
- Log Rotation: Docker 配置
max-size: 100m,max-file: 3。 - 元数据记录: 对所有请求,只记
TraceID,Token_Count,Latency,Status_Code,这些数据量很小但足够分析性能。
284. 在 Docker 里,/dev/shm(共享内存)太小会导致 DataLoader 报错,你一般给容器挂载多大的 shm?
答案:
- 报错:
Bus error (core dumped)。 - 默认值: Docker 默认为 64MB,跑 PyTorch 肯定不够。
- 设置:
- Docker:
--shm-size=8g。 - K8s: 挂载一个
emptyDir卷,并设置medium: Memory。大小建议设置为物理内存的 30%。
- Docker:
285. 如果模型推理时出现了 CUDA Error: device-side assert triggered,这种报错一般不准,你怎么定位真实的错误位置?
答案:
- 原因: GPU 是异步执行的。当 CPU 收到报错时,GPU 可能已经跑过了好几个 Kernel,堆栈对不上。
- 定位: 设置环境变量
CUDA_LAUNCH_BLOCKING=1。- 这会强制 CPU 等待每个 GPU Kernel 执行完(同步模式)。
- 虽然程序会变慢,但报错时的 Python 堆栈会准确指向出错的那一行代码(通常是 Embedding 层索引越界,即 Input ID 超过了 Vocab Size)。
286. 客户端突然断开连接,后端正在跑的推理任务能自动 Cancel 吗?还是必须等它跑完?这对资源浪费影响大吗?
答案:
- 现状: 如果不做特殊处理,后端通常会跑完,严重浪费算力。
- 处理:
- HTTP/FastAPI: 监听
client_disconnect事件。 - Asyncio: 捕获
asyncio.CancelledError。 - vLLM 集成: 调用
engine.abort_request(request_id)。
- HTTP/FastAPI: 监听
- 必须做: 对于生成长文本的任务,用户可能等了 5 秒没耐心就刷新的,如果不 Cancel,GPU 还在傻傻生成剩下的 2000 字,纯属浪费。
287. 你们做没做过“降级预案”?比如 A100 集群全挂了,能不能自动切到 T4 集群或者 CPU 集群顶一会儿?
答案:
- 做过。 高可用(HA)的核心。
- 链路: 网关层(Nginx/Kong)配置 Upstream Group。
Primary: A100 集群。Backup: T4 量化集群(速度慢点,但能用)。Fallback: 甚至可以切到 Azure OpenAI/DeepSeek API(作为最后的兜底,虽然贵)。
- 逻辑: 当 Primary 返回 5xx 错误比例超过阈值,自动切 Backup。
288. 模型加载时间太长(比如 2 分钟),导致 K8s 认为服务启动失败(Liveness Probe 失败)并杀掉重启,这怎么解?
答案:
- 配置错误: 把 Liveness Probe 当 Startup Probe 用了。
- 修正: 使用 Startup Probe(启动探针)。
- 配置
failureThreshold: 30,periodSeconds: 10。这意味着 K8s 会给容器 300 秒的时间去启动。 - 在 Startup Probe 成功之前,Liveness Probe 不会启用。这样就避免了“还没加载完就被杀掉”的死循环。
- 配置
289. 遇到过 PyTorch 版本和 CUDA 版本不匹配导致的奇怪 Bug 吗?比如算子计算结果全为 0。
答案:
- 遇到过。 或者是报错
symbol lookup error。 - 场景: 宿主机驱动是 CUDA 11.4,Docker 里装了 PyTorch (CUDA 12.1 版)。虽然通常兼容,但在某些特定算子(如 FlashAttention)编译时依赖的 Driver 版本如果不一致,会出灵异现象。
- 解决: 严格使用 NVIDIA 官方的 NGC 容器(如
nvcr.io/nvidia/pytorch:23.10-py3),这里的 Torch 和 CUDA 是经过严格测试配对的。
290. 在高并发下,Python 的 GC(垃圾回收)会导致明显的 Stop-the-world 顿卡吗?你们有没有调整过 GC 阈值?
答案:
- 会。 当内存中对象极多时,GC 扫描会暂停主线程几十毫秒,造成 Latency 抖动(P99 飙升)。
- 优化:
- 禁用自动 GC: 在推理主循环开始前
gc.disable()。 - 手动 GC: 在处理完一个 Batch 的请求后,或者显存/内存达到警戒线时,手动调用
gc.collect()。 - 调整阈值:
gc.set_threshold(700, 10, 10)调大一点,减少扫描频率。
- 禁用自动 GC: 在推理主循环开始前
291. 怎么保证 API Key 不被刷爆?你们在网关层做了什么样的 Rate Limit?是针对 IP 还是针对 User ID?
答案:
- 针对 User ID / Key。 针对 IP 是没用的(学校/公司出口 IP 相同,或者攻击者用代理池)。
- 算法: 令牌桶 (Token Bucket) 或 滑动窗口 (Sliding Window)。
- 存储: 使用 Redis + Lua 脚本 实现原子计数。
- 策略: 分级限流。
- Free User: 10 RPM (Requests Per Minute).
- Pro User: 60 RPM.
- Total Global Limit: 保护后端不被打死。
292. 如果发现某个 Worker 进程 CPU 占用率 100% 但 GPU 利用率 0%,这通常是卡在什么地方了?(死循环?锁竞争?)
答案:
- 排查: 使用
py-spy dump --pid [pid]查看 Python 堆栈。 - 常见原因:
- Tokenizer 死循环: 遇到了极其特殊的 Unicode 字符串,正则匹配回溯卡死。
- GIL 锁竞争: 多线程处理 Log 或 Metrics 时死锁。
- 后处理逻辑: 比如在 Python 里做了一个巨大的 List 拼接或字符串处理,把 CPU 跑满了,还没轮到 GPU 推理。
293. 你们的模型权重文件是放在 Docker 镜像里,还是启动时从 S3 拉取?哪种启动更快?
答案:
- 方式: 启动时挂载(PVC/HostPath/NAS)。
- 对比:
- 打入镜像: 镜像会变成 20GB+。Pull 镜像极其慢,且每次更新模型都要重新 Build,分发效率极低。
- 挂载存储: 镜像只有代码(500MB)。模型文件存在 NFS/Ceph 上,Pod 启动挂载即可读取。结合 Fluid/Alluxio 缓存,启动最快。
294. 遇到过“显存泄漏”排查最难的一次是什么情况?最后是用 torch.cuda.memory_summary() 查出来的吗?
答案:
- 案例: 一个由
torch.compile(PyTorch 2.0) 引发的泄露。 - 过程:
memory_summary显示显存被占用但没被 Tensor 引用。 - 真凶: 是计算图缓存(Graph Cache)。因为输入的 Shape 极其多变(动态 Shape),导致 PyTorch 2.0 不断编译新的 Kernel 并缓存,撑爆了显存。
- 解决: 固定 Input Shape 分桶,或者限制 Compile 的 Cache Size。
295. 生产环境你们敢用 Spot Instances(抢占式实例)来跑推理吗?如果机器被回收了,怎么保证服务不中断?
答案:
- 敢用。 为了省钱(便宜 60%-80%)。
- 保障机制:
- 混合部署: Spot 实例和 On-Demand 实例混跑(如 80% Spot + 20% Stable)。
- 监听中断信号: 云厂商回收前 2 分钟会发信号。程序捕获后,将节点设为 Cordon(不调度新流量),并利用这 2 分钟处理完 In-flight 请求,然后优雅退出 (Graceful Shutdown)。
- 快速补货: K8s Cluster Autoscaler 自动购买新机器。
296. 怎么监控“显存带宽利用率”?nvidia-smi 看不到这个,你们用 Nsight Systems 还是 DCGM?
答案:
- 线上监控: 用 DCGM Exporter。指标是
DCGM_FI_DEV_MEM_COPY_UTIL(显存复制利用率)。 - 深度分析: 用 Nsight Systems (
nsys)。DCGM 只能看大概,nsys能看到微秒级的 Kernel 显存读写情况,判断是 H2D 慢还是 D2D 慢。
297. 遇到过 NCCL timeout 错误吗?在跨机训练或推理时,这通常是防火墙问题还是网卡问题?
答案:
- 原因: 90% 是 网络不可达。
- 检查点:
- 防火墙/安全组: NCCL 使用随机高位端口。必须开放所有 TCP 端口或指定范围。
- 网卡绑定: 多网卡机器上,NCCL 抓错了网卡(比如抓到了 Docker 的虚拟网卡)。需设置
NCCL_SOCKET_IFNAME=eth0。 - MTU 问题: 某些交换机开启了 Jumbo Frame (MTU 9000),但服务器没配,导致大包丢包。
298. 你们的 Python 服务是用多进程(Multiprocessing)还是多线程(Multithreading)?在大模型推理场景下,GIL 锁的影响还大吗?
答案:
- 选型: 多进程(Process-based)。
- 原因:
- 推理不仅仅是 GPU 跑,还有大量的 Tokenization 和 Detokenization,以及 HTTP 协议解析。这些都是 CPU 密集型操作。
- 在 GIL 限制下,多线程跑这些会争抢 CPU,甚至导致 GPU 等待 CPU(Starvation)。
- vLLM 内部就是通过 Ray 或 Python Multiprocessing 启动多个 Worker 来规避 GIL。
299. 如果 Update 模型版本,怎么做到“无损滚动更新”?旧的请求还在处理,新的 Pod 刚启动,怎么平滑切换?
答案:
- K8s RollingUpdate:
- 设置
maxSurge: 1,maxUnavailable: 0(先起新,再杀旧)。
- 设置
- 关键点: Graceful Shutdown。
- 旧 Pod 收到
SIGTERM后,从 Service Endpoint 摘除(不接新客)。 - 应用层捕获信号,等待所有正在推理的请求(In-flight Requests)跑完,再退出进程。
- K8s 的
terminationGracePeriodSeconds要设得足够长(比如 120s),给它收尾的时间。
- 旧 Pod 收到
300. 终极一问: 如果现在线上服务全崩了,老板就在你后面站着,你恢复服务的标准 SOP(操作流程)前三步是什么?
答案:
- 止损(切流/熔断): 不要先查 Bug!先切断流量或者降级(切到备用集群/Azure API)。如果是因为发布导致的,立即一键回滚 (Rollback) 到上个镜像版本。保证用户先能用,或者看到友好的降级提示。
- 扩容/重启: 如果是突发流量打挂的,立即扩容(Scale Out)。如果是内存泄露导致的假死,立即重启所有 Pod(Restart)。暴力但有效。
- 保留现场: 在重启前,务必保留 1-2 个故障 Pod(Remove Label 让它脱离 Service 但不被杀掉),以便后续抓 Core Dump 或分析日志查根因。
- (回答要体现:业务连续性第一,查 Bug 第二的运维原则)
1000道大模型算法工程师面试题汇总(1-35部分 · 将持续更细)
- 第01部分:Python并发、GIL、多进程协程、内存管理与性能分析
- 第02部分:Linux排查、Docker瘦身、K8s资源调度与MLOps流水线
- 第03部分:深度学习基础、优化器、混合精度、分布式与Transformer结构
- 第04部分:指令微调、LoRA/QLoRA、DeepSpeed/Megatron并行与防遗忘
- 第05部分:推理加速、vLLM、PagedAttention、KV Cache与SGLang
- 第06部分:CUDA编程、Kernel优化、Warp Divergence与算子开发
- 第07部分:RAG基础入门、全链路架构、检索召回与Rerank策略
- 第08部分:在线服务架构、高并发、缓存体系、灰度发布与路由
- 第09部分:RAG向量检索、索引构建、混合检索与Embedding选型
- 第10部分:大模型评估体系、对齐安全、自动评测与红队测试
- 第11部分:推理性能优化、多租户调度、吞吐延迟与KV显存管理
- 第12部分:训练数据工程、MLOps流水线、数据清洗与质量控制
- 第13部分:国产算力适配、昇腾/海光/沐曦异构迁移与生态差异
- 第14部分:项目经验、STAR法则、RAG落地工程与简历面试技巧
- 第15部分:线上服务排障、推理QPS优化、Tracing与工程部署坑
- 第16部分:Code代码生成、Function Calling与Agent工程实战
- 第17部分:数据安全、隐私合规、敏感数据处理与私有化部署
- 第18部分:大模型评测基准、榜单解读、对齐评测与评估方法论
- 第19部分:架构演进、成本控制、FinOps与可观测性Observability
- 第20部分:企业级平台战略、自研vs采购、国产化迁移与技术蓝图
- 第21部分:参考答案:Python与深度学习框架基础(1-20题)
- 第22部分:参考答案:推理加速与框架实战(vLLM/MindIE/SGLang)
- 第23部分:参考答案:微调训练工程(DeepSpeed/ZeRO/显存优化)
- 第24部分:参考答案:CUDA编程、底层算子优化与硬件工程
- 第25部分:参考答案:综合混合题与面试总结收尾
- 第27部分:参考答案:对齐算法、RLHF、DPO/PPO与奖励模型
- 第28部分:参考答案:多模态模型、LLaVA/Qwen-VL与跨模态对齐
- 第29部分:参考答案:容器化、K8s资源调度、MLOps与GPU运维
- 第30部分:参考答案:Transformer底层原理、RoPE/GQA与算法细节
- 第31部分:参考答案:系统设计、企业级RAG、网关路由与降本增效
- 第32部分:参考答案:推理性能极限调优(参数调整/并发瓶颈)
- 第33部分:参考答案:国产算力踩坑(昇腾MindIE/HCCL/生态兼容)
- 第34部分:参考答案:RAG业务落地、分片/改写/混检与性能优化
- 第35部分:参考答案:SRE稳定性保障、故障排查、OOM与降级预案
更多推荐


所有评论(0)