README.md

AI Infra 工程师面经(305 题版)

本专栏为 AI 基础设施 / 机器学习系统 方向面试与知识体系整理,覆盖:PyTorch 底层、TensorFlow/XLA、自定义算子、编译器、数据/模型/流水线并行、显存与通信、推理引擎、量化、服务化与调度、训练/推理平台设计、C++/CUDA、Python、算法与网络、存储与虚拟化等。

每篇文章包含:完整讲解 + 面试要点 + 记忆要点


先读导读(推荐)


目录结构

模块 题号 说明
PyTorch 底层 1–15 Autograd、Module、Dispatch、CUDA 算子、内存池、JIT、DDP/FSDP、torch.compile、hook、QAT、checkpoint、AMP、profiler
TensorFlow/XLA 16–20 XLA 优化、tf.function、HLO IR、SavedModel、TF Serving
自定义算子开发 21–30 CUDA vector add、Triton、融合算子、CUTLASS、memory coalescing、Nsight、warp divergence、PagedAttention
编译器优化 31–45 TVM、MLIR、Inductor、ONNX、TensorRT、loop tiling、PTQ/QAT、sparsity、pass manager、control flow
数据并行 46–60 DDP、FSDP、ZeRO、梯度累积、SyncBatchNorm、NCCL、梯度压缩
模型并行与流水线 61–75 TP、PP、bubble、1F1B、3D 并行、序列并行、MoE、Zero Bubble
显存优化与 Offload 76–85 ZeRO-Offload、DeepSpeed-Infinity、checkpoint、碎片、显存估算
通信优化 86–95 NCCL Tree/Ring、all-reduce、NVLink/IB、overlap、RDMA
推理引擎 96–115 TensorRT、vLLM、TGI、llama.cpp、batching、延迟、多 stream
量化与压缩 116–130 INT8、SmoothQuant、AWQ、GPTQ、GGUF、FP8、校准、剪枝
服务化与调度 131–145 Triton、K8s、MIG、priority、health check、gRPC、多租户
训练框架 146–160 Megatron、DeepSpeed、Colossal、FSDP、Accelerate、checkpoint、RLHF、MoE
存储与 IO 161–170 checkpoint 格式、Lustre、caching、DALI、S3
集群调度 171–180 Slurm、Volcano、gang scheduling、preemption、utilization
性能分析工具 181–195 nvidia-smi、Nsight、PyTorch Profiler、Chrome Trace、perf、scaling efficiency
优化技术 196–215 FlashAttention、xFormers、CUDA Graph、arithmetic intensity、LARS/LAMB
训练平台设计 216–235 1000 卡平台、scheduler、存储、网络、fault tolerance、CI/CD
推理平台设计 236–255 10 万 QPS、auto-scaling、routing、streaming、A/B、latency SLO
C++/CUDA 编程 256–270 memory pool、shared memory、ring buffer、stream、CUTLASS、NCCL、CUDA Graph
Python 高级 271–280 GIL、asyncio、Cython、pybind11、descriptor、metaclass
算法与数据结构 281–290 LRU、external sort、consistent hashing、bloom filter、rate limiter
网络 291–300 TCP/RDMA、InfiniBand、RoCE、NCCL、fat-tree、DPDK
存储与虚拟化 301–305 containerd、CNI、GPU 虚拟化、CSI、etcd

使用方式

  • 按题号在对应模块下查找文章(文件名 001.md305.md)。
  • 每篇文章含 完整讲解 + 面试要点 + 记忆要点
  • 建议搭配 305 题漫游指南 按主题线通读后再精刷。

单页复习页 study.html

build_study_html.py 扫描本仓库全部 Markdown 生成。修改任意 .md 后请重新生成再提交:

pip install markdown
python build_study_html.py

侧栏标题与 <title> 可由 study_html_meta.txt(最多三行:主标题、副标题、浏览器标题)定制;未提供时则从 README.md 首行标题推断。


共 305 题,覆盖 AI Infra 全栈。

305题漫游指南.md

305 题漫游指南:从 PyTorch 底层到集群调度的一天

文中所有可点击的链接都会跳转到对应面试题的详解。

建议边读边点,像翻地图一样逛完 305 个知识点。

单页浏览:本地 study.html;在线请用 Pages 链接(勿用 Raw)。改 .md 后运行 python build_study_html.py 再提交 study.html


序章:AI Infra 面经 305 题,一夜能摸到哪?

你收到 HR 的消息:面试范围是 AI 基础设施 / 机器学习系统,从框架底层到集群调度都可能问。

「Infra」俩字听起来很广:从你写的 model(x) 背后怎么求导、怎么分到多卡,到推理服务怎么扛 10 万 QPS、K8s 怎么调度 GPU,中间每一环都可能考。

你打开那份 305 题 清单——从 PyTorch Autogradetcd 在 K8s 中的作用,从 DDP 与 FSDPvLLM PagedAttention——密密麻麻,像一张从「单机训练」画到「多租户集群」的长卷。

与其对着题号硬啃,不如换一种玩法:按「一天搞懂 AI Infra」的主线,从框架底层 → 编译器与算子 → 分布式训练 → 显存与通信 → 推理引擎与量化 → 服务化与平台设计 → 语言与网络存储,把 305 题串成一条线。每条线底下都挂着一串可点的链接。

  • 若你想按模块或题号查,直接看 总目录 README
  • 若你想先通读故事再精刷,就顺着这篇指南一段段往下点。

两样配合用,效果更好。祝面试顺利。


一、PyTorch 底层(第 1–15 题)

一天从「你写的代码到底是怎么跑的」开始。PyTorch 底层决定了训练脚本里的每一行 tensor、每一个 backward 在 C++/CUDA 里长什么样。

第 1 题:Autograd 与 torch.autograd.Function第 2 题:Module 的 call 与 forward第 3 题:Dispatch、ATen、c10、torch.library第 4 题:自定义 CUDA 算子在 PyTorch 中调用第 5 题:内存池与显存碎片第 6 题:torch.jit.trace 与 script第 7 题:DataLoader num_workers 与 too many open files第 8 题:DDP 与 FSDP 区别第 9 题:torch.compile 与 TorchDynamo/AOTAutograd/Inductor第 10 题:CUDA kernel 调试与 CUDA_LAUNCH_BLOCKING第 11 题:hook、forward_pre_hook、backward_hook第 12 题:QAT 与 torch.ao.quantization第 13 题:checkpoint 梯度检查点第 14 题:AMP 与 GradScaler第 15 题:torch.profiler 与 nvprof

返回本模块目录


二、TensorFlow 与 XLA(第 16–20 题)

除了 PyTorch,TF 栈在工业界仍大量存在。XLA 把计算图编译成更高效的 kernel,tf.function 和 PyTorch 的 JIT 设计理念不同;SavedModel、TF Serving 的 batching 也是常考点。

第 16 题:XLA 优化场景与 jit_compile第 17 题:tf.function 与 torch.jit 差异第 18 题:XLA HLO IR 与编译日志第 19 题:SavedModel 与 TorchScript第 20 题:TF Serving batching

返回本模块目录


三、自定义算子开发(第 21–30 题)

从「用框架」到「写 kernel」:CUDA / Triton / CUTLASS、memory coalescing、bank conflict、occupancy、warp divergence、Nsight、以及 vLLM 的 PagedAttention 如何应对动态 shape。

第 21 题:CUDA vector add 绑定到 Python第 22 题:Triton 与 CUDA 区别第 23 题:融合算子 layernorm+residual+activation第 24 题:CUTLASS 何时用第 25 题:memory coalescing、bank conflict、occupancy第 26 题:Nsight Compute 与 metrics第 27 题:register 与 occupancy 平衡第 28 题:warp divergence第 29 题:动态 shape 与 PagedAttention第 30 题:算子融合收益评估

返回本模块目录


四、编译器优化(第 31–45 题)

TVM、MLIR、TorchInductor、ONNX、TensorRT:loop tiling、unrolling、vectorization、PTQ/QAT 在编译器中的处理、稀疏与 pass manager、control flow 的 tracing 与 symbolic execution。

第 31 题:TVM Ansor 与 MetaSchedule第 32 题:MLIR dialect、operation、pass第 33 题:TorchInductor 到 Triton第 34 题:ONNX Runtime 图优化第 35 题:TensorRT plugin 与 dynamic shape第 36 题:loop tiling、unrolling、vectorization第 37 题:PTQ 与 QAT 在编译器第 38 题:稀疏与 2:4 structured sparsity第 39 题:pass manager top-down vs bottom-up第 40 题:新硬件后端编译器支持第 41 题:TVM vs MLIR vs TorchDynamo第 42 题:AOT vs JIT第 43 题:编译时间与缓存第 44 题:operator decomposing 与 fusion 边界第 45 题:control flow tracing vs symbolic

返回本模块目录


五、数据并行(第 46–60 题)

多卡同模型:DDP 的 gradient bucketing、find_unused_parametersFSDP 的 sharding、auto_wrap_policyZeRO-1/2/3;梯度累积、SyncBatchNorm、NCCL 排查、torchrun 与 mp.spawn、梯度压缩。

第 46 题:DDP gradient bucketing第 47 题:find_unused_parameters第 48 题:FSDP sharding strategy第 49 题:FSDP auto_wrap_policy第 50 题:ZeRO-1/2/3第 51 题:loss scaling 分布式第 52 题:梯度累积在 DDP 中第 53 题:分布式 sampler第 54 题:SyncBatchNorm第 55 题:分布式 hang 与 NCCL_DEBUG第 56 题:torchrun 与 mp.spawn第 57 题:NCCL_SOCKET_IFNAME、NCCL_IB_DISABLE第 58 题:梯度压缩 fp16/bf16/1bit Adam第 59 题:异步训练 Hogwild第 60 题:自定义分布式优化器

返回本模块目录


六、模型并行与流水线并行(第 61–75 题)

单卡放不下就切模型TP 的 fused attention、Megatron column/row parallelPP 的 bubble、GPipe/PipeDream、1F1B;all-gather、reduce-scatter、micro-batch、3D 并行、序列并行、MoE Expert Parallelism、Zero Bubble、通信 profile。

第 61 题:TP fused attention第 62 题:Megatron column/row parallel第 63 题:PP bubble GPipe vs PipeDream第 64 题:interleaved pipeline 1F1B第 65 题:PP 中 activation checkpointing第 66 题:TP/PP/DP 平衡 175B第 67 题:torch.distributed.pipeline.sync.Pipe第 68 题:all-gather、reduce-scatter第 69 题:micro-batch 与吞吐第 70 题:PP 负载均衡与 recompute第 71 题:3D 并行通信复杂度第 72 题:Sequence Parallelism第 73 题:Expert Parallelism MoE all-to-all第 74 题:Zero Bubble 流水线第 75 题:分布式通信 profile

返回本模块目录


七、显存优化与 Offload(第 76–85 题)

ZeRO-Offload、DeepSpeed-Infinity、checkpoint、empty_cache、显存估算公式、activation compression、CPU-GPU 流水线重叠、多节点显存策略、ROI 评估。

第 76 题:ZeRO-Offload 到 CPU第 77 题:DeepSpeed-Infinity NVMe第 78 题:checkpoint_sequential 与 checkpoint第 79 题:显存碎片分布式第 80 题:empty_cache 副作用第 81 题:大模型显存估算第 82 题:checkpoint 与 activation compression第 83 题:CPU offload 与计算重叠第 84 题:多节点显存策略第 85 题:显存优化 ROI

返回本模块目录


八、通信优化(第 86–95 题)

NCCL Tree/Ring、all-reduce 通信量、NVLink/IB/TCP、NCCL_TOPO_FILE、通信计算重叠、nccl/gloo/mpi、RDMA RoCE/IB、iftop/nicstat、自定义 reduce_op、异构网络。

第 86 题:NCCL Tree 与 Ring第 87 题:all-reduce 通信量第 88 题:NVLink、InfiniBand、TCP第 89 题:NCCL_TOPO_FILE第 90 题:通信计算重叠 double buffering第 91 题:backend nccl/gloo/mpi第 92 题:RDMA RoCE v1/v2/IB第 93 题:网络拥塞诊断 iftop nicstat第 94 题:自定义通信算子 reduce_op第 95 题:异构网络通信

返回本模块目录


九、推理引擎(第 96–115 题)

TensorRT builder/runtime、dynamic shape、pluginONNX Runtime EPvLLM PagedAttention、continuous batching、prefix caching;TensorRT-LLM、FasterTransformer、TGI、llama.cpp 量化、移动端 MNN/TNN、warmup、多 stream、padding/packing、P50/P90/P99、auto-scaling、MPS、精度 debug。

第 96 题:TensorRT builder 与 runtime第 97 题:TensorRT dynamic shape第 98 题:IPluginV2DynamicExt 与 IPluginV2IOExt第 99 题:ONNX Runtime execution provider第 100 题:torch.compile 推理模式第 101 题:vLLM PagedAttention第 102 题:vLLM continuous batching第 103 题:vLLM prefix caching第 104 题:TensorRT-LLM in-flight batching第 105 题:FasterTransformer decoder第 106 题:TGI 架构第 107 题:llama.cpp 量化 Q4_0 Q5_K_M第 108 题:移动端 MNN TNN Paddle Lite第 109 题:warmup 策略第 110 题:多 stream 推理第 111 题:padding 与 packing第 112 题:延迟 P50 P90 P99第 113 题:auto-scaling 策略第 114 题:多模型混部 MPS第 115 题:推理 debug 精度

返回本模块目录


十、量化与压缩(第 116–130 题)

INT8 symmetric/asymmetric、per-tensor/per-channelSmoothQuant、AWQ、GPTQ、OBQGGUF、FP8、H100 Transformer Engine;校准、sensitivity、k-means、BNN、知识蒸馏、剪枝、动态量化、算子融合、混合精度推理。

第 116 题:INT8 symmetric/asymmetric第 117 题:SmoothQuant第 118 题:AWQ第 119 题:GPTQ 与 OBQ第 120 题:GGUF Q4_K_M第 121 题:FP8 与 H100第 122 题:校准数据集第 123 题:精度损失 layer-wise第 124 题:k-means 与非均匀量化第 125 题:二值化网络 BNN第 126 题:知识蒸馏 MiniLLM DistilBERT第 127 题:结构化与非结构化剪枝第 128 题:动态量化与静态量化第 129 题:量化算子融合第 130 题:混合精度推理策略

返回本模块目录


十一、服务化与调度(第 131–145 题)

Triton model ensemble、dynamic batchingA/B testing、K8s GPU Operator、MIG;priority scheduling、preemption、health check、GPU 内存泄漏、hot reload、gRPC vs REST、timeout、多租户 quota、cost optimization、Edge deployment。

第 131 题:Triton model ensemble第 132 题:Triton dynamic batching第 133 题:A/B testing 模型版本第 134 题:K8s GPU Operator第 135 题:MIG 配置第 136 题:priority scheduling第 137 题:长文本 preemption KV swap第 138 题:health check graceful degradation第 139 题:GPU memory 泄漏监控第 140 题:hot reload 零停机第 141 题:gRPC vs REST第 142 题:timeout 部分结果第 143 题:多租户 quota limit request第 144 题:cost optimization Spot第 145 题:Edge 模型加密与兼容

返回本模块目录


十二、训练框架(第 146–160 题)

Megatron、DeepSpeed ZeRO-Infinity/Offload、Colossal-AI Gemini/PatrickStar、FairScale FSDP、Accelerate、limit_all_gathers;checkpoint 格式与 sharded 合并、resume 一致性、data pipeline WebDataset/tfrecord、多模态与 RLHF、MoE all-to-all、长上下文 Ring Attention、elastic training、experiment tracking。

第 146 题:Megatron 与 megatron/core第 147 题:ZeRO-Infinity 与 ZeRO-Offload 入口第 148 题:Colossal-AI Gemini PatrickStar第 149 题:FairScale FSDP第 150 题:Accelerate 分布式第 151 题:limit_all_gathers第 152 题:checkpoint 格式与 sharded 合并第 153 题:resume consistency第 154 题:data pipeline WebDataset tfrecord第 155 题:多模态训练 infra第 156 题:RLHF PPO 分布式第 157 题:MoE Tutel FasterMoE第 158 题:长上下文 Ring Attention第 159 题:fault tolerance elastic第 160 题:W&B MLflow

返回本模块目录


十三、存储与 IO(第 161–170 题)

safetensors vs pytorch.bin、Lustre/GPFS/Alluxio、caching burst buffer、memory mapping lazy loading、异步 checkpoint、nvidia-smi dmon、DALI、sharding、S3/s3fs、parquet/arrow。

第 161 题:safetensors vs pytorch.bin第 162 题:Lustre GPFS Alluxio第 163 题:caching SSD burst buffer第 164 题:权重 memory mapping lazy load第 165 题:多节点 checkpoint 同步第 166 题:数据加载 bottleneck dmon第 167 题:DALI 使用场景第 168 题:sharding 按文件 vs 按样本第 169 题:S3 OSS s3fs第 170 题:metadata parquet arrow

返回本模块目录


十四、集群调度(第 171–180 题)

Slurm sbatch gres、Volcano、gang scheduling、PyTorchJob、resource quota、topology awareness、preemption checkpoint resume、Prometheus Grafana、federated learning、cost accounting、heterogeneous GPU。

第 171 题:Slurm sbatch gres第 172 题:Volcano AI 场景第 173 题:gang scheduling PyTorchJob第 174 题:resource quota priority class第 175 题:GPU topology NVLink第 176 题:preemption checkpoint resume第 177 题:Prometheus Grafana utilization第 178 题:多集群 federated learning第 179 题:cost accounting GPU 小时第 180 题:heterogeneous A100 H100 4090

返回本模块目录


十五、性能分析工具(第 181–195 题)

nvidia-smi dmon/pmon、Nsight Systems timeline、Nsight Compute roofline、PyTorch Profiler memory、record_shapes profile_memory、Chrome Trace、perf eBPF、iperf qperf、fio iostat、dashboard、scaling efficiency、通信 breakdown、aten dispatch、cProfile py-spy、性能回归。

第 181 题:nvidia-smi dmon pmon第 182 题:Nsight Systems timeline gap第 183 题:Nsight Compute roofline第 184 题:PyTorch Profiler memory第 185 题:record_shapes profile_memory第 186 题:Chrome Trace 解读第 187 题:perf eBPF CPU第 188 题:iperf qperf 网络第 189 题:fio iostat 存储第 190 题:端到端监控 dashboard第 191 题:scaling efficiency第 192 题:通信 breakdown第 193 题:aten 算子耗时第 194 题:cProfile py-spy第 195 题:性能回归检测

返回本模块目录


十六、优化技术(第 196–215 题)

FlashAttention IO-aware、FlashAttention-2、xFormers、cuDNN fused attention、融合边界、arithmetic intensity、kernel fusion 手动 vs 编译、CUDA Graph、dynamic shape torch.compile、cudnn.benchmark、pin_memory non_blocking、num_workers、混合精度数值稳定性、effective batch size、LR scaling、LARS LAMB、communication hiding、pipeline bubble 数学、稀疏 attention。

第 196 题:FlashAttention IO-aware第 197 题:FlashAttention-2 改进第 198 题:xFormers memory_efficient_attention第 199 题:cuDNN fused attention第 200 题:融合边界 register pressure第 201 题:带宽 bound vs 计算 bound第 202 题:kernel fusion 手动 vs 编译第 203 题:CUDA Graph make_graphed_callables第 204 题:dynamic shape torch.compile第 205 题:cudnn.benchmark第 206 题:pin_memory non_blocking第 207 题:num_workers 调优第 208 题:DALI GPU decode augment第 209 题:混合精度数值稳定性第 210 题:gradient accumulation effective batch第 211 题:大 batch LR scaling第 212 题:LARS LAMB 大 batch第 213 题:communication hiding第 214 题:pipeline bubble 数学第 215 题:稀疏 attention Sparse Longformer

返回本模块目录


十七、训练平台设计(第 216–235 题)

1000 卡平台组件、job scheduler FIFO/priority/fair、Ceph/JuiceFS/GPFS、镜像 layer registry、InfiniBand RoCE fat-tree、heartbeat watchdog、global shuffle、模型仓库版本血缘、HPO Optuna Ray Tune、multi-tenancy namespace cgroup、defragmentation、dry-run profiling、量化剪枝流水线、cost model、异构 CPU/GPU/TPU、SLA、联邦学习、disaster recovery、CI/CD、observability。

第 216 题:1000 卡平台组件第 217 题:job scheduler 设计第 218 题:Ceph JuiceFS GPFS第 219 题:镜像 layer registry第 220 题:网络 InfiniBand RoCE第 221 题:故障检测恢复第 222 题:global shuffle第 223 题:模型仓库版本血缘第 224 题:HPO Optuna Ray Tune第 225 题:multi-tenancy 隔离第 226 题:defragmentation第 227 题:dry-run profiling第 228 题:量化剪枝流水线第 229 题:cost model第 230 题:异构 CPU GPU TPU第 231 题:SLA job completion第 232 题:联邦学习 infra第 233 题:disaster recovery第 234 题:模型 CI/CD第 235 题:observability

返回本模块目录


十八、推理平台设计(第 236–255 题)

10 万 QPS 设计、HPA VPA KEDA、MPS vs MIG、routing least loaded consistent hashing、CDN for models、A/B canary、streaming SSE、prompt caching、多模态 pipeline、safety guardrails、fine-tuning as a service、spot batching、Core ML TFLite、p99 latency SLO、admission control、ensemble cascade、request tracing、实时离线统一、security、carbon footprint。

第 236 题:10 万 QPS 推理服务第 237 题:HPA VPA KEDA第 238 题:MPS vs MIG 多模型第 239 题:routing 策略第 240 题:边缘 model caching CDN第 241 题:A/B canary第 242 题:streaming SSE第 243 题:推理结果 caching第 244 题:多模态 pipeline第 245 题:safety guardrails第 246 题:fine-tuning as a service第 247 题:cost optimization第 248 题:on-device Core ML TFLite第 249 题:latency SLO p99第 250 题:admission control第 251 题:ensemble cascade第 252 题:debuggability tracing第 253 题:实时离线统一第 254 题:security 加密认证第 255 题:carbon footprint

返回本模块目录


十九、C++/CUDA 编程(第 256–270 题)

线程安全 memory pool、shared bank conflict、ring buffer CPU-GPU、stream 与 event、thrust transform_reduce、CUTLASS gemm Epilogue、NCCL ring all-reduce、zero-copy cudaHostAlloc、P2P、CUDA Graph 捕获条件、template、RAII、CUDA_CHECK、warp shuffle、cooperative groups。

第 256 题:线程安全 memory pool第 257 题:shared bank conflict第 258 题:ring buffer CPU-GPU第 259 题:stream event 同步第 260 题:thrust transform_reduce第 261 题:CUTLASS gemm Epilogue第 262 题:NCCL ring all-reduce第 263 题:zero-copy cudaHostAlloc第 264 题:P2P cudaDeviceEnablePeerAccess第 265 题:CUDA Graph 捕获条件第 266 题:template metaprogramming第 267 题:RAII unique_ptr deleter第 268 题:CUDA error CUDA_CHECK第 269 题:warp shuffle __shfl_sync第 270 题:cooperative groups grid_group

返回本模块目录


二十、Python 高级(第 271–280 题)

GIL、multiprocessing vs threading、asyncio aiohttp、tracemalloc、Cython vs pybind11、descriptor property、context manager、metaclass abc、import sys.path、pickle cloudpickle dill、cProfile line_profiler。

第 271 题:GIL multiprocessing threading第 272 题:asyncio aiohttp第 273 题:memory profiler tracemalloc第 274 题:Cython pybind11第 275 题:descriptor property第 276 题:context manager第 277 题:metaclass abc第 278 题:import sys.path第 279 题:pickle cloudpickle dill第 280 题:cProfile line_profiler

返回本模块目录


二十一、算法与数据结构(第 281–290 题)

并发 LRU、external sort k-way merge、consistent hashing virtual node、bloom filter 假阳性、skip list、B+ tree、rate limiter token bucket leaky bucket、KMP prefix、shortest path Dijkstra Bellman-Ford、并查集 path compression。

第 281 题:并发 LRU cache第 282 题:external sort k-way第 283 题:consistent hashing第 284 题:bloom filter 假阳性第 285 题:skip list level第 286 题:B+ tree 数据库第 287 题:rate limiter第 288 题:KMP prefix第 289 题:shortest path第 290 题:并查集 path compression

返回本模块目录


二十二、网络(第 291–300 题)

TCP vs RDMA、InfiniBand Verbs ibv_post_send、RoCE ECN PFC、fat-tree dragonfly、NCCL bootstrap transport、jitter、DPDK、RDMA memory registration、SR-IOV virtio、跨 AZ。

第 291 题:TCP 与 RDMA第 292 题:InfiniBand Verbs第 293 题:RoCE v2 ECN PFC第 294 题:fat-tree dragonfly第 295 题:NCCL bootstrap transport第 296 题:jitter 对训练影响第 297 题:DPDK AI 网络第 298 题:RDMA memory registration第 299 题:SR-IOV vs virtio第 300 题:跨 AZ 训练

返回本模块目录


二十三、存储与虚拟化(第 301–305 题)

containerd、cri-o、CNI Calico Cilium、vGPU MIG SR-IOV、CSI 驱动、etcd 作用与调优。 最后一站:容器与集群底座。

第 301 题:containerd cri-o第 302 题:CNI Calico Cilium第 303 题:vGPU MIG SR-IOV第 304 题:CSI 驱动第 305 题:etcd 在 K8s 中作用与调优

返回本模块目录


尾声:305 题都在这条线上

PyTorch Autogradetcd 在 K8s 中的作用,这条漫游把 305 题 按「框架 → 算子/编译 → 分布式 → 显存/通信 → 推理/量化/服务 → 平台 → 语言/算法/网络/虚拟化」串成一条线。每一个可点击的链接都会带你到对应那道题的详解;读到哪、点到哪,像翻地图一样把 AI Infra 走一遍。

  • 若你想按模块或题号查,直接看 总目录 README
  • 若你想先通读故事再精刷,就顺着这篇指南一段段往下点。

祝面试顺利。


本文为「AI Infra 工程师面经(305 题版)」漫游导读,所有链接指向本仓库内对应题目的 Markdown 文章。

01-PyTorch底层/README.md

01-PyTorch底层(第 1–15 题)

题号 主题 文章
1 PyTorch的Autograd机制是如何实现的?解释`torch.au… 001-PyTorch的Autograd机制是如何实现的.md
2 torch.nn.Module__call__和`forwar… 002-torch.nn.Module的__call__和forward有什么区别.md
3 PyTorch的Dispatch机制是什么?ATenc10、`… 003-PyTorch的Dispatch机制是什么.md
4 如何实现一个自定义的CUDA算子并在PyTorch中调用?详细步骤是什么… 004-如何实现一个自定义的CUDA算子并在PyTorch中调用.md
5 PyTorch的内存池管理(Caching Allocator)策略是什… 005-PyTorch的内存池管理(Caching-Allocator)策略是什么.md
6 torch.jit.tracetorch.jit.script 006-torch.jit.trace和torch.jit.script的区别.md
7 PyTorch的DataLoadernum_workers设置… 007-PyTorch的DataLoader中num_workers设置多少合适.md
8 解释PyTorch的torch.distributed中的DDP 008-解释PyTorch的torch.distributed中的DDP和FSDP的.md
9 PyTorch 2.0的torch.compile背后的技术栈是什么… 009-PyTorch-2.0的torch.compile背后的技术栈是什么.md
10 如何调试PyTorch的CUDA kernel launch失败?`CU… 010-如何调试PyTorch的CUDA-kernel-launch失败.md
11 PyTorch的hook机制有哪些?`forward_pre_hoo… 011-PyTorch的hook机制有哪些.md
12 如何实现模型的量化感知训练(QAT)?`torch.ao.quantiz… 012-如何实现模型的量化感知训练(QAT).md
13 PyTorch的checkpoint机制(梯度检查点)如何节省显存?… 013-PyTorch的checkpoint机制(梯度检查点)如何节省显存.md
14 解释torch.cuda.amp的自动混合精度训练,什么情况下`Gr… 014-解释torch.cuda.amp的自动混合精度训练,什么情况下GradSca.md
15 如何profile PyTorch模型的性能?`torch.profil… 015-如何profile-PyTorch模型的性能.md

返回总览

01-PyTorch底层/001-PyTorch的Autograd机制是如何实现的.md

第 1 题:PyTorch的Autograd机制是如何实现的?解释torch.autograd.Function的工作原理

题目

PyTorch的Autograd机制是如何实现的?解释torch.autograd.Function的工作原理


完整讲解

一、Autograd 在做什么?

Autograd 是 PyTorch 的自动求导引擎:根据前向计算自动构建计算图,在 backward() 时按图反传梯度,无需手写导数。核心思想:每个参与运算的 Tensorrequires_grad=True 时会被记录在图中,算子成为图的边;反向时从 loss 的 grad_fn 沿边回溯,对每个节点执行其 grad_fn 中定义的梯度公式。

为什么重要?loss.backward() 就能训练,背后是 DAG、动态图、按需求导;面试常问「和 TF 的静态图区别」——PyTorch 是 define-by-run,每次前向现建图,灵活但图优化空间小。


二、计算图与梯度传播

  • 计算图:节点 = Tensor(存 datagradgrad_fn),边 = 产生该 Tensor 的运算。grad_fn 指向创建该 Tensor 的 Function 节点,从而形成反向边。
  • 反向过程:从输出节点(如 loss)的 grad_fn 开始,调用 backward(grad_output);每个 Functionbackward 根据链式法则用上游梯度乘本地雅可比,得到输入的梯度并传给前驱节点;若某 Tensor 有多个后继,梯度会累加
  • 叶子节点:不由其它 Tensor 计算得到的(如 x = torch.tensor(..., requires_grad=True)),反向到叶子后停止;叶子梯度存在 .grad 里供优化器使用。

三、torch.autograd.Function 是什么?

Function 是 Autograd 中一个可微算子的抽象:既负责前向forward),又负责反向backward)。用户或 C++ 扩展实现一个子类,注册到 Autograd 后,前向时建图、反向时按你写的梯度公式算。

  • forward(ctx, *args):执行前向;需要给反向用的中间结果用 ctx.save_for_backward(*tensors) 存到 ctx;非 Tensor 用 ctx.xxx = ...
  • backward(ctx, grad_output):输入是输出端传下来的梯度,返回每个前向输入的梯度(个数、顺序与 forward 的输入一致);若某输入不需要梯度可返回 None
  • apply:通常用 MyFunc.apply(...) 调用,内部会建图并挂上 grad_fn,这样 backward 时才会被调用。

自定义算子(包括 C++/CUDA)若要参与自动求导,就要实现一个 Function,在 forward 里调你的 kernel,在 backward 里写梯度公式并再调一次梯度 kernel。


四、与 torch.nn.Module 的区别

  • Module:管理参数nn.Parameter)、子模块、设备;其 forward 里调用的算子才真正参与 Autograd(算子背后是各种 Function)。
  • Function:无参数、无状态(或仅用 ctx 传临时量),只描述「这一层前向+反向」;一个 Module 里可能调用很多个 Function。

面试可一句话区分:Module 管「有什么参数、怎么组织」,Function 管「这一步步前向怎么算、反向梯度怎么传」。


面试要点

  • Autograd 通过计算图(Tensor + grad_fn)在 backward 时按链式法则反传梯度;叶子节点存 .grad
  • torch.autograd.Function 定义可微算子:forward 建图并可选 ctx.save_for_backwardbackward 根据链式法则返回各输入梯度。
  • 自定义 CUDA 算子要参与训练时,需用 Function 包装:forward 调你的 kernel,backward 实现梯度并调梯度 kernel 或用 at:: 算子。
  • 能说清「动态图 define-by-run」和「反向时梯度累加」两个点。

记忆要点

  1. Autograd = 前向建 DAG(Tensor + grad_fn),backward 从 loss 沿图反传,梯度在分支处累加。
  2. Function = 一个可微算子:forward(ctx, *args) + backward(ctx, grad_output);用 apply 调用以挂上 grad_fn。
  3. 自定义带梯度的算子 = 实现 Function,forward 里调 kernel、backward 里写梯度公式。
  4. Module 管参数和结构,Function 管单步前向/反向;二者配合构成训练图。

返回模块 | 返回总览

01-PyTorch底层/002-torch.nn.Module的__call__和forward有什么区别.md

第 2 题:torch.nn.Module__call__forward有什么区别?为什么要这样设计?

题目

torch.nn.Module__call__forward有什么区别?为什么要这样设计?


完整讲解

一、调用链:你写的是 __call__,实际算的是 forward

用户写的是 model(x),Python 会调用 model.__call__(x)nn.Module__call__ 内部会做一堆前后处理,最后再调 self.forward(x)。所以:

  • __call__:入口,负责 hook、training 模式、类型转换、最终调用 forward 等,不要在子类里重写(除非你很清楚在做什么)。
  • forward:子类必须重写,这里写「输入到输出的计算逻辑」;真正参与计算图、被 Autograd 记录的是 forward 里的运算。

一句话:__call__ = 框架层壳子,forward = 你写的数学/计算。


二、__call__ 里通常做了哪些事?

(以常见 PyTorch 实现为准,细节可能随版本略有差异。)

  1. 多次 forward 检查:防止在已执行的 forward 里再次触发 forward(递归调用导致图错乱)。
  2. 调用 before / after forward hookforward_pre_hookforward_hook,便于调试、可视化、插层。
  3. 真正执行result = self.forward(*input, **kwargs)
  4. 类型与设备:有的封装会保证输入/输出类型一致、放到正确设备。

所以若子类重写 __call__ 而不调 forward,或改了调用顺序,hook 和 Autograd 都可能错乱;规范做法是只重写 forward


三、为什么要这样设计?

  • 职责分离__call__ 统一处理「所有 Module 都要做的事」(hook、模式、检查),forward 只关心「这一层怎么算」,代码清晰、扩展方便。
  • Hook 与扩展:框架在 __call__ 里固定了 hook 的调用时机,用户和第三方库只要注册 hook,不用改 forward;若逻辑写在 forward 里,每个子类都要记得调 hook,容易漏。
  • 兼容性与安全:将来若在 __call__ 里加新逻辑(如编译、图捕获),所有子类自动受益;若大家都重写 __call__,就难以统一升级。

面试可答:__call__ 是框架入口负责通用逻辑和 hook,forward 是子类实现的纯计算;这样 hook 和扩展都集中在入口,子类只写数学。


面试要点

  • 调用 model(x) 触发的是 __call__(x),内部再调 forward(x);不要重写 __call__,只重写 forward
  • __call__ 负责:重复调用检查、forward_pre_hook / forward_hook、调用 forward、以及可能的类型/设备处理。
  • 设计原因:职责分离(通用逻辑 vs 单层计算)、便于统一挂 hook、便于以后在入口加编译/图优化等。

记忆要点

  1. model(x)Module.__call__(x) → 做 hook 与检查 → self.forward(x)
  2. 子类只重写 forward;重写 __call__ 容易破坏 hook 与 Autograd。
  3. 设计目的:入口统一处理 hook 与扩展,子类只关心前向计算。

返回模块 | 返回总览

01-PyTorch底层/003-PyTorch的Dispatch机制是什么.md

第 3 题:PyTorch的Dispatch机制是什么?ATenc10torch.library分别负责什么?

题目

PyTorch的Dispatch机制是什么?ATenc10torch.library分别负责什么?


完整讲解

一、Dispatch 机制在解决什么问题?

同一个「逻辑算子」(比如 torch.add)在不同设备(CPU/CUDA)、不同数据类型(float/int)、不同后端(如 MPS、XLA)上要有不同实现。若在 Python 里写满 if-else,代码会爆炸且难以扩展。Dispatch 的作用:根据 tensor 的设备、dtype、layout 等,在运行时把一次调用派发到对应的 C++/CUDA 实现,对用户只暴露一个 torch.add 接口。


二、Dispatch 的层次(概念)

  1. Python 层torch.add(a, b) 等,多数会进 C++ 的 dispatch 表。
  2. Dispatch key:每个 Tensor 有一组「key」(如 CPUCUDAAutogradAutocast 等),按优先级选一个 key,再根据 key 找到已注册的 kernel(实现体)。
  3. Kernel 注册:某 (算子名, dispatch_key) 对应一个 kernel;例如 addCUDA key 下注册了 CUDA 实现,在 CPU 下注册了 CPU 实现。反向时还有 Autograd key 下的梯度实现。

这样,加新设备或新 dtype 只需注册新 kernel,不必改所有调用方。


三、ATen 是什么?

ATen(A Tensor Library) 是 PyTorch 的核心 C++ 张量运算库:绝大多数「数学算子」的实现都在这里(CPU 与 CUDA)。你用的 torch.addtorch.mm、conv2d 等,在 C++ 侧大多是 ATen 里的函数。ATen 本身会参与 dispatch:例如根据 device 选 CPU 或 CUDA 的 kernel。可以粗略理解为:ATen = PyTorch 的算子实现集合 + 与 dispatch 的对接


四、c10 是什么?

c10(Caffe2 的「10」)是 PyTorch 的底层基础设施库,和 ATen 并列/被 ATen 依赖,提供:

  • Tensor 核心数据结构:存储、shape、stride、device、dtype 等;
  • Device、Dtype、Layout 等抽象:dispatch 时用的「key」和类型信息来自这里;
  • 多线程与同步:如 c10::optional、线程安全设施;
  • Dispatch 机制本身:dispatch key 的定义、kernel 注册表、调用链(如 Dispatcher::call)等。

所以:c10 = 张量基础类型 + 设备/类型抽象 + dispatch 机制;ATen = 建在 c10 之上的算子实现。


五、torch.library 是什么?

torch.library 是 PyTorch 提供的在 Python/C++ 中注册自定义算子并接入现有 dispatch 体系的 API。你可以:

  • torch.library.define() 等定义新算子名;
  • 为不同 dispatch key(如 CPUCUDA)注册 impl
  • 可选地注册 autograd 实现或用 torch.library.autograd 相关 API 挂上反向。

这样自定义算子可以和 torch.add 一样参与设备派发、自动求导、torch.compile 等,而不必改 ATen/c10 源码。一句话:torch.library = 扩展算子并接入 PyTorch dispatch 与 autograd 的官方方式。


面试要点

  • Dispatch = 按 tensor 的 device/dtype 等在运行时把调用派发到对应 kernel,避免 Python 里写满 if-else。
  • ATen = 核心 C++ 张量算子库(CPU/CUDA 实现);c10 = 张量结构、Device/Dtype、以及 dispatch 机制本身;ATen 建在 c10 之上。
  • torch.library = 注册自定义算子并接入 dispatch(及 autograd)的官方扩展方式。

记忆要点

  1. Dispatch:按 device/dtype 等 key 选 kernel,一次接口多套实现。
  2. ATen = 算子实现(CPU/CUDA);c10 = Tensor 基础 + 类型/设备抽象 + dispatch 机制。
  3. torch.library = 自定义算子注册到 dispatch(和 autograd)的官方入口。

返回模块 | 返回总览

01-PyTorch底层/004-如何实现一个自定义的CUDA算子并在PyTorch中调用.md

第 4 题:如何实现一个自定义的CUDA算子并在PyTorch中调用?详细步骤是什么?

题目

如何实现一个自定义的CUDA算子并在PyTorch中调用?详细步骤是什么?


完整讲解

一、整体流程概览

要在 PyTorch 里用上自定义 CUDA 算子,通常需要:① 写 CUDA kernel② 用 C++/pybind11 或 torch.library 做绑定并注册③ 可选:实现 autograd 的 backward。下面按「手写 C++ 扩展 + pybind11」和「torch.library」两条路说。


二、路线 A:C++ 扩展 + pybind11 + setuptools

  1. 写 CUDA kernel.cu):实现 __global__ kernel,例如 my_kernel<<<grid, block>>>(...)
  2. 写 C++ 桥接.cpp):用 ATen API 取 tensor 的 data_ptr、shape,分配输出,调 CUDA kernel(通过 cudaLaunchKernel 或把 kernel 包成函数指针);处理 stream、device。
  3. pybind11 绑定:在 C++ 里 m.def("my_op", &my_op_impl, "my op");,把函数暴露给 Python。
  4. setuptools 编译:用 torch.utils.cpp_extension.loadload_inline,或写 setup.pyCUDAExtension,编译生成 .so
  5. Python 调用import torch; from my_extension import my_op; y = my_op(x)
  6. 若要参与训练:在 Python 侧用 torch.autograd.Function 包一层,forward 里调 my_opbackward 里写梯度公式并再调梯度 kernel 或 ATen 算子。

三、路线 B:torch.library(PyTorch 官方推荐方式)

  1. 写 CUDA kernel:同上,或先用 Triton 写再在 C++ 里调。
  2. 在 C++ 里用 torch.library 注册(或纯 Python 用 torch.library.define + impl):
    - 定义算子名:TORCH_LIBRARY_IMPL(..., CUDA, m) { m.impl("my_op", my_op_cuda_impl); }
    - 实现 my_op_cuda_impl:取 tensor、调你的 kernel、返回结果。
  3. Python 侧torch.ops.xxx.my_op(...) 或先 load_library("lib.so") 再调;若需 autograd,用 torch.library.autograd 或自定义 autograd.Function 包一层。
  4. 编译:用 torch.utils.cpp_extension.load 或 CMake 生成带 CUDA 的 so,在 Python 里 load_library 加载。

这样算子会走 PyTorch 的 dispatch,和内置 op 一样参与设备选择、torch.compile 等。


四、关键注意点

  • 设备与 stream:在实现里用 tensor.device()at::cuda::getCurrentCUDAStream() 等,保证在正确的 GPU 上、正确的 stream 上执行。
  • 梯度:若只做推理,可不实现 backward;若训练,必须提供梯度(自定义 backward kernel 或用 ATen 组合)。
  • 数据类型与 shape:C++ 里用 tensor.scalar_type()tensor.sizes() 做校验与分支;支持多 dtype 时可模板化或按 dtype 分派。

面试要点

  • 步骤概括:CUDA kernel → C++ 桥接(ATen 取指针、调 kernel)→ pybind11 或 torch.library 暴露 → 编译成 so → Python 调用;要训练再包一层 autograd.Function。
  • torch.library 是官方推荐的扩展方式,算子会进 dispatch 体系;C++ 扩展 + pybind11 是传统方式,灵活但需自己管设备/stream。
  • 能说清「forward 调我的 kernel、backward 写梯度并调梯度 kernel 或 ATen」即可。

记忆要点

  1. 自定义 CUDA 算子 = CUDA kernel + C++ 桥接(ATen)+ 暴露(pybind11 或 torch.library)+ 编译 so;要 autograd 则用 Function 包装。
  2. torch.library 注册后走 dispatch,和内置 op 一致;传统方式用 cpp_extension + pybind11。
  3. 注意 device、stream、dtype/shape 与梯度实现。

返回模块 | 返回总览

01-PyTorch底层/005-PyTorch的内存池管理(Caching-Allocator)策略是什么.md

第 5 题:PyTorch的内存池管理(Caching Allocator)策略是什么?如何分析和优化显存碎片?

题目

PyTorch的内存池管理(Caching Allocator)策略是什么?如何分析和优化显存碎片?


完整讲解

一、Caching Allocator 在做什么?

PyTorch 的 CUDA 内存分配不是每次 malloc 都向 CUDA driver 要一块新显存,而是用缓存分配器:向 driver 申请大块(如 2MB 的 block),再按请求大小切成块还给用户;用户 free 时块不立刻还給 driver,而是放进进程内缓存池,下次相同或更小尺寸的请求可直接从池里拿,减少 cudaMalloc/cudaFree 调用(这两者很慢且易产生碎片)。


二、策略要点

  • Block 与 size class:分配器维护多种「块大小」的池;请求会 round 到某 size class,从对应空闲链表取块;没有则向 driver 要新的大块再切。
  • 缓存与释放:释放的块回收到池里;当「空闲块总显存」超过一定阈值时,会把部分块真正 cudaFree 还给 driver,避免进程长期占着不用。
  • Stream 关联:为减少同步,分配器会按 CUDA stream 区分缓存(同一 stream 上 free 的块优先复用于该 stream 的 alloc),避免跨 stream 复用导致隐式同步。

三、显存碎片从哪来?

  • 外部碎片:多次 alloc/free 后,空闲块不连续,总空闲够但单块不够大,无法满足一次大 alloc。
  • 内部碎片:round 到 size class 后,实际只用了一部分,剩余浪费。
  • 峰值与释放顺序:若先分配大块、再分配很多小块,大块释放后可能被切成小块用掉,后面再要「一大块」就没了,表现为「显存占用不高但 OOM」。

四、如何分析?

  • torch.cuda.memory_summary() / torch.cuda.memory_stats():看 allocated、cached、reserved 等;cached 大说明分配器持有很多未还給 driver 的块。
  • torch.profiler 的 memory 选项:看时间线上 alloc/free 的分布,定位哪一步导致峰值或碎片。
  • Nsight Systems:看 GPU 时间线旁的内存占用曲线,结合 kernel 发射判断是否因碎片导致大块分配失败。
  • 经验:若「nvidia-smi 显存不大但 PyTorch 报 OOM」,多半是碎片或分配器缓存策略导致「逻辑上」没有连续大块。

五、如何优化?

  • 减少不必要的中间大 tensor:用 inplace、view、及时 del 大变量,让大块尽早释放、复用时序更可控。
  • 梯度 checkpoint:用激活重计算换显存,降低峰值激活占用,间接缓解碎片。
  • 避免频繁小块 alloc/free:如循环里反复创建临时小 tensor,可尽量复用 buffer。
  • torch.cuda.empty_cache():把当前未用的缓存块还给 driver,能缓解「缓存占满」但可能带来后续 alloc 变慢;不能根治碎片,且不宜在训练循环里频繁调。
  • 换更大 batch 或调小模型:降低单次大块需求,有时能「绕过」当前碎片分布。

面试要点

  • Caching Allocator:向 driver 要大块再切分、free 后回收到池、按 stream 缓存,减少 cudaMalloc/Free 次数。
  • 碎片:外部(空闲不连续)、内部(size class 取整浪费)、释放顺序导致「看似够用却 OOM」;用 memory_summary、profiler、Nsight 分析。
  • 优化:减少中间大 tensor、checkpoint、少频繁小块分配、必要时 empty_cache;不能依赖 empty_cache 治本。

记忆要点

  1. 缓存分配器 = 大块申请 → 按 size class 切分与复用;free 回池,超阈值才 cudaFree。
  2. 碎片 = 外部(不连续)+ 内部(取整)+ 释放顺序;分析用 memory_summary、profiler、Nsight。
  3. 优化 = 降峰值(checkpoint、inplace)、少频繁小块、慎用 empty_cache。

返回模块 | 返回总览

01-PyTorch底层/006-torch.jit.trace和torch.jit.script的区别.md

第 6 题:torch.jit.tracetorch.jit.script的区别?什么情况下会失败?

题目

torch.jit.tracetorch.jit.script的区别?什么情况下会失败?


完整讲解

一、Trace 和 Script 各自在干什么?

  • torch.jit.trace:用一组具体输入跑一遍你的 model.forward,把实际执行到的算子序列录成一张静态图;控制流(if/for)会按「这一轮输入」走的分支被固化成图,不会出现「另一条分支」。输出是 TorchScript 图,可序列化、在 C++ 里跑、做算子融合等。
  • torch.jit.script不跑模型,而是把 Python 源码(函数或 Module)解析、编译成 TorchScript 的 IR;if/for 会变成图里的控制流节点,运行时按条件走不同分支。适合控制流多、依赖输入动态变化的逻辑。

一句话:trace = 用一次运行「拍快照」;script = 把代码「翻译」成图。


二、主要区别

维度 trace script
输入 需要示例输入,跑一遍 不需要运行,解析源码
控制流 固化为当时走的那条分支 保留 if/for,图中有控制流
数据相关 与示例输入绑死(如 shape 固定) 可写动态 shape、动态分支
Python 特性 只保留执行到的代码 受限支持(见下),部分不支持

三、Trace 什么时候会失败或不对?

  • 控制流依赖数据:如 if x.sum() > 0: ... else: ...,trace 只录当前输入走的那条分支,换输入可能逻辑错。
  • 动态 shape:trace 时若 shape 固定,图里会写死;换 batch/seq 长可能错或要重新 trace。
  • 未执行到的代码:某分支没被示例输入走到,就不会出现在图里,部署时若走到该分支会缺算子或行为不符。
  • 非 Tensor 或复杂 Python:部分 Python 对象、反射、eval 等无法被记录进图。

四、Script 什么时候会失败?

  • 不支持的 Python 语法:如部分动态类型、任意 list/dict 操作、字符串操作、反射、open/文件等,TorchScript 的 Python 子集不支持就会报错。
  • 类型推断失败:Script 需要能推断 tensor 类型和 shape;若推断不出或类型不一致会失败。
  • 调用了非 script 的代码:若函数里调了没被 @torch.jit.script 的 Python 函数或第三方库,通常无法 script。

五、实践建议

  • 控制流少、shape 较固定、想快速得到一张图:用 trace;注意用有代表性的输入,并检查不同输入是否仍符合预期。
  • 控制流多、依赖输入动态分支:用 scripttrace + script 混合(如部分子模块 script,再 trace 整体);script 不通过时再考虑重写为 TorchScript 支持的写法。
  • PyTorch 2.0 后很多场景用 torch.compile 替代 JIT,但 trace/script 仍用于导出 ONNX、LibTorch 部署等,面试可提「trace 适合静态、script 适合动态控制流」。

面试要点

  • trace = 用示例输入跑一遍,录成静态图;控制流和 shape 易被固化为那一轮;script = 解析源码成图,保留 if/for。
  • trace 失败/不对:数据相关分支、动态 shape、未执行到的代码;script 失败:不支持的 Python 语法、类型推断失败、调了非 script 代码。
  • 选型:静态/少分支用 trace;多控制流用 script 或混合。

记忆要点

  1. trace:跑一次录图,控制流和 shape 绑死示例输入;script:解析源码,图里带控制流。
  2. trace 坑:数据相关 if、动态 shape、未走到分支;script 坑:语法/类型/非 script 调用。
  3. 静态场景 trace,动态分支 script;部署/ONNX 仍常用 trace。

返回模块 | 返回总览

01-PyTorch底层/007-PyTorch的DataLoader中num_workers设置多少合适.md

第 7 题:PyTorch的DataLoadernum_workers设置多少合适?遇到过too many open files吗?

题目

PyTorch的DataLoadernum_workers设置多少合适?遇到过too many open files吗?


完整讲解

一、num_workers 在干什么?

num_workers > 0 时,DataLoader 会起多个子进程,每个进程负责从 dataset 里取样本、做 collate、放到队列里;主进程只从队列里取 batch。目的是把数据加载和预处理GPU 计算并行,避免 GPU 等数据(数据瓶颈)。workers 越多,理论上吞吐越高,但进程数多了会占 CPU/内存、增加 IPC 和打开文件数。


二、设多少合适?

  • 经验值:常用 4、8、16;可先设成 CPU 物理核数或略小(如 8 核设 4–8),再根据 GPU 利用率和 dataloader 的 num_workers 对吞吐的影响做微调。
  • 原则:若 nvidia-smi 里 GPU 利用率长期偏低、且不是模型太小,多半是数据跟不上,可适当加大 num_workers;若 CPU 或 I/O 已经打满,再加 workers 收益不大,反而可能因上下文切换或内存变慢。
  • batch 大时:每个 batch 要准备的数据多,可适当多开几个 workers;但 workers 数 × 每进程打开文件/内存要小于系统限制(见下)。

三、too many open files 从哪来?

每个 worker 进程会打开数据文件(如每张图一个 fd、或每个 shard 一个 fd)、可能还有 pipe/socket(和主进程通信)。打开文件数 = 进程数 × 每进程打开文件数,超过系统 ulimit(open files) 就会报 too many open files(或 OSError 类似错误)。

常见场景:num_workers 较大 + 每个 sample 打开一个文件(如每张图一个文件)、或 dataset 里没及时 close、或系统默认 ulimit 较小(如 1024)。


四、怎么解决?

  • 临时提高 ulimitulimit -n 65535(或更大),只对当前 shell 及子进程有效。
  • 永久提高:在 /etc/security/limits.conf 或 systemd 的 service 里设 nofile,然后重新登录或重启服务。
  • 减少每进程打开数:数据用大文件 + 偏移读取(如 TFRecord、WebDataset 的 tar、数据库)而不是「一个 sample 一个文件」;或在 dataset 的 __getitem__用完即 close,不要长期持有 fd。
  • 适当减小 num_workers:在满足吞吐的前提下减小,使 workers × 每进程 fd 数 < ulimit。

面试要点

  • num_workers:子进程数,用于数据加载与 GPU 并行;建议从 CPU 核数附近起调(如 4–8),看 GPU 利用率与吞吐再调。
  • too many open files:进程打开 fd 总数超过 ulimit;多因 num_workers 大 + 每 sample 一文件或未及时 close。
  • 解决:提高 ulimit、改用大文件/流式读取、保证用完 close、或适当减 num_workers。

记忆要点

  1. num_workers = 数据加载子进程数;一般 4–8 起步,按 GPU 利用率和 CPU 负载调。
  2. too many open files = 打开 fd 数 > ulimit;常为 workers 多 + 每 sample 一文件。
  3. 解决:ulimit -n、大文件/流式、及时 close、或减 workers。

返回模块 | 返回总览

01-PyTorch底层/008-解释PyTorch的torch.distributed中的DDP和FSDP的.md

第 8 题:解释PyTorch的torch.distributed中的DDPFSDP的区别

题目

解释PyTorch的torch.distributed中的DDPFSDP的区别


完整讲解

一、DDP(DistributedDataParallel)在做什么?

DDP数据并行:每张卡上有一份完整模型,每轮各卡用不同数据算 forward 和 backward;backward 结束后,各卡上的梯度要同步(通常 all-reduce),再在本卡用同一份梯度更新参数,所以每卡参数始终保持一致。显存占用 ≈ 单卡模型 + 单卡激活 + 梯度,模型必须能放进单卡。


二、FSDP(Fully Sharded Data Parallel)在做什么?

FSDP分片数据并行:把模型参数、梯度、有时还有优化器状态按卡分片,每张卡只存 1/N(N=卡数);forward 时用 all-gather 把当前层所需参数临时拼起来算,算完丢掉;backward 同样 all-gather → 算梯度 → reduce-scatter 把梯度按片回写。这样单卡显存 ≈ 1/N 模型 + 当前层激活,可以训「单卡放不下」的大模型。


三、核心区别对比

维度 DDP FSDP
参数存储 每卡一份完整模型 每卡 1/N 参数(分片)
梯度 每卡一份完整梯度,all-reduce 分片,reduce-scatter 写回
优化器状态 每卡一份完整 可只存本卡分片(显存再省)
单卡显存 约 1× 模型 + 激活 + 梯度 约 1/N 模型 + 激活(可训大模型)
通信 backward 后梯度 all-reduce 每层 forward/backward 的 all-gather/reduce-scatter
典型场景 模型能放进单卡、多卡加速 模型太大单卡放不下、大模型训练

四、为什么需要 FSDP?

当模型参数量大(如数十 B、上百 B),即使用上梯度 checkpoint,单卡也存不下「完整参数 + 梯度 + 优化器」。FSDP 用分片换通信:每次只 all-gather 当前层需要的参数,算完就丢,所以显存从「整模型」变成「1/N 模型 + 当前层激活」,能显著扩大可训模型规模;代价是每层多一次 all-gather/reduce-scatter,通信量比 DDP 的「一次梯度 all-reduce」大,需要好的通信和 overlap 设计。


五、面试可怎么说?

  • DDP:每卡完整模型、不同数据、梯度 all-reduce 后一致更新;适合模型能塞进单卡、追求训练速度。
  • FSDP:参数(及可选梯度/优化器)分片,按层 all-gather 算、reduce-scatter 回写;显存约 1/N,能训大模型;通信更复杂、每层有集合通信。
  • 选型:单卡能放下用 DDP;放不下或要省显存用 FSDP(或与 ZeRO 等结合)。

面试要点

  • DDP:完整模型每卡、数据并行、梯度 all-reduce;显存 ≈ 单卡模型+激活+梯度。
  • FSDP:参数(及可选梯度和优化器)分片,forward/backward 时 all-gather 用、reduce-scatter 回;显存约 1/N,可训大模型;通信为每层 all-gather + reduce-scatter。
  • 区别:存储方式(完整 vs 分片)、显存规模、通信模式与量。

记忆要点

  1. DDP = 数据并行 + 每卡完整模型 + 梯度 all-reduce;单卡能放下模型时用。
  2. FSDP = 参数分片 + 按层 all-gather/reduce-scatter;单卡放不下或要省显存时用。
  3. FSDP 显存约 1/N,通信量和次数比 DDP 多;两者可和 ZeRO、混合精度等组合用。

返回模块 | 返回总览

01-PyTorch底层/009-PyTorch-2.0的torch.compile背后的技术栈是什么.md

第 9 题:PyTorch 2.0的torch.compile背后的技术栈是什么?TorchDynamoAOTAutogradInductor分别做什么?

题目

PyTorch 2.0的torch.compile背后的技术栈是什么?TorchDynamoAOTAutogradInductor分别做什么?


完整讲解

一、torch.compile 的目标

torch.compile 把 Python 里「eager 执行」的 PyTorch 代码编译成更高效的图/内核:减少 Python 开销、做算子融合、利用 Triton/其他后端生成更快 kernel,从而在不改模型代码的前提下提速。整体流水线可以概括为:捕获图 → 处理 autograd → lowering 到后端代码生成


二、TorchDynamo:把 Python 转成 FX 图

TorchDynamo 负责「怎么把动态的 PyTorch 执行变成一张图」。它不重写 Python 解释器,而是用 CPython 的 frame 与 bytecode,在每帧执行前做一次检查(guard):若这次执行的「关键状态」(如 tensor 的 shape、dtype、device)和上次一样,就复用已编译的图;否则重新捕获。捕获到的是一串 ATen 算子,再转成 FX IR(PyTorch 的图表示),交给下游。这样既保留 Python 的灵活(控制流、动态 shape 可多次编译),又能在「稳定」的路径上得到静态图做优化。一句话:Dynamo = 通过 guard 和帧捕获,把 PyTorch 执行录成 FX 图。


三、AOTAutograd:提前(AOT)做 Autograd

AOTAutograd(Ahead-of-Time Autograd)在「已得到的 FX 图」上,提前把反向传播也变成图:根据前向图自动生成对应的梯度计算图(backward graph),并和 forward 一起交给后端。这样编译期就能对「整段 forward + backward」做融合、重排、内存规划等,而不是在 Python 里每次 backward 再解释执行。一句话:AOTAutograd = 对捕获的前向图做自动求导,得到完整 forward+backward 图供后端编译。


四、Inductor:图到可执行代码

Inductor 是 PyTorch 2.0 的默认代码生成后端:接收 FX 图(通常已是 forward+backward),做算子融合、循环优化、内存规划等,最后生成 Triton 或 C++/OpenMP 代码并编译成 so,在运行时调用。这样很多小算子会被融合成少量 kernel,减少 launch 和内存读写,提升 GPU 利用率。一句话:Inductor = 把 FX 图 lower 成 Triton/C++ 等,做融合与调度,生成实际跑的 kernel。


五、整体串联

用户调用 torch.compile(model) 后,一次 forward 的大致流程是:

  1. TorchDynamo:在 Python 执行时 guard + 捕获,得到 ATen 序列 → FX 图。
  2. AOTAutograd:对 FX 前向图做 AOT 求导,得到 forward+backward 的 FX 图。
  3. Inductor:对 FX 图做融合与 lowering,生成 Triton(或其它后端)代码并编译。
  4. 后续在「guard 通过」时直接跑编译好的 kernel,不再走 Python 逐 op 执行。

所以面试可以答:Dynamo 负责「把 PyTorch 执行录成图」,AOTAutograd 负责「把 backward 也变成图」,Inductor 负责「把图编译成高性能 kernel」。


面试要点

  • torch.compile 流水线:图捕获 → AOT 求导 → 后端代码生成。
  • TorchDynamo:用 guard + 帧捕获把 PyTorch 执行录成 FX 图,支持动态与重编译。
  • AOTAutograd:对前向 FX 图自动生成反向图,得到完整 forward+backward 供编译。
  • Inductor:FX 图做融合与 lowering,生成 Triton/C++ 等 kernel,是默认后端。

记忆要点

  1. Dynamo = 捕获执行成 FX 图(guard + 帧);AOTAutograd = 前向图 → 前向+反向图;Inductor = 图 → Triton/C++ kernel。
  2. 三者分工:谁录图、谁算梯度图、谁生成代码。
  3. 效果:减 Python 开销、算子融合、更好 GPU 利用;动态 shape 会触发重编译。

返回模块 | 返回总览

01-PyTorch底层/010-如何调试PyTorch的CUDA-kernel-launch失败.md

第 10 题:如何调试PyTorch的CUDA kernel launch失败?CUDA_LAUNCH_BLOCKING=1的原理?

题目

如何调试PyTorch的CUDA kernel launch失败?CUDA_LAUNCH_BLOCKING=1的原理?


完整讲解

一、CUDA kernel「launch 失败」常见原因

  • 显存不足:分配失败或碎片导致大块分配不到。
  • 参数错误:grid/block 维度不合法(如 0、超过硬件限制)、shared memory 超限。
  • 异步性:默认 kernel 是异步发射的,报错可能出现在后面某次 sync 时,堆栈指向 sync 而不是真正出错的 kernel,难以定位。
  • 设备不匹配:在错误 device 上 launch 或 pointer 指向错误设备内存。

二、CUDA_LAUNCH_BLOCKING=1 在干什么?

设置环境变量 CUDA_LAUNCH_BLOCKING=1 后,每次 kernel launch 都会变成同步:driver 会等这个 kernel 执行完再返回,且一旦 kernel 内部出错,报错会立刻发生在对应的 launch 调用处,而不是等到后面的 cudaDeviceSynchronize() 或下一次同步点。这样:

  • 堆栈会指向真正触发错误的那个 API 调用(如某次 tensor.add_ 或自定义 kernel)。
  • 顺序与代码顺序一致,不会因为异步执行而「错位」。

代价是 GPU 和 CPU 无法并行,整体变慢,所以只用于调试,生产环境不要开。


三、调试步骤建议

  1. 先开 CUDA_LAUNCH_BLOCKING=1export CUDA_LAUNCH_BLOCKING=1(或 Windows 下在环境变量里设),再跑,看报错堆栈指向哪一行、哪个 op。
  2. 看完整错误信息:CUDA 会报 error code(如 invalid configuration、out of memory);对照文档判断是显存、配置还是设备问题。
  3. 缩小范围:若报错指向某一大段,可注释掉部分代码或减小 batch/shape,确认是哪个 tensor 或哪次 launch 导致。
  4. 显存:用 torch.cuda.memory_summary()nvidia-smi 看是否 OOM 或碎片;可先减小模型/ batch 验证。
  5. 自定义 kernel:检查 grid/block、shared memory、是否在正确 device;用 cuda-memcheck 或 compute-sanitizer 查越界和非法访问。

四、其他常用手段

  • CUDA_LAUNCH_BLOCKING=1:同步 launch,精确定位出错 kernel(如上)。
  • TORCH_SHOW_CPP_STACKTRACES=1:让 PyTorch 打印 C++ 堆栈,便于看到是哪个 ATen op。
  • cuda-gdb / Nsight Compute:单步调试或 profile 某个 kernel,看寄存器、shared memory、越界。
  • compute-sanitizer:查内存越界、未初始化等。

面试要点

  • CUDA 默认异步 launch,错误可能延迟到后面 sync 才报,堆栈不对应真正出错的 kernel。
  • CUDA_LAUNCH_BLOCKING=1:每次 launch 同步执行,错误立刻报在对应 launch 处,便于定位;会丧失 CPU-GPU 并行,仅调试用。
  • 调试流程:开 blocking → 看堆栈和 error code → 缩范围、查显存/配置/自定义 kernel 参数。

记忆要点

  1. launch 失败常见:OOM、grid/block 非法、异步导致报错位置滞后。
  2. CUDA_LAUNCH_BLOCKING=1 = 同步 launch,错误立刻落在正确调用点;仅调试用。
  3. 配合 TORCH_SHOW_CPP_STACKTRACES、memory_summary、cuda-gdb 等缩小范围。

返回模块 | 返回总览

01-PyTorch底层/011-PyTorch的hook机制有哪些.md

第 11 题:PyTorch的hook机制有哪些?forward_pre_hookbackward_hook的应用场景?

题目

PyTorch的hook机制有哪些?forward_pre_hookbackward_hook的应用场景?


完整讲解

一、Hook 有哪些?

  • forward_pre_hook:在某一层的 forward 被调用之前 执行;签名 hook(module, input),可修改或查看输入,再交给该层 forward。
  • forward_hook:在该层 forward 被调用之后 执行;签名 hook(module, input, output),可查看或替换输出
  • backward_hook:在该层 backward 时 执行(即梯度反传到这一层时);签名 hook(module, grad_input, grad_output),可查看或修改梯度(grad_output 是上一层传下来的,grad_input 是传给再上一层的)。

前两个在 Module 上注册(module.register_forward_pre_hook(...) 等),backward_hook 同样在 Module 上注册,在反向传播经过该 module 时被调用。


二、forward_pre_hook 能干什么?

  • 改输入:例如做输入归一化、插入噪声(对抗训练)、把输入转到另一设备。
  • 调试与可视化:打印每层输入的 shape、范围、是否有 NaN;或把中间结果导出做可视化。
  • 插层 / 条件计算:根据输入决定是否执行该层、或插入额外计算(注意返回值格式要符合下一层预期)。

典型场景:调试时看某一层入口的 tensor 长什么样、是否数值异常;或在做输入预处理/增强时统一在某一层前做。


三、forward_hook 能干什么?

  • 取中间特征:做特征可视化、CAM、或把某几层的输出当「特征」喂给下游任务(如蒸馏、多任务头)。
  • 改输出:例如做输出归一化、dropout 式 mask、或替换成自己算的结果(如替换 attention 输出做分析)。
  • 记录激活:为激活重计算、显存分析、或离线分析记录每层输出(注意显存,大模型可只记 shape 或采样)。

典型场景:可视化某层特征图、做知识蒸馏时取教师中间层输出、或做剪枝/敏感度分析时记录每层输出。


四、backward_hook 能干什么?

  • 梯度检查与可视化:看某层收到的梯度(grad_output)和传出的梯度(grad_input),查梯度消失/爆炸、是否某层梯度为 0。
  • 梯度修改:如梯度裁剪(在 hook 里 clamp)、梯度噪声、或自定义的梯度重加权(如某通道乘一个系数)。
  • 敏感度与剪枝:根据梯度大小判断参数/通道重要性,用于剪枝或 NAS。

典型场景:调试「某层不更新」时看该层梯度是否为空或过小;或实现 per-layer 梯度缩放/裁剪。


五、使用注意

  • Hook 里不要做耗时或阻塞操作,否则会拖慢训练;记录到列表再在别处处理更安全。
  • 修改 tensor 时注意 inplace 与计算图:若在 forward_hook 里改 output,要保证不破坏 backward 需要的图;backward_hook 里改梯度要保证形状一致。
  • full_backward_hook 的 API(PyTorch 新版本)在 pack 的输入下行为更一致,旧版 backward_hook 在 pack 时可能有 tuple 拆包问题,需看文档。

面试要点

  • 三种 hook:forward_pre_hook(forward 前,改/看输入)、forward_hook(forward 后,改/看输出)、backward_hook(反向时,改/看梯度)。
  • 应用:pre = 输入预处理、调试;forward = 特征可视化、蒸馏、记录激活;backward = 梯度检查、裁剪、敏感度分析。
  • 注意:别在 hook 里做重活、改 tensor 别破坏图/形状。

记忆要点

  1. forward_pre_hook:入口,改/看输入;forward_hook:出口,改/看输出;backward_hook:反向,改/看梯度。
  2. 应用:调试、可视化、蒸馏、梯度检查与修改、剪枝敏感度。
  3. 只做轻量操作;改 tensor 注意图和形状。

返回模块 | 返回总览

01-PyTorch底层/012-如何实现模型的量化感知训练(QAT).md

第 12 题:如何实现模型的量化感知训练(QAT)?torch.ao.quantization的workflow是什么?

题目

如何实现模型的量化感知训练(QAT)?torch.ao.quantization的workflow是什么?


完整讲解

一、QAT 在做什么?

量化感知训练(QAT):在训练阶段就模拟量化(float → 量化再反量化),让权重和激活在「舍入 + 缩放」的误差下更新,这样训出的模型在真正部署成 INT8 时精度损失更小。和 PTQ(训练后量化) 的区别是:PTQ 不训练、只校准;QAT 会反向传播、更新参数,专门适应量化误差。


二、核心组件(torch.ao.quantization)

  • QuantStub / DeQuantStub:在模型入口放 QuantStub、出口放 DeQuantStub,表示「从这里开始模拟量化」「到这里结束模拟量化」;推理时会被替换成真实 quantize/dequantize。
  • QConfig:描述「用什么量化配置」:如 activationMinMaxObserver 还是 MovingAverageMinMaxObserverweight 用 per-channel 还是 per-tensor、dtype 选 qint8 等;通过 torch.ao.quantization.get_default_qconfig('qnnpack') 或自定义。
  • prepare_qat:把 float 的 Module 改成「QAT 模式」:在 Conv/Linear 等前后插入 fake quantize 模块(前向时做 round+scale 模拟量化,但用 float 算,梯度可传),并挂上 observer 收集 min/max 等统计量。
  • 训练:正常 forward/backward,梯度会穿过 fake quantize;observer 会更新 running min/max(若用 moving average)。
  • convert:训练完后 convert(model),把 fake quantize 和 observer 换成真实的 quantize / dequantize / packed params(如 int8 权重的 Linear),得到可部署的量化模型。

三、典型 workflow(PyTorch 官方风格)

  1. 定义 float 模型,在入口/出口加 QuantStub()DeQuantStub()(若用 eager 模式)。
  2. 设 qconfigmodel.qconfig = get_default_qconfig('qnnpack')(或 'fbgemm' for server)。
  3. prepare_qatmodel_prepared = prepare_qat(model, inplace=False),得到带 fake quant 和 observer 的模型。
  4. 训练若干 epoch:正常 loss.backward() 等,observer 会更新。
  5. 转成推理量化模型model_prepared.eval()model_quantized = convert(model_prepared),得到真正 int8 的模型,可保存、在 C++/ONNX 里用。

(若用 FX Graph Mode,则用 prepare_qat_fxconvert_fx,不依赖 Stub,按图自动插入 fake quant。)


四、要点小结

  • Fake quantize:前向 = 量化再反量化(round + scale),用 float 算,所以能求导;这样 loss 会感受到量化误差并更新参数。
  • Observer:在 QAT 里顺带统计 min/max(或直方图),convert 时用这些统计量确定 scale/zero_point;QAT 常用 moving average,避免初期统计抖动。
  • Per-channel / per-tensor:权重常用 per-channel 减轻通道间分布差异;激活常用 per-tensor 或 per-channel 视后端支持。

面试要点

  • QAT = 训练时用 fake quantize 模拟量化,让梯度在量化误差下更新;部署时 convert 成真实 int8。
  • workflow:float 模型 + qconfig → prepare_qat(插入 fake quant 和 observer)→ 训练 → convert 得到量化模型。
  • torch.ao.quantization:QuantStub/DeQuantStub、get_default_qconfig、prepare_qat、convert;FX 用 prepare_qat_fx/convert_fx。

记忆要点

  1. QAT = 训练阶段模拟量化(fake quant),反向传播适应量化误差;convert 后变真实 int8。
  2. 流程:qconfig → prepare_qat → 训练 → convert。
  3. Fake quant = 前向 round+scale 用 float 算可导;observer 收集统计量供 convert 用。

返回模块 | 返回总览

01-PyTorch底层/013-PyTorch的checkpoint机制(梯度检查点)如何节省显存.md

第 13 题:PyTorch的checkpoint机制(梯度检查点)如何节省显存?计算开销在哪里?

题目

PyTorch的checkpoint机制(梯度检查点)如何节省显存?计算开销在哪里?


完整讲解

一、为什么需要 checkpoint?

前向时,为了 backward 能算梯度,通常要把中间激活都存下来,显存占用 ≈ 与层数/序列长度成正比。大模型或长序列时,激活显存很容易成为瓶颈。梯度检查点(gradient checkpointing) 的思路是:前向时只存一部分激活(如每隔几层存一次),其余不存;反向时用到某段中间激活时,从最近的一个检查点重新算一遍那段前向,得到激活再算梯度。这样用重复计算显存


二、显存怎么省下来的?

  • 不 checkpoint:前向每一层的激活都保留,backward 时直接用;显存 ∝ 层数 × 每层激活大小。
  • Checkpoint:只保留「检查点」处的激活(如每 k 层一个),中间层的激活算完就丢;backward 到某层需要激活时,从上一个检查点重算到该层,得到激活后再继续反向。所以显存从「所有层」变成「检查点数量 × 单点激活 + 重算时的临时激活」,通常能降到原来的 1/√k 量级(k 为分段长度)或更好,取决于分段策略。

三、计算开销在哪里?

  • 多算一遍(或半遍)前向:反向时每两检查点之间的层要重新 forward 一次才能拿到激活,再 backward。所以总计算量 ≈ 1 次完整前向 + 1 次完整反向 + 若干次「分段前向」;分段越细,重算次数越多,训练变慢。
  • 典型 trade-off:若每 2 层一个检查点,显存约可减半,但 backward 时大约多算 0.5 次前向;若每 √L 层一个,显存可降到 O(√L) 量级,多算量也在 O(√L) 量级(L=层数)。所以 checkpoint 是「用时间换显存」

四、PyTorch 里怎么用?

  • torch.utils.checkpoint.checkpoint(fn, *args, **kwargs):把 fn 当成一个「块」:前向时只算一遍、不存中间激活(只保留 fn 的输入若需要);backward 时用 args 重新调用 fn 得到中间结果再反传。常用于把某一层或几层包起来:out = checkpoint(block, x)
  • checkpoint_sequential:对 nn.Sequential 的多个子模块分段做 checkpoint,每段一个检查点。
  • 自定义:大模型里常按「每 N 层」或「每个 transformer block」做 checkpoint,在 forward 里手动调用 checkpoint(block, x)

五、面试可怎么说?

  • 省显存:不存所有中间激活,只存检查点;反向时从检查点重算得到激活再反传,显存从 O(层数) 降到 O(检查点数) 量级。
  • 开销:反向时要多算若干次「分段前向」,训练变慢;是典型的用算力换显存
  • 用法checkpoint(fn, *args) 把 fn 包成一段,或对 Sequential 用 checkpoint_sequential,或在大模型里按 block 包。

面试要点

  • Checkpoint = 前向少存激活、只存检查点;反向时从检查点重算前向再反传,从而省显存。
  • 开销 = 反向阶段多算若干次分段前向,训练变慢;用计算换显存。
  • PyTorch:checkpoint(fn, *args)、checkpoint_sequential;大模型常按 block 或每 N 层包。

记忆要点

  1. 省显存:只存部分激活(检查点),其余反向时重算;显存从 O(L) 到 O(检查点数)。
  2. 开销:反向时多算分段前向,总计算量增加;trade-off 算力换显存。
  3. 使用:checkpoint(fn,...)、checkpoint_sequential 或按 block 包装。

返回模块 | 返回总览

01-PyTorch底层/014-解释torch.cuda.amp的自动混合精度训练,什么情况下GradSca.md

第 14 题:解释torch.cuda.amp的自动混合精度训练,什么情况下GradScaler会跳过参数更新?

题目

解释torch.cuda.amp的自动混合精度训练,什么情况下GradScaler会跳过参数更新?


完整讲解

一、混合精度(AMP)在做什么?

FP16 算前向和部分反向,可以省显存、提速(Tensor Core 等),但 FP16 范围小,容易出现梯度下溢(太小变成 0)。所以做法是:前向和梯度用 FP16 算,但梯度在更新前先乘一个 scale(放大),用 FP16 或 FP32 做累加/更新,再把 scale 除回去(unscale),这样小梯度不会被舍成 0;若发现梯度出现 inf/nan,就跳过本次更新并调整 scale,避免后续全崩。torch.cuda.amp 里的 GradScaler 就是管这个 scale 和「是否跳过 step」的。


二、GradScaler 的工作流程

  1. scale:在 backward 前对 loss 乘 scaler.get_scale(),这样链式法则后梯度整体被放大,减少 FP16 下溢。
  2. unscale:在 optimizer.step() 前,scaler 会先把各参数梯度除回 scale(unscale),并检查是否有 inf/nan
  3. step 或 skip:若 unscale 后梯度里没有 inf/nan,则调用 optimizer.step(),并可选地增大 scale(如每次乘 2,直到上限);若有 inf/nan,则不调用 step(跳过本次参数更新),并把 scale 减小(如减半),下次用更小的 scale 再试。

所以「跳过参数更新」= 当次 backward 产生的梯度在 unscale 后仍含有 inf 或 nan,scaler 为了数值安全不执行 optimizer.step()


三、什么情况下会跳过?

  • 梯度爆炸:某层梯度很大,乘 scale 后或 unscale 前就溢出成 inf;unscale 后仍为 inf,scaler 会 skip。
  • 梯度里有 nan:例如某处除零、log(0)、或 loss 里已有 nan,反向传播后梯度带 nan;scaler 检测到就 skip。
  • 学习率或 scale 过大:scale 设得太大,unscale 后梯度仍然超大,更新后可能下一轮就崩;scaler 通过「发现 inf/nan 就 skip 并减小 scale」来自适应。

所以跳过 = 本次梯度不可信(inf/nan),为安全不更新参数,并调小 scale 以便后续稳定。


四、使用注意

  • 频繁 skip,说明可能学习率过大、或模型/数据有问题(如 nan loss);要查数据、学习率、loss 是否稳定,而不是一味依赖 scaler。
  • 梯度累积时:多次 backward 再 step,要在最后一次 backward 之后、step 之前做 unscale;通常用 scaler.scale(loss).backward() 累积,一次 scaler.step(optimizer) 即可,scaler 会处理。
  • 多优化器 / 多 backward:每个 step 前只 unscale 一次、检查一次;若有两个优化器,要按文档决定是否两次 scaler.step 或先 unscale 再分两次 step。

面试要点

  • AMP = FP16 前向/梯度 + scale 放大梯度防下溢,unscale 后更新;GradScaler 管 scale 与 unscale。
  • 跳过更新 = unscale 后梯度含 inf 或 nan,为安全不执行 optimizer.step,并减小 scale。
  • 原因常为梯度爆炸、梯度/loss 中有 nan、或 scale/学习率过大;频繁 skip 需查学习率与数据。

记忆要点

  1. GradScaler:scale 梯度 → backward → unscale → 检查 inf/nan;有则 skip step 并减小 scale。
  2. 跳过 = 梯度 inf 或 nan,不执行 step;目的防崩溃。
  3. 频繁 skip 要查学习率、loss、数据是否正常。

返回模块 | 返回总览

01-PyTorch底层/015-如何profile-PyTorch模型的性能.md

第 15 题:如何profile PyTorch模型的性能?torch.profilernvprof的使用经验?

题目

如何profile PyTorch模型的性能?torch.profilernvprof的使用经验?


完整讲解

一、torch.profiler 能干什么?

torch.profiler(或旧版 torch.autograd.profiler.profile)在 Python 侧记录:每个算子的 CPU/GPU 时间、调用次数、显存分配/释放、以及(若开 CUDA)kernel 级信息。可配合 Chrome Trace(tensorboard 的 trace viewer)看时间线,或导出表格做「谁最慢」的排序。

  • 基本用法with torch.profiler.profile(...) as prof: model(x),然后 prof.key_averages().table()prof.export_chrome_trace("trace.json")
  • 常用参数activities=[ProfilerActivity.CPU, ProfilerActivity.CUDA]record_shapes=True(记 tensor shape)、profile_memory=True(显存)、with_stack=True(调用栈)。schedule 可做「预热 + 只录几轮」避免录太多。
  • TensorBoardtorch.profiler.tensorboard 把 trace 写到 logdir,用 tensorboard --logdir ... 打开,在 PyTorch Profiler 的 trace 视图里看 CPU/GPU 时间线和 gap。

二、看什么、怎么优化?

  • CPU 侧:Python 开销、DataLoader、to(device)、每个 op 的 dispatch;若 CPU 时间远大于 GPU,多半是数据或 Python 瓶颈。
  • GPU 侧:每个 kernel 的时长、间隔(gap);若 GPU 中间有大段空白,可能是 CPU 没及时喂数据或同步点太多。
  • 显存profile_memory=True 看分配/释放时间线,找峰值和泄漏;结合 memory_summary() 看谁在占。
  • 算子级:按「self CPU time」或「self CUDA time」排序,找到最贵的 op,再决定是否融合、换 kernel、或减计算。

三、nvprof / Nsight 系列(nvidia 工具)

  • nvprof(旧,部分新卡已弃用):命令行 nvprof python train.py,会录 GPU kernel、显存、API 调用;输出可转成 timeline。新驱动上推荐用 Nsight Systems / Nsight Compute
  • Nsight Systems:录 CPU + GPU 时间线、kernel 发射、CUDA API、多进程;看「GPU 利用率低、中间有大 gap」时用,定位是等数据、等同步还是 kernel 太碎。
  • Nsight Compute:针对单个 kernel 的详细指标: occupancy、memory throughput、warp 效率、roofline 等;在「已知某 kernel 慢」时做深度优化用。

经验:先 torch.profiler 看「哪一段、哪个 op 慢」和「CPU/GPU 谁在等」;再 Nsight Systems 看时间线 gap;最后对关键 kernel 用 Nsight Compute 抠指标。


四、简要对比

工具 层级 典型用途
torch.profiler Python/op 哪个 op 慢、显存、CPU/GPU 占比
Nsight Systems 进程/线程/kernel 时间线、gap、谁在等
Nsight Compute 单 kernel occupancy、带宽、roofline
nvprof kernel/API 旧卡粗略 timeline(逐渐被替代)

面试要点

  • torch.profiler:录 op/kernel 时间、显存、shape;用 schedule、record_shapes、profile_memory;看 table 或 Chrome Trace(tensorboard)。
  • 分析:看 CPU vs GPU 谁主导、gap、最贵 op;再决定优化数据、融合、或换 kernel。
  • nvprof 渐退场;Nsight Systems 看整体时间线与 gap;Nsight Compute 看单 kernel 指标;和 profiler 配合用。

记忆要点

  1. torch.profiler:Python/op 级,activities/record_shapes/profile_memory,Chrome Trace 看时间线。
  2. 优化顺序:profiler 找慢 op 和 gap → Nsight Systems 看时间线 → Nsight Compute 抠关键 kernel。
  3. nvprof 旧;Nsight 是当前推荐 GPU 工具链。

返回模块 | 返回总览

02-TensorFlow与XLA/README.md

02-TensorFlow与XLA(第 16–20 题)

题号 主题 文章
16 TensorFlow的XLA编译器优化了哪些场景?`jit_compil… 016-TensorFlow的XLA编译器优化了哪些场景.md
17 TF的tf.function和PyTorch的torch.jit 017-TF的tf.function和PyTorch的torch.jit设计理念差异.md
18 XLA的HLO IR长什么样?如何阅读XLA的编译日志? 018-XLA的HLO-IR长什么样.md
19 TensorFlow的SavedModel格式和PyTorch的Torc… 019-TensorFlow的SavedModel格式和PyTorch的TorchS.md
20 TF Serving的batching策略如何配置?遇到过哪些坑? 020-TF-Serving的batching策略如何配置.md

返回总览

02-TensorFlow与XLA/016-TensorFlow的XLA编译器优化了哪些场景.md

第 16 题:TensorFlow的XLA编译器优化了哪些场景?jit_compile=True的触发条件?

题目

TensorFlow的XLA编译器优化了哪些场景?jit_compile=True的触发条件?


完整讲解

一、XLA 在做什么?

XLA(Accelerated Linear Algebra) 是 TensorFlow 的图编译器:把 TF 的计算图(或子图)编译成面向 GPU/TPU 等后端的高效可执行代码。它做算子融合、常量折叠、布局优化、内存规划等,减少 kernel launch 和内存访问,尤其对「小 op 很多」的图收益大。


二、优化了哪些场景?

  • 算子融合:把多个小 op(如 add + relu + scale)融合成一个大 kernel,减少 launch 和显存读写。
  • 常量折叠:编译期能算出来的子图(如 shape 推导、常量运算)直接算成常量,不放到运行时。
  • 布局与内存:选择更合适的 tensor 布局(如 NHWC vs NCHW)、减少中间 tensor、复用 buffer。
  • 针对后端:为 GPU 生成 CUDA/cuDNN 调用,为 TPU 生成 HLO 再 lower 到 TPU 指令;可做后端特定的调度与选 kernel。
  • 控制流:把 cond/while 等编译成后端支持的表示,减少 Python 与 runtime 交互。

适合:计算密集、图较静态、重复执行同一图的模型;若图经常变或以动态控制流为主,编译收益可能不如开销。


三、jit_compile=True 的触发条件与用法

  • 在 Keras 里model.compile(..., jit_compile=True) 会让该模型在首次执行时对「该次执行涉及的计算」做 XLA 编译,编译结果会缓存(按输入 shape 等 key),后续相同 shape 的调用直接用缓存,不再重编。
  • 触发:第一次用该模型做 fit/predict__call__ 时,若走到 XLA 路径就会触发编译;若输入 shape 变了,可能生成新 cache、再编一次。
  • 条件:图要能被 XLA 支持(大部分 TF 算子支持,少数不支持的会 fallback 或报错);动态 shape 在部分场景下会触发重编译或限制优化。
  • tf.function@tf.function(jit_compile=True) 对该 function 的图做 XLA 编译,同样首次调用时编译并缓存。

面试要点

  • XLA 做:算子融合、常量折叠、布局与内存优化、后端代码生成;适合计算密集、图较静态的模型。
  • jit_compile=True:在 compile 或 tf.function 里打开,首次执行时触发编译并缓存;shape 变化可能触发重编。
  • 能说清「编译换运行效率、缓存 key 常与 shape 相关」即可。

记忆要点

  1. XLA = 图编译 → 融合、常量折叠、布局、后端代码;减少 launch 与内存访问。
  2. jit_compile=True = 首次执行触发编译、结果缓存;Keras compile 或 tf.function 里设。
  3. 适合静态/重复图;动态 shape 可能多轮编译。

返回模块 | 返回总览

02-TensorFlow与XLA/017-TF的tf.function和PyTorch的torch.jit设计理念差异.md

第 17 题:TF的tf.function和PyTorch的torch.jit设计理念差异?

题目

TF的tf.function和PyTorch的torch.jit设计理念差异?


完整讲解

一、tf.function 的设计

tf.function 把 Python 函数按执行轨迹 trace 成 TF 图,之后用图 + 缓存执行:相同输入「签名」(如 shape、dtype)走缓存,不同则重新 trace 并缓存。设计偏向「默认用、透明加速」:用户加个装饰器,TF 负责 trace、retrace、concrete function 管理;控制流用 tf.cond/tf.whileAutoGraph 转成图内节点,尽量不落回 Python。理念是:一次定义、多签名缓存、图执行为主。


二、torch.jit 的设计

torch.jit 提供 tracescript 两种路径:trace 用示例输入跑一遍,录成静态图(控制流被固化为当时分支);script 解析 Python 源码编译成 TorchScript IR,保留 if/for。用户通常要显式选 trace 或 script,并处理「不支持的语法」「动态 shape」等问题。理念是:提供两种捕获方式,部署/导出时用,eager 仍是默认开发体验。


三、主要差异

维度 tf.function torch.jit
默认体验 装饰即用,图执行透明 开发多为 eager,JIT 用于部署/导出
控制流 AutoGraph 转图内 cond/while trace 固化为单分支;script 保留控制流
多 signature 多 concrete function 缓存 trace 绑死示例 shape;script 更灵活
与 eager 关系 与 eager 互转,可关图执行 两套路径,trace/script 与 eager 分离
生态 TF 全栈围绕图与 SavedModel PyTorch 2.0 更多用 torch.compile

四、一句话概括

tf.function:以图为中心,装饰器即可、多签名缓存、控制流进图,透明加速。torch.jit:eager 为主,trace/script 两条路显式选,用于导出和部署;PyTorch 2.0 后很多场景用 torch.compile 替代 JIT 做训练侧加速。


面试要点

  • tf.function:trace 成图、多 signature 缓存、AutoGraph 处理控制流;透明图执行。
  • torch.jit:trace(绑死分支)或 script(保留控制流);显式、多用于部署/导出。
  • 差异:图是否「默认」、控制流进图方式、多 shape 处理;PyTorch 2.0 推 compile 多于 jit。

记忆要点

  1. tf.function = 图为主、透明、多签名;torch.jit = trace/script 二选一、偏部署。
  2. 控制流:TF AutoGraph 进图;JIT trace 固化为单分支、script 保留。
  3. 当前 PyTorch 训练加速更多用 torch.compile,JIT 仍用于 ONNX/LibTorch 等导出。

返回模块 | 返回总览

02-TensorFlow与XLA/018-XLA的HLO-IR长什么样.md

第 18 题:XLA的HLO IR长什么样?如何阅读XLA的编译日志?

题目

XLA的HLO IR长什么样?如何阅读XLA的编译日志?


完整讲解

一、HLO 是什么?

HLO(High Level Operations) 是 XLA 的高层 IR:在「图优化」之后、lower 到后端具体指令之前的一层表示。可以理解为 XLA 的「与硬件无关的算子级 IR」:节点是粗粒度 op(如 dot、conv、reduce、broadcast),边是数据流;每个 op 带 shape、dtype、属性等,便于做融合、布局选择、再往下到 GPU/TPU 的代码生成。


二、HLO 长什么样?

  • 节点:通常一个 HLO 节点对应一类计算,如 dotconvolutionreduce_windowbroadcast_in_dimparameterconstant 等;节点有输入边输出 shape
  • 层级:HLO 之上可能是 TF Graph / StableHLO 等;之下会 lower 成 LHO(或 backend 特定 IR) 再生成机器码。
  • 形式:可以是文本(类似 S 表达式或自定义 DSL)、或编译器内部数据结构;TF 里可通过 XLA 编译选项环境变量 dump 出 HLO 文本,便于排查「图长什么样、有没有被融合」。

三、如何阅读 XLA 编译日志?

  • 打开 HLO dump:设置环境变量或编译选项,如 XLA_FLAGS="--xla_dump_to=/path"、或 TF 的 XLA_DUMP_HLO_GRAPH=1 等(具体随版本查文档),编译时会写出 HLO 图或 IR 文本。
  • 看什么:先找入口(如 entry 或 root);看大 op 序列是否和预期一致、有没有被错误融合或删除;看 shape 是否与模型一致;若有报错,报错里的 op 名或编号对应到 HLO 里的节点。
  • 与优化阶段对应:编译日志里可能有多个阶段(HLO → 优化后 HLO → backend IR);对照「优化前/后」可看出融合、常量折叠等是否生效。
  • TF 文档与社区:XLA 的 op 列表、HLO 语义在 TensorFlow/XLA 官方文档有说明;遇到未知 op 可查 HLO 规范。

四、实践建议

  • 调模型或性能时:先确认 HLO 里的图是否符合预期(有没有多算、少算、错融合);再结合 backend 层 的 kernel 选择与调度。
  • 报错时:把报错里的 op 名 / 编号 和 dump 出的 HLO 对应,看是哪个节点、输入 shape 是否合法。

面试要点

  • HLO = XLA 高层 IR,节点为粗粒度 op(dot、conv、reduce 等),带 shape/dtype;在 backend 代码生成之前。
  • 阅读:通过 XLA dump 选项得到 HLO 文本;看入口、op 序列、shape、与报错节点对应。
  • 用途:确认图是否正确、优化是否生效、定位编译/运行错误。

记忆要点

  1. HLO = 高层 op 级 IR,与硬件无关;下有 LHO/backend 层。
  2. 阅读:开 dump → 看 entry、op 序列、shape;报错对应到节点。
  3. 用于查图正确性、融合与优化、错误定位。

返回模块 | 返回总览

02-TensorFlow与XLA/019-TensorFlow的SavedModel格式和PyTorch的TorchS.md

第 19 题:TensorFlow的SavedModel格式和PyTorch的TorchScript对比?

题目

TensorFlow的SavedModel格式和PyTorch的TorchScript对比?


完整讲解

一、SavedModel 是什么?

SavedModel 是 TensorFlow 的标准部署格式:一个目录,包含 pb 图(或 MLIR)、变量/权重(如 variables/)、签名(输入/输出名与 shape)、以及 assets 等。支持多 signature(如 predict、train_step),TF Serving、TFLite、TF.js 等都能直接加载;图通常是「已优化、可执行」的静态图,控制流已用 tf.cond/while 等固化。


二、TorchScript 是什么?

TorchScript 是 PyTorch 的可序列化、可部署的表示:可以是 trace 得到的图(与示例输入绑定的静态图),或 script 得到的图(带控制流的 IR)。保存成 .pt/.pts 文件,在 C++ 的 LibTorch 里用 torch::jit::load() 加载、无 Python 运行;也可再转 ONNX。和 eager 的「Python + 动态图」是两套:TorchScript 偏部署与跨语言。


三、对比

维度 SavedModel TorchScript
形态 目录(图 + 变量 + 签名) 文件(.pt/.pts,图 + 权重)
图来源 tf.function / 建图 API trace 或 script
控制流 图内 tf.cond/while trace 固化为单分支;script 保留
多签名 原生多 signature 一般单入口,可多方法
加载环境 TF runtime、TF Serving 等 LibTorch C++、或再转 ONNX
生态 TF 全栈、TFLite、TF.js PyTorch 部署、ONNX、移动端需再转

四、使用场景

  • SavedModel:TF 模型上线、TF Serving、跨平台(TFLite/TF.js)时用;强调「一份格式、多运行时」。
  • TorchScript:PyTorch 模型要无 Python 部署(C++、移动端)或转 ONNX 前的中间表示;trace 适合静态、script 适合带控制流的模型。

面试要点

  • SavedModel = 目录、图+变量+签名、多 signature、TF 生态标准部署格式。
  • TorchScript = 序列化图+权重、trace/script 两种、LibTorch 加载无 Python、可转 ONNX。
  • 差异:形态、图来源、控制流、多签名、加载方与生态。

记忆要点

  1. SavedModel:目录、多签名、TF 部署与 Serving;TorchScript:文件、trace/script、LibTorch/ONNX。
  2. 控制流:SavedModel 图内;TorchScript trace 固化为单分支、script 保留。
  3. 选型:TF 栈用 SavedModel;PyTorch 无 Python 部署用 TorchScript 或再转 ONNX。

返回模块 | 返回总览

02-TensorFlow与XLA/020-TF-Serving的batching策略如何配置.md

第 20 题:TF Serving的batching策略如何配置?遇到过哪些坑?

题目

TF Serving的batching策略如何配置?遇到过哪些坑?


完整讲解

一、TF Serving 的 batching 在做什么?

请求到达后不是「一个请求立刻推理一次」,而是先入队,由 Batch Scheduler 按策略攒成一批再一起送进模型,从而提高 GPU 利用率、降低单请求平均延迟(在吞吐优先时)。策略包括:多久等一批(batch timeout)、最多多少个(max batch size)、以及可选的优先级等。


二、如何配置?

  • Batching 参数(在 model config 或 batching parameters 里):
  • max_batch_size:一批最多多少个请求。
  • batch_timeout_micros:等待凑批的最长时间(微秒),超时则当前已入队的也送走。
  • max_enqueued_batches:队列里最多允许多少个「未满的批」在等,超过可拒绝新请求或背压。
  • 动态 batching:TF Serving 支持「动态」把多个请求拼成一个 batch(padding 或 packing),模型需支持变长或 batch 维;配置里打开相应 batching 并设上述参数。
  • 与模型签名一致:输入是 batched 的(batch 维在第一维),模型 export 时就要按 batch 输入导出;否则会 shape 不匹配。

三、常见坑

  • timeout 与延迟:batch_timeout 设太大,请求会等很久才凑批,尾延迟变高;设太小,批小、GPU 利用率低。要按 P99 延迟和吞吐做权衡。
  • shape 与 padding:变长请求要 padding 到同一长度 或做 packing;padding 浪费算力,packing 要模型支持。若模型只支持固定 shape,动态 batch 需保证 padding 后 shape 一致。
  • OOM:max_batch_size 过大,单批显存超 GPU 容量会 OOM;要按单请求显存 × batch 上限估算。
  • 队列堆积:高 QPS 时若处理跟不上,enqueued batches 满会拒绝或拖慢;需配合限流、扩容或降 batch_size。
  • 与预处理一致:Serving 端做 batching 时,预处理(解码、归一化)要在 batch 维度正确拼接,否则逻辑错或性能差。

四、建议

  • 先压测:看单请求显存、延迟,再定 max_batch_size、batch_timeout;观察 P50/P99 与吞吐。
  • 变长模型:明确用 padding 还是 packing、谁做、shape 上限多少。
  • 监控队列长度、batch 实际大小、超时次数,便于调参和排障。

面试要点

  • 配置:max_batch_size、batch_timeout_micros、max_enqueued_batches;与模型 batch 输入一致。
  • 坑:timeout 与尾延迟、shape/padding/packing、OOM、队列堆积、预处理与 batch 维一致。
  • 调参看 P99 与吞吐;监控队列与实际 batch 大小。

记忆要点

  1. 参数:max_batch_size、batch_timeout、max_enqueued_batches;模型需支持 batch 输入。
  2. 坑:大 timeout → 高尾延迟;小 → 批小利用率低;OOM、shape/padding、队列满。
  3. 按显存与延迟压测定参;监控队列与 batch 分布。

返回模块 | 返回总览

03-自定义算子开发/README.md

03-自定义算子开发(第 21–30 题)

题号 主题 文章
21 用CUDA写一个简单的vector add,如何绑定到Python? 021-用CUDA写一个简单的vector-add,如何绑定到Python.md
22 Triton和CUDA的区别?什么时候用Triton更合适? 022-Triton和CUDA的区别.md
23 如何编写一个融合算子(fused op)?以`layernorm + r… 023-如何编写一个融合算子(fused-op).md
24 CUTLASS是什么?什么时候需要用它而不是手写CUDA? 024-CUTLASS是什么.md
25 算子优化中的memory coalescing、bank conflic… 025-算子优化中的memory-coalescing、bank-conflict、.md
26 如何用Nsight Compute分析kernel性能?关注哪些metr… 026-如何用Nsight-Compute分析kernel性能.md
27 编写CUDA时如何平衡register使用和occupancy? 027-编写CUDA时如何平衡register使用和occupancy.md
28 什么是warp divergence?如何检测和避免? 028-什么是warp-divergence.md
29 动态shape的算子如何优化?vllm中的`PagedAttenti… 029-动态shape的算子如何优化.md
30 算子融合的收益如何评估?什么时候融合反而变慢? 030-算子融合的收益如何评估.md

返回总览

03-自定义算子开发/021-用CUDA写一个简单的vector-add,如何绑定到Python.md

第 21 题:用CUDA写一个简单的vector add,如何绑定到Python?

题目

用CUDA写一个简单的vector add,如何绑定到Python?


完整讲解

一、CUDA vector add 怎么写?

用 CUDA 写 vector add:在 kernel 里每个线程负责若干元素(或一对一),从 global memory 读 a[i]b[i],写回 c[i] = a[i] + b[i]。注意 grid/block 维度:block 内线程数常取 256,grid 大小 = (n + blockSize - 1) / blockSize;kernel 内用 blockIdx.x * blockDim.x + threadIdx.x 得到全局下标,并加 bounds checkif (i < n))防止越界。

二、如何暴露给 Python?

常见方式:PyTorch C++ 扩展torch.utils.cpp_extension)、pybind11 + 自己编译、或 CuPy/NumPy 的 C 扩展

  • PyTorch 扩展:写 .cu__global__ kernel,在 .cpp 里用 at::Tensor 取 data ptr、调 CUDA kernel;用 load_inlineload 编译成 so,Python 里 import torch.utils.cpp_extension; torch.ops.load_library(...) 或通过 torch.library.define 注册,即可 torch.ops.my_ns.vector_add(a, b) 调用。
  • pybind11:CUDA 分配/拷贝自己管,用 py::array_t 或 raw pointer 传进 Python;需在 C++ 侧做 host/device 拷贝,或接受已 in GPU 的 buffer(如从 CuPy 传过来)。

三、工程要点

  • 编译依赖:CUDA toolkit、与当前 PyTorch 一致的 CUDA 版本;Windows 上需配 nvcc、PATH。
  • 若要在 Autograd 里用,需再包一层 torch.autograd.Function,在 backward 里实现梯度(vector add 的梯度就是直传)。
  • 小规模可先 CPU 或 torch 算子验证正确性,再对比 GPU 结果与性能。

面试要点

  • CUDA kernel:grid/block、全局下标、bounds check;vector add 是 memory-bound,注意 coalesced 访问。
  • 绑定 Python:PyTorch C++ 扩展(cpp_extension + at::Tensor)或 pybind11;扩展需正确链接 CUDA、与 PyTorch CUDA 版本一致。
  • 要参与训练需用 autograd.Function 包装,backward 实现梯度并可选再调 kernel。

记忆要点

  1. CUDA vector add:每线程算下标 i,读 a[i]、b[i],写 c[i];grid/block 覆盖 n,加 i < n 判断。
  2. 绑 Python:PyTorch 扩展(.cu + .cpp,load_library)或 pybind11;at::Tensor 取 ptr 调 kernel。
  3. 参与 Autograd 需包一层 Function,forward 调 kernel,backward 传梯度。

返回模块 | 返回总览

03-自定义算子开发/022-Triton和CUDA的区别.md

第 22 题:Triton和CUDA的区别?什么时候用Triton更合适?

题目

Triton和CUDA的区别?什么时候用Triton更合适?


完整讲解

一、Triton 和 CUDA 的区别

CUDA:显式写 thread/block/grid、shared memory、同步;控制细、调优空间大,但开发成本高、要手管寄存器与 occupancy。Triton:用 块级编程(tile 为单元),写「对一块数据做什么」,由编译器生成 GPU kernel;自动管 block、shared memory、循环与向量化,代码更短、可读性好,易做 auto-tuning(如 grid 大小、tile 大小)。

  • 抽象层级:CUDA 是「线程/ warp 级」;Triton 是「tile/block 级」,更接近「矩阵块运算」。
  • 内存:Triton 用 tl.load/tl.store 声明访问模式,编译器做 coalescing、bank 优化;CUDA 需手写。
  • 生态:CUDA 通用、所有 NVIDIA 卡;Triton 目前主要 NVIDIA,与 PyTorch 2 的 Inductor 深度集成。

二、什么时候用 Triton 更合适?

  • 新算子/原型:快速实现 matmul、softmax、layernorm 等,改 tile 和 num_warps 即可调优,不必手写 shared 与循环。
  • 与 PyTorch 编译栈一致:TorchInductor 会生成 Triton;自定义 kernel 用 Triton 便于和 Inductor 融合、统一调度。
  • 不适合:极度依赖 warp 级技巧、复杂分支、或需精确控制每条指令的 kernel;以及非 NVIDIA 后端(Triton 暂不支持)。

三、简要对比

维度 CUDA Triton
抽象 线程/block tile/block
开发效率 低、细节多 高、声明式
调优 手调 易 auto-tune
适用 通用、极致性能 新算子、PyTorch 栈

面试要点

  • Triton:块级编程、编译器生成 kernel,自动管 shared/循环;CUDA 是线程级、手写细节。
  • Triton 适合新算子、与 Inductor 统一、快速调 tile/num_warps;CUDA 适合要极致手控或非 NVIDIA 的场景。
  • 能说清「块级 vs 线程级」和「谁负责 coalescing / occupancy」即可。

记忆要点

  1. Triton = 块级编程,编译器生成 kernel;CUDA = 线程级,手写 grid/block/shared。
  2. Triton 适合快速写 matmul/softmax/layernorm、与 PyTorch Inductor 集成;CUDA 适合极致手控。
  3. 抽象层级不同:Triton 管 tile,CUDA 管 thread;Triton 易 auto-tune。

返回模块 | 返回总览

03-自定义算子开发/023-如何编写一个融合算子(fused-op).md

第 23 题:如何编写一个融合算子(fused op)?以layernorm + residual + activation为例

题目

如何编写一个融合算子(fused op)?以layernorm + residual + activation为例


完整讲解

一、融合算子是什么?

把多个小算子(如 LayerNorm + residual + activation)合成一个 kernel,减少 kernel launch 开销中间结果写回 global memory,并提高 访存局部性(中间结果留在 register/shared),从而降延迟、提带宽利用率。

二、以 layernorm + residual + activation 为例

  • 数学:先 x_norm = LayerNorm(x)(减均值、除方差、仿射),再 out = act(x_norm + residual);若 residual 是 branch 的输入,即 Pre-LN 里「norm → 子层 → + residual」中的那一段。
  • 融合思路:一个 kernel 内按元素(或按行)做:读 x[i]residual[i],算 mean/var(可先一遍归约或 Welford),再 normed = (x - mean)/std * gamma + beta,然后 out = act(normed + residual) 写回。这样 norm、加 residual、激活 都在同一 kernel,无中间 global 读写。
  • 实现:可用 CUDA(手写归约 + 逐元素)、Triton(用 tl.reducetl.load/store 拼一块)、或 TVM/CUTLASS 模板;需处理 反向:若训练,要写融合的 backward(LN 梯度 + residual 直传 + act 梯度)。

三、工程要点

  • 正确性:与「分步调 LN + add + act」数值对齐(fp32/fp16 注意顺序与精度)。
  • 收益:在 小 batch、短序列带宽瓶颈 时收益大;大 batch 纯算力瓶颈时收益变小。
  • 可维护性:融合后调试难,可保留「非融合路径」做 CI 对比。

面试要点

  • 融合目的:减 kernel 数、减中间 global 读写、提高访存局部性;layernorm + residual + act 可在一个 kernel 内完成 norm、加、激活。
  • 实现:同一 kernel 内做归约(mean/var)、归一化、加 residual、激活;CUDA/Triton 均可;训练需融合 backward。
  • 收益在小 batch/带宽受限时明显;要校验与分步实现的数值一致。

记忆要点

  1. 融合 = 多 op 一 kernel,减 launch 与中间写回;layernorm + residual + act 可一次做完 norm、加、激活。
  2. 实现:归约求 mean/var → norm → + residual → act,写回;训练需对应 backward。
  3. 收益在带宽受限时大;需数值校验与可选非融合对照。

返回模块 | 返回总览

03-自定义算子开发/024-CUTLASS是什么.md

第 24 题:CUTLASS是什么?什么时候需要用它而不是手写CUDA?

题目

CUTLASS是什么?什么时候需要用它而不是手写CUDA?


完整讲解

一、CUTLASS 是什么?

CUTLASS(CUDA Templates for Linear Algebra Subroutines)是 NVIDIA 的 CUDA 模板库,提供高性能 矩阵乘、卷积 等 building blocks;用 C++ 模板 抽象 threadblock tile、warp 级 MMA(matrix multiply-accumulate)、shared memory 分块、双缓冲等,方便组合出不同 shape、精度(fp16/bf16/int8)、Epilogue(加 bias、relu 等)的 kernel,而不必从零手写每类 GEMM。

  • 层级:Device → Threadblock → Warp → MMA;每层可配置 tile 大小、stages(流水)、Epilogue。
  • 用途:做 GEMM、batched GEMM、conv;很多推理/训练库底层用 CUTLASS 或类似思路。

二、什么时候用 CUTLASS 而不是手写 CUDA?

  • 用 CUTLASS:要快速得到 接近 cuBLAS 水平 的 matmul/conv,或要 多种 shape、精度、Epilogue 组合;接受模板编译慢、二进制大,以换开发效率与可维护性。适合做推理引擎、算子库、新硬件的 GEMM 参考。
  • 手写 CUDA极端定制(非常规 layout、稀疏、特殊融合)、教学/研究、或 非 NVIDIA GPU;以及不想引入 CUTLASS 依赖与编译成本时。
  • 折中:用 CUTLASS 的 概念(tile、warp MMA、epilogue)自己写简化版 kernel,或只接 CUTLASS 生成的某几类 kernel。

三、与 cuBLAS、Triton 的关系

  • cuBLAS:闭源、接口固定;CUTLASS 开源、可改 Epilogue 和融合。
  • Triton:更上层、块级语言;CUTLASS 是 C++ 模板、控制更细,二者可互补(Triton 调 CUTLASS 或仿其思路)。

面试要点

  • CUTLASS = NVIDIA 的 GEMM/卷积模板库,抽象 threadblock/warp MMA/Epilogue,便于组合不同 shape、精度、融合。
  • 用 CUTLASS:要高性能 GEMM/conv、多种组合、少写手写代码;手写 CUDA:极端定制、非 NVIDIA、或轻量依赖。
  • 与 cuBLAS(闭源固定)和 Triton(更上层)的定位差异要能说清。

记忆要点

  1. CUTLASS = CUDA 模板库,做 GEMM/conv;模板抽象 tile、warp MMA、Epilogue。
  2. 用 CUTLASS 换开发效率与接近 cuBLAS 性能;手写用于极端定制或非 NVIDIA。
  3. cuBLAS 闭源;Triton 更上层;CUTLASS 可改 Epilogue、做融合。

返回模块 | 返回总览

03-自定义算子开发/025-算子优化中的memory-coalescing、bank-conflict、.md

第 25 题:算子优化中的memory coalescing、bank conflict、occupancy分别指什么?

题目

算子优化中的memory coalescing、bank conflict、occupancy分别指什么?


完整讲解

一、Memory coalescing

Coalescing:同一 warp 的线程访问 连续地址(如 thread i 访问 addr_base + i)时,硬件可合并成少量(甚至一次)global memory 事务;若线程访问分散或错位,会产生多次事务,带宽利用率低。优化:让 相邻 thread 访问相邻地址(如 threadIdx.x 对应连续下标)、避免随机步长;对 2D/3D 注意 行主序 下把连续维映射到 threadIdx.x。

二、Bank conflict

Shared memory 按 bank 分(如 32 bank、4B 宽);同一 warp 内不同线程访问同一 bank 的不同地址bank conflict,访问被串行化。避免方式:padding(在行末加空位使错开 bank)、改变访问模式(如转置用 shared 做分块避免同一 bank 多地址)、或设计成同一 warp 访问同一地址(broadcast,无 conflict)。

三、Occupancy

Occupancy = 同时驻留的 warp 数 / 硬件最大 warp 数,反映 延迟隐藏 能力。受限于:每 block 的 register每 block 的 shared memory每 SM 的 block 上限。register 用得多 → 每 block 能放的 warp 少 → occupancy 低;但有时 少 register、高 occupancy 反而因更多 warp 争抢而变慢。要在 occupancy 与 per-thread 资源 之间做权衡,用 Nsight Compute 看实际 occupancy 与 stall 原因。

四、关系简述

  • Coalescing 决定 global 带宽;bank conflict 决定 shared 有效带宽;occupancy 决定 能否用足够多 warp 藏延迟
  • 三者都影响 kernel 最终性能,需一起看;先保证 coalescing 与无严重 bank conflict,再调 occupancy。

面试要点

  • Memory coalescing:同 warp 访问连续地址可合并为少量事务;优化为相邻 thread 访问相邻地址。
  • Bank conflict:shared 同 warp 多线程访问同 bank 不同地址会串行化;用 padding 或改访问模式避免。
  • Occupancy:驻留 warp 数/最大 warp 数,受 register/shared 限制;与 per-thread 资源权衡,看 Nsight 实际值。

记忆要点

  1. Coalescing:同 warp 连续地址 → 合并访存;相邻 thread 对应连续下标。
  2. Bank conflict:shared 同 bank 多地址 → 串行;padding 或改布局可避免。
  3. Occupancy:受 register/shared 限制;高 occupancy 不一定更快,需结合 stall 分析。

返回模块 | 返回总览

03-自定义算子开发/026-如何用Nsight-Compute分析kernel性能.md

第 26 题:如何用Nsight Compute分析kernel性能?关注哪些metrics?

题目

如何用Nsight Compute分析kernel性能?关注哪些metrics?


完整讲解

一、Nsight Compute 能看什么?

Nsight Compute(ncu)针对 单个 kernel 做细粒度分析:占用率(occupancy)warp 执行效率memory throughput(与 roofline 对比)、指令吞吐stall 原因(等内存、等指令、等同步等)、shared memory bank conflictL1/L2 缓存 等。先录一次 run:ncu -o report python script.py 或对已抓的 kernel 指定名字;再用 GUI 或 ncu --import report.ncu-rep 看指标。

二、关键 metrics 怎么读?

  • Occupancy:实际 vs 理论最大;若很低且 stall 以「等依赖」为主,可尝试减 register、减 shared 提高 occupancy。
  • Memory throughput:Achieved 与 Peak(GB/s);若接近 peak 仍慢,多半是 compute bound;远低于 peak 是 memory bound,看 coalescing、bank conflict、cache 利用。
  • Warp Execution Efficiency:非 divergent 的 warp 比例;低说明 warp divergence 严重。
  • Stall reasons:Memory Throttle / Instruction Fetch / Sync 等;指导是加 occupancy 还是改访存、减分支。
  • Roofline:算术强度与带宽/算力上限的关系,判断当前 kernel 在带宽墙还是算力墙一侧。

三、使用流程建议

先用 Nsight Systems 找「哪个 kernel 占时多」,再用 Nsight Compute 对该 kernel 看上述指标;根据 stall 与 throughput 决定:加 occupancy、改 coalescing、减 bank conflict、或优化计算密度。


面试要点

  • Nsight Compute 看单 kernel:occupancy、memory throughput、warp 效率、stall 原因、roofline。
  • 关键指标:occupancy 与 stall 关系;throughput 判断 memory vs compute bound;warp 效率看 divergence。
  • 与 Nsight Systems 配合:Systems 找慢 kernel,Compute 深入该 kernel 做优化依据。

记忆要点

  1. Nsight Compute = 单 kernel 分析;occupancy、throughput、warp 效率、stall、roofline。
  2. 低 occupancy + 依赖 stall → 试减 register/shared;低 throughput → 看 coalescing/bank/cache。
  3. 流程:Systems 定 kernel → Compute 看指标 → 按 stall/throughput 改。

返回模块 | 返回总览

03-自定义算子开发/027-编写CUDA时如何平衡register使用和occupancy.md

第 27 题:编写CUDA时如何平衡register使用和occupancy?

题目

编写CUDA时如何平衡register使用和occupancy?


完整讲解

一、Register 和 occupancy 的关系

每个 block 使用的 register 总数 = 每线程 register 数 × 每 block 线程数;SM 上 register 总量有限,每 block 用得多 → 同时能驻留的 block 少 → 每 SM 的 warp 数少 → occupancy 低。反之,少用 register(如把中间结果放进 shared、或拆 kernel)可提高 occupancy,用更多 warp 隐藏 latency(尤其是 memory latency)。

二、为什么不能一味追求高 occupancy?

  • Occupancy 高 只说明「有很多 warp 可切换」,若 kernel 本身 compute bound、不常等内存,多加 warp 反而增加 register/shared 竞争、可能更慢。
  • Occupancy 低每个 warp 做更多有用计算(如循环展开、更多寄存器缓存)有时更快;典型如 GEMM 里用较大 tile、多 stage,register 用得多、occupancy 中等,但吞吐更高。
  • 因此要结合 stall 原因(Nsight Compute):若主要是 Memory Throttle,提 occupancy 常有帮助;若是 Instruction/Compute,优先优化计算与指令吞吐。

三、怎么平衡?

  • 先测:用 Nsight Compute 看当前 occupancy、stall 分布;若 memory stall 高且 occupancy 低,尝试 --maxrregcount 或改代码减 register(少局部变量、用 shared 代替)。
  • 再试:在「减 register 提 occupancy」与「多 register 做展开/缓存」之间做 A/B;不同 kernel 最优点不同。
  • 经验:memory-bound kernel 常受益于更高 occupancy;compute-bound 的看 instruction throughput 与 occupancy 的折中。

面试要点

  • Register 多 → 每 block 占得多 → occupancy 低;减 register(或 shared 替代)可提 occupancy,利于藏内存延迟。
  • 高 occupancy 不一定更快:compute bound 时多 warp 可能只增加竞争;要看 stall 原因再决定。
  • 平衡:看 Nsight stall;memory stall 多则试提 occupancy;compute 多则看指令与 register 的折中。

记忆要点

  1. Register 用量 ↔ 每 block 占用 ↔ occupancy 成反比;减 register 可提 occupancy。
  2. 高 occupancy 主要利于隐藏内存延迟;compute bound 时未必更好,有时更多 register 做展开更快。
  3. 用 Nsight 看 stall;按 memory vs compute 决定是提 occupancy 还是提单 warp 效率。

返回模块 | 返回总览

03-自定义算子开发/028-什么是warp-divergence.md

第 28 题:什么是warp divergence?如何检测和避免?

题目

什么是warp divergence?如何检测和避免?


完整讲解

一、什么是 warp divergence?

Warp 是 32 个线程一起取指、执行;若这 32 线程走 不同分支(如 if (tid < 8) ... else ...),硬件会 串行执行 各分支(先执行满足条件的,再执行不满足的),未参与的分支线程被 mask 掉。这种同一 warp 内分支不一致叫 warp divergence,会导致有效并行度下降、利用率低。

二、如何检测?

  • Nsight Compute:看 Warp Execution Efficiency(活跃线程比例)、Divergence 相关指标;若某 kernel 效率明显低于 100%,多半有 divergence。
  • 代码审查:找 分支条件依赖 threadIdx / blockIdxif/elseswitch;尤其是 tid % 某数tid < 常数 等,易造成 warp 内部分叉。

三、如何避免或减轻?

  • 分支与 warp 对齐:让同一 warp 内线程走同一分支;例如「前 8 个 thread 做 A、后 24 个做 B」可改成「前 8 个 warp 做 A、后若干 warp 做 B」,或用 warp 内 ballot/sync 做一致决策。
  • 用无分支写法:用 predicateselect/三元算术 代替分支(如 x = (cond ? a : b) 有时被编译成 predicated 指令,两路都算再选,避免真正分支);小范围可接受。
  • 重排数据/线程:让「同一分支」的数据由同一 warp 处理(sort by branch、或 thread 映射到连续区间),减少 warp 内分支不一致。

面试要点

  • Warp divergence:同一 warp 内走不同分支,硬件串行执行各分支,mask 未参与线程,导致利用率低。
  • 检测:Nsight Compute 的 warp 效率、divergence 指标;代码里找依赖 threadIdx 的分支。
  • 避免:分支与 warp 对齐、用 predicate/select 代替分支、重排使同分支同 warp。

记忆要点

  1. Divergence = 同 warp 内分支不同 → 串行执行各分支,mask 部分线程。
  2. 看 Nsight warp 效率;分支条件依赖 tid 易产生 divergence。
  3. 对齐分支到 warp、用无分支写法、或重排数据使同分支同 warp。

返回模块 | 返回总览

03-自定义算子开发/029-动态shape的算子如何优化.md

第 29 题:动态shape的算子如何优化?vllm中的PagedAttention是如何解决这个问题的?

题目

动态shape的算子如何优化?vllm中的PagedAttention是如何解决这个问题的?


完整讲解

一、动态 shape 的难点

动态 shape(batch/seq 等维度运行时才定)导致:一、 难以在编译期做满 静态分配与循环边界,易生成多份 kernel 或泛化代码;二、 不同 shape 下最优 tile、block 可能不同;三、 若按最大 shape 分配显存会浪费,按当前 shape 又可能频繁重编译或分配。

二、常见优化思路

  • 多 kernel / 分派:按 shape 区间或关键维(如 seq_len 是否大于某值)选不同 kernel 或配置,减少「一个 kernel 吃遍所有 shape」的保守代价。
  • 符号 shape + 统一 kernel:用符号变量表示维度,生成一份带符号边界的 kernel,运行时代入实际值;TVM/Triton 等支持,可减少代码膨胀,但调试与优化难度增加。
  • PagedAttention / 显存管理:不按「整块连续 tensor」分配,而是 分页(block 或 page 为单位)、按需映射;变长序列只占实际用的页,避免按 max length 分配,并利于 KV cache 复用 与碎片控制。

三、vLLM 的 PagedAttention

PagedAttentionKV cache 切成固定大小的 block(如 16 个 token 一 block),物理上按 block 分配、逻辑上用 block 表 记录每个序列用了哪些 block;不同序列可共享未用 block、且 同一序列内 block 不必连续。这样 动态长度 只影响 block 个数,不触发「整块大 buffer 重分配」;显存利用率高、碎片少,且便于与 prefetch、并行解码配合。算子侧可针对「按 block 取 KV」做优化,而不是假设一大块连续 layout。


面试要点

  • 动态 shape:难在编译期优化、多 shape 最优配置不同、显存按 max 浪费;优化有多 kernel 分派、符号 shape 统一 kernel、分页显存。
  • PagedAttention:KV 按 block 分页,block 表记录序列占用;按需分配、少碎片、易复用,适配动态长度。
  • 算子优化可围绕「按 block 访问」设计,而非假设连续大 buffer。

记忆要点

  1. 动态 shape 优化:分派多 kernel、符号 shape、分页显存;避免按 max shape 一刀切。
  2. PagedAttention = KV 分 block、block 表管理;按需占 block,显存利用率高、适配变长。
  3. 算子侧可针对 block 级访问做优化,与分页策略一致。

返回模块 | 返回总览

03-自定义算子开发/030-算子融合的收益如何评估.md

第 30 题:算子融合的收益如何评估?什么时候融合反而变慢?

题目

算子融合的收益如何评估?什么时候融合反而变慢?


完整讲解

一、融合收益如何评估?

  • 理论:省 kernel launch 次数(每次 launch 有固定开销)、省 中间结果写回/读回 global memory(带宽与延迟);可粗略算「融合前读写字节数 − 融合后」和「launch 次数差」。
  • 实测:用 profiler(torch.profiler、Nsight Systems)对比「融合前多 kernel 总时间 + 间隙」与「融合后单 kernel 时间」;看 端到端 延迟/吞吐,因为还可能受其他 op 影响。
  • Roofline:若融合前是 memory bound(多趟读写),融合后减少访存,收益大;若已是 compute bound,融合主要省 launch,收益有限。

二、什么时候融合反而变慢?

  • Register / shared 压力过大:融合后单 kernel 用太多 register 或 shared,导致 occupancy 明显下降,延迟隐藏变差,可能比「多个小 kernel、高 occupancy」更慢。
  • 不利于并行:例如把可并行的两条独立链强行融成一个串行 kernel,或融合后 block 内负载不均(如分支多、warp divergence 增加)。
  • 编译/代码膨胀:融合多种组合导致 多份 kernel 或巨大泛化 kernel,编译慢、缓存差、或指令 cache 压力大。
  • 与硬件/调度不匹配:某些 GPU 上小 kernel 更易被调度器重叠;融合成一个大 kernel 反而减少 overlap。

三、建议

profile 确认瓶颈在 launch 与中间读写,再做融合;融合后 再 profile 看 occupancy、stall、throughput;若变慢,检查 register/shared、分支与并行度。


面试要点

  • 收益评估:省 launch 与中间 global 读写;用 profiler 对比融合前后时间,结合 roofline 看是否 memory bound。
  • 融合变慢:occupancy 掉太多、并行度下降、warp 效率变差、编译/代码膨胀、或调度重叠变差。
  • 先 profile 再融合,融合后再测 occupancy 与 throughput。

记忆要点

  1. 收益 = 少 launch + 少中间访存;用 profiler 和 roofline 评估,memory bound 时收益大。
  2. 变慢常见原因:register/shared 导致 occupancy 降、并行度/divergence 变差、编译膨胀。
  3. 流程:profile → 融合 → 再 profile(occupancy、stall);不行则回退或拆开。

返回模块 | 返回总览

04-编译器优化/README.md

04-编译器优化(第 31–45 题)

题号 主题 文章
31 TVM的Ansor和MetaSchedule的区别?如何搜索最优sche… 031-TVM的Ansor和MetaSchedule的区别.md
32 MLIR的设计哲学是什么?dialectoperation、`… 032-MLIR的设计哲学是什么.md
33 TorchInductor如何将PyTorch graph编译成Trit… 033-TorchInductor如何将PyTorch-graph编译成Triton.md
34 ONNX Runtime的图优化有哪些?`constant foldin… 034-ONNX-Runtime的图优化有哪些.md
35 TensorRT的plugin开发流程?如何支持dynamic shap… 035-TensorRT的plugin开发流程.md
36 解释loop tilingloop unrolling、`ve… 036-解释loop-tiling、loop-unrolling、vectoriza.md
37 量化编译中的PTQQAT在编译器层面如何处理? 037-量化编译中的PTQ和QAT在编译器层面如何处理.md
38 稀疏化(sparsity)如何被编译器利用?`2:4 structure… 038-稀疏化(sparsity)如何被编译器利用.md
39 编译器的pass manager如何工作?top-down vs `… 039-编译器的pass-manager如何工作.md
40 如何为新的硬件后端添加编译器支持?以自定义AI芯片为例 040-如何为新的硬件后端添加编译器支持.md
41 Apache TVM vs MLIR vs TorchDynamo,技术… 041-Apache-TVM-vs-MLIR-vs-TorchDynamo,技术路线.md
42 编译时优化和运行时优化的权衡?AOT vs JIT 042-编译时优化和运行时优化的权衡.md
43 如何处理编译器的编译时间过长问题?缓存策略? 043-如何处理编译器的编译时间过长问题.md
44 operator decomposing和`operator fus… 044-operator-decomposing和operator-fusion的边.md
45 编译器如何处理control flow(if/while)?`traci… 045-编译器如何处理control-flow(if-while).md

返回总览

04-编译器优化/031-TVM的Ansor和MetaSchedule的区别.md

第 31 题:TVM的Ansor和MetaSchedule的区别?如何搜索最优schedule?

题目

TVM的Ansor和MetaSchedule的区别?如何搜索最优schedule?


完整讲解

一、Ansor 与 MetaSchedule 的定位

Ansor(TVM 的 auto-scheduler):通过 层次化搜索空间(从 compute 到 threadblock 到 warp 到 tensor core)、随机采样 + 进化/爬山 生成 schedule,用 cost model(ML 或基于特征)预测性能并选优,再 实测 得到最优或近优 schedule。MetaSchedule 是 TVM 后续的 统一自动调度框架:把「搜索空间、采样、cost model、实测」抽象成模块,支持 多后端可扩展的 schedule 规则更丰富的搜索策略(如遗传、贝叶斯、ML-based),并集成到 TVM 主分支,逐步替代 Ansor 的用法。

二、主要区别

  • 抽象层次:Ansor 偏「一套完整 pipeline」;MetaSchedule 是「调度元框架」,规则与搜索可插拔、可复用到不同 DSL/IR。
  • 搜索空间与规则:MetaSchedule 更强调 schedule 规则 的声明式描述与组合,便于加新硬件/新 op 的规则;Ansor 的层次化空间是内置的。
  • 生态:MetaSchedule 与 TVM 的 TensorIR、新 BYOC 等配合,是当前 TVM 主推的自动调度路径;Ansor 仍可用但处于维护/迁移状态。

三、如何搜索最优 schedule?

通用流程:定义计算(TE 或 TensorIR)→ 定义/选择搜索空间(哪些 loop 可 tile、split、vectorize、并行等)→ 采样(随机或基于策略)→ cost model 打分直接实测选最优。Ansor/MetaSchedule 都提供「自动建搜索空间 + 自动搜索」;若要手控,可写 schedule 模板、只对少量参数(如 tile 大小)做 auto-tune。


面试要点

  • Ansor:TVM 的 auto-scheduler,层次化搜索空间 + cost model + 实测;MetaSchedule:统一调度框架,规则与搜索可插拔、多后端。
  • 区别:MetaSchedule 更模块化、可扩展,与 TensorIR 等配合,是当前主推;Ansor 是前代完整 pipeline。
  • 搜索最优:定义计算与搜索空间 → 采样 → cost model 或实测 → 取最优;可全自动或模板+少量 tune。

记忆要点

  1. Ansor = 层次化搜索 + cost model + 实测;MetaSchedule = 可插拔的调度框架,替代/扩展 Ansor。
  2. MetaSchedule 更模块化、多后端,与 TensorIR 集成;搜索流程:空间 → 采样 → 评估 → 选优。
  3. 最优 schedule:自动建空间 + 搜索,或手写模板 + 对关键参数 auto-tune。

返回模块 | 返回总览

04-编译器优化/032-MLIR的设计哲学是什么.md

第 32 题:MLIR的设计哲学是什么?dialectoperationpass的概念?

题目

MLIR的设计哲学是什么?dialectoperationpass的概念?


完整讲解

一、MLIR 的设计哲学

MLIR(Multi-Level Intermediate Representation)强调 多级抽象:不同前端、领域、硬件用不同 dialect 表达,通过 渐进式 loweringpass 逐步降级到更底层的 dialect,最终到 LLVM IR 或机器码。核心思想:可复用、可组合、可扩展——不强迫一种 IR 吃天下,而是「每一层用合适的抽象,层与层之间用 well-defined 的 op 与转换」连接。

二、Dialect、Operation、Pass 的概念

  • Dialect:一组 相关 operation类型/属性 的命名空间与语义集合;如 linalgtensorscfgpu。不同 dialect 对应不同抽象层级(高层如 linalg 的矩阵 op,底层如 gpu 的 launch、barrier)。
  • Operation:IR 中的 节点,表示一次计算、一次控制流、或一次区域构造;有 op 名(含 dialect 前缀)、operand、result、attribute、region 等。例如 linalg.matmulscf.forgpu.launch
  • Pass:对 IR 的 转换:分析、改写、或 lowering。Pass 输入输出通常是同一 dialect 或跨 dialect(如 linalg → loops → gpu);PassManager 负责顺序、条件执行与 pipeline。

三、为什么重要?

  • 分层 让前端(如 PyTorch、TensorFlow)和硬件后端(GPU、NPU)用各自 dialect,中间用标准转换衔接;复用 公共的 loop、memref、gpu 等基础设施。
  • 面试常问「和 LLVM 的关系」:MLIR 可降级到 LLVM IR,也可不经过 LLVM(如直接生成 GPU kernel);LLVM 是「一种后端」,MLIR 是「多级 + 多后端」的框架。

面试要点

  • MLIR 哲学:多级 IR、每层用合适抽象、渐进 lowering;可复用、可组合、可扩展。
  • Dialect = 一组 op/类型/属性的命名空间;Operation = IR 节点;Pass = 对 IR 的转换。
  • 分层便于前端与后端解耦,复用公共 loop/memref/gpu 等;可降到 LLVM 也可直出 kernel。

记忆要点

  1. MLIR = 多级 IR,不同 dialect 对应不同抽象,渐进 lowering。
  2. Dialect(命名空间)→ Operation(节点)→ Pass(转换);PassManager 管顺序。
  3. 前端/后端用不同 dialect,中间用 pass 衔接;可接 LLVM 或直出后端。

返回模块 | 返回总览

04-编译器优化/033-TorchInductor如何将PyTorch-graph编译成Triton.md

第 33 题:TorchInductor如何将PyTorch graph编译成Triton kernel?

题目

TorchInductor如何将PyTorch graph编译成Triton kernel?


完整讲解

一、TorchInductor 的定位

TorchInductor 是 PyTorch 2 的 默认编译后端:把 FX graph(或 Dynamo 捕获的 graph)转成 高性能代码;对 GPU 主要生成 Triton kernel,对 CPU 生成 C++/OpenMP 等。流程大致:Graph 捕获图级优化lowering 到 Inductor IR(ops)按 op/融合块生成 Triton 或 C++编译并调用

二、从 PyTorch graph 到 Triton 的步骤

  • Graph 输入:Dynamo 或 FX 得到的 ATen ops 组成的计算图(可能带 guards 与重放)。
  • 图优化:如 算子融合(把 matmul+add+relu 等合成一个节点)、等价替换常量折叠layout 优化;在 Inductor 的 IR 层Scheduler 把多个 op 分组成 fusion 节点(一个 fusion 对应一个或若干 Triton kernel)。
  • Lowering 到 Triton:每个 fusion 或单 op 被 codegen 成 Triton 的 Python 源码(@triton.jit 函数);Triton 编译器把这段代码编译成 GPU kernel;Inductor 再生成 调用这些 kernel 的 Python/C++ 胶水(grid、传入 tensor ptr 等)。
  • 运行:首次或 shape 变化时 编译 Triton,得到 so;后续同 shape 直接调缓存的 kernel。

三、关键点

  • 融合决策:Inductor 的 scheduler 决定哪些 op 放在同一个 kernel(考虑依赖、读写、收益);过大会 register 压力大,过小则 launch 多。
  • Triton 作为目标:块级、易 auto-tune(tile size、num_warps),与 PyTorch 生态统一;不直接出 CUDA 是兼顾开发效率与性能。

面试要点

  • Inductor 流程:FX/Dynamo graph → 图优化(融合、常量折叠等)→ Lowering 到 Inductor IR → Scheduler 分组 → 生成 Triton 源码 → Triton 编译成 kernel。
  • 融合由 Scheduler 决定;每个 fusion 对应一段 Triton 代码,再编译成 so 执行。
  • 选 Triton 做 GPU 目标:块级、可 tune、与 PyTorch 统一;首跑或 shape 变时编译并缓存。

记忆要点

  1. 路径:PyTorch graph → 图优化 → Inductor IR → 按 fusion 生成 Triton → 编译成 kernel。
  2. Scheduler 决定哪些 op 进同一 kernel;codegen 出 Triton Python,Triton 编译出 so。
  3. Triton 作为目标:易融合、易 tune、与 PyTorch 栈一致。

返回模块 | 返回总览

04-编译器优化/034-ONNX-Runtime的图优化有哪些.md

第 34 题:ONNX Runtime的图优化有哪些?constant foldingoperator fusion

题目

ONNX Runtime的图优化有哪些?constant foldingoperator fusion


完整讲解

一、ONNX Runtime 图优化概览

ONNX Runtime 在加载 ONNX 模型后会做一系列 图级优化(graph-level passes),在保持语义等价的前提下减少 op 数、减少访存、提升执行效率。常见包括:常量折叠算子融合冗余消除layout 转换子图替换(用更快的融合 op 替代多 op 子图)等。

二、Constant folding

Constant folding:若某 op 的输入都是 常量(如 initializer 或前序 fold 的结果),在 编译时 直接算出该 op 的输出,用 常量 替换该节点,从而减少运行时计算。例如 Add(Const(1), Const(2)) → 替换为 Const(3)。可递归做,直到没有新的常量可算。收益:少 kernel、少中间 tensor,有时还能触发后续更多融合。

三、Operator fusion

Operator fusion:把 多个小 op 合并成一个融合 op(如 Conv+BN+Relu → 一个 FusedConvBNRelu kernel),减少 kernel launch 与中间结果读写。OR 内置多种 融合规则(pattern:某一子图 → 一个融合 op);也支持 EP(Execution Provider) 提供的融合(如 CUDA EP 的 Conv+Add+Relu 等)。与 constant folding 配合:先 fold 掉常量,图更简单,融合 pattern 更易匹配。

四、其他常见优化

  • 冗余消除:重复的 transpose、identity、零贡献的 op 删除或合并。
  • Layout 优化:选择 NCHW/NHWC 等,与 EP 和 kernel 实现对齐。
  • 子图替换:用更高效的实现替换整块子图(如 Attention 整块用 FlashAttention 等)。

面试要点

  • OR 图优化:常量折叠、算子融合、冗余消除、layout、子图替换等;在加载模型后、执行前做。
  • Constant folding:常量输入在编译期算完,用常量替换节点,可递归;利于后续融合。
  • Operator fusion:多 op 合并为融合 kernel,减少 launch 与中间读写;按 pattern 匹配,EP 可扩展。

记忆要点

  1. ONNX Runtime 图优化:constant folding、operator fusion、冗余消除、layout、子图替换。
  2. Constant folding = 编译期算常量 op,节点换常量;fusion = 多 op 一 kernel,按 pattern。
  3. 先 fold 再 fusion 更易匹配;EP 可提供额外融合规则。

返回模块 | 返回总览

04-编译器优化/035-TensorRT的plugin开发流程.md

第 35 题:TensorRT的plugin开发流程?如何支持dynamic shape?

题目

TensorRT的plugin开发流程?如何支持dynamic shape?


完整讲解

一、TensorRT Plugin 开发流程

Plugin 用于在 TensorRT 中实现 不支持的 op自定义融合。流程要点:

  • 定义 Plugin 类:继承 IPluginV2DynamicExt(或 V2 的静态 shape 版本),实现 getOutputDimensionsenqueueconfigurePlugincloneserialize/deserialize 等;Dynamic 版本支持运行时 shape。
  • 注册:通过 REGISTER_TENSORRT_PLUGIN(MyPluginCreator) 把 plugin 注册到 TensorRT,parser(ONNX 等)通过 op 类型名plugin 名 找到并实例化。
  • 与 ONNX 对接:在 ONNX 里把自定义 op 的 op_type 写成 TRT 注册的 plugin 名,或使用 trt.OnnxParser 的 custom op 映射;必要时写 ONNX 到 TRT 的转换(把 ONNX 节点转成 Plugin 层)。
  • 构建与运行builder 构建 engine 时会把对应节点建为 Plugin 层;enqueue 在推理时被调用,里层写 CUDA kernel 或调库。

二、如何支持 dynamic shape?

  • 用 Dynamic 接口:实现 IPluginV2DynamicExt,在 getOutputDimensions 里根据输入维度 推导 输出维度(可含 -1 或符号);在 configurePlugin 里根据 min/max/opt profile 做准备(如选 kernel、分配 workspace)。
  • enqueue:接收实际 inputDimsoutputDims,根据 当前 shape 启动对应 kernel 或分支;若不同 shape 需不同实现,可在 plugin 内按 shape 分派。
  • Profile:builder 阶段要设 min/max/opt shape,TRT 会为 dynamic 维度做优化或选 kernel;plugin 的 configurePlugin 会收到这些范围,可据此预分配或选策略。

三、注意点

  • 序列化:plugin 参数、类型要在 serialize 里写全,deserialize 时还原,否则 engine 跨进程/版本会失败。
  • 线程安全:clone 与多 context 并发要按 TRT 文档保证正确。
  • 性能:dynamic shape 下 TRT 可能为多 shape 生成多 kernel 或通用 kernel,plugin 内也可自己按 shape 选最优实现。

面试要点

  • Plugin 流程:实现 IPluginV2DynamicExt(或 V2)、实现 getOutputDimensions/enqueue/configurePlugin/serialize;注册并和 ONNX op 对应。
  • Dynamic shape:用 Dynamic 接口,getOutputDimensions 推导输出维;enqueue 按实际 shape 派发;设 min/max/opt profile。
  • 序列化要完整;多 context 注意线程安全;dynamic 下可按 shape 选 kernel。

记忆要点

  1. Plugin = 继承 IPluginV2DynamicExt,实现 getOutputDimensions、enqueue、configure、serialize;注册后 parser 可挂到图上。
  2. Dynamic:输出维由输入维推导;enqueue 看实际 dims;builder 设 profile。
  3. 序列化完整、线程安全;dynamic 时可按 shape 多分支实现。

返回模块 | 返回总览

04-编译器优化/036-解释loop-tiling、loop-unrolling、vectoriza.md

第 36 题:解释loop tilingloop unrollingvectorization在编译器优化中的作用

题目

解释loop tilingloop unrollingvectorization在编译器优化中的作用


完整讲解

一、Loop tiling(分块)

Tiling 把大循环 按块划分:外层遍历「块」,内层遍历「块内」。例如 for i in 0..N 变成「for bi 遍历块,for i 遍历块内」。作用:提高局部性——块内数据可放进 cache 或 register,重复使用后再换下一块,减少主存/全局内存访问;同时便于 并行(不同块可不同 thread/block)。在矩阵乘、卷积等里 tiling 是基础优化,对应 CUTLASS/TVM 的 threadblock tile、warp tile。

二、Loop unrolling(循环展开)

Unrolling 把循环体 复制多份,减少循环判断与分支、增加指令级并行与寄存器复用。例如 for (i=0;i<4;i++) a[i]=... 展开成 4 条赋值。编译器可自动做(#pragma unroll 或 -O3),也可手写。注意:展开过多会 代码膨胀、register 压力大;要结合 tiling 与后端限制(如 GPU 每 block register 数)权衡展开因子。

三、Vectorization(向量化)

向量化 让一条指令处理 多个数据(SIMD):用向量 load/store、向量运算代替标量循环。例如标量 for i: c[i]=a[i]+b[i] 变成向量 c[0:4]=a[0:4]+b[0:4]。作用:提高吞吐、更好利用 带宽与算力。在 CPU 上对应 SSE/AVX/NEON;在 GPU 上对应 warp 内线程协作、或 tensor core。编译器通过 循环向量化 pass 或显式向量类型实现;需 连续/对齐访问、无循环依赖等条件。

四、在编译器中的配合

  • Tiling 先缩小「单块」规模,使块内适合 cache/register,并为 unroll/vectorize 提供小范围循环。
  • Unroll 在块内减少分支、增加并行与复用。
  • Vectorize 在最内层或合适层级用 SIMD/向量指令提高吞吐。
  • 三者常一起用:tile 外层 → 内层 unroll + vectorize;TVM/MLIR 的 schedule 或 pass 会应用这些变换。

面试要点

  • Tiling:按块划分循环,提高局部性、利于 cache/并行;矩阵类算子的基础。
  • Unrolling:复制循环体,减分支、增指令并行与复用;过度会代码膨胀、register 压力大。
  • Vectorization:SIMD/向量指令,提高吞吐;需连续访问、无依赖等;与 tiling/unroll 配合。

记忆要点

  1. Tiling = 分块,提局部性、利 cache 与并行;unroll = 展开减分支;vectorize = SIMD 提吞吐。
  2. 顺序常为:tile 外层 → 内层 unroll + vectorize;编译器 pass 或 schedule 应用。
  3. 三者配合:tile 定块大小,块内 unroll/vectorize 榨取性能。

返回模块 | 返回总览

04-编译器优化/037-量化编译中的PTQ和QAT在编译器层面如何处理.md

第 37 题:量化编译中的PTQQAT在编译器层面如何处理?

题目

量化编译中的PTQQAT在编译器层面如何处理?


完整讲解

一、PTQ 与 QAT 在编译器视角

PTQ(Post-Training Quantization):训练完后 一次性 用校准数据统计 scale/zero_point(或分布),把权与激活量化;QAT(Quantization-Aware Training):训练时 前向用量化、反向用直通估计,权重按量化格式更新。编译器不负责「怎么定 scale」,但负责:把浮点图转成量化图(插入/改写 quantize/dequantize、整数 op)、融合 Q/DQ 与相邻 op选择后端支持的量化 op(如 int8 conv、per-channel 等)。

二、PTQ 在编译层的处理

  • 图改写:根据 已定的 scale/zero_point(由校准阶段产生,存在模型或配置里),把 Float op 换成 Quantized op(权与激活用 int8/uint8),并在合适位置插 QuantizeLinear / DequantizeLinear(或等价节点)。
  • 融合Q → Op → DQ 常融合成「量化 op」一个 kernel(如 int8 conv),减少往返整数与浮点的转换。
  • 常量折叠:权重量化后的常量可 fold 进引擎或 kernel,不占运行时计算。

三、QAT 在编译层的处理

  • 训练时:编译器/框架把「假量化」(fake quantize:前向量化再反量化、梯度直通)当成普通 op 建图;通常不在此阶段做激进融合,以便梯度正确。
  • 导出/部署时:QAT 导出的图往往 已带 Q/DQ 或量化参数;编译器同样做 图改写与 Q-Op-DQ 融合,与 PTQ 导出后的处理类似;区别是 scale 来自训练过程而非事后校准。
  • 统一点:无论 PTQ 还是 QAT,部署侧 都是「量化图 + 融合 + 后端 int8 实现」;编译器不区分 scale 来源,只按图上 Q/DQ 与 op 做融合与 lowering。

四、小结

  • PTQ:校准得到 scale → 图改写为量化 op + Q/DQ → 融合 Q-Op-DQ。
  • QAT:训练时假量化,导出带 Q/DQ 的图 → 部署时同样改写与融合。
  • 编译器重点:图级量化 op 插入/替换、Q-DQ 与 op 融合、对接到后端 int8 kernel。

面试要点

  • 编译器不决定 scale,只做:量化图改写(Q/DQ、整数 op)、Q-Op-DQ 融合、对后端 int8 实现。
  • PTQ:校准后图改写 + 融合;QAT:导出图已带 Q/DQ,部署时同样改写与融合。
  • 融合减少 Q/DQ 往返;训练时假量化一般不做激进融合以保梯度。

记忆要点

  1. PTQ/QAT 的 scale 由校准或训练定;编译器做图改写与融合。
  2. 共同处理:插入/替换量化 op、融合 Q-Op-DQ、对接 int8 后端。
  3. QAT 导出图带 Q/DQ;部署侧与 PTQ 一样做融合与 lowering。

返回模块 | 返回总览

04-编译器优化/038-稀疏化(sparsity)如何被编译器利用.md

第 38 题:稀疏化(sparsity)如何被编译器利用?2:4 structured sparsity的硬件支持?

题目

稀疏化(sparsity)如何被编译器利用?2:4 structured sparsity的硬件支持?


完整讲解

一、稀疏化如何被编译器利用?

稀疏化(sparsity)指权重或激活中大量为 0;编译器可 识别稀疏表示(如 COO、CSR、block-sparse、2:4 结构)并做:一、稀疏 kernel(只算非零或按块跳过);二、 图改写(把 dense op 换成 sparse op、或插入稀疏格式转换);三、 与融合/调度结合(如稀疏 matmul 后接的激活可融合进同一 kernel)。前提是 IR 或前端能表达「稀疏」——要么用稀疏类型/属性,要么用专门 op(如 SparseTensor、2:4 压缩 op)。

二、2:4 structured sparsity 是什么?

2:4 稀疏:每连续 4 个元素中恰好 2 个非零(2 个为 0);是 NVIDIA 在 Ampere 上支持的格式,硬件可 一条指令 完成「2:4 稀疏 × 稠密」的乘加,吞吐高于纯稠密。编译器/库(如 cuSPARSELt)需要:一、 把权重量化成 2:4 格式(含索引/元数据);二、 在图上用 2:4 稀疏 op(或调用库)替代原 dense matmul;三、 保证 layout 与硬件约定一致(如 4 元组内 2 非零的索引编码)。

三、硬件支持与编译配合

  • Ampere 及更新:Tensor Core 支持 2:4 稀疏 GEMM;编译器/运行时选「稀疏 GEMM」实现,并保证权重已按 2:4 剪枝与编码。
  • 剪枝:2:4 通常由 训练时或训后剪枝 得到,编译器侧主要做 格式转换 + 图替换,不负责「剪哪两个」。
  • 其他稀疏:非 2:4 的稀疏(如任意稀疏、block-sparse)多由 软件 实现(稀疏 kernel、或先解压再算);编译器可做稀疏 op 融合、layout 选择等。

面试要点

  • 编译器利用稀疏:选稀疏 kernel、图改写为稀疏 op、与融合/调度结合;需 IR 能表达稀疏类型或稀疏 op。
  • 2:4:每 4 元组中 2 非零;Ampere+ 有硬件支持,编译器/库用 2:4 op 替代 dense matmul,权重要按 2:4 编码。
  • 2:4 由训练/剪枝得到;编译器做格式与图替换;其他稀疏多软件实现。

记忆要点

  1. 稀疏利用:稀疏 kernel、图改写、融合;IR 需能表达稀疏或专用 op。
  2. 2:4 = 每 4 个中 2 个非零;Ampere Tensor Core 支持,需权重 2:4 编码。
  3. 编译器做 2:4 图替换与格式对接;非 2:4 稀疏多走软件 kernel。

返回模块 | 返回总览

04-编译器优化/039-编译器的pass-manager如何工作.md

第 39 题:编译器的pass manager如何工作?top-down vs bottom-up遍历?

题目

编译器的pass manager如何工作?top-down vs bottom-up遍历?


完整讲解

一、Pass manager 在做什么?

Pass manager 负责 按顺序或条件执行一系列 pass(每个 pass 对 IR 做分析或变换):保证 依赖关系(如 A pass 在 B 之前)、失效信息的维护(某 pass 改了 IR,后续可能依赖的分析要重算或标记失效)、可选并行(无依赖的 pass 可并行)。用户或编译器把 pass 注册成 pipeline,run 时依次执行,直到得到目标 IR 或完成优化。

二、Top-down 与 bottom-up 遍历

  • Top-down:从 根/入口子节点/后继 遍历(如从函数到 block 到 op 到 operand)。适合:先处理「外层结构」再处理内层;例如先决定「这个 loop 要不要展开」再处理内部 op。某些分析(如 dominance、CFG)也常从入口向下。
  • Bottom-up:从 叶子/无后继 遍历(如从 use 到 def、从子 region 到父)。适合:先知道「子节点/子区域」的结果再决定父节点;例如 常量折叠 要先知道 operand 是否常量(子已算完),再决定当前 op 能否 fold;指令调度 有时从 def-use 链底往上排。
  • 在 pass 中的应用:不同 pass 按需求选遍历顺序;有的 pass 内部用 top-down(如 legalization 从外到内),有的用 bottom-up(如 fold、CSE);PassManager 只保证 pass 之间的顺序,每个 pass 内部可自定遍历。

三、与 MLIR/LLVM 的对应

  • MLIR:PassManager 跑 pass pipeline;遍历 IR 时可按 region 块op 列表 做 top-down 或 bottom-up;walk 可指定顺序。
  • LLVM:FunctionPass、ModulePass 等;分析/变换的遍历顺序由各 pass 实现(如 dom tree 先算再 top-down 用)。

面试要点

  • Pass manager:按序/条件执行 pass,管依赖与失效;用户组 pipeline,run 时依次执行。
  • Top-down:根→子,先外后内;bottom-up:叶子→根,先子后父(如 fold 需先知道 operand)。
  • 不同 pass 按需选遍历;PassManager 管 pass 顺序,单 pass 内可自定 top-down/bottom-up。

记忆要点

  1. Pass manager = 顺序执行 pass、管依赖与失效;pipeline 由用户/编译器注册。
  2. Top-down = 根到子;bottom-up = 子到根;fold 等常用 bottom-up。
  3. 遍历顺序由各 pass 自定;PassManager 不强制单 pass 内顺序。

返回模块 | 返回总览

04-编译器优化/040-如何为新的硬件后端添加编译器支持.md

第 40 题:如何为新的硬件后端添加编译器支持?以自定义AI芯片为例

题目

如何为新的硬件后端添加编译器支持?以自定义AI芯片为例


完整讲解

一、为新硬件添加编译器支持要做什么?

自定义 AI 芯片 为例,大致层次:一、 在编译器 IR 中能 表达 该硬件的计算与数据(新 dialect 或扩展现有 dialect);二、 实现 lowering:从高层 op(如 linalg、tensor)降到该硬件的 op/指令;三、 代码生成runtime 接口:生成该芯片可执行的代码/配置,或调其 driver/SDK;四、 调优:tile 大小、映射、双缓冲等,可手写规则或接 auto-schedule。

二、以 MLIR 为例的落地步骤

  • 定义 Dialect:为自定义芯片建 dialect,定义其 operation(如 mychip.computemychip.copy)、类型(如 mychip.buffer)、属性(如 tile 大小、mapping)。这样高层图可 lower 到「mychip 的 op」。
  • Lowering passes:写 passlinalgtensorscf 等降到 mychip op;包括 loop 到硬件的映射(哪个 loop 对应哪个维度、tiling、并行)。
  • Codegen / Runtime:把 mychip op 序列转成该芯片的 指令流API 调用(如 DMA、compute、sync);若芯片有自家编译器,可能生成其 IR 或源码。
  • 集成与测试:在统一 pipeline 里插「高层 → mychip dialect → codegen」;用典型子图/模型做正确性与性能回归。

三、以 TVM 为例

  • Target:注册新 target(如 mychip),声明能力(thread、vector 等)。
  • Schedule / TIR:高层 TE 或 TensorIR lower 到 TIR;为 mychip 写 schedule 规则TIR 到设备代码 的 codegen。
  • Runtime:实现 DeviceAPI、kernel 加载等,使 host 能调该芯片上的 kernel。

四、共性

  • 抽象:用 IR/dialect 描述硬件能力与映射;lowering:高层 → 设备相关 op/IR;codegen/runtime:出可执行形式。
  • 新硬件往往要 手写或半自动 的映射与 codegen,再逐步加 auto-tune。

面试要点

  • 三步:用 IR/dialect 表达硬件、写 lowering 从高层到该 dialect、codegen 或 runtime 出可执行代码。
  • MLIR:新 dialect + op/类型 → lowering pass → codegen/runtime;TVM:target + schedule/codegen + DeviceAPI。
  • 新芯片通常先手写映射与 codegen,再补 auto-tune 与融合规则。

记忆要点

  1. 新后端 = 表达(dialect/IR)+ lowering(高层→设备 op)+ codegen/runtime。
  2. MLIR:dialect + passes + codegen;TVM:target + schedule + DeviceAPI。
  3. 先实现正确性与基本映射,再优化与 auto-tune。

返回模块 | 返回总览

04-编译器优化/041-Apache-TVM-vs-MLIR-vs-TorchDynamo,技术路线.md

第 41 题:Apache TVM vs MLIR vs TorchDynamo,技术路线差异?

题目

Apache TVM vs MLIR vs TorchDynamo,技术路线差异?


完整讲解

一、Apache TVM

TVM端到端深度学习编译器:从 Relay(高层计算图)或 TensorIR调度与优化(auto-schedule 如 MetaSchedule、手写 schedule)到 TIR,再 codegen 到 LLVM/CUDA/Metal 等。特点:以性能为导向搜索/模板 做算子级优化、多后端(CPU/GPU/NPU);偏「从图到可执行」的完整栈,IR 自成一系(Relay、TIR),与 PyTorch/TF 通过 前端导入(ONNX、TorchScript 等)连接。

二、MLIR

MLIR多级 IR 与基础设施:不绑死某一前端或后端,提供 Dialect、Operation、Pass 抽象,让不同项目定义自己的 dialect 并 渐进 lowering。TensorFlow、IREE、TPU 等都用 MLIR;PyTorch 的 LTC 也可用 MLIR。特点:可扩展、可复用、强调「层与层之间的接口」;偏 编译器基础设施,具体「怎么从 PyTorch 到 GPU」由上层项目(如 Torch-MLIR、IREE)完成。

三、TorchDynamo

TorchDynamo 是 PyTorch 2 的 图捕获机制:通过 CPython 帧的 bytecode 与 guard,在 运行时 追踪执行、重建计算图(FX graph),再交给 后端(如 Inductor、ONNX、或自定义)编译。特点:不改用户代码(装饰器或默认开启)、按需编译、guard 失效则重捕获;偏 捕获与兼容,与 Inductor 组合成「Dynamo 捕获 → Inductor 编译」的 PyTorch 2 默认路径。

四、技术路线差异简表

维度 TVM MLIR TorchDynamo
定位 端到端编译器 多级 IR 基础设施 图捕获与分发
前端 Relay/TensorIR、ONNX 等 各项目自定 PyTorch 运行时
优化 Schedule、AutoTVM/MetaSchedule Pass、各 dialect 交给后端(如 Inductor)
后端 LLVM/CUDA 等 多后端、可接 LLVM Inductor/ONNX 等

面试要点

  • TVM:端到端编译器,Relay/TensorIR → schedule → TIR → codegen;多后端、重搜索与性能。
  • MLIR:多级 IR 框架,dialect/pass 可扩展;各项目在其上建前端与后端;偏基础设施。
  • TorchDynamo:PyTorch 图捕获(bytecode+guard),不绑死后端;常与 Inductor 搭配。

记忆要点

  1. TVM = 端到端编译栈,自研 IR + schedule + codegen;MLIR = 多级 IR 基础设施,可扩展。
  2. Dynamo = 捕获图,后端可换;TVM/MLIR 偏「编译与优化」本身。
  3. 组合关系:Dynamo 可把图交给 ONNX/Torch-MLIR 等;TVM 可接 ONNX;MLIR 可作 TVM 或 PyTorch 的中间层。

返回模块 | 返回总览

04-编译器优化/042-编译时优化和运行时优化的权衡.md

第 42 题:编译时优化和运行时优化的权衡?AOT vs JIT

题目

编译时优化和运行时优化的权衡?AOT vs JIT


完整讲解

一、AOT 与 JIT 的含义

AOT(Ahead-of-Time):在 运行前(或部署前)完成编译,生成 固定 的可执行/库;运行时直接加载,无编译开销,启动快,但 无法根据运行时信息(如实际 shape、数据)再优化。JIT(Just-in-Time):在 首次运行或条件触发时 编译,可 根据当前 shape、设备、数据 做特化与优化,但 首包/首步延迟 高,且需 缓存 避免重复编译。

二、编译时 vs 运行时优化的权衡

  • 编译时:能做的 全局优化、激进融合、静态分配 多;但 无运行时信息(如真实 batch、序列长),只能按 profile 或符号做保守/多版本。AOT 偏编译时:一次编译,多次运行;适合 部署形态固定、对冷启敏感的场景。
  • 运行时:能 根据实际 shape、设备、甚至数据 选 kernel、做特化;但 编译不能太重,否则延迟不可接受。JIT 偏运行时:首次或条件触发编译,可特化;适合 动态 shape、多后端,接受一定首包成本。
  • 权衡启动与首步延迟(AOT 优)vs 特化与适配动态(JIT 优);编译时间与缓存(JIT 需缓存与失效策略);部署复杂度(AOT 需提前建好所有版本,JIT 需带编译器或预编译缓存)。

三、实践中的折中

  • AOT + 多版本:为常见 shape/profile 预编译多份,运行时按 shape 选;折中是 二进制数量与覆盖度
  • JIT + 缓存:首次编译后写盘或内存缓存,同 shape 直接用;guard 失效(如新 shape)再编译并更新缓存。
  • 分层:部分子图 AOT(稳定、热点),部分 JIT(动态、长尾);或 hybrid:AOT 主路径,JIT 兜底新 shape。

面试要点

  • AOT = 运行前编译,无运行时编译开销,启动快;无法根据运行时信息再优化。
  • JIT = 运行时编译,可特化 shape/设备,首包延迟高,需缓存与失效策略。
  • 权衡:冷启与固定性(AOT)vs 动态与特化(JIT);实践中可 AOT 多版本、JIT+缓存、或分层。

记忆要点

  1. AOT:提前编译、一次运行多次;JIT:运行时编译、可特化,首包慢。
  2. 编译时优化多但无运行时信息;运行时可特化但编译不能太重。
  3. 折中:AOT 多版本、JIT 缓存、或热点 AOT + 长尾 JIT。

返回模块 | 返回总览

04-编译器优化/043-如何处理编译器的编译时间过长问题.md

第 43 题:如何处理编译器的编译时间过长问题?缓存策略?

题目

如何处理编译器的编译时间过长问题?缓存策略?


完整讲解

一、编译时间为什么长?

AI 编译器要做的多:图优化(融合、等价替换)、schedule 搜索(auto-tune、多配置尝试)、lowering(多级 IR)、codegen(生成并调外部编译器如 nvcc/llvm)。尤其是 搜索/枚举多 shape/多后端 会成倍放大时间;首次cache 未命中 时用户会明显感到编译慢。

二、缓存策略

  • 按图/子图指纹缓存:对 计算图(或子图)做 hash(op 类型、拓扑、shape 符号、dtype 等),命中则直接加载 已编译产物(so、ptx、引擎文件),跳过编译。TorchDynamo/InductorTensorRTTVM 等都支持类似机制。
  • 按 shape 或 key 缓存:同一图、不同 shape 可能对应不同 kernel;用 (graph_id, shape_key)(config_hash) 做 key,只对 新 key 编译,其余用缓存。Guard 决定何时失效:例如「只有 shape 完全一致才命中」vs「符号 shape 兼容」。
  • 持久化:缓存写 磁盘(目录或数据库),进程重启、多进程可复用;带 版本/ABI 信息,避免错误复用。增量:只对 变更的子图或配置 重编,其余用旧缓存。
  • 分层缓存IR 级 缓存(优化后的图)、编译产物 缓存(so/engine);重编时可从 IR 缓存开始,只重做后端 codegen。

三、其他减编译时间的手段

  • 缩小搜索空间:少试几种 tile、少跑几轮 measure;用 cost model 代替部分实测。
  • 预编译 / 预热:部署时对 典型 shape 先跑一遍触发编译并写缓存;线上请求来时多命中。
  • 超时与降级:编译超时则用 未优化或通用 kernel 兜底,避免卡死。

面试要点

  • 编译慢原因:图优化、schedule 搜索、多级 lowering、多 shape/后端;搜索与多版本尤其耗时。
  • 缓存:按图/子图 hash、shape/key、guard 命中则跳过编译;持久化到盘、带版本、可增量。
  • 其他:缩小搜索、cost model、预编译预热、超时降级。

记忆要点

  1. 慢在:图优化、搜索、lowering、codegen;搜索与多 shape 放大时间。
  2. 缓存 key:图 hash、shape/config、guard;命中则加载 so/engine,否则编译并写缓存。
  3. 持久化、版本、预编译、超时降级可进一步减感知延迟。

返回模块 | 返回总览

04-编译器优化/044-operator-decomposing和operator-fusion的边.md

第 44 题:operator decomposingoperator fusion的边界在哪里?

题目

operator decomposingoperator fusion的边界在哪里?


完整讲解

一、Decomposing 与 fusion 在做什么?

算子分解(decomposing):把 大/复杂 op 拆成 多个小 op 或更基础的 op,以便:后端有实现、便于做更多 图级优化(如和相邻 op 再融合)、或 简化语义(如把自定义 op 用标准 op 表示)。算子融合(fusion):把 多个小 op 合并成 一个或少个 kernel,减少 launch、中间读写与调度开销。二者方向 相反:一个「拆」、一个「合」。

二、边界在哪里?

  • 何时先 decompose一、 某 op 在某后端 没有实现,需拆成该后端有的 op;二、 某 op 过于复杂,拆开后能匹配到更多 融合 pattern(例如拆成 A+B+C 再与前后 op 融成 A'+B');三、等价替换 以便用更优的融合子图(如某库的融合 Conv+BN+Relu 要求先有单独的 Conv/BN/Relu 再被识别)。
  • 何时不拆、直接融合一、 后端已有 高效融合实现(如 CuDNN 的 fused op),保留大 op 更优;二、 拆开会导致 无法再融合(如硬件只认「一整块」才给加速);三、 拆开 增加调度与 launch 开销、且无更好融合机会时,不拆更划算。
  • 边界:取决于 后端能力(有无单 op、有无融合 pattern)、图上下文(拆开后能否和邻居融得更好)、性能实测(拆+融 vs 保留大 op 谁快)。没有绝对规则,一般是 先 legalize(必要时 decompose)再 fusion,用 cost 或 heuristics 决定某处是否拆。

三、在 pipeline 中的顺序

常见顺序:前端图legalize(复杂/不支持的 op 做 decompose)→ 融合 pass(pattern 匹配,多 op 合一)→ lowering。有时 多轮:融合后再 legalize(新 op 可能需再拆),再融合。边界由 pass 顺序与每条规则的条件 共同决定。


面试要点

  • Decomposing = 拆成小 op,便于后端实现或后续融合;fusion = 多 op 合一 kernel,减 launch 与访存。
  • 边界:后端有无实现、拆开能否带来更好融合、实测谁快;先 legalize(含 decompose)再 fusion 常见。
  • 无绝对规则;多轮 legalize + fusion 时,每条规则的条件与顺序决定最终形态。

记忆要点

  1. 分解 = 拆(为后端或更好融合);融合 = 合(减 launch 与中间读写);方向相反。
  2. 先 decompose 当后端无实现或拆开能更好融合;不拆当有现成融合实现或拆了融不回来。
  3. Pipeline 常为 legalize(含 decompose)→ fusion;可多轮,边界由规则与顺序定。

返回模块 | 返回总览

04-编译器优化/045-编译器如何处理control-flow(if-while).md

第 45 题:编译器如何处理control flow(if/while)?tracing vs `symbolic executi…

题目

编译器如何处理control flow(if/while)?tracing vs symbolic execution


完整讲解

一、Control flow 带来的挑战

Control flow(if/while、动态分支)在 静态图 里不好直接表示:图是 DAG,而 if/while 有 环与分支。编译器要么用 专用节点(如 If/While 子图)、要么把控制流 线性化/展开,才能做优化与 codegen。难点:一、 捕获时要知道 走哪条分支(依赖数据或 shape);二、 优化时不能错误地假设「只走一条路径」;三、 不同路径可能对应不同 shape,需能表达或特化。

二、Tracing(追踪)

Tracing:用 一次或若干次 具体输入 跑一遍 程序,按 实际执行路径 记录 op 序列,得到 一条线性化的子图(无分支、无环,只有实际走过的 op)。优点:实现简单、图简单、易优化。缺点:只记录到走过的路径——若运行时走了 未追踪过的分支(如 if 的另一边),图就错或需 guard 失效重捕获循环 会被 展开成有限次,循环次数变或未知时难以正确。

三、Symbolic execution(符号执行)

Symbolic execution:用 符号(如符号变量表示 shape、或布尔表示条件)去 推理 分支与循环,生成 带条件 的图或 多路径 的表示(如「若 cond 则 A 否则 B」)。优点:能表达 未执行到的分支依赖符号的循环,更完整。缺点:实现复杂、路径/状态可能爆炸、与后端优化器的结合难(很多后端偏好线性图)。

四、实践中的折中

  • PyTorch Dynamo:偏 tracing(按执行追踪),用 guards(如 shape、dtype)保证「当前图仅当 guard 成立时有效」;分支或 shape 变则 break 并重捕获,或交给 fallback
  • TorchScript / FX:可 部分符号(如 Tensor 的 shape 符号)、部分 trace;控制流用 显式 If/Loop 节点 保留,后端再 lower 成具体实现。
  • 编译器侧:若图里已有 If/While 节点,lowering 时转成 目标后端的控制流(如 MLIR 的 scf.if、scf.while,或 LLVM 的 branch/loop);若来自 tracing,则图本身已无分支,只需处理「guard 失效」与重编。

面试要点

  • Control flow 难在:图要表达分支/环、捕获要知道走哪条路、优化不能误假设单路径。
  • Tracing:按执行记 op 序列,图简单但只含走过路径;未走分支或循环次数变会失效,需 guard 或重捕获。
  • Symbolic execution:用符号推理分支/循环,图更完整但实现复杂;实践中多 tracing + guard,或显式 If/Loop 节点。

记忆要点

  1. 控制流要专用节点或线性化;tracing 得线性子图,symbolic 得带条件/多路径。
  2. Tracing = 只记走过路径,简单但路径变则失效;symbolic = 符号推理,完整但复杂。
  3. Dynamo 用 tracing + guards;图中有 If/Loop 时 lowering 成后端控制流。

返回模块 | 返回总览

05-数据并行/README.md

05-数据并行(第 46–60 题)

题号 主题 文章
46 DDP的gradient bucketing机制是什么?bucket… 046-DDP的gradient-bucketing机制是什么.md
47 DDP的find_unused_parameters参数什么时候需要… 047-DDP的find_unused_parameters参数什么时候需要设置.md
48 FSDP的sharding strategy有哪些?`FULL_SH… 048-FSDP的sharding-strategy有哪些.md
49 FSDP的auto_wrap_policy如何配置?`size_ba… 049-FSDP的auto_wrap_policy如何配置.md
50 DeepSpeed的ZeRO-1/2/3分别offload了什么?显存节… 050-DeepSpeed的ZeRO-1-2-3分别offload了什么.md
51 混合精度训练中的loss scaling在分布式场景下如何处理? 051-混合精度训练中的loss-scaling在分布式场景下如何处理.md
52 梯度累积(gradient accumulation)在DDP中的正确实… 052-梯度累积(gradient-accumulation)在DDP中的正确实现方.md
53 分布式sampler如何保证每个epoch的数据不重复? 053-分布式sampler如何保证每个epoch的数据不重复.md
54 DDP的SyncBatchNorm原理?什么时候必须用? 054-DDP的SyncBatchNorm原理.md
55 如何排查分布式训练中的hang问题?NCCL_DEBUG=INFO的… 055-如何排查分布式训练中的hang问题.md
56 DDP的torchrunmp.spawn启动方式的区别? 056-DDP的torchrun和mp.spawn启动方式的区别.md
57 多机多卡训练时,如何设置NCCL_SOCKET_IFNAME和`NC… 057-多机多卡训练时,如何设置NCCL_SOCKET_IFNAME和NCCL_IB.md
58 梯度压缩(gradient compression)的方法有哪些?`fp… 058-梯度压缩(gradient-compression)的方法有哪些.md
59 异步训练(如Hogwild!)在工业界为什么很少用? 059-异步训练(如Hogwild!)在工业界为什么很少用.md
60 如何实现自定义的分布式优化器?继承`torch.optim.Optimi… 060-如何实现自定义的分布式优化器.md

返回总览

05-数据并行/046-DDP的gradient-bucketing机制是什么.md

第 46 题:DDP的gradient bucketing机制是什么?bucket size如何调优?

题目

DDP的gradient bucketing机制是什么?bucket size如何调优?


完整讲解

一、Gradient bucketing 在做什么?

DDP 在 backward 结束后要对所有参数的梯度做 all-reduce(或 reduce-scatter 等)以同步。若每个参数张量单独一次通信,小张量会产生大量小消息,通信效率差(延迟主导)。Gradient bucketing 的做法是:按参数在模型中的顺序(或按 size)把多个小梯度打包进一个 bucket,凑满一定大小(如 25MB)或到 bucket 数量上限后,整桶做一次 all-reduce,从而减少通信次数、提高带宽利用率。


二、机制要点

  • 桶的划分:参数按 model.parameters() 顺序(或 DDP 内部等价顺序)排列,依次填入 bucket,直到当前 bucket 的「待通信梯度总字节数」≥ bucket_cap_mb(默认约 25MB)或达到其他上限,就开新桶。
  • 通信时机:当某 bucket 内所有参数的梯度都已算完(即 backward 传到了该桶的最后一层),就立刻对该桶做 all-reduce;不必等全部 backward 结束,从而通信与计算可重叠
  • 重叠:靠「桶内参数顺序与 backward 顺序一致」保证:先算完的桶先通信,后面的 backward 和前面的 all-reduce 可并行。

三、bucket size(bucket_cap_mb)如何调优?

  • 过大:桶少、单次通信量大,要等桶内所有梯度都算完才能发,重叠机会少,可能 backward 后半段才集中通信,延迟高。
  • 过小:桶多、通信次数多,小消息多、带宽利用率低、延迟也高。
  • 经验:默认 25MB 对很多模型已不错;若 GPU 间带宽高、模型层多,可适当增大(如 50MB)让单次通信更饱满;若 模型小、梯度张量碎,可适当减小让更早的桶先发、增加重叠。可结合 profiler 看 all-reduce 与 backward 的时间线,调一两次对比。

面试要点

  • Bucketing = 多个小梯度打包成一桶,按桶做 all-reduce,减少通信次数、提高带宽利用。
  • 桶内参数顺序与 backward 一致,使「桶满即发」能与后续 backward 重叠。
  • bucket_cap_mb 过大重叠少、过小消息碎;按带宽与模型结构试 25MB 上下。

记忆要点

  1. 目的:小梯度打包成桶,按桶 all-reduce,减少次数、提高带宽。
  2. 桶满即发、与 backward 顺序一致,实现通信与计算重叠。
  3. 调优:默认 25MB;高带宽可略大,小模型可略小;用 profiler 看时间线。

返回模块 | 返回总览

05-数据并行/047-DDP的find_unused_parameters参数什么时候需要设置.md

第 47 题:DDP的find_unused_parameters参数什么时候需要设置?性能影响?

题目

DDP的find_unused_parameters参数什么时候需要设置?性能影响?


完整讲解

一、为什么会有「未使用参数」?

有些模型在部分 forward 路径里不会用到所有参数(例如多任务头只走一个分支、或条件计算里某分支不用某层)。backward 时,没参与计算的参数梯度为 None;DDP 默认假设「所有参数都会参与 backward」,在同步梯度时若发现某参数没有梯度会报错,避免静默错误。


二、find_unused_parameters=True 做什么?

设为 True 时,DDP 会在每次 backward 前扫描当前计算图,找出没有梯度的参数,在 all-reduce 时跳过这些参数(不参与通信、不更新)。这样「部分参数未使用」的模型(如多任务、稀疏 MoE 的 expert)就能正常跑 DDP。


三、什么时候需要设?

  • 需要:forward 里确实存在某些参数本轮未参与计算(如某 head 未用、某 expert 未选),且你希望 DDP 不报错、只同步「有梯度」的参数时,设 find_unused_parameters=True
  • 不需要:所有参数每轮都参与计算时,保持默认 False 即可。

四、性能影响

  • 额外开销:每次 backward 前要遍历计算图找未使用参数,有额外 CPU 与时间;图大时开销明显。
  • 通信:未使用参数不参与 all-reduce,通信量略减;但扫描开销常占主导。
  • 建议:只有模型确实存在「部分参数未用」时才开;若可以改模型结构让所有参数每轮都参与(如 dummy forward),优先改结构、保持 False,性能更好。

面试要点

  • 未使用参数 = 某轮 forward 未参与计算,梯度为 None;DDP 默认会报错。
  • find_unused_parameters=True = 扫描图找未使用参数,all-reduce 时跳过它们。
  • 性能:每次 backward 前扫描图有开销;仅在有「部分参数未用」时开,否则保持 False。

记忆要点

  1. 未使用参数:本轮未参与计算,梯度 None;DDP 默认报错。
  2. True = 扫描图、跳过未使用参数的同步;有扫描开销。
  3. 仅多任务/条件/稀疏 MoE 等确实存在未用参数时开;能避免则保持 False。

返回模块 | 返回总览

05-数据并行/048-FSDP的sharding-strategy有哪些.md

第 48 题:FSDP的sharding strategy有哪些?FULL_SHARD vs SHARD_GRAD_OP

题目

FSDP的sharding strategy有哪些?FULL_SHARD vs SHARD_GRAD_OP


完整讲解

一、FSDP 的 sharding 在 shard 什么?

FSDP 对参数(以及可选地梯度、优化器状态)做分片:每张卡只存 1/N,forward/backward 时按需 all-gather。Sharding strategy 决定「在哪个阶段对哪些东西做分片」。


二、常见策略(PyTorch FSDP 命名)

  • FULL_SHARD(全分片)参数、梯度、优化器状态都按卡分片。每卡显存最少;forward 时 all-gather 参数、算完就丢,backward 时 all-gather 再 reduce-scatter 梯度,优化器只更新本卡分片。通信量最大、显存最省,适合「模型很大、单卡放不下」。
  • SHARD_GRAD_OP参数可能每卡一份(或分片),梯度分片、优化器状态分片。即梯度与优化器做 ZeRO-2 式分片,参数可全复制或部分复制。显存比 FULL_SHARD 略高(若参数全复制),但通信比 FULL_SHARD 少(少参数 all-gather)。
  • NO_SHARD(或类似):参数、梯度都不分片,每卡一份,等价于 DDP;仅用 FSDP 的包装与调度,显存最大、通信最少。
  • HYBRID_SHARD:节点内全分片、节点间复制等混合,用于多机时平衡机内通信与机间通信。

三、FULL_SHARD vs SHARD_GRAD_OP

  • FULL_SHARD:参数+梯度+优化器全分片;显存最省,通信最多(每层 all-gather + reduce-scatter)。
  • SHARD_GRAD_OP:梯度(及优化器)分片,参数可全复制;显存略高,通信较少(无参数 all-gather 或减少)。适合「参数能放下、但梯度+优化器想省」的中间规模。

选型:单卡放不下整模型 → FULL_SHARD;能放下参数、只想省梯度和优化器 → SHARD_GRAD_OP 或 ZeRO-2 风格。


面试要点

  • FULL_SHARD = 参数+梯度+优化器全分片;显存最省,通信最多。
  • SHARD_GRAD_OP = 梯度(及优化器)分片,参数可全复制;通信较少,显存略高。
  • 选型按「单卡能否放下参数」与「要省到哪一层」决定。

记忆要点

  1. FULL_SHARD:全分片,显存最小,通信最大;SHARD_GRAD_OP:梯度/优化器分片,参数可复制。
  2. NO_SHARD ≈ DDP;HYBRID 用于多机。
  3. 模型过大用 FULL_SHARD;能放参数用 SHARD_GRAD_OP 折中。

返回模块 | 返回总览

05-数据并行/049-FSDP的auto_wrap_policy如何配置.md

第 49 题:FSDP的auto_wrap_policy如何配置?size_based vs module_based

题目

FSDP的auto_wrap_policy如何配置?size_based vs module_based


完整讲解

一、为什么需要 wrap policy?

FSDP 不是「整模型一个大块」做分片,而是把模型切成多个子模块,每个子模块是一个 FSDP 单元:单元内做 all-gather → 算 → 丢,单元间顺序执行。Wrap policy 决定「哪些子模块被包成 FSDP 单元」:包得太粗(如整模型一块)显存峰值高、重叠少;包得太细(每层一个)通信次数多、开销大。auto_wrap_policy 用规则自动决定包装边界。


二、size_based

  • 思路:按参数量划界;子树的参数总量超过某阈值(如 1e8)就包成一个 FSDP 单元,否则继续往子节点看。
  • 效果:大块(如一大坨 Linear)会单独成单元,小块会合并到父节点或相邻;单元大小相对均匀、易控显存峰值。
  • 配置:如 size_based_auto_wrap_policy(min_params=1e8),min_params 可调;调大则单元更大、通信次数少但单次 all-gather 大、显存峰值高。

三、module_based

  • 思路:按模块类型划界;指定「哪些类」的实例要包成 FSDP 单元(如 TransformerBlockResBlock),其他层和它们一起按层级包装。
  • 效果:与模型结构对齐,如每个 Transformer block 一个单元,便于理解和调优;对已知结构(如 Megatron 风格)很合适。
  • 配置:如 module_based_auto_wrap_policy(module_classes={TransformerBlock}),只对这些类做「切分点」。

四、如何选?

  • 结构清晰、有明确 block(如 Transformer、ResNet block):用 module_based,按 block 包,易控且符合直觉。
  • 结构杂、或想按参数量均衡:用 size_based,按 min_params 调到一个合适单元大小,平衡显存与通信。
  • 也可组合:先按 module 切几刀,再对剩余部分用 size_based;或手写 policy 函数,混合两种逻辑。

面试要点

  • Wrap policy 决定哪些子模块被包成 FSDP 单元;太粗显存高、太细通信多。
  • size_based:按参数量阈值(如 min_params)划单元;均衡、易控。
  • module_based:按模块类型(如 TransformerBlock)划单元;与结构对齐,易理解。

记忆要点

  1. 单元太粗→显存高;太细→通信多;policy 自动划界。
  2. size_based = 按参数量阈值;module_based = 按指定类(如 Block)。
  3. 有明确 block 用 module_based;否则或混合用 size_based。

返回模块 | 返回总览

05-数据并行/050-DeepSpeed的ZeRO-1-2-3分别offload了什么.md

第 50 题:DeepSpeed的ZeRO-1/2/3分别offload了什么?显存节省和通信开销的trade-off?

题目

DeepSpeed的ZeRO-1/2/3分别offload了什么?显存节省和通信开销的trade-off?


完整讲解

一、ZeRO 在解决什么?

数据并行时每卡存完整参数、梯度、优化器状态,显存是单卡的 3 倍量级(参数+梯度+优化器)。ZeRO 通过分片把这些状态分布到多卡,每卡只存 1/N,需要时再 all-gather 或 reduce,从而把总显存从 3× 降到约 3×/N(理想情况)。


二、ZeRO-1 / 2 / 3 各 offload(分片)了什么?

  • ZeRO-1:只分片优化器状态(如 Adam 的 momentum、variance);参数和梯度每卡仍完整。显存省「优化器」部分(约 2× 参数量),通信只在 optimizer step 时做一次 reduce-scatter/gather 类同步。
  • ZeRO-2:分片优化器状态 + 梯度。backward 后梯度 reduce-scatter 到各卡分片;优化器只更新本卡分片。显存再省「梯度」;通信增加 backward 后的梯度 reduce-scatter(以及 step 时的 gather 若需)。
  • ZeRO-3:分片优化器状态 + 梯度 + 参数。forward 时每层 all-gather 参数、算完丢;backward 时 all-gather 再 reduce-scatter 梯度。显存最省(约 3×/N),通信最多:每层都有 all-gather + reduce-scatter。

(「Offload」有时指 CPU/NVMe offload,如 ZeRO-Offload;这里 ZeRO-1/2/3 主要指跨卡分片,不涉及 CPU。)


三、显存与通信 trade-off

阶段 分片内容 显存(相对) 通信(相对)
ZeRO-1 优化器状态 省一部分 少(step 时)
ZeRO-2 优化器 + 梯度 再省 多(梯度 reduce-scatter)
ZeRO-3 优化器 + 梯度 + 参数 最省 最多(每层 all-gather + reduce-scatter)

选型:单卡能放下参数+梯度、只想省优化器 → ZeRO-1;能放参数、要省梯度 → ZeRO-2;单卡放不下参数 → ZeRO-3(或 + offload 到 CPU/NVMe)。


面试要点

  • ZeRO-1:只分片优化器状态;ZeRO-2:+ 梯度;ZeRO-3:+ 参数。
  • 显存:ZeRO-3 最省;通信:ZeRO-3 最多(每层 all-gather/reduce-scatter)。
  • Trade-off:省显存就要多通信;按单卡能否放下参数/梯度选 stage。

记忆要点

  1. ZeRO-1 = 优化器分片;ZeRO-2 = + 梯度分片;ZeRO-3 = + 参数分片。
  2. 显存 ZeRO-3 < ZeRO-2 < ZeRO-1;通信 ZeRO-3 > ZeRO-2 > ZeRO-1。
  3. 单卡放不下参数用 ZeRO-3;能放则 ZeRO-1/2 减通信。

返回模块 | 返回总览

05-数据并行/051-混合精度训练中的loss-scaling在分布式场景下如何处理.md

第 51 题:混合精度训练中的loss scaling在分布式场景下如何处理?

题目

混合精度训练中的loss scaling在分布式场景下如何处理?


完整讲解

一、Loss scaling 在做什么?

FP16 梯度容易下溢(太小变成 0),所以在 backward 前对 loss 乘一个 scale(如 2^16),梯度整体放大;在 optimizer step 前再 unscale(除回 scale),并检查 inf/nan,有则 skip step 并减小 scale。GradScaler 管这件事。


二、分布式下的要点

  • 每卡独立 scale:每张卡有自己的 scaler 和 scale 值;backward 时每卡用同一 loss 的 scale 后的值(若 loss 是各卡 local loss 的 mean/sum,先 scale 再 backward 或先 backward 再 scale 要一致)。
  • 一致性:若用 all-reduce 后的梯度(如 DDP),每卡 unscale 后梯度应一致;scaler 的 unscale 在每卡本地做,然后 all-reduce 梯度,所以每卡 unscale 的输入(本地梯度)在 DDP 里其实是「未 all-reduce 的本地梯度」——要在 all-reduce 之前 unscale,或对 all-reduce 之后的梯度 做一次 unscale(取决于框架实现)。常见做法:backward 时每卡 scale(loss).backward(),梯度是 scale 后的本地梯度;DDP 再 all-reduce;step 前每卡对 all-reduce 后的梯度 unscale,这样每卡看到的是同一份「全局梯度」的 unscale 结果。
  • Skip step:若某卡 unscale 后发现 inf/nan,该卡 skip step;所有卡必须一致 skip,否则会参数不一致。所以通常 scaler.step(optimizer) 里若 skip,会通过 collective(如 all_reduce 一个 flag)让所有进程一起 skip,并统一减小 scale。

三、总结

  • 每卡用同一套 scale 逻辑;unscale 的时机要对:要么对 all-reduce 前的本地梯度 unscale 再 all-reduce,要么对 all-reduce 后的梯度做一次 unscale(框架会封装好)。
  • Skip step 要全局一致:用 collective 同步「是否 skip」,避免部分卡更新、部分卡不更新导致分叉。

面试要点

  • Loss scaling:scale loss → backward → unscale 梯度 → step 或 skip;分布式下每卡 scale 一致。
  • Unscale 时机:与梯度 all-reduce 顺序要正确(通常 all-reduce 后对全局梯度 unscale,或框架封装)。
  • Skip step 必须所有卡一致,用 collective 同步 skip 与 scale 更新。

记忆要点

  1. 分布式下每卡同一 scale;unscale 与 all-reduce 顺序由框架保证。
  2. Skip 时所有卡一起 skip,用 all_reduce 同步 flag。
  3. 保证「全局梯度」只被 unscale 一次、所有卡同一 step/skip 决策。

返回模块 | 返回总览

05-数据并行/052-梯度累积(gradient-accumulation)在DDP中的正确实现方.md

第 52 题:梯度累积(gradient accumulation)在DDP中的正确实现方式?

题目

梯度累积(gradient accumulation)在DDP中的正确实现方式?


完整讲解

一、梯度累积的目的

想用 大 effective batch size,但单次 forward/backward 显存放不下那么大 batch,就分多步算:每步小 batch forward+backward,不立刻 step,梯度累加.grad 里;累加够 K 步后再 optimizer.step()zero_grad()。Effective batch = 单步 batch × K。


二、DDP 下的正确方式

  • 每步loss = model(x) / K(或 loss 不除 K、step 前对梯度除 K),loss.backward()。DDP 会对当前步的梯度做 all-reduce,所以每步 backward 后每卡的梯度已经是「当前步的全局梯度」
  • 累积不要在梯度累积的中间步调 optimizer.zero_grad();只在第 1 步前 zero_grad,然后 K 步内只 backward,梯度会自动累加(PyTorch 默认 grad += 新梯度)。
  • Step:第 K 步 backward 后,若 loss 没除 K,要对梯度 ÷K(或 optimizer 的 lr 等价成 lr/K),再 optimizer.step(),然后 optimizer.zero_grad() 为下一轮累积做准备。
  • No_sync:DDP 默认每次 backward 结束都会 all-reduce。梯度累积时前 K-1 步不需要同步(只累加本地梯度),可在这几步用 model.no_sync() 包住 forward/backward,最后一步不用 no_sync,让最后一步 backward 做 all-reduce,此时每卡上的梯度是「K 步累积后的全局梯度」。这样通信量从「K 次 all-reduce」变成「1 次」,正确且更高效。

三、小结

  • 前 K-1 步:with model.no_sync(): loss.backward(),不 all-reduce,梯度只在本卡累加。
  • 第 K 步:正常 loss.backward(),DDP all-reduce;若未对 loss 除 K,则 step 前 scaler.unscale_() 后对梯度除 K(或等价方式)。
  • 然后 optimizer.step()zero_grad()(若用 AMP 还有 scaler.update())。

面试要点

  • 累积 K 步再 step;中间步不 zero_grad;梯度自动累加。
  • 前 K-1 步用 no_sync() 关掉 all-reduce,最后一步再 all-reduce,通信从 K 次变 1 次。
  • Step 前若 loss 未除 K,需对梯度除 K(或调 lr)保证 effective batch 语义。

记忆要点

  1. 前 K-1 步 no_sync(),最后一步正常 backward 做 all-reduce。
  2. 中间不 zero_grad;step 后 zero_grad;梯度除 K 或 loss 除 K 二选一。
  3. 正确 + 高效 = no_sync 减通信。

返回模块 | 返回总览

05-数据并行/053-分布式sampler如何保证每个epoch的数据不重复.md

第 53 题:分布式sampler如何保证每个epoch的数据不重复?

题目

分布式sampler如何保证每个epoch的数据不重复?


完整讲解

一、目标

多卡数据并行时,每张卡用不同的数据子集,且整个 epoch 内所有卡合起来正好把数据集覆盖一遍、不重不漏。DistributedSampler 就是按 rank、world_size 把样本划分到各卡,并可选打乱(shuffle)后每卡只取自己的那一段。


二、常见做法(PyTorch DistributedSampler)

  • 划分:总样本数 N,world_size W。每卡样本数 n_per_rank = ceil(N/W),总长度可能补到 n_per_rank * W(不足用重复或 drop)。卡 rank 拿的下标rank, rank+W, rank+2W, ...,即按 rank 交错,这样每卡拿到不重叠的一批下标。
  • Shuffle:若 shuffle=True每个 epoch 开始时对「全局下标 0..N-1」做一次 shuffle(用相同的 seed,如 epoch),再按上面规则按 rank 取;这样每 epoch 每卡看到的顺序不同,但卡间仍不重叠。关键:所有进程用同一 seed(例如 sampler.set_epoch(epoch) 里用 epoch 作 seed),这样每卡上的 shuffle 结果一致,再按 rank 切分后仍不重不漏。
  • set_epoch(epoch):每个 epoch 调用一次 sampler.set_epoch(epoch),让 shuffle 的 seed 随 epoch 变,否则每个 epoch 每卡拿到的是同一顺序,可能影响收敛。

三、不重复的保证

  • 下标划分是确定性的(rank 0 拿 0,W,2W,...;rank 1 拿 1,W+1,...),且彼此无交。
  • Shuffle 后仍是「全局一个排列」,再按 rank 切,所以整个 epoch 内全局不重不漏;每卡内也无重复(除非 N 不能被 W 整除且实现用重复补齐,此时可能有个别样本重复,可选用 drop_last 去掉尾批)。

面试要点

  • 按 rank 交错取下标(rank, rank+W, ...),保证卡间不重叠。
  • Shuffle 用同一 seed(如 set_epoch(epoch)),再按 rank 切,保证全局不重不漏且每 epoch 顺序变。
  • 每 epoch 调用 set_epoch(epoch),否则每 epoch 顺序相同。

记忆要点

  1. 划分:下标按 rank 交错,每卡一段,不重叠。
  2. Shuffle:全局同一 seed(set_epoch),再切分;每 epoch 换 seed。
  3. 不重不漏 = 划分不交 + shuffle 一致;set_epoch 必须调。

返回模块 | 返回总览

05-数据并行/054-DDP的SyncBatchNorm原理.md

第 54 题:DDP的SyncBatchNorm原理?什么时候必须用?

题目

DDP的SyncBatchNorm原理?什么时候必须用?


完整讲解

一、普通 BatchNorm 在 DDP 下有什么问题?

BatchNorm当前 batch 的均值和方差做归一化。DDP 时每卡只有本地 batch(如 batch_size=32,每卡 32 个样本),BN 的 mean/var 只基于这 32 个样本;卡间统计量不一致,等价于「每卡在用自己的小 batch 做 BN」,和单卡大 batch(如 32×8=256)的 BN 统计量不同,可能影响精度和稳定性。


二、SyncBatchNorm 在做什么?

SyncBatchNorm 在算 mean/var 时跨卡同步:先在各卡上算本地 mean/var 和 count,再 all-reduce(或 all-gather 后合并)得到全局 mean/var,用全局统计量做归一化;反向时对「全局统计量」的梯度再做一次同步。这样 BN 的统计量与「单卡大 batch」一致,等价于用 global batch 做 BN。


三、什么时候必须用?

  • 小 local batch:每卡 batch 很小时(如 2、4),单卡 BN 统计量噪声大;用 SyncBatchNorm 用全局 batch 的统计量更稳定,建议用
  • 大 local batch:每卡已经很大(如 64、128),本地 BN 统计量已较准,SyncBN 收益小但有多一次同步开销;可不用,除非你刻意要「和单卡大 batch BN 完全一致」。
  • 多机 / 多卡数多:SyncBN 要 all-reduce,卡多时通信明显;若 local batch 够大,可权衡是否用。
  • 总结每卡 batch 小、或要严格对齐单卡大 batch BN 时用 SyncBatchNorm;local batch 大、且不强调一致时可不用。

四、实现要点

  • torch.nn.SyncBatchNorm.convert_sync_batchnorm(model) 把模型里的 BN 换成 SyncBN;或自己建 SyncBN 层。
  • SyncBN 内部在 forward 里做一次 all-reduce(mean/var),backward 里再做梯度同步;需保证进程组一致。

面试要点

  • 普通 BN 用本地 batch 统计量;DDP 下每卡本地 batch 小,统计量不一致。
  • SyncBN = 算 mean/var 时 all-reduce,用全局统计量做 BN,与单卡大 batch BN 一致。
  • 必须/建议用:每卡 batch 小、或要严格一致时;local batch 大时可不用。

记忆要点

  1. DDP 下 BN 用本地 batch → 卡间统计量不同;SyncBN 用全局 mean/var。
  2. SyncBN = forward/backward 里 all-reduce 统计量(及梯度)。
  3. 小 local batch 用 SyncBN;大 local batch 可不用。

返回模块 | 返回总览

05-数据并行/055-如何排查分布式训练中的hang问题.md

第 55 题:如何排查分布式训练中的hang问题?NCCL_DEBUG=INFO的输出如何解读?

题目

如何排查分布式训练中的hang问题?NCCL_DEBUG=INFO的输出如何解读?


完整讲解

一、分布式 hang 的常见原因

  • 集体通信不同步:某卡没参与某次 all-reduce/all-gather,或参与顺序/次数不一致,其他卡会一直等 → hang。
  • 死锁:例如某卡在等数据、另一卡在等梯度;或 DDP 里 find_unused_parameters 与梯度不同步导致某卡多/少一次通信。
  • 网络/驱动:丢包、超时、NCCL 与网络配置不匹配(如 IB 未正确配置),某次 collective 永远不返回。
  • 资源:某进程 OOM 或被 kill,其他进程一直等其参与 collective。

二、NCCL_DEBUG=INFO 能看什么?

设置 NCCL_DEBUG=INFO(或 WARN)后,NCCL 会打印每次 collective 的参与信息、transport 选择、超时等。典型输出包括:

  • 各 rank 的 transport:用 TCP 还是 IB、RoCE;若部分卡走 TCP、部分走 IB,可能慢或异常。
  • Collective 的 op 与 size:哪次 all-reduce、多少字节;可对照代码看「应该是第几次、多大」。
  • 超时 / 错误:若某卡没发或没收,会看到 timeout 或 peer 不可达;最后一行往往指向「谁在等谁」。
  • Rank 与 world_size:确认每卡认为的 rank 和 world_size 一致,避免漏进程或重复 rank。

三、如何用这些信息排查?

  • 先看最后几行:hang 时哪几个 rank 在等、等什么 op;若只有部分 rank 打印,说明有的进程已卡死或没进到该 collective。
  • 对照代码:确认 backward、optimizer.step、SyncBN、自定义 collective 的次数和顺序在所有 rank 上一致;不一致就会在某次 collective 上 hang。
  • 结合 PyTorch:用 TORCH_DISTRIBUTED_DEBUG=DETAIL 可打印每次 collective 的调用栈,看是 DDP、FSDP 还是用户代码里哪一步;再配合 NCCL_DEBUG 看是哪个 op 卡住。
  • 网络:看 transport 是否一致、是否有 IB 未 up、防火墙/端口问题;可先 NCCL_IB_DISABLE=1 强制 TCP 试是否能跑通。

四、小结

  • Hang 多为 collective 不同步或网络/进程异常;NCCL_DEBUG=INFO 看 transport、op、超时、rank。
  • 排查:最后输出看「谁在等」→ 对照代码找「谁多/少调了 collective」→ 结合 TORCH_DISTRIBUTED_DEBUG 定位调用点;网络问题可试关 IB 或查端口/防火墙。

面试要点

  • Hang 常见:collective 不同步、死锁、网络/进程异常。
  • NCCL_DEBUG=INFO:看 transport、collective op/size、超时、rank;最后几行指向「谁在等」。
  • 排查:对照代码保证每 rank 调用 collective 次数顺序一致;用 TORCH_DISTRIBUTED_DEBUG 看调用栈;网络可试 NCCL_IB_DISABLE=1。

记忆要点

  1. Hang ≈ collective 不同步或网络/进程挂;NCCL_DEBUG 看 op、transport、超时。
  2. 最后输出看谁在等;对照代码找多/少调用的 rank。
  3. TORCH_DISTRIBUTED_DEBUG=DETAIL + NCCL_DEBUG 组合定位;网络问题试 TCP-only。

返回模块 | 返回总览

05-数据并行/056-DDP的torchrun和mp.spawn启动方式的区别.md

第 56 题:DDP的torchrunmp.spawn启动方式的区别?

题目

DDP的torchrunmp.spawn启动方式的区别?


完整讲解

一、torchrun(推荐)

torchrun(原 torch.distributed.launch)是单命令启动多进程:在一台或多台机器上执行一次 torchrun --nproc_per_node=4 --nnodes=2 ... train.py,由 torchrun 进程 fork 出多个 worker(每 node 4 个,共 8 个),每个 worker 里会设好 RANKWORLD_SIZEMASTER_ADDRMASTER_PORT 等环境变量,然后执行 train.py不需要在脚本里写 spawn,脚本只需在入口处 init_process_group() 并拿到 rank;适合多机:主节点指定 --nnodes--node_rank,从节点用同样命令或通过 job 调度拿到相同 env 即可。


二、mp.spawn

torch.multiprocessing.spawn单机上由主进程 spawn 出 N 个子进程,每个子进程跑同一 train_fn(rank, ...);在 train_fn 里根据 rankinit_process_group(rank=rank, world_size=world_size, ...),需手动传或设 MASTER_ADDRMASTER_PORT(通常用本机 127.0.0.1)。不需要单独起多个进程再传 env,一切在一个 Python 进程里写:mp.spawn(train_fn, nprocs=4, args=(...))多机时不太方便,因为 spawn 是单进程起子进程,跨机要自己起多个进程并配好 env,不如 torchrun 统一。


三、区别小结

维度 torchrun mp.spawn
谁起进程 torchrun 命令行起多进程 脚本里主进程 spawn 子进程
环境变量 torchrun 自动设 RANK 等 需在 train_fn 里 init 时传 rank
多机 原生支持(--nnodes 等) 需自己起进程、配 env
脚本写法 脚本只 init_process_group 脚本里写 spawn + train_fn
推荐 生产与多机首选 单机快速试验、脚本自包含时可用

四、使用建议

  • 多机、生产、统一入口:用 torchrun,由调度器或运维一次启动,env 一致。
  • 单机、本地试跑:两种都行;torchrun 更简单(不用写 spawn),spawn 适合「一个脚本里包圆」的写法。

面试要点

  • torchrun:命令行起多进程、自动设 RANK/WORLD_SIZE/MASTER_*;支持多机;脚本只 init。
  • mp.spawn:单脚本里主进程 spawn 子进程,train_fn(rank) 里 init;多机需自配。
  • 选型:多机/生产用 torchrun;单机可 torchrun 或 spawn。

记忆要点

  1. torchrun = 外部起进程 + 自动 env;mp.spawn = 脚本内 spawn + 手动传 rank。
  2. 多机用 torchrun(--nnodes、--node_rank);单机两者皆可。
  3. 脚本写法:torchrun 下只写 init;spawn 下写 spawn(train_fn, nprocs, args)。

返回模块 | 返回总览

05-数据并行/057-多机多卡训练时,如何设置NCCL_SOCKET_IFNAME和NCCL_IB.md

第 57 题:多机多卡训练时,如何设置NCCL_SOCKET_IFNAMENCCL_IB_DISABLE

题目

多机多卡训练时,如何设置NCCL_SOCKET_IFNAMENCCL_IB_DISABLE


完整讲解

一、NCCL_SOCKET_IFNAME

NCCL 做 TCP 通信(bootstrap 或 fallback transport)时要绑定网卡接口。多机多网卡时,若用错网卡(如用了管理网、带宽小的网),会慢或连不上。NCCL_SOCKET_IFNAME 指定使用的网络接口名,如 eth0ib0(部分环境里 IB 也走 socket 名)、bond0 等。

  • 设成什么:用 ifconfigip link 看本机网卡名,选数据面、高带宽的那块(如万兆、IB);设成该名,如 export NCCL_SOCKET_IFNAME=eth1
  • 多机一致:各节点同一逻辑角色的网卡名最好一致(都是 eth1),否则要在每台机设对;若名不一致,可每台机单独设或通过调度器传 env。
  • 不设:NCCL 会自选,可能选到 lo 或错误网卡,多机常连不上或很慢,建议显式设

二、NCCL_IB_DISABLE

NCCL_IB_DISABLE=1 表示禁用 InfiniBand,NCCL 只用 TCP(和可能的 NVLink 等)。用途:

  • 没有 IB 或驱动未配好:机器没有 IB 卡、或驱动/OFED 有问题,开 IB 会报错或 hang;设成 1 强制 TCP,先跑通。
  • 排查问题:多机 hang 或很慢时,先设 NCCL_IB_DISABLE=1 看是否 TCP 能正常;若 TCP 正常,再查 IB 配置(子网、MTU、防火墙等)。
  • 有 IB 且正常:不设或设 0,用 IB 获得更高带宽和更低延迟。

三、典型组合

  • 多机、有 IB、已配置NCCL_SOCKET_IFNAME=ib0(或你数据面网卡名),不设 NCCL_IB_DISABLE(或 =0)。
  • 多机、无 IB 或 IB 有问题NCCL_IB_DISABLE=1NCCL_SOCKET_IFNAME=eth1(选数据面 TCP 网卡)。
  • 单机多卡:常走 NVLink/PCIe,不依赖 TCP/IB,可不必设;若用 TCP(如多机模拟),同上。

面试要点

  • NCCL_SOCKET_IFNAME:指定 TCP 用的网卡(如 eth1、ib0);多机要选数据面、高带宽,且各节点一致或每机设对。
  • NCCL_IB_DISABLE=1:禁用 IB,只用 TCP;用于无 IB、IB 异常或排查时。
  • 有 IB 且正常不设 IB_DISABLE;无 IB 或排查时设 1 + 指定 SOCKET_IFNAME。

记忆要点

  1. SOCKET_IFNAME = 选 TCP 网卡;多机选数据面网卡、名一致或每机配好。
  2. IB_DISABLE=1 = 只用 TCP;无 IB 或排错时用。
  3. 有 IB 用 IB;无/异常时 IB_DISABLE=1 + 正确 IFNAME。

返回模块 | 返回总览

05-数据并行/058-梯度压缩(gradient-compression)的方法有哪些.md

第 58 题:梯度压缩(gradient compression)的方法有哪些?fp16 vs bf16 vs 1bit Adam

题目

梯度压缩(gradient compression)的方法有哪些?fp16 vs bf16 vs 1bit Adam


完整讲解

一、为什么要梯度压缩?

分布式训练里梯度 all-reduce 占大量通信量(与参数量同量级)。通过压缩梯度(精度、稀疏、量化)可减少通信字节数或次数,加速训练,代价是可能影响收敛(需通过误差补偿、调学习率等弥补)。


二、fp16 / bf16(精度压缩)

  • FP16:梯度用 16 位浮点做 all-reduce,通信量约为 FP32 的一半;要配合 loss scaling 防下溢。常用作「默认」混合精度通信。
  • BF16:16 位、指数与 FP32 同,尾数更短;范围大、不易溢出,但精度略低。通信量同 FP16;大模型训练常用 bf16 省通信且稳定。
  • 对比:bf16 不依赖 loss scaling 防溢出,易用;fp16 要 GradScaler。两者都是「减半通信」,属于精度压缩。

三、1bit Adam / 更高压缩

  • 1bit Adam(DeepSpeed 等):把梯度量化成 1 bit(如符号)+ 误差补偿(把量化误差加回下一轮),all-reduce 只传 1 bit 或极少 bit,通信量大幅下降;需额外维护「误差项」和调参(如学习率、warmup)。适合带宽极紧的场景。
  • 其他:如 梯度稀疏化(只传 top-k 或大于阈值的梯度)、随机 kPowerSGD 等,用稀疏或低秩近似减通信,各有收敛与实现复杂度权衡。

四、小结

  • fp16/bf16:简单、通信减半、常用;bf16 更稳、大模型常用。
  • 1bit Adam:极高压缩、通信极小,需误差补偿与调参;带宽瓶颈时考虑。
  • 选型:先 fp16/bf16;带宽仍不够再试稀疏或 1bit 类,并做收敛验证。

面试要点

  • 梯度压缩目的:减 all-reduce 通信量;方法有精度(fp16/bf16)、量化(1bit)、稀疏等。
  • fp16 = 半精度 + loss scaling;bf16 = 半精度、范围大、不需 scaling;通信都减半。
  • 1bit Adam = 1bit 量化 + 误差补偿,通信极低;需调参与验证收敛。

记忆要点

  1. fp16/bf16:通信减半;bf16 不易溢出,大模型常用。
  2. 1bit Adam:1bit 量化 + 误差补偿,通信大幅降;带宽瓶颈时用。
  3. 选型:先半精度;再视带宽与收敛试稀疏/1bit。

返回模块 | 返回总览

05-数据并行/059-异步训练(如Hogwild!)在工业界为什么很少用.md

第 59 题:异步训练(如Hogwild!)在工业界为什么很少用?

题目

异步训练(如Hogwild!)在工业界为什么很少用?


完整讲解

一、Hogwild! 在做什么?

Hogwild!异步 SGD:多个 worker 各自读当前参数、算梯度、不锁地直接写回参数(或写回共享的梯度累加器)。没有「等所有卡同步再更新」的 all-reduce,所以延迟低、吞吐高,但并发写导致参数更新不是「原子」的,存在陈旧梯度(stale gradient)和写冲突,收敛性依赖问题本身(稀疏更新、凸等),理论上要加延迟补偿、动量等才能稳。


二、工业界为什么很少用?

  • 收敛与稳定性:深度模型非凸、对陈旧梯度和冲突敏感;异步容易震荡、难调参、复现差;工业要可复现、稳收敛,同步 DDP/FSDP 更放心。
  • 硬件与通信:现代多卡/多机带宽高(NVLink、IB),同步 all-reduce 成本可接受;异步的「省通信」优势变小,而收敛风险仍在。
  • 实现与调试:异步要处理冲突、延迟、一致性;调试 hang、数值错更难;同步语义简单、工具链成熟(NCCL、DDP)。
  • 大模型:大模型训练更强调正确性与可复现,ZeRO/FSDP 等同步方案已能扩展,没必要冒险用异步。
  • 小结:工业界优先稳定与可复现;同步 DDP 已够快,异步收益有限、风险大,故少见。

三、什么时候还会考虑?

  • 通信极差、同步成本主导时(如跨地域、弱网络),异步可减少「等同步」时间;但通常会配合延迟补偿、梯度压缩等,且多用于特定场景(如联邦、边缘),不是通用训练主流。

面试要点

  • Hogwild! = 异步 SGD,无锁写参数;省同步、但有陈旧梯度和写冲突。
  • 少用原因:收敛不稳、难调参、工业要可复现;现代硬件同步成本可接受;实现与调试复杂。
  • 大模型与通用训练以同步为主;异步多在通信极差或特殊场景。

记忆要点

  1. 异步 = 无锁更新,延迟低但陈旧梯度与冲突;收敛依赖问题与补偿。
  2. 工业界重稳定与复现;同步 DDP 够用且简单。
  3. 通信极差时异步仍有价值;通常配合延迟补偿与压缩。

返回模块 | 返回总览

05-数据并行/060-如何实现自定义的分布式优化器.md

第 60 题:如何实现自定义的分布式优化器?继承torch.optim.Optimizer的注意事项?

题目

如何实现自定义的分布式优化器?继承torch.optim.Optimizer的注意事项?


完整讲解

一、继承 Optimizer 要做什么?

torch.optim.Optimizer 要求子类:

  • __init__ 里调 super().__init__(params, defaults),并保存 self.param_groups(及每个 group 的 param 列表和超参)。
  • 实现 step(closure=None):遍历 self.param_groups 里每个 param,用其 param.grad 按你的算法更新 param.data;若支持 closure(如 LBFGS),可执行 closure 再更新。
  • 在 step 里默认调 zero_grad();由用户在 backward 后、step 前自己调,或你在 step 里可选地调。

分布式下:梯度通常已由 DDP/FSDP 等做 all-reduce,每个 rank 上的 param.grad 已是「全局梯度」;自定义优化器只需在 本 rank 上按梯度更新本 rank 的参数(FSDP 下参数是分片的,每卡只更新自己的分片)。所以「分布式」部分多数由 DDP/FSDP 解决,优化器侧主要是正确读 grad、写 data


二、注意事项

  • 状态与分片:若优化器有状态(如 Adam 的 m、v),在 FSDP 下状态也应按分片存:每卡只存本卡参数分片对应的状态;all-gather 参数时不同步状态(状态随分片走)。若用 DDP,每卡完整参数,状态也完整,与单机一致。
  • 设备与 dtypeparam.dataparam.grad 的 device/dtype 要一致;混合精度时 grad 可能是 fp16,若优化器用 fp32 状态,要转成 fp32 再更、写回时再转(或用 master weight)。
  • 梯度是否为 None:若某 param 未参与计算(如 find_unused_parameters),grad 可能为 None;step 里要 skip 这类 param,不要用 None 做运算。
  • closure:若实现 step(closure),应先执行 closure() 再更新,并返回 closure 的返回值(若需要);多数优化器 closure 可为 None。
  • 与 DDP/FSDP 顺序:先 backward()(DDP 会 all-reduce),再 optimizer.step();若用 AMP,先 scaler.unscale_(optimizer)、检查 inf/nan,再 optimizer.step()scaler.update()

三、小结

  • 子类实现 __init__(params, defaults)step();step 里遍历 param_groups、用 grad 更新 data。
  • 分布式:梯度已由 DDP/FSDP 同步,优化器只做本地更新;FSDP 下状态要随分片、只更新本卡分片。
  • 注意:grad 为 None 时 skip、设备与 dtype、与 AMP 的配合顺序。

面试要点

  • 继承 Optimizer:init 调 super、保存 param_groups;step 里遍历 params、用 grad 更新 data。
  • 分布式:梯度已 all-reduce,优化器只做本地更新;FSDP 下状态随分片。
  • 注意:None grad 要 skip、设备/dtype、AMP 时 unscale 再 step。

记忆要点

  1. 必须:super().init、实现 step;step 里用 param.grad 更新 param.data。
  2. 分布式由 DDP/FSDP 管梯度;优化器管本地更新;FSDP 状态随分片。
  3. 处理 None grad、设备/dtype、与 scaler 顺序。

返回模块 | 返回总览

06-模型并行与流水线/README.md

06-模型并行与流水线(第 61–75 题)

题号 主题 文章
61 Tensor Parallelism(TP)的`fused attent… 061-Tensor-Parallelism(TP)的fused-attention.md
62 Megatron-LM的column parallel和`row p… 062-Megatron-LM的column-parallel和row-parall.md
63 Pipeline Parallelism(PP)的bubble问题如… 063-Pipeline-Parallelism(PP)的bubble问题如何量化.md
64 interleaved pipeline(如Megatron的1F1… 064-interleaved-pipeline(如Megatron的1F1B)如何.md
65 激活重计算(activation checkpointing)在PP中的… 065-激活重计算(activation-checkpointing)在PP中的特殊.md
66 如何平衡TP、PP、DP的维度划分?以175B模型为例 066-如何平衡TP、PP、DP的维度划分.md
67 `torch.distributed.pipeline.sync.Pip… 067-torch.distributed.pipeline.sync.Pipe的使.md
68 模型并行中的all-gatherreduce-scatter通… 068-模型并行中的all-gather和reduce-scatter通信模式.md
69 流水线并行中的micro-batch大小如何影响吞吐? 069-流水线并行中的micro-batch大小如何影响吞吐.md
70 如何处理PP中的负载不均衡?recompute和`no-recomp… 070-如何处理PP中的负载不均衡.md
71 3D并行(3D parallelism)的通信复杂度分析? 071-3D并行(3D-parallelism)的通信复杂度分析.md
72 序列并行(Sequence Parallelism)在长文本训练中的应用… 072-序列并行(Sequence-Parallelism)在长文本训练中的应用.md
73 Expert Parallelism在MoE模型中的all-to-all… 073-Expert-Parallelism在MoE模型中的all-to-all通信.md
74 零气泡流水线(Zero Bubble)的最新进展? 074-零气泡流水线(Zero-Bubble)的最新进展.md
75 如何profile分布式训练的通信开销?torch.profiler 075-如何profile分布式训练的通信开销.md

返回总览

06-模型并行与流水线/061-Tensor-Parallelism(TP)的fused-attention.md

第 61 题:Tensor Parallelism(TP)的fused attention实现细节?

题目

Tensor Parallelism(TP)的fused attention实现细节?


完整讲解

一、TP 与 Attention 的切分关系

Tensor Parallelism 在 attention 层按 head 或 hidden 维度切分到多卡。Fused attention 把 Q/K/V 投影、softmax、output 投影合并成少量 kernel,减少显存读写与 launch 开销,在 TP 下每卡只算本分片的 Q、K、V,再做 all-gather/reduce-scatter 拼回或归约。

二、Fused attention 在 TP 下的实现要点

  • QKV 线性层:按 column parallel 切分,每卡输出本卡对应的 head 子集;或按 hidden 维切分,前向各卡独立,backward 需 all-gather 梯度。
  • Attention 计算:每卡持有部分 head 的 Q、K、V,先做局部 attention(或为减少通信做 split 后 all-gather K/V 再算);flash attention / xformers 等 fused 实现需与 TP 的通信点对齐,避免重复 all-gather。
  • Output 投影:row parallel,各卡算一部分 output 维度,再 all-gather 得到完整输出;或 reduce-scatter 从各卡 partial sum 归约。

三、与 Megatron 的对应

Megatron-LM 的 fused QKV 与 column/row parallel 即上述模式:column 切 QKV 输出、row 切 O 输入,中间 attention 用 ring 或 all-gather 拼 full K/V 再算。实现时 fused kernel 的输入输出 shape 需与 TP 分片一致,通信插入在「需要完整 tensor」的边界。


面试要点

  • TP 下 attention 按 head 或 hidden 切分;fused attention 合并 QKV+attention+O,减少 kernel 与显存访问。
  • Column parallel 用于 QKV 输出,row parallel 用于 O;中间需 all-gather 或通信拼 full K/V 再算 attention。
  • 与 FlashAttention/xformers 结合时,通信点放在 fused 块边界,避免重复 all-gather。

记忆要点

  1. TP fused attention = column 切 QKV + 中间通信拼 K/V + row 切 O。
  2. Fused 减少 launch 与显存带宽;通信与 Megatron column/row 策略一致。
  3. 实现时注意 fused kernel 的输入输出 shape 与分片一致。

返回模块 | 返回总览

06-模型并行与流水线/062-Megatron-LM的column-parallel和row-parall.md

第 62 题:Megatron-LM的column parallelrow parallel的矩阵划分策略?

题目

Megatron-LM的column parallelrow parallel的矩阵划分策略?


完整讲解

一、Column Parallel(列并行)

线性层 (Y = XA),A 按切分:每卡持 (A_k),(Y_k = X A_k),各卡独立算,无需通信得到分片 (Y_k)。前向:每卡输出 (Y_k);若下游需要完整 (Y),再 all-gather。典型用于 Q、K、V 三个线性层:输出维(head×head_dim)按列切,每卡算部分 head。

二、Row Parallel(行并行)

线性层 (Y = XA),A 按切分:每卡持 (A_k)(行块),(Y = \sum_k X A_k)。前向各卡算 (X A_k) 得到 partial sum,再 all-reducereduce-scatter 得到 (Y)。典型用于 output 投影(attention 后的 O、FFN 第二层):输入维按行切,各卡产出 partial,归约后得完整输出。

三、为何这样划分?

  • Column parallel:(X) 各卡相同(或已 broadcast),(A) 列切后每卡算 (Y_k),无前向通信;反向时对 (A_k) 的梯度需 all-gather (X) 的梯度。
  • Row parallel:(X) 已是分片(如 column 的输出),(A) 行切后 partial sum 再 reduce,通信一次;反向时梯度传播与分片一致。Megatron 里 QKV 用 column、O 用 row,使 attention 块内通信次数与量最小化。

面试要点

  • Column parallel:矩阵按列切,(Y_k = X A_k),前向无通信;用于 QKV 等「输出维」切分。
  • Row parallel:矩阵按行切,partial sum 再 all-reduce;用于 O、FFN 第二层等「输入维」切分。
  • 组合使用使 attention/FFN 块内通信可预测且最少(一次 all-gather 或 reduce)。

记忆要点

  1. Column = 列切 A,每卡算一块 Y,用于 QKV。
  2. Row = 行切 A,partial sum + reduce,用于 O。
  3. 目的:前向/反向通信次数与量最小,与 fused attention 配合。

返回模块 | 返回总览

06-模型并行与流水线/063-Pipeline-Parallelism(PP)的bubble问题如何量化.md

第 63 题:Pipeline Parallelism(PP)的bubble问题如何量化?GPipe vs `PipeDrea…

题目

Pipeline Parallelism(PP)的bubble问题如何量化?GPipe vs PipeDream


完整讲解

一、Bubble 的量化

流水线中 bubble 指部分 stage 在等待数据时的空闲。设 stage 数 (S)、micro-batch 数 (M):GPipe 等 G-MB 策略(先全 forward 再全 backward)下,前向填满管道要 (S) 步,后向再 (S) 步,首尾各有约 (S-1) 个「空 slot」,理想稳定阶段有 (M-S) 个有效 slot。Bubble 比例可近似为 (\frac{2(S-1)}{M + 2(S-1)}),(M) 越大 bubble 占比越低,但显存随 (M) 增大。

二、GPipe 的特点

GPipe:同一 batch 切成 (M) 个 micro-batch,按序全部 forward 完再全部 backward。实现简单,但 显存峰值高(要存 (M) 份激活),且 bubble 明显;通过增大 (M) 摊薄 bubble,代价是激活重计算或显存压力。

三、PipeDream 的改进

PipeDream1F1B(One Forward One Backward)或 stale gradient 等策略,同一 micro-batch 的 backward 不必等全 batch forward 结束,管道中同时有不同 batch 的 F/B,显存与 bubble 折中。PipeDream 还引入 weight stashing(存多版本权重以应对流水线中并行的不同 batch),复杂度更高;Megatron 的 1F1B 不存多版本,用 recompute 换显存,bubble 仍可量化为与 (S、M) 相关的公式,通常优于 GPipe。


面试要点

  • Bubble 比例约 (\frac{2(S-1)}{M+2(S-1)});(M) 大则 bubble 小,显存大。
  • GPipe:全 F 再全 B,实现简单,显存高、bubble 大。
  • PipeDream/1F1B:F 与 B 交错,bubble 更小;PipeDream 有 weight stashing,Megatron 1F1B 常用 recompute。

记忆要点

  1. Bubble ≈ (2(S-1)) 空 slot / 总 slot;增大 micro-batch 数可降低比例。
  2. GPipe = 先全 forward 再全 backward;PipeDream/1F1B = 交错 F/B 减 bubble。
  3. 工程上多用 1F1B + recompute,避免多版本权重。

返回模块 | 返回总览

06-模型并行与流水线/064-interleaved-pipeline(如Megatron的1F1B)如何.md

第 64 题:interleaved pipeline(如Megatron的1F1B)如何减少bubble?

题目

interleaved pipeline(如Megatron的1F1B)如何减少bubble?


完整讲解

一、Interleaved 的含义

Interleaved pipeline 把同一 stage 的多个子块(如同一 GPU 上的若干层)拆成多段,不同 micro-batch 在这些段之间「交错」执行,而不是一个 stage 连续跑完所有层再交给下一 stage。这样同一物理 stage 会轮流处理多个 micro-batch,管道更满,bubble 更少

二、1F1B(One Forward One Backward)

Megatron 的 1F1B:每个 stage 按序执行「一个 micro-batch 的 forward → 一个 micro-batch 的 backward」,而不是「所有 micro-batch forward → 再全部 backward」。这样管道中同时存在不同 micro-batch 的 F 和 B,空闲 slot 减少。与 GPipe 的 G-MB 相比,在相同 (M、S) 下 bubble 比例更低。

三、Interleaved 1F1B 的进一步优化

Interleaved 1F1B:在 1F1B 基础上,把每个 stage 的层再分成若干「子 stage」,调度时让不同 micro-batch 交错经过这些子 stage。效果是同一设备上多个子块轮流工作,bubble 可进一步下降(理想情况可逼近 (O(1/S)) 量级)。代价是调度与依赖更复杂,需保证同一 micro-batch 的 F/B 顺序正确。


面试要点

  • Interleaved:同一 stage 内多子块,micro-batch 交错经过,管道更满、bubble 更小。
  • 1F1B:每 stage 做「一 F 一 B」交替,相比全 F 再全 B 减少空闲。
  • Interleaved 1F1B 结合两者,bubble 可进一步降低,实现与调度更复杂。

记忆要点

  1. 1F1B = 每 stage 一 forward 一 backward 交替,减 bubble。
  2. Interleaved = stage 内多子块、micro-batch 交错,提高利用率。
  3. Megatron 的 interleaved 1F1B 是常用生产配置。

返回模块 | 返回总览

06-模型并行与流水线/065-激活重计算(activation-checkpointing)在PP中的特殊.md

第 65 题:激活重计算(activation checkpointing)在PP中的特殊处理?

题目

激活重计算(activation checkpointing)在PP中的特殊处理?


完整讲解

一、PP 中为何需要激活重计算

流水线并行下,多个 micro-batch 的激活会同时存在于不同 stage,显存峰值随 micro-batch 数和层数增长。Activation checkpointing(激活重计算)只存部分层的激活(如每层或每隔几层存一次),其余在 backward 时用存下来的激活重新 forward 算一遍,用算力换显存,在 PP 里可显著降低每 stage 的显存,从而允许更大 micro-batch 或更深 stage。

二、PP 中的特殊考虑

  • Stage 边界:边界处激活必须保留或能重算,否则跨 stage 的 backward 无法进行;通常 stage 内用 checkpoint,边界输出要保留。
  • 与 1F1B 的配合:1F1B 下同一 stage 会交替做 F 和 B,checkpoint 策略要保证做 B 时所需激活要么已存、要么能由 checkpoint 重算,且重算顺序与依赖一致(例如从最近一个 checkpoint 重算到当前层)。
  • 选择性 checkpoint:不是每层都 checkpoint;通常「大激活、小计算」的层更适合重算(如 attention 前),可针对 PP 的 stage 划分单独调哪些层 checkpoint。

三、实现要点

Megatron 等框架在 PP 中通常对每个 stage 的若干层做 checkpoint,保留 stage 输出;backward 时在 stage 内从 checkpoint 重算到需要梯度的层。与纯数据并行相比,PP 的 checkpoint 还要考虑「同一设备上多 micro-batch 的激活生命周期」,避免重算与释放顺序错误。


面试要点

  • PP 显存压力大,activation checkpointing 用算力换显存,允许更大 M 或更深 stage。
  • Stage 边界激活需保留或可重算;1F1B 下重算顺序与依赖要与 F/B 交替一致。
  • 选择性 checkpoint 大激活层;实现时注意多 micro-batch 的激活生命周期。

记忆要点

  1. PP 中 checkpoint 降显存、换算力;stage 边界不能丢激活。
  2. 1F1B 下 backward 依赖的激活要么存要么重算,顺序要正确。
  3. 大激活层优先 checkpoint,与 stage 划分一起调。

返回模块 | 返回总览

06-模型并行与流水线/066-如何平衡TP、PP、DP的维度划分.md

第 66 题:如何平衡TP、PP、DP的维度划分?以175B模型为例

题目

如何平衡TP、PP、DP的维度划分?以175B模型为例


完整讲解

一、三维并行的角色

  • DP(Data Parallelism):复制模型,数据分片,梯度 all-reduce;通信量 (O(参数量)),与数据并行度成反比。
  • TP(Tensor Parallelism):单层内切分,all-gather/reduce-scatter,通信在节点内高带宽(NVLink)更合适;通常 TP 度 ≤ 单机 GPU 数。
  • PP(Pipeline Parallelism):按层切 stage,通信量 (O(激活)),跨节点可接受;PP 度受 pipeline depth 与 bubble 约束。

二、175B 的典型划分思路

175B 参数量、单卡放不下整模型,需 PP+TP(或 +DP)。示例:8 机 × 8 GPU = 64 卡。TP=8(单机 8 卡做张量并行,NVLink 通信);PP=4(4 个 stage 跨 4 机);DP=2(2 份复制)。这样每 DP 复制有 32 卡:TP×PP=32,梯度在 DP 维 all-reduce。原则:TP 尽量放同机、PP 跨机、DP 视 global batch 与通信能力定。

三、平衡要点

  • 通信:TP 通信频繁且量级大,放 NVLink;PP 通信次数少、单次激活大,可跨机;DP 仅梯度 all-reduce,跨机可接受。
  • 显存:单卡显存决定每 stage 能放多少层、micro-batch 多大;TP 度大则每卡参数与激活都减少。
  • 吞吐:micro-batch 数要足够摊薄 bubble;DP 度大则 global batch 大,但 all-reduce 成本上升。175B 常用 TP=8、PP=4~8、DP=2~4 量级,按卡数与拓扑微调。

面试要点

  • TP 放同机(NVLink)、PP 跨机、DP 视 batch 与带宽定;175B 典型 TP=8、PP=4~8、DP=2~4。
  • 通信:TP 最吃带宽且频繁,PP 次之,DP 梯度 all-reduce。
  • 显存与 bubble 共同约束 PP 深度与 micro-batch 数。

记忆要点

  1. TP 同机、PP 跨机、DP 复制;175B 常用 8×4×2 或类似。
  2. 通信量/频率:TP > PP > DP(梯度)。
  3. 按显存定 stage 与 M,按带宽定 TP/PP/DP 度。

返回模块 | 返回总览

06-模型并行与流水线/067-torch.distributed.pipeline.sync.Pipe的使.md

第 67 题:torch.distributed.pipeline.sync.Pipe的使用限制?

题目

torch.distributed.pipeline.sync.Pipe的使用限制?


完整讲解

一、Pipe 的基本限制

torch.distributed.pipeline.sync.Pipenn.Module 按顺序切成若干 submodule(stage),每个 stage 可放到不同 device,用 sync 方式执行:同一 micro-batch 的 forward 在各 stage 间顺序执行,backward 亦然。限制包括:只支持顺序的 module list(不能任意 DAG)、单进程多 device(或配合 spawn 多进程时每进程多 device)、无内置 TP/DP,需用户自己与 DDP 等组合。

二、使用上的约束

  • 拓扑:stage 数 = device 数(或 1:1 映射);device 需在同一个进程内可见(如多 GPU 单机)。
  • Chunk:micro-batch 数(chunks)需 ≥ stage 数,否则 bubble 极大;且第一个 tensor 输入要在 batch 维可切。
  • No cross-stage 的 skip:若模型有 skip connection 跨 stage,Pipe 默认不支持,需把整块放同一 stage 或改用自定义 schedule。
  • 调试:hang 或 OOM 时需结合 stage 划分与 chunk 数排查;与 DDP 一起用时注意进程与 backend 一致。

三、与 Megatron/DeepSpeed 的对比

PyTorch Pipe 是同步、单进程的轻量实现;Megatron、DeepSpeed 的 pipeline 支持多进程、1F1B、interleaved、与 TP/DP 结合,适合大模型。生产大模型多用 Megatron 或 DeepSpeed pipeline,Pipe 适合原型或小规模流水线验证。


面试要点

  • Pipe 只支持顺序 stage、单进程多 device;chunks ≥ stage 数;无内置 TP/DP。
  • 跨 stage 的 skip 不直接支持;与 DDP 组合需自己处理进程与 backend。
  • 大模型生产多用 Megatron/DeepSpeed pipeline,Pipe 适合小规模或原型。

记忆要点

  1. sync.Pipe = 顺序 stage、sync 执行;chunks ≥ stages。
  2. 单进程多 device、无 TP/DP;跨 stage skip 不支持。
  3. 生产用 Megatron/DeepSpeed,Pipe 做原型。

返回模块 | 返回总览

06-模型并行与流水线/068-模型并行中的all-gather和reduce-scatter通信模式.md

第 68 题:模型并行中的all-gatherreduce-scatter通信模式?

题目

模型并行中的all-gatherreduce-scatter通信模式?


完整讲解

一、All-Gather

All-gather:每卡持有 tensor 的一个分片,通信后每卡得到完整 tensor。例如 column parallel 的 QKV 输出分片在每卡,下游需要完整 K、V 时做 all-gather 拼成 full K、V 再算 attention。通信量:(P) 卡、每卡 (n) 元素,总数据 (nP),每卡收 ((P-1)n),发 (n);ring 或 tree 算法约 (2(P-1)n/P) 单卡流量。

二、Reduce-Scatter

Reduce-scatter:每卡持有一个完整 tensor 的 copy,通信后每卡得到归约结果的一个分片(如 sum 后按卡切分)。例如 row parallel 的 output:各卡有 partial sum,reduce-scatter 得到「全局 sum 的一个分片」,可直接作为下一层 column 的输入。通信量量级与 all-gather 同量级,但语义是「先 reduce 再 scatter」。

三、在 TP 中的典型用法

  • Column → 下游需要 full:all-gather 拼成完整 tensor(如 K、V 给 attention)。
  • Row 的 partial sum → 下一层 column 的输入:reduce-scatter 得到分片,避免再 all-gather 一整份;即 all-gather 与 reduce-scatter 配对 可把一次「all-reduce」拆成两次通信,有时能更好重叠或适配内存布局。Megatron 里 linear 的 column/row 与 attention 的通信就是这类模式。

面试要点

  • All-gather:分片 → 每卡得完整 tensor;用于拼 K/V 等。
  • Reduce-scatter:每卡有 copy → 每卡得归约结果的一个分片;用于 row 后给下一 column。
  • 与 all-reduce 的关系:all-reduce ≈ reduce-scatter + all-gather;拆开可优化重叠与显存。

记忆要点

  1. All-gather = 分片拼成完整;reduce-scatter = 归约后得分片。
  2. TP 中 column 后常 all-gather,row 后常 reduce-scatter 给下一层。
  3. 通信量级与 all-reduce 同阶,拆成两步可优化重叠。

返回模块 | 返回总览

06-模型并行与流水线/069-流水线并行中的micro-batch大小如何影响吞吐.md

第 69 题:流水线并行中的micro-batch大小如何影响吞吐?

题目

流水线并行中的micro-batch大小如何影响吞吐?


完整讲解

一、Micro-batch 与吞吐的关系

Micro-batch 大小 = global batch / (DP × chunks)。chunks 越大,单次 forward/backward 的粒度越小,管道更易填满、bubble 占比下降,理论上吞吐上升。但 chunks 越大,同时存活的激活越多,每 stage 显存增加;若用 activation checkpointing,重算次数也随 chunks 增加,算力开销上升。

二、吞吐随 M 的变化

  • M 过小:bubble 比例高(约 (\frac{2(S-1)}{M+2(S-1)})),GPU 空闲多,吞吐低。
  • M 适中:bubble 与显存、重算达到平衡,吞吐最优。
  • M 过大:显存吃满或 OOM,或重算过多导致单 step 变慢,吞吐可能反而下降。实践中对给定模型与卡数,需 sweep chunks(或等价地 micro-batch size)测 throughput。

三、与 batch size、DP 的联合影响

Global batch = DP × chunks × micro_batch_size。固定 global batch 时,增大 chunks 会减小 micro_batch_size,单次 F/B 更轻、管道更满,但单次通信/ kernel 效率可能略降;反之 chunks 小则 micro_batch 大,bubble 大。通常先定 global batch 与 DP,再在显存允许范围内尽量增大 chunks 以压 bubble,必要时用 checkpoint 换显存。


面试要点

  • Micro-batch 数(chunks)大 → bubble 小、管道满,但显存与重算增加。
  • 吞吐先随 chunks 升后可能因显存/重算降;需 sweep 找最优点。
  • 与 DP、global batch 联合调:固定 global batch 下优先在显存允许时增大 chunks。

记忆要点

  1. Chunks 大 = bubble 小、显存与重算大;存在最优 chunks。
  2. 公式上 bubble ∝ 1/M,M 为 micro-batch 数。
  3. 工程上先定 batch 与 DP,再尽量大 chunks + checkpoint 保显存。

返回模块 | 返回总览

06-模型并行与流水线/070-如何处理PP中的负载不均衡.md

第 70 题:如何处理PP中的负载不均衡?recomputeno-recompute层的分配?

题目

如何处理PP中的负载不均衡?recomputeno-recompute层的分配?


完整讲解

一、PP 负载不均衡的来源

不同 stage 的层数、参数量、计算量不同(如 attention 与 FFN 比例、embed 与 head 数),导致各 stage 的 F/B 时间不一致,快的 stage 等慢的,bubble 或空闲增加。此外,recompute(activation checkpointing)只对部分层做,有 recompute 的 stage backward 时要多一次重算,时间变长,若分配不当会加重不均衡。

二、Recompute 与 no-recompute 的分配

  • Recompute 层:计算相对便宜、激活大的层(如部分 attention、大 hidden 的 FFN)适合做 checkpoint,用算力换显存;若把这些层集中到少数 stage,这些 stage 的 backward 会明显变长。
  • No-recompute 层:小激活或计算贵的层不 checkpoint;若集中到某 stage,该 stage 显存压力大但算得快。策略:尽量让各 stage 的「计算+通信+重算」时间接近,例如把部分 recompute 层与 no-recompute 层交错到不同 stage,或按实测时间微调 stage 切分点。

三、其他手段

  • Stage 划分:按层数或按「预估 F+B 时间」切分,使各 stage 耗时接近;工具可 profile 各层耗时再划分。
  • Interleaved:同一设备多子 stage 交错,从统计上平滑单设备内负载。
  • Pipeline 调度:1F1B 等已能减轻 bubble;再结合均衡的 stage 与合理的 recompute 分配,可进一步减少等待。

面试要点

  • 负载不均衡来自各 stage 层数/计算/重算不同;需让各 stage 总耗时接近。
  • Recompute 放「大激活、小计算」层;避免把大量 recompute 集中到同一 stage。
  • 手段:按耗时划分 stage、interleaved、合理分配 recompute/no-recompute。

记忆要点

  1. 不均衡 = 各 stage F+B+recompute 时间不一致;按耗时划分 stage。
  2. Recompute 分散到各 stage,避免单 stage 重算过多。
  3. Interleaved + 1F1B + 均衡划分 一起用。

返回模块 | 返回总览

06-模型并行与流水线/071-3D并行(3D-parallelism)的通信复杂度分析.md

第 71 题:3D并行(3D parallelism)的通信复杂度分析?

题目

3D并行(3D parallelism)的通信复杂度分析?


完整讲解

一、三维并行的通信来源

  • DP:每 step 一次梯度 all-reduce,数据量 (2 \cdot \frac{参数量}{DP})(fp32 梯度+优化器状态等),跨节点时受机间带宽限制。
  • TP:每层前向/反向有 all-gather 或 reduce-scatter,数据量 (O(\frac{层参数量}{TP})),通常同机 NVLink,带宽高、延迟低。
  • PP:stage 间传激活与梯度,数据量 (O(激活体积)),与 micro-batch size、序列长、hidden 相关;跨节点时单次量大但次数少。

二、通信量级(定性)

设参数量 (P)、层数 (L)、DP/TP/PP 度 (D_p,T_p,S)。DP all-reduce:(O(P/D_p)) 每 step。TP:每层 (O(\frac{每层参数量}{T_p})),共 (L) 层,前向+反向约 (O(2L \cdot \frac{每层参数量}{T_p}))。PP:(2(S-1)) 次激活/梯度传递(每 micro-batch),每次 (O(激活体积))。总通信字节与上述三者之和同阶;时间还取决于各通信所在链路(NVLink vs IB)与是否与计算重叠。

三、复杂度与优化方向

通信复杂度可写为 (O(P/D_p) + O(L \cdot 层参数量/T_p) + O(S \cdot 激活))。优化:DP 用梯度压缩或增大 (D_p) 摊薄;TP 保持同机、用 fused 与 overlap;PP 减少 (S) 或激活体积(序列并行、checkpoint)。3D 同时开时以「DP 跨机、TP 同机、PP 适度」为原则,使总通信时间与计算时间匹配。


面试要点

  • DP:每 step all-reduce (O(P/D_p));TP:每层 all-gather/reduce-scatter (O(层参数量/T_p));PP:stage 间激活/梯度 (O(激活))。
  • 总通信量 = DP + TP×层数 + PP×激活;时间还看链路与 overlap。
  • 优化:DP 压缩/增大度,TP 同机,PP 减激活或 stage 数。

记忆要点

  1. 3D 通信 = DP all-reduce + TP 每层通信 + PP 激活传递。
  2. TP 同机降延迟,DP/PP 可跨机;量级按参数量与激活估算。
  3. 重叠与链路选择决定实际耗时。

返回模块 | 返回总览

06-模型并行与流水线/072-序列并行(Sequence-Parallelism)在长文本训练中的应用.md

第 72 题:序列并行(Sequence Parallelism)在长文本训练中的应用?

题目

序列并行(Sequence Parallelism)在长文本训练中的应用?


完整讲解

一、序列维度的显存与计算瓶颈

长序列时,激活在 sequence 维是 (O(L^2))(attention)或 (O(L))(其余),显存与计算都随序列长快速增长。若把 sequence 维也做并行,每卡只持有一段序列的激活,可降低单卡显存与单次 attention 的规模。

二、Sequence Parallelism(SP)做法

  • 切分:把 sequence 维切到多卡(常与 TP 同组),每卡持 (L/N) 长;attention 需 all-gather 或通信拼 full Q/K/V 再算,或做 distributed attention(每卡算局部再合并)。
  • 典型用法:Megatron 的 sequence parallel 常与 TP 结合,在 attention 的 QKV 与 O 处做 all-gather/reduce-scatter 时,把 sequence 维也一起切分,这样单卡激活从 (O(L \cdot H)) 降为 (O((L/N) \cdot H)),适合长文本训练。
  • 与 FlashAttention 等结合:变长或长序列下,SP 降低单卡显存使更大 batch 或更长序列可行;需注意通信量与 overlap,避免 sequence 维 all-gather 成为新瓶颈。

三、应用场景

长文本预训练、长上下文微调、文档级任务等,当单卡放不下「全长序列的激活」时,用 SP 在序列维切分;通常与 TP 同机,通信 pattern 与 TP 的 all-gather/reduce-scatter 一致或融合。


面试要点

  • SP 在序列维切分,单卡激活从 (O(L))/(O(L^2)) 降为 (O(L/N)),适合长序列。
  • 常与 TP 结合,在 QKV/O 的 all-gather/reduce-scatter 中带 sequence 维。
  • 长文本训练、长上下文微调是典型场景。

记忆要点

  1. Sequence parallel = 序列维切分,降单卡激活与 attention 规模。
  2. 与 TP 同组,通信 pattern 与 column/row 一致或融合。
  3. 长序列、长上下文训练必备手段之一。

返回模块 | 返回总览

06-模型并行与流水线/073-Expert-Parallelism在MoE模型中的all-to-all通信.md

第 73 题:Expert Parallelism在MoE模型中的all-to-all通信优化?

题目

Expert Parallelism在MoE模型中的all-to-all通信优化?


完整讲解

一、MoE 与 Expert Parallelism

MoE(Mixture of Experts)中,不同 token 被路由到不同 expert(子网络)。Expert Parallelism(EP):把不同 expert 放到不同 GPU,每卡负责若干 expert;前向时 token 按路由结果发送到对应卡,算完再按需汇总,涉及 all-to-all 或类似通信(token 按 expert 重排)。

二、All-to-All 的语义与成本

All-to-all:每卡有 (P) 个分片(如按 expert 或 token 分),通信后每卡得到来自所有卡的对应分片。数据量:(P) 卡、每卡原持 (n) 元素,总 (nP),all-to-all 后每卡仍约 (n) 量级但内容重排。通信量约 (n(P-1)/P) 每卡发送、类似接收,与 token 路由分布 相关;若路由不均,某卡可能收多发少或反之,需负载均衡。

三、优化方向

  • Fused all-to-all:与计算融合,减少 kernel launch 与显存读写;在 expert 前做「token → expert」重排,expert 后做「expert → token」还原。
  • Overlap:all-to-all 与上一层的计算或下一层的准备重叠;双缓冲或异步通信。
  • 拓扑:all-to-all 对带宽敏感,同机或高带宽集群更合适;与 TP/PP 组合时,EP 的 all-to-all 常放在与 DP 或 PP 的通信错开,避免同时打满网络。
  • 负载均衡:路由策略(如 capacity constraint、aux loss)影响各卡负载;可配合 expert 复制或动态分配减轻不均衡。

面试要点

  • EP 把 expert 分到多卡;前向/反向需按路由做 token 重排,即 all-to-all 类通信。
  • All-to-all 数据量 (O(总 token 数)),与路由分布相关;fused、overlap、拓扑可优化。
  • 负载均衡依赖路由策略与 expert 分配。

记忆要点

  1. Expert parallel = expert 分卡,token 按路由 all-to-all 重排。
  2. 通信量级 = token 重排量;fused + overlap 降延迟。
  3. 路由与 capacity 影响负载均衡,需与 TP/PP 协调。

返回模块 | 返回总览

06-模型并行与流水线/074-零气泡流水线(Zero-Bubble)的最新进展.md

第 74 题:零气泡流水线(Zero Bubble)的最新进展?

题目

零气泡流水线(Zero Bubble)的最新进展?


完整讲解

一、Bubble 与「零气泡」目标

传统 PP 中 bubble 来自「管道填满前/排空时」的空闲,比例约 (\frac{2(S-1)}{M+2(S-1)})。零气泡指理想情况下 bubble 趋近 0:即任意时刻所有 stage 都在算,无空闲。这需要调度与依赖设计满足严格条件(如无限 micro-batch 或特殊 schedule)。

二、近年进展概览

  • Interleaved 1F1B / 2F1B 等:通过交错与多子 stage 把 bubble 压到很低(如 (O(1/S))),工程上已接近「几乎无 bubble」。
  • Bubble-free 理论:有工作证明在特定假设(如各 stage 等耗时、无限 micro-batch)下可构造 bubble-free schedule;实际中 stage 不等、M 有限,只能逼近。
  • 异步与 speculation:如异步 PP、用推测执行填满空闲,换取一致性或复杂度;部分研究在探索与 checkpoint/recompute 的结合。
  • 系统实现:Megatron、DeepSpeed、Varuna 等持续优化 schedule(如 1F1B、interleaved、early backward),生产环境已能获得很低 bubble 比例。

三、实践中的「近零」

工程上「零气泡」多指 bubble 占比 < 5%~10%:通过 interleaved、足够大的 M、均衡 stage、以及 1F1B 等 schedule 达到;严格数学上的零气泡在有限 M、不等 stage 下难以实现,但已足够支撑高效训练。


面试要点

  • 零气泡 = bubble 趋近 0;理论上有 bubble-free schedule,实际受 M 与 stage 不等限制。
  • 进展:interleaved 1F1B、2F1B、多子 stage、异步/推测等;Megatron/DeepSpeed 已能压到很低。
  • 工程上「近零」指 bubble 占比个位数,通过 M 与 schedule 调优达到。

记忆要点

  1. 零气泡 = 理想无空闲;实际用 interleaved + 大 M + 均衡 stage 逼近。
  2. 理论有 bubble-free 构造,有限 M 与不等耗时下只能近似。
  3. 生产上 bubble <10% 即视为良好。

返回模块 | 返回总览

06-模型并行与流水线/075-如何profile分布式训练的通信开销.md

第 75 题:如何profile分布式训练的通信开销?torch.profilerdistributed view?

题目

如何profile分布式训练的通信开销?torch.profilerdistributed view?


完整讲解

一、torch.profiler 与分布式

torch.profiler 支持多进程下的时间线汇总:用 scheduleactivities 等记录各 rank 的 CPU/CUDA 与通信事件,导出 Chrome trace 或用 profiler.key_averages() 看汇总。Distributed 视角:需在各 rank 上一致地 start/stop profiler,并确保记录 NCCL/custom collective 事件(通常通过 CUDA 活动或 backend hook 看到通信 kernel)。

二、看到通信开销的方式

  • activities 包含 torch.profiler.ProfilerActivity.CUDA 时,NCCL 的 kernel 会出现在 timeline 上,可看到 all-reduce、all-gather 等占用的时间与重叠情况。
  • distributed view:部分用法指「按 rank 对比各卡 timeline」,看是否某卡通信或计算明显更长」;PyTorch profiler 导出 trace 后可在 Perfetto/Chrome 中按 process/stream 过滤各 rank。
  • key_averages:按 operator 或 name 聚合,可看到 nccl:all_reduce 等占 CPU/CUDA 时间比例;group_by_stack_n=5 可看调用栈,定位是 DDP、FSDP 还是自定义 collective。

三、实操要点

  • torch.profiler.profile(..., record_shapes=True) 可看到 tensor 大小,便于对照通信量。
  • 多进程时每个 rank 写单独 trace 文件(如 trace_rank{rank}.json),再一起打开对比;或使用能合并多进程的 profiler 后端。
  • 结合 NCCL_DEBUG=INFO 看实际 collective 次数与大小,与 profile 里的通信事件对应,判断是否有多余或过大的 collective。

面试要点

  • torch.profiler 记录 CPU/CUDA 与 NCCL 事件;各 rank 一致 start/stop,导出 trace 按 rank 对比。
  • Distributed view = 按 rank 看 timeline,找通信或计算热点;key_averages 看 collective 占比。
  • 与 NCCL_DEBUG、record_shapes 结合,对照 collective 次数与大小做优化。

记忆要点

  1. Profiler 开 CUDA 活动可见 NCCL kernel;多 rank 分别导出 trace 对比。
  2. key_averages 看 all_reduce 等占比;group_by_stack_n 看调用栈。
  3. 与 NCCL_DEBUG、record_shapes 一起用,定位多余或过大通信。

返回模块 | 返回总览

07-显存优化与Offload/README.md

07-显存优化与Offload(第 76–85 题)

题号 主题 文章
76 ZeRO-Offload如何将optimizer state offlo… 076-ZeRO-Offload如何将optimizer-state-offload.md
77 DeepSpeed-Infinity如何利用NVMe扩展显存? 077-DeepSpeed-Infinity如何利用NVMe扩展显存.md
78 激活检查点的checkpoint_sequential和`check… 078-激活检查点的checkpoint_sequential和checkpoint.md
79 显存碎片问题在分布式场景下更严重吗?如何解决? 079-显存碎片问题在分布式场景下更严重吗.md
80 torch.cuda.empty_cache()的副作用?为什么不能… 080-torch.cuda.empty_cache()的副作用.md
81 如何估算大模型训练所需的显存?公式推导? 081-如何估算大模型训练所需的显存.md
82 gradient checkpointing和`activation… 082-gradient-checkpointing和activation-comp.md
83 CPU offload和GPU计算的流水线重叠如何实现? 083-CPU-offload和GPU计算的流水线重叠如何实现.md
84 多节点场景下的显存优化策略差异? 084-多节点场景下的显存优化策略差异.md
85 显存优化的ROI如何评估?训练速度vs模型规模的trade-off? 085-显存优化的ROI如何评估.md

返回总览

07-显存优化与Offload/076-ZeRO-Offload如何将optimizer-state-offload.md

第 76 题:ZeRO-Offload如何将optimizer state offload到CPU?带宽瓶颈?

题目

ZeRO-Offload如何将optimizer state offload到CPU?带宽瓶颈?


完整讲解

一、ZeRO-Offload 做了什么

ZeRO 把 optimizer state、gradient、parameter 分片到多卡;ZeRO-Offload 进一步把 optimizer state(及可选 gradient)放到 CPU 内存,GPU 只保留当前 step 计算所需的分片。前向/反向在 GPU 算,optimizer step 时把梯度拷到 CPU,在 CPU 上更新 optimizer state 与参数,再把更新后的参数(或所需分片)拷回 GPU,从而用 CPU 内存扩展「等效显存」。

二、带宽瓶颈

  • GPU↔CPU 带宽(PCIe)远低于 GPU 显存带宽与 NVLink;optimizer state 体积大(如 Adam 两份动量 + 参数,fp32),每 step 要搬 optimizer state 与参数,PCIe 成为瓶颈,训练变慢。
  • 缓解:只 offload optimizer state,参数仍留 GPU(或按需搬);用 fp16/bf16 的 optimizer state 减半搬运量;overlap:下一 layer 的 backward 与上一 layer 的 CPU 更新 + 回拷重叠,用 double buffer 或异步拷贝。
  • 适用:单卡或少量卡显存不够、但 CPU 内存充足时;多卡时可与 ZeRO-2/3 结合,部分 state 在 CPU、部分在 GPU 分片。

三、公式与量级

Optimizer state 约 (2 \times 参数量 \times 4)(Adam fp32 两份);若每 step 全量搬一次,通信量 (O(参数量)),时间 (\approx 参数量 \times 4 / PCIe带宽)。Overlap 与压缩可降低有效瓶颈,但本质仍是「用 CPU 内存换显存、用 PCIe 带宽换容量」的 trade-off。


面试要点

  • ZeRO-Offload 把 optimizer state(及可选梯度)放 CPU,用 PCIe 搬运;GPU 显存需求下降。
  • 瓶颈在 PCIe 带宽;overlap、fp16 state、只 offload 部分 state 可缓解。
  • 适用:显存紧、CPU 内存够;可与 ZeRO-2/3 组合。

记忆要点

  1. Offload = optimizer state 放 CPU,step 时 CPU 更新再拷回。
  2. 瓶颈 = PCIe;overlap + 减精度/减量 缓解。
  3. 用 CPU 内存换显存,用带宽换容量。

返回模块 | 返回总览

07-显存优化与Offload/077-DeepSpeed-Infinity如何利用NVMe扩展显存.md

第 77 题:DeepSpeed-Infinity如何利用NVMe扩展显存?

题目

DeepSpeed-Infinity如何利用NVMe扩展显存?


完整讲解

一、DeepSpeed-Infinity 的思路

DeepSpeed-InfinityNVMe SSD 作为「第三级存储」:显存不够时把 optimizer state、梯度、甚至参数 offload 到 NVMe,需要时再按块读回。NVMe 容量大(TB 级)、带宽高于传统 SATA,比纯 CPU offload 的「CPU 内存」更可扩展,适合超大模型或长序列。

二、如何利用 NVMe 扩展显存

  • 分层 offload:热数据在 GPU,温数据在 CPU 内存,冷数据在 NVMe;按访问频率与 step 需求调度,减少 NVMe 读写。
  • 预取与流水线:下一 stage 需要的数据提前从 NVMe 读到 CPU 或 GPU(prefetch),与当前计算重叠;类似 ZeRO-Offload 的 overlap,但多了一层 NVMe→CPU 的流水。
  • 块与压缩:按块(chunk)读写、可选压缩,降低 IO 次数与体积;NVMe 带宽仍远低于 GPU,所以尽量只搬必要块、并重叠计算。

三、带宽与适用场景

NVMe 顺序读约数百 MB/s~数 GB/s,仍低于 PCIe GPU 带宽;因此 Infinity 适合「显存与 CPU 内存都不够、但可接受一定 IO 延迟」的超大模型训练。通过 overlap、预取、分层,把 IO 藏在计算后面,减轻对吞吐的影响。


面试要点

  • Infinity 用 NVMe 做第三级存储,offload optimizer/梯度/参数,按需读回。
  • 分层 offload + 预取 + 与计算重叠,减轻 NVMe 带宽瓶颈。
  • 适合超大模型、显存与 CPU 内存都紧张时;IO 需与计算流水重叠。

记忆要点

  1. NVMe = 第三级存储,容量大、带宽低于 GPU/PCIe。
  2. 分层 + prefetch + overlap 是关键;按块读写、可选压缩。
  3. 适用:超大模型、显存与 CPU 都不够。

返回模块 | 返回总览

07-显存优化与Offload/078-激活检查点的checkpoint_sequential和checkpoint.md

第 78 题:激活检查点的checkpoint_sequentialcheckpoint区别?

题目

激活检查点的checkpoint_sequentialcheckpoint区别?


完整讲解

一、Activation checkpointing 的目的

前向时只保存部分层的激活(如每层或每隔几层存一次),其余在 backward 时按需重算,用算力换显存,使更深的网络或更大 batch 能跑起来。

二、checkpoint_sequential

checkpoint_sequential(如 torch.utils.checkpoint.checkpoint_sequential):把 一个 sequence 的 submodule 列表 当作一整段,只在这段的首或尾存一次 checkpoint,中间全部重算。适用:顺序的若干层(如 ResNet 的 stage、Transformer 的若干连续层),接口简单,但粒度较粗,重算范围大。

三、checkpoint(通用)

checkpoint(如 torch.utils.checkpoint.checkpoint):对 单个 可调用的 function 或子模块做 checkpoint;前向时只记输入,不存中间激活,backward 时用同一输入重新执行 function 得到激活再算梯度。粒度细,可只对某一层或某一 block 用,非顺序 或自定义 block 也可用;需保证 function 无副作用、确定性(否则重算结果可能不一致)。

四、对比与选择

  • checkpoint_sequential:顺序子模块列表、一段只一个 checkpoint;实现简单,重算多。
  • checkpoint:任意单次调用、粒度细;灵活,适合单层或自定义块。大模型里常用 checkpoint 对 attention 或 FFN 逐块包装,或配合自定义 segment 实现「每 N 层一个 checkpoint」。

面试要点

  • checkpoint_sequential:一段顺序子模块共用一个 checkpoint,粒度粗、重算多。
  • checkpoint:单次 function/模块,粒度细、可任意包装;需无副作用、确定性。
  • 大模型常用 checkpoint 对 attention/FFN 逐块或按段包装。

记忆要点

  1. sequential = 一段顺序层共用一个存点;checkpoint = 单层/单块。
  2. sequential 粗、重算多;checkpoint 细、灵活。
  3. 生产多用 checkpoint 包装单层或自定义 segment。

返回模块 | 返回总览

07-显存优化与Offload/079-显存碎片问题在分布式场景下更严重吗.md

第 79 题:显存碎片问题在分布式场景下更严重吗?如何解决?

题目

显存碎片问题在分布式场景下更严重吗?如何解决?


完整讲解

一、显存碎片从哪来

显存分配/释放顺序与 tensor 生命周期不一致,会产生空洞:总空闲足够,但没有连续块满足新申请,导致 OOM 或分配失败。动态图、变长序列、临时 tensor 多、以及 不同 rank 或不同 stage 分配节奏不同 都会加剧碎片。

二、分布式下是否更严重

  • 可能更严重:多进程/多卡下,各 rank 的 alloc 顺序与 size 不完全一致(如 DDP 梯度、PP 各 stage 激活、TP 分片),导致每卡碎片模式不同,某卡先 OOM;或 collective 同步点 前后大量临时 tensor 同时释放,形成「波浪式」分配,易产生碎片。
  • 也可能相当:若各 rank 执行严格一致、分配模式相同,碎片程度与单卡类似,但 单卡 OOM 会拖挂整组,所以对碎片更敏感,需要更主动的应对。

三、解决思路

  • 预分配与池化:启动时按最大需求预分配大块,内部再切分(类似 memory pool),减少运行时零散 alloc/free。
  • 统一分配顺序:尽量让各 rank 的 alloc 顺序与 size 一致(如统一 layer 顺序、统一 gradient buffer 申请),减轻碎片差异。
  • 重算换显存:activation checkpointing 减少峰值激活,间接减少大块分配与释放的波动。
  • 碎片整理:部分框架支持「compact」或重排(代价高);或重启进程清空显存。实践中以「预分配 + 一致顺序 + checkpoint」为主。

面试要点

  • 碎片 = 空闲不连续;分布式下各 rank 分配节奏不一或 collective 前后波动可能加重。
  • 单卡 OOM 拖挂整组,分布式对碎片更敏感。
  • 手段:预分配/池化、统一分配顺序、checkpoint、少用临时大 tensor。

记忆要点

  1. 分布式下分配节奏不一易加重碎片;单卡 OOM 影响全组。
  2. 预分配 + 一致顺序 + checkpoint 是主要手段。
  3. 避免 collective 前后大量临时 tensor 同时 alloc/free。

返回模块 | 返回总览

07-显存优化与Offload/080-torch.cuda.empty_cache()的副作用.md

第 80 题:torch.cuda.empty_cache()的副作用?为什么不能频繁调用?

题目

torch.cuda.empty_cache()的副作用?为什么不能频繁调用?


完整讲解

一、empty_cache() 做什么

torch.cuda.empty_cache() 会释放 PyTorch 的 CUDA 缓存池 中当前未占用的块归还给 CUDA driver,不释放 仍被 tensor 占用的显存。目的是在「已 free 但被缓存池持有」时,让后续 alloc 能向 driver 要新块或让其他进程用到显存。

二、副作用

  • 同步:会与 CUDA 同步(或触发 driver 回收),可能 stall 当前 stream,带来一次全局同步点,影响性能与 overlap。
  • 碎片:缓存池清空后,后续分配重新从 driver 要块,历史「大块」布局被打散,可能反而增加碎片或分配失败(尤其在大块与小块交替分配时)。
  • 不能减「在用」显存:只还回未用缓存,不改变已分配 tensor 的占用;误以为「调了就能省显存」而频繁调用,只会增加同步与碎片风险。

三、何时用、为何不能频繁调

  • 适合:进程内显存已大量释放、且希望尽快把空闲还给系统(如多阶段脚本、中间换模型)时,偶尔 调一次。
  • 不宜频繁:训练循环内每 step 或每 N step 调一次没有意义(显存仍被占用),且会引入同步与碎片,降低吞吐、增加 OOM 风险。正确做法是优化模型与 batch、用 checkpoint 等减峰值,而不是依赖 empty_cache。

面试要点

  • empty_cache 只释放缓存池中未用块,不释放在用 tensor;会触发同步、可能加剧碎片。
  • 频繁调用无益且有害:同步 stall、碎片增加;不能当「省显存」手段。
  • 仅适合阶段切换时偶尔调用,训练循环内不要用。

记忆要点

  1. 只还缓存池空闲块,不释放在用显存;会同步、可能加重碎片。
  2. 训练循环里不要频繁调;用 checkpoint/batch 优化代替。
  3. 仅阶段切换、希望还显存给系统时偶尔用。

返回模块 | 返回总览

07-显存优化与Offload/081-如何估算大模型训练所需的显存.md

第 81 题:如何估算大模型训练所需的显存?公式推导?

题目

如何估算大模型训练所需的显存?公式推导?


完整讲解

一、显存组成

训练时显存主要来自:模型参数 (P);梯度(与参数量同量级);optimizer state(如 Adam 为 (2P) 的 fp32 动量+方差);激活(与 batch、序列长、层数相关)。推理只需参数(及少量 KV cache 等)。

二、参数量与优化器

  • 参数:fp16/bf16 为 (2P) 字节,fp32 为 (4P)。
  • 梯度:通常与参数同精度,(2P) 或 (4P)。
  • Adam state:两份 fp32,(8P);若用 8bit optimizer 或 fused kernel 可减少。
  • 总计(不含激活):约 (4P + 8P = 12P)(fp16 参数+梯度 + Adam fp32);ZeRO 分片后每卡除以 DP,再考虑 TP/PP 的切分。

三、激活的估算

  • Transformer:每层激活约 (batch \times seq \times hidden \times (常数)),attention 还有 (batch \times head \times seq^2);总激活约 (L \times (batch \cdot seq \cdot H + batch \cdot seq^2 \cdot H/L)),再乘 2(fp16)或 4(fp32)。用 checkpoint 可只存部分层,峰值约 (1/\sqrt{L}) 或按存点数量比例下降。
  • 公式:显存 ≈ 参数+梯度+optimizer + 激活;激活 ≈ (L \cdot batch \cdot seq \cdot hidden \cdot C)(C 为常数与精度相关),或查表/经验系数。估算时先算 12P,再加激活项;激活项用 batch×seq×hidden×层数×系数 粗算。

面试要点

  • 训练显存 ≈ 参数 + 梯度 + optimizer state + 激活;Adam 下约 12P + 激活。
  • 激活与 batch、seq、L、hidden 相关;checkpoint 可显著降激活峰值。
  • ZeRO/TP/PP 分片后每卡除以相应并行度,再按激活公式加总。

记忆要点

  1. 训练 ≈ 12P(fp16+Adam)+ 激活;激活 ∝ batch×seq×L×hidden。
  2. Checkpoint 降激活;ZeRO/TP/PP 分片降每卡参数与 state。
  3. 先算 12P 与激活量级,再按并行度除。

返回模块 | 返回总览

07-显存优化与Offload/082-gradient-checkpointing和activation-comp.md

第 82 题:gradient checkpointingactivation compression的结合?

题目

gradient checkpointingactivation compression的结合?


完整讲解

一、Gradient checkpointing 与 activation compression

Gradient checkpointing(即 activation checkpointing):少存激活、backward 时重算,用算力换显存。Activation compression:对激活做量化、稀疏或低秩近似再存,用精度/算力换显存。两者都可降低「激活占用」的显存,可叠加使用。

二、结合的方式与注意点

  • 先 checkpoint 再压缩:checkpoint 处只存「压缩后」的激活(如 int8 或稀疏),重算时解压再算梯度;显存进一步降,但解压与重算有额外算力,且压缩误差可能影响梯度。
  • 选择性组合:大激活层用 checkpoint,部分层再对存下来的激活做压缩(如只对非 checkpoint 的中间层做轻量压缩),平衡显存、算力与精度。
  • 误差与收敛:压缩会引入误差,需做误差分析或小规模实验验证收敛;通常先单独用 checkpoint 稳定,再谨慎加压缩(如 8bit 激活)并监控 loss。

三、工程实践

  • 多数框架先支持 checkpoint;activation compression 多在研究或特定场景(如超长序列、显存极紧)使用。
  • 结合时:checkpoint 的「存点」存压缩版本,backward 时解压→重算→反传;或对非 checkpoint 的激活做在线压缩再写回,需注意与 autograd 的兼容性(如自定义 backward)。

面试要点

  • Checkpoint 用算力换显存;compression 用精度/算力换显存;可叠加。
  • 结合时:存压缩激活、重算时解压;或部分层 checkpoint、部分层压缩;注意误差与收敛。
  • 工程上先 checkpoint 稳,再视需要加压缩并验证。

记忆要点

  1. Checkpoint = 重算换显存;compression = 量化/稀疏换显存;可一起用。
  2. 存压缩版激活、backward 解压重算;注意精度与收敛。
  3. 先上 checkpoint,再谨慎加 compression。

返回模块 | 返回总览

07-显存优化与Offload/083-CPU-offload和GPU计算的流水线重叠如何实现.md

第 83 题:CPU offload和GPU计算的流水线重叠如何实现?

题目

CPU offload和GPU计算的流水线重叠如何实现?


完整讲解

一、为何要重叠

CPU offload 时,数据在 GPU↔CPU 间搬运(PCIe),若「等拷贝完成再算」会浪费 GPU 算力。Overlap:在 GPU 计算当前 layer 时,异步把上一 layer 的 offload 数据搬回 GPU(或把下一阶段要用的数据从 CPU 搬到 GPU),使 拷贝与计算并行,隐藏部分 PCIe 延迟。

二、实现手段

  • 双缓冲(double buffering):两块 buffer A/B;GPU 算用 A 时,异步把 B 从 CPU 拷到 GPU(或反向);下一 step 交换角色,算 B 时拷 A。这样「算」与「拷」在时间上重叠。
  • CUDA stream:计算在一个 stream、拷贝在另一个 stream,用 cudaMemcpyAsync + 适当的 event 与依赖,保证「算完再拷」或「拷完再算」的依赖正确,其余时间两 stream 并行。
  • Pipeline 多阶段:把「计算 stage」与「拷贝 stage」组成流水线:stage1 算 layer1,同时 stage2 在拷 layer0 的数据;下一时刻 stage1 拷 layer1 结果,stage2 算 layer0 的 backward,依此类推。

三、与 ZeRO-Offload 等的对应

ZeRO-Offload、DeepSpeed 等实现中,optimizer step 的「梯度→CPU、CPU 更新、参数→GPU」会拆成异步拷贝 + 计算重叠:例如当前 layer 的 backward 与上一 layer 的 CPU 更新 + 回拷重叠,用 prefetch 与 double buffer 实现,从而在 PCIe 瓶颈下仍尽量拉高 GPU 利用率。


面试要点

  • Overlap = 拷贝与计算并行;double buffer + 异步拷贝 + 多 stream。
  • 实现:算 buffer A 时异步拷 B;用 cudaMemcpyAsync 与 stream/event 管理依赖。
  • ZeRO-Offload 等用「当前 backward 与上一 stage 的 CPU 更新+回拷」重叠。

记忆要点

  1. 双缓冲 + async copy + 多 stream = 拷贝与计算重叠。
  2. 算 A 时拷 B,下一 step 交换;依赖用 event 保证。
  3. Offload 框架里 prefetch 与 pipeline 是同一思想。

返回模块 | 返回总览

07-显存优化与Offload/084-多节点场景下的显存优化策略差异.md

第 84 题:多节点场景下的显存优化策略差异?

题目

多节点场景下的显存优化策略差异?


完整讲解

一、多节点带来的差异

多节点下 显存 仍是「每卡本地」的,但 通信 跨节点(机间带宽低、延迟高)。显存优化策略本身(checkpoint、offload、分片)不变,但 通信与显存的权衡 会变:例如梯度 all-reduce 跨机,通信更贵,可能倾向 增大 batch 或减少通信次数(如梯度累积、压缩);offload 到 CPU 时,若 CPU 内存也在本机,多节点与单机类似,若涉及跨机 CPU 则一般不这么做。

二、策略差异要点

  • ZeRO/分片:多节点时 DP 的 all-reduce 跨机,梯度压缩(fp16/bf16、稀疏)收益更大;ZeRO-3 参数也跨机 gather,通信量更大,需权衡 stage 与 overlap。
  • Checkpoint:与单机相同,多用 checkpoint 降显存可换更大 batch;多节点下 global batch 往往更大,单卡 batch 不变时 DP 度更高,all-reduce 成本上升,有时会适当减 DP 或做通信重叠。
  • Offload:ZeRO-Offload 的 CPU 在本机,多节点时每机独立 offload;Infinity 的 NVMe 也可每机本地,避免跨机 IO。多节点一般不把显存 offload 到「其他节点的 CPU」,延迟与带宽都差。

三、小结

多节点下显存优化手段一致,但 通信成本 上升,需更注重:通信压缩、通信与计算重叠、以及 DP/TP/PP 的划分(TP 同机、DP 跨机时 all-reduce 量要控制)。Offload 仍以本机 CPU/NVMe 为主。


面试要点

  • 多节点显存仍是每卡本地;差异在通信跨机、延迟与带宽更差。
  • 策略:更重视梯度压缩、通信重叠;ZeRO/checkpoint 仍用,offload 限本机。
  • TP 同机、DP 跨机时控制 all-reduce 量与 overlap。

记忆要点

  1. 多节点 = 通信贵;显存手段不变,更强调压缩与重叠。
  2. Offload 用本机 CPU/NVMe,不跨机 offload。
  3. 划分上 TP 同机、DP 跨机,控制通信量。

返回模块 | 返回总览

07-显存优化与Offload/085-显存优化的ROI如何评估.md

第 85 题:显存优化的ROI如何评估?训练速度vs模型规模的trade-off?

题目

显存优化的ROI如何评估?训练速度vs模型规模的trade-off?


完整讲解

一、ROI 的含义

显存优化的 ROI:投入「显存优化」(如 checkpoint、offload、分片)带来的 收益(能跑更大模型/更大 batch、或避免 OOM)与 成本(训练变慢、实现复杂度、调参成本)的权衡。评估时通常看:在相同硬件上能否跑起来训练速度(throughput)下降多少是否影响收敛(如 checkpoint 一般不影响,offload 可能略慢)。

二、训练速度 vs 模型规模

  • Checkpoint:用约 20%~30% 的额外计算换 40%~50% 的激活显存下降,吞吐通常略降(如 10%~20%),模型规模或 batch 可显著提升;ROI 高,优先用。
  • Offload:用 PCIe/NVMe 换容量,速度可能降 2x~数倍,但能跑否则跑不动的规模;ROI 在「能跑」与「不能跑」之间,适合资源紧张时。
  • 分片(ZeRO/TP/PP):分片增加通信与调度,但能线性扩展规模;在通信不成为瓶颈时,多卡分片的吞吐随卡数接近线性,ROI 高;通信瓶颈时需调 DP/TP/PP 比例。

三、如何评估

  • 目标:先定「要跑多大模型、多大 batch、多少卡」,再看显存是否够;不够则按「checkpoint → ZeRO → offload」顺序加,每次测 throughput 与收敛。
  • Trade-off:记录「无优化 baseline」「+checkpoint」「+offload」等的 throughput 与 max batch/max 模型规模,画曲线;结合业务对时延与成本的要求决定采用哪一档。一般 checkpoint 是「必选」,offload 是「保底」,分片是「扩展」。

面试要点

  • ROI = 显存优化带来的可跑规模/吞吐 与 速度下降/复杂度的权衡。
  • Checkpoint 略降吞吐、显著提规模,ROI 高;offload 明显降速、换容量;分片在通信不瓶颈时扩展性好。
  • 评估:先定目标规模与卡数,再按 checkpoint→ZeRO→offload 加,测 throughput 与收敛。

记忆要点

  1. Checkpoint 优先,略慢换大 batch/大模型;offload 保底,明显慢。
  2. 分片扩展规模,通信不瓶颈时 ROI 高。
  3. 评估 = 目标规模 + 测各组合的 throughput 与收敛。

返回模块 | 返回总览

08-通信优化/README.md

08-通信优化(第 86–95 题)

题号 主题 文章
86 NCCL的Tree算法和Ring算法分别在什么场景下更快? 086-NCCL的Tree算法和Ring算法分别在什么场景下更快.md
87 如何计算all-reduce的通信量?公式是什么? 087-如何计算all-reduce的通信量.md
88 NVLinkInfiniBandTCP的带宽和延迟差异? 088-NVLink、InfiniBand、TCP的带宽和延迟差异.md
89 多机训练中的网络拓扑感知?NCCL_TOPO_FILE 089-多机训练中的网络拓扑感知.md
90 通信和计算重叠(overlap)的技术手段?`double buffer… 090-通信和计算重叠(overlap)的技术手段.md
91 torch.distributedbackend选择:`ncc… 091-torch.distributed的backend选择:nccl、gloo、.md
92 RDMA技术原理?RoCE v1 vs RoCE v2 vs `… 092-RDMA技术原理.md
93 如何诊断网络拥塞导致的训练卡顿?iftopnicstat 093-如何诊断网络拥塞导致的训练卡顿.md
94 自定义通信算子的实现?torch.distributed的`redu… 094-自定义通信算子的实现.md
95 异构网络环境下的通信优化策略? 095-异构网络环境下的通信优化策略.md

返回总览

08-通信优化/086-NCCL的Tree算法和Ring算法分别在什么场景下更快.md

第 86 题:NCCL的Tree算法和Ring算法分别在什么场景下更快?

题目

NCCL的Tree算法和Ring算法分别在什么场景下更快?


完整讲解

一、Ring All-Reduce

Ring:(P) 个节点成环,数据分 (P) 块;每步每节点向邻居发一块、收一块,(P-1) 步后完成 reduce-scatter,再 (P-1) 步 all-gather,共 (2(P-1)) 步。每步每节点只与两个邻居通信,带宽利用率高(可逼近链路带宽),适合 多节点、大 message、带宽受限 场景;步数随 (P) 线性增,小 (P) 或 latency 敏感 时可能不如 tree。

二、Tree(如 Tree Reduce + Tree Broadcast)

Tree:用二叉树(或多叉)做 reduce 再 broadcast:reduce 时叶子→根逐层归约,broadcast 时根→叶子下发。步数 (O(\log P)),延迟低;但每层只有部分节点参与,总带宽利用不如 ring,适合 小 message、延迟敏感P 较大且单次数据量不大 时。若网络拓扑本身是树(如 fat-tree),tree 算法与拓扑匹配,也能减少跨架通信。

三、场景选择

  • 大 message、多节点、要打满带宽:选 Ring(NCCL 默认或推荐)。
  • 小 message、要低延迟:选 Tree 或 NCCL 的 tree 变体。
  • 单机多卡:NVLink 下两者差异可能不大,NCCL 会按 size 与 GPU 数自动选;多机时通常 ring 更常见。可通过环境变量或 NCCL 配置强制算法,再 benchmark 验证。

面试要点

  • Ring:步数 (2(P-1)),带宽利用率高,适合大 message、多节点。
  • Tree:步数 (O(\log P)),延迟低,适合小 message 或延迟敏感。
  • 大 message 多用 ring;小 message 或要低延迟可试 tree;单机多卡可交给 NCCL 自动选。

记忆要点

  1. Ring = 高带宽、步数线性;Tree = 低延迟、步数对数。
  2. 大 message → ring;小 message / 低延迟 → tree。
  3. NCCL 可按 size 自动选,多机常用 ring。

返回模块 | 返回总览

08-通信优化/087-如何计算all-reduce的通信量.md

第 87 题:如何计算all-reduce的通信量?公式是什么?

题目

如何计算all-reduce的通信量?公式是什么?


完整讲解

一、All-Reduce 的语义

All-reduce:(P) 个节点各有一个 tensor,归约(如 sum)后每个节点得到相同的全局结果。等价于 reduce-scatter(每节点得结果的一个分片)+ all-gather(拼成完整结果)。

二、通信量(以 Ring 为例)

  • 数据总量:(P) 份,每份 (N) 元素(如 float32 则 (4N) 字节)。归约后每节点需得到完整结果,即 (N) 元素。
  • Ring all-reduce:先 reduce-scatter((P-1) 步,每步传 (N/P)),再 all-gather((P-1) 步,每步传 (N/P))。每节点总发送/接收量 各为 (2 \cdot (P-1) \cdot (N/P) \approx 2N)(当 (P) 较大时),即 约 (2N) 元素(或 (8N) 字节 for fp32)的「单卡流量」。
  • 公式:单卡通信量 (\approx 2 \times (P-1)/P \times N \approx 2N)(元素数);字节数再乘 4(fp32)或 2(fp16)。有时也说「all-reduce 通信量 = (2(P-1)N/P) 每卡」,与上述一致。

三、时间估算

时间 (\approx) 通信量 / 带宽。若带宽为 (B)(字节/秒),单卡发送 (2N \times 4) 字节,则时间约 (8N/B)(fp32)。实际还有 latency、算法与拓扑影响,可用 (T \approx \alpha \cdot \log P + \beta \cdot 2N) 粗估((\alpha) 延迟项、(\beta) 与带宽相关)。


面试要点

  • All-reduce 语义:P 份数据归约后每节点得同一结果;等价 reduce-scatter + all-gather。
  • Ring 下每卡通信量 ≈ (2(P-1)N/P \approx 2N) 元素(单卡发送+接收各约 2N)。
  • 时间 ≈ 通信量/带宽;fp32 时字节数 = 8N(每卡)。

记忆要点

  1. 每卡通信量 ≈ 2N 元素(ring);字节 = 2N×精度。
  2. 公式:(2(P-1)N/P) 每卡;P 大时趋近 2N。
  3. 时间 = 量/带宽 + 延迟项。

返回模块 | 返回总览

08-通信优化/088-NVLink、InfiniBand、TCP的带宽和延迟差异.md

第 88 题:NVLinkInfiniBandTCP的带宽和延迟差异?

题目

NVLinkInfiniBandTCP的带宽和延迟差异?


完整讲解

一、NVLink

NVLink:GPU 间直连、多通道(如 300–600 GB/s 双向),延迟极低(微秒级),用于单机多卡或 NVSwitch 机内多卡。带宽与延迟都优于 PCIe;NCCL 单机内会优先走 NVLink,适合 TP、单机 all-reduce

二、InfiniBand(IB)

InfiniBand:专用 RDMA 网络,高带宽(如 100–400 Gb/s 单口)、低延迟(微秒级)、内核旁路(zero-copy)。多机训练常用 IB 做机间 all-reduce;需专用网卡与交换机,成本高,适合集群。

三、TCP(以太网)

TCP:走标准以太网与内核协议栈,带宽 通常 10–100 Gb/s、延迟 数十微秒到毫秒级,易部署、无专用硬件。多机无 IB 时用 TCP(NCCL 的 socket 或 gloo);带宽与延迟都逊于 NVLink/IB,适合 DP 的梯度 all-reduce 或小规模多机。

四、对比小结

类型 带宽(量级) 延迟 典型场景
NVLink 300+ GB/s 极低 单机多卡 TP
InfiniBand 100–400 Gb/s 微秒级 多机集群
TCP 10–100 Gb/s 数十 μs~ms 无 IB 多机、小规模

面试要点

  • NVLink:单机 GPU 直连,带宽与延迟最优;InfiniBand:多机 RDMA,高带宽低延迟;TCP:以太网,易部署、性能次之。
  • 单机 TP 走 NVLink;多机优先 IB,无 IB 用 TCP。

记忆要点

  1. NVLink > IB > TCP(带宽与延迟);TCP 易部署。
  2. 单机 = NVLink;多机 = IB 或 TCP。
  3. 延迟:NVLink/IB 微秒级,TCP 更高。

返回模块 | 返回总览

08-通信优化/089-多机训练中的网络拓扑感知.md

第 89 题:多机训练中的网络拓扑感知?NCCL_TOPO_FILE

题目

多机训练中的网络拓扑感知?NCCL_TOPO_FILE


完整讲解

一、为何要拓扑感知

多机多卡时,物理拓扑(哪些 GPU 同机、哪些跨机、交换机层级)影响通信路径与带宽。拓扑感知:让 NCCL 知道「谁和谁更近」,从而优先在同机/同架内通信、减少跨架跳数,可降低延迟与拥塞,提升 all-reduce 等 collective 的效率。

二、NCCL_TOPO_FILE

NCCL_TOPO_FILE:指定一个拓扑描述文件(如 XML),描述节点、GPU、网卡、交换机之间的连接关系与带宽。NCCL 在初始化时读取该文件,据此构建 optimal ring 或 tree,使通信尽量走高速链路(如同机 NVLink、同架 IB),避免绕远或打满某条弱链路。若不指定,NCCL 会自动探测(如 PCIe、NVLink、IB),但在复杂拓扑下可能不如手写拓扑准。

三、使用方式与注意点

  • 文件格式:NCCL 支持 XML 等格式,描述 GPU、NIC、node 及彼此带宽/距离。
  • NCCL_SOCKET_IFNAMENCCL_IB_DISABLE 等配合:指定网卡、是否用 IB 等,再通过拓扑文件约束路径。
  • 多机训练启动时设置 export NCCL_TOPO_FILE=/path/to/topo.xml,再启动训练;适合固定集群与重复实验,避免每次自动探测不一致。

面试要点

  • 拓扑感知 = 让 NCCL 按物理拓扑选通信路径,同机/同架优先,减少跨架与拥塞。
  • NCCL_TOPO_FILE 指定拓扑描述文件(如 XML),NCCL 据此建 ring/tree。
  • 复杂集群或要稳定路径时手写拓扑;简单环境可依赖自动探测。

记忆要点

  1. 拓扑感知 = 按「谁和谁近」选路径,同机/同架优先。
  2. NCCL_TOPO_FILE = 拓扑文件路径,XML 描述 GPU/NIC/带宽。
  3. 固定集群建议写拓扑,保证路径一致。

返回模块 | 返回总览

08-通信优化/090-通信和计算重叠(overlap)的技术手段.md

第 90 题:通信和计算重叠(overlap)的技术手段?double buffering

题目

通信和计算重叠(overlap)的技术手段?double buffering


完整讲解

一、重叠的目标

通信与计算重叠:在 GPU 做当前 layer 的算时,同时在后台做 all-reduce 或其它 collective(上一 layer 的梯度),这样通信时间被「藏在」计算里,总 step 时间 ≈ max(计算, 通信) 而非 计算+通信。

二、技术手段

  • 梯度 bucket 与异步 all-reduce:DDP 把参数按 bucket 分组,某 bucket 的 backward 一完成就立即对该 bucket 发起 all-reduce(非阻塞),GPU 继续算下一 bucket;这样「算」与「通信」在时间上重叠。关键是把 all-reduce 拆成多段、每段与对应计算重叠。
  • Double buffering:两块 buffer 轮流:一块用于当前计算、一块用于通信(如拷贝或 collective);下一 step 交换。保证计算与通信并行。
  • CUDA stream:计算 stream 与通信 stream 分离;通信用 cudaMemcpyAsync 或 NCCL 的 async API,用 event 保证「梯度就绪再 all-reduce」「all-reduce 完成再 optimizer step」的依赖,其余时间两 stream 并行。
  • Overlap 与 DDP:DDP 的 find_unused_parameters=False、bucket_cap_mb 等会影响 bucket 划分与 overlap 程度;gradient_as_bucket_view 可减少一次拷贝,利于重叠。

三、注意点

  • 通信量或延迟过大时,再重叠也可能无法完全隐藏,此时需压缩或减少通信次数。
  • 保证正确性:依赖要明确(哪步算完才可通信、通信完才可更新),用 stream/event 或 framework 内建语义保证。

面试要点

  • 重叠 = 计算与通信并行;DDP bucket + 异步 all-reduce、double buffer、多 stream。
  • DDP 通过 bucket 分组,每 bucket 就绪即发起 all-reduce,与后续计算重叠。
  • 依赖用 stream/event 保证;通信过大时重叠可能无法完全隐藏。

记忆要点

  1. Bucket 就绪即 all-reduce + 继续算下一 bucket = 重叠。
  2. Double buffer + 多 stream 是通用手段;DDP 已内置 bucket overlap。
  3. 正确性靠依赖与 event 保证。

返回模块 | 返回总览

08-通信优化/091-torch.distributed的backend选择:nccl、gloo、.md

第 91 题:torch.distributedbackend选择:ncclgloompi

题目

torch.distributedbackend选择:ncclgloompi


完整讲解

一、NCCL

NCCL(NVIDIA Collective Communications Library):面向 GPU 集体通信(all-reduce、all-gather、broadcast 等),利用 NVLink、多 GPU、多机 IB/TCP,性能最优限制:仅支持 GPU tensor;多机需 NCCL 与网络(IB 或 socket)正确配置。PyTorch 多卡/多机 GPU 训练默认推荐 nccl

二、Gloo

Gloo:PyTorch 自带的 CPU/GPU collective 实现,支持 CPU tensor、也支持 GPU(通过 CUDA)。优点:无需 NCCL、易调试、支持更多 reduce 类型与自定义 op。缺点:GPU 上性能通常不如 NCCL,多机用 TCP。适合 CPU 训练、或 GPU 上调试/小规模,或无 NCCL 环境。

三、MPI

MPI:使用系统 MPI 库(如 OpenMPI、MVAPICH)做 collective。优点:与现有 HPC 环境兼容、功能全。缺点:需单独安装 MPI、与 PyTorch 的集成不如 nccl/gloo 简单,调试与部署略重。适合 已有 MPI 的集群、或与其它 MPI 程序协同 时。

四、选择建议

  • 多卡/多机 GPU 训练:用 nccl;无 IB 时 nccl 走 socket 也可。
  • 仅 CPU 或调试:用 gloo
  • 与 HPC/MPI 生态集成:用 mpi backend。设置方式:torch.distributed.init_process_group(backend='nccl', ...)

面试要点

  • nccl:GPU 集体通信、性能最好,多卡/多机首选;gloo:CPU 或调试、易用;mpi:与 HPC 集成。
  • GPU 训练默认 nccl;仅 CPU 或无 NCCL 用 gloo。
  • init_process_group(backend='nccl'/'gloo'/'mpi')。

记忆要点

  1. nccl = GPU 最优;gloo = CPU/调试;mpi = HPC 集成。
  2. 多卡 GPU → nccl;CPU 或调试 → gloo。
  3. Backend 需与设备与环境匹配。

返回模块 | 返回总览

08-通信优化/092-RDMA技术原理.md

第 92 题:RDMA技术原理?RoCE v1 vs RoCE v2 vs InfiniBand

题目

RDMA技术原理?RoCE v1 vs RoCE v2 vs InfiniBand


完整讲解

一、RDMA 原理

RDMA(Remote Direct Memory Access):绕过 CPU 与内核,网卡直接读写对端内存,零拷贝、低延迟、高带宽,适合大规模分布式训练。InfiniBandRoCE(RDMA over Converged Ethernet)是两种常见实现:IB 专用网络,RoCE 跑在以太网上。

二、InfiniBand

InfiniBand:原生 RDMA 网络,专用网卡与交换机,延迟最低、带宽高(如 200 Gb/s),需 IB 硬件。多机训练集群常用。

三、RoCE v1 vs RoCE v2

  • RoCE v1:RDMA over 无损以太网(Layer 2),同一 L2 域内;依赖数据中心无损以太网(PFC 等),配置要求高。
  • RoCE v2:在 UDP/IP(Layer 3)上跑 RDMA,可跨子网、路由,部署更灵活;延迟略高于 RoCE v1 与 IB,但仍优于 TCP。生产环境多选 RoCE v2 或 IB;RoCE v1 在纯 L2 无损网络中可用。

四、对比小结

类型 网络 部署 延迟/带宽
InfiniBand 专用 IB 需 IB 硬件 最优
RoCE v1 L2 以太网 需无损网络 次之
RoCE v2 L3 UDP 易部署 略高仍优于 TCP

面试要点

  • RDMA = 网卡直读对端内存,零拷贝、低延迟;IB 与 RoCE 是两种实现。
  • RoCE v1 = L2 无损以太网;RoCE v2 = L3 UDP,可路由、易部署。
  • 性能:IB ≥ RoCE v1 > RoCE v2 > TCP;多机无 IB 常用 RoCE v2。

记忆要点

  1. RDMA = 内核旁路、零拷贝;IB 专用,RoCE 跑在以太网上。
  2. RoCE v1 = L2;RoCE v2 = L3 UDP,可跨子网。
  3. 选型:有 IB 用 IB;否则 RoCE v2 常用。

返回模块 | 返回总览

08-通信优化/093-如何诊断网络拥塞导致的训练卡顿.md

第 93 题:如何诊断网络拥塞导致的训练卡顿?iftopnicstat

题目

如何诊断网络拥塞导致的训练卡顿?iftopnicstat


完整讲解

一、现象与原因

训练卡顿(如 step 时间突增、周期性变慢)可能来自 网络拥塞:多机 all-reduce 或大量点对点流量打满某条链路,导致排队与重传,NCCL collective 变慢。需区分是「计算慢」还是「通信慢」,再针对通信做诊断。

二、工具与用法

  • iftop / nethogs:看实时流量与占用带宽的进程/连接;可看到某网卡或某 IP 对是否持续高占用,判断是否有多机流量打满。
  • nicstat / sar -n:看网卡利用率、包数、错误与丢包;若某 NIC 持续高 util 或 errors/drop 上升,可能是拥塞或硬件问题。
  • NCCL_DEBUG=INFO / TIMING:看 collective 的耗时与 transport;若某次 all-reduce 明显变长,对应时间点再结合 iftop/nicstat 看是否网络尖峰。
  • torch.profiler:看 timeline 上 NCCL kernel 的时长与间隔;若通信段明显拉长且呈周期性,可怀疑网络或某节点慢。

三、排查思路

  • 先确认「卡顿」是通信:profile 看 NCCL 占比、或关掉部分 DP 看是否缓解。
  • 再用 iftop/nicstat 看拥塞点:哪条链路、哪个节点在高峰;结合拓扑看是否跨架、单链路过载。
  • 优化:调 NCCL 拓扑(NCCL_TOPO_FILE)、减少同时通信、或增加带宽/换路径;梯度压缩减通信量。

面试要点

  • 卡顿可能来自网络拥塞;先 profile 确认是通信慢,再用 iftop/nicstat 看流量与网卡。
  • iftop 看实时流量与连接;nicstat/sar 看网卡利用率与丢包。
  • NCCL_DEBUG + profiler 看 collective 耗时;结合拓扑与流量找拥塞点。

记忆要点

  1. 先区分计算 vs 通信(profile);再 iftop/nicstat 看流量与 NIC。
  2. 拥塞 = 某链路或某 NIC 持续高占用/丢包。
  3. 优化 = 拓扑、减通信量、梯度压缩。

返回模块 | 返回总览

08-通信优化/094-自定义通信算子的实现.md

第 94 题:自定义通信算子的实现?torch.distributedreduce_op

题目

自定义通信算子的实现?torch.distributedreduce_op


完整讲解

一、PyTorch 内置 collective 与 reduce_op

torch.distributed 提供 all_reduceall_gatherreduce_scatterbroadcast 等,并支持 reduce_op 参数:如 dist.ReduceOp.SUMMINMAXPRODUCT 等,指定归约语义。自定义逻辑(如梯度裁剪后再 all-reduce、或自定义聚合)可在调用前后用 Python 处理,再调标准 collective;若只需非 SUM 的归约,直接传对应 reduce_op 即可。

二、自定义通信算子

  • 组合现有 collective:例如「先 all_gather 再本地 reduce 再 scatter」实现某种自定义聚合;或多次 all_reduce 与 point-to-point(send/recv)组合成新语义。
  • NCCL 扩展:若需与现有 collective 不同的算法(如自定义 ring、tree),需用 NCCL 的 APICUDA + 自定义 kernel 发数据,再调 NCCL 的 group 与 communicator;PyTorch 侧用 torch.distributed 的 C++ 扩展或 ProcessGroupNCCL 的 custom op 挂接。
  • 后端init_process_group 时选 nccl/gloo;gloo 支持更多 reduce 类型,nccl 主要支持 SUM/PRODUCT/MIN/MAX 等,自定义复杂逻辑时可先用 gloo 验证再考虑 nccl 扩展。

三、实现注意点

  • 所有 rank 必须同序、同参调用 collective,否则 hang;自定义算子要保证调用顺序与 tensor shape 一致。
  • 性能:自定义多次 collective 或 send/recv 可能不如单次 all-reduce,需权衡语义与带宽;可配合 overlap 与 stream 隐藏部分延迟。

面试要点

  • 标准 collective + reduce_op(SUM/MIN/MAX 等)满足多数需求;复杂聚合可「前后处理 + 多次 collective」或 send/recv 组合。
  • 真正自定义算法需 NCCL API 或 C++ 扩展挂 ProcessGroup;gloo 支持更多 op 类型。
  • 所有 rank 同序同参,避免 hang;注意性能与 overlap。

记忆要点

  1. reduce_op 指定 SUM/MIN/MAX 等;复杂逻辑 = 组合 collective 或 send/recv。
  2. 完全自定义 = NCCL/C++ 扩展;gloo 可做更多 op 验证。
  3. 集体通信必须同序同参。

返回模块 | 返回总览

08-通信优化/095-异构网络环境下的通信优化策略.md

第 95 题:异构网络环境下的通信优化策略?

题目

异构网络环境下的通信优化策略?


完整讲解

一、异构网络的含义

异构:同一训练任务中,部分链路是 高速(如 NVLink、IB),部分是 低速(如 10G 以太网、或部分节点仅 TCP)。例如多机集群中部分机架用 IB、部分用 TCP,或单机多卡有 NVLink 但跨机只有 25G 以太网。此时若 collective 路径不经意经过慢链路,会成为瓶颈。

二、策略概览

  • 拓扑感知:用 NCCL_TOPO_FILE 或等价配置标明「快慢」与连接关系,让 NCCL 优先在快链路上做 ring/tree,减少慢链路参与或让慢链路只传少量数据。
  • 划分与放置:把 通信密集 的并行(如 TP)放在同机/同架(高速),通信较少 的(如 DP)跨机时影响小;即 TP 同机、DP 跨机,避免 TP 走慢链路。
  • 压缩与减少通信:在慢链路上减少数据量(梯度压缩、fp16、稀疏)或减少通信次数(梯度累积、大 batch),使慢链路不成为主导瓶颈。
  • Overlap:在快链路上尽量重叠计算与通信;慢链路无法完全隐藏时,至少保证计算不空等(如预取、双缓冲)。

三、监控与调优

  • NCCL_DEBUGprofiler 看各 collective 耗时,定位是否某次通信明显更长(可能走慢链路)。
  • 结合 iftop/nicstat 看各 NIC 利用率,确认慢链路是否被过度使用;再通过拓扑与 placement 把关键路径放到快链路。

面试要点

  • 异构 = 部分快(NVLink/IB)、部分慢(TCP/弱网);策略 = 拓扑感知 + 放置 + 压缩 + overlap。
  • TP 放快链路、DP 可跨慢链路;用拓扑文件引导 NCCL 路径。
  • 慢链路上减量(压缩)或减次数;用 profile 找瓶颈链路。

记忆要点

  1. 拓扑感知 + 放置:TP 同快链路,DP 可跨慢链路。
  2. 慢链路:压缩、减次数、overlap 计算。
  3. Profile + 拓扑文件定位瓶颈链路并调优。

返回模块 | 返回总览

09-推理引擎/README.md

09-推理引擎(第 96–115 题)

题号 主题 文章
96 TensorRT的builderruntime工作流程?`pl… 096-TensorRT的builder和runtime工作流程.md
97 TensorRT的dynamic shape优化技巧?`optimi… 097-TensorRT的dynamic-shape优化技巧.md
98 TensorRT的plugin开发中,`IPluginV2Dynam… 098-TensorRT的plugin开发中,IPluginV2DynamicExt.md
99 ONNX Runtime的execution provider有哪些… 099-ONNX-Runtime的execution-provider有哪些.md
100 torch.compile的推理优化模式?`reduce-overh… 100-torch.compile的推理优化模式.md
101 vLLM的PagedAttention核心思想?`block tab… 101-vLLM的PagedAttention核心思想.md
102 vLLM的continuous batching如何实现?和`sta… 102-vLLM的continuous-batching如何实现.md
103 vLLM的prefix caching机制?命中率如何提升? 103-vLLM的prefix-caching机制.md
104 TensorRT-LLM的in-flight batching原理? 104-TensorRT-LLM的in-flight-batching原理.md
105 FasterTransformer的decoder优化技术?`mem… 105-FasterTransformer的decoder优化技术.md
106 Hugging Face的`text-generation-infere… 106-Hugging-Face的text-generation-inference.md
107 llama.cpp的量化策略?Q4_0Q5_K_M的区别? 107-llama.cpp的量化策略.md
108 移动端推理框架选择?MNNTNNPaddle Lite对… 108-移动端推理框架选择.md
109 推理引擎的warmup为什么重要?如何设计warmup策略? 109-推理引擎的warmup为什么重要.md
110 多stream推理的实现?CUDA stream的同步机制? 110-多stream推理的实现.md
111 推理batching的paddingpacking策略?`Fl… 111-推理batching的padding和packing策略.md
112 如何评估推理引擎的延迟分布?P50、P90、P99的优化重点? 112-如何评估推理引擎的延迟分布.md
113 推理服务的auto-scaling策略?基于GPU利用率还是请求队列… 113-推理服务的auto-scaling策略.md
114 多模型混部的资源隔离?MPS(Multi-Process Servi… 114-多模型混部的资源隔离.md
115 推理引擎的debug模式?如何定位精度下降问题? 115-推理引擎的debug模式.md

返回总览

09-推理引擎/096-TensorRT的builder和runtime工作流程.md

第 96 题:TensorRT的builderruntime工作流程?plan文件包含什么?

题目

TensorRT的builderruntime工作流程?plan文件包含什么?


完整讲解

一、Builder 阶段

Builder:读入模型(ONNX、Caffe、或 TensorRT API 构建),做图优化(层融合、精度校准、kernel 选择、显存规划等),输出 Engine(即优化后的可执行计划)。Builder 通常离线、较慢,会尝试多种 kernel 与精度组合(如 fp16、int8),生成针对目标 GPU 的最优执行计划。

二、Runtime 阶段

Runtime:加载已构建好的 Engine(或从 plan 反序列化),在目标设备上执行 inference。Runtime 轻量、无优化开销,适合部署时反复执行;可多线程/多 stream 并发执行同一 engine。

三、Plan 文件

Plan:序列化后的 Engine,包含 优化后的网络结构kernel 选择显存分配精度与 calibration 信息(若 int8)等;不含原始权重路径,权重通常单独存或在 engine 内嵌。同一 plan 可在同架构同 GPU 上直接加载;换 GPU 或驱动大版本升级建议重 build。流程:Builder 生成 Engine → 序列化写 plan → 部署时 Runtime 读 plan → 反序列化执行。


面试要点

  • Builder:图优化、kernel 选择、生成 Engine;Runtime:加载 Engine 执行。
  • Plan = 序列化 Engine,含结构、kernel、显存与精度信息;部署用 Runtime + plan。
  • Builder 离线、Runtime 在线;同架构可复用 plan,换 GPU 建议重 build。

记忆要点

  1. Builder 建 Engine,Runtime 跑 Engine;plan = 序列化 Engine。
  2. Plan 含结构、kernel、显存;权重可内嵌或单独。
  3. 同卡复用 plan;换卡/换驱动重 build。

返回模块 | 返回总览

09-推理引擎/097-TensorRT的dynamic-shape优化技巧.md

第 97 题:TensorRT的dynamic shape优化技巧?optimization profile

题目

TensorRT的dynamic shape优化技巧?optimization profile


完整讲解

一、Dynamic Shape 的挑战

输入 shape 在运行时变化(如 batch、seq_len 可变)时,TensorRT 需在 build 时 知道范围或若干典型值,才能选 kernel、做融合与显存分配。若完全动态,需用 dynamic shape APIoptimization profile

二、Optimization Profile

Optimization profile:为 dynamic 维度指定 min / opt / max(如 batch=1,8,32;seq=16,128,512)。Builder 会针对 opt 做主要优化,并保证 min~max 内均可执行;Runtime 执行时若在范围内则用同一 engine,超出则需多 profile 或重 build。多个 profile 可并存(如不同 batch 段),运行时按当前 shape 选 profile。

三、优化技巧

  • opt 选常见/热点 shape:让 opt 接近线上 P50/P90 的 shape,延迟与吞吐更稳。
  • min/max 不要过宽:过宽会增大显存与 kernel 通用性,可能牺牲 opt 点性能;按业务上下界设即可。
  • 避免不必要的动态维:能固定的维度(如 feature 维)尽量固定,只对 batch、seq 等必要维开 dynamic。
  • 多 profile:若 min~max 跨度大,可建多个 profile(如小 batch 一个、大 batch 一个),运行时按 shape 选,比单一大 range 更高效。

面试要点

  • Dynamic shape 需在 build 时给 min/opt/max;optimization profile 指定各 dynamic 维范围。
  • opt 决定主要优化点,选常见 shape;min/max 不过宽,必要时多 profile。
  • 能固定的维尽量固定,减少动态维数量。

记忆要点

  1. Optimization profile = min/opt/max;opt 为主优化目标。
  2. 范围不过宽;多 profile 可覆盖大跨度。
  3. 固定维尽量固定。

返回模块 | 返回总览

09-推理引擎/098-TensorRT的plugin开发中,IPluginV2DynamicExt.md

第 98 题:TensorRT的plugin开发中,IPluginV2DynamicExtIPluginV2IOExt区…

题目

TensorRT的plugin开发中,IPluginV2DynamicExtIPluginV2IOExt区别?


完整讲解

一、IPluginV2 系列

TensorRT plugin 用于不支持或需自定义的算子。IPluginV2 为固定 shape;IPluginV2Ext 扩展了类型与 format;IPluginV2DynamicExtIPluginV2IOExt 用于动态与 IO 扩展。

二、IPluginV2DynamicExt

IPluginV2DynamicExt:支持 dynamic shape 的 plugin。关键方法:getOutputDimensionsconfigurePlugin 根据输入维度推导输出维度与内部配置;enqueue 接收 runtime 的 actual shape,执行计算。用于 输入/输出维在运行时变化 的算子(如变长 seq、dynamic batch),需在 build 时通过 optimization profile 给范围。

三、IPluginV2IOExt

IPluginV2IOExt:扩展 输入输出类型与 layout(如 FP32/FP16/INT8、NCHW/NHWC),不强调 dynamic shape。用于需要多精度或多 layout 的 plugin,或与 IO 格式转换配合。若只需 dynamic shape,用 IPluginV2DynamicExt;若需丰富 IO 类型/layout,用 IPluginV2IOExt 或与 DynamicExt 组合(视 TensorRT 版本 API)。

四、对比小结

  • DynamicExt:核心是 动态维;getOutputDimensions/configurePlugin 按输入维推导,enqueue 用 actual shape。
  • IOExt:核心是 类型与 layout;支持多精度与格式。两者可同时继承(若 API 允许)或按需求二选一。

面试要点

  • IPluginV2DynamicExt:支持 dynamic shape;getOutputDimensions/configurePlugin/enqueue 与运行时 shape 相关。
  • IPluginV2IOExt:扩展 IO 类型与 layout(精度、NCHW 等),不强调动态维。
  • 需要变长/变 batch 用 DynamicExt;需要多精度/格式用 IOExt。

记忆要点

  1. DynamicExt = 动态 shape;IOExt = 多类型/layout。
  2. Dynamic 需实现维度推导与 enqueue(actual shape)。
  3. 按需求选或组合(视版本)。

返回模块 | 返回总览

09-推理引擎/099-ONNX-Runtime的execution-provider有哪些.md

第 99 题:ONNX Runtime的execution provider有哪些?CUDATensorRT、`Dire…

题目

ONNX Runtime的execution provider有哪些?CUDATensorRTDirectML


完整讲解

一、Execution Provider(EP)的作用

ONNX Runtime 的 Execution Provider 把算子在不同后端上执行:CPU、CUDA、TensorRT、DirectML 等。同一 ONNX 模型可切换 EP,在 GPU/CPU/不同框架间选择,无需改模型。

二、常见 EP

  • CPU:默认,跨平台,无 GPU 依赖;适合小模型或无 GPU 环境。
  • CUDA:NVIDIA GPU,用 cuDNN/cuBLAS;延迟与吞吐优于 CPU,需 CUDA 环境。
  • TensorRT:将子图或整图交给 TensorRT 优化执行,在 NVIDIA 上往往比纯 CUDA EP 更快;需 TensorRT 库,build 可能较慢。
  • DirectML:Windows 上利用 DirectX 12 与多种 GPU(NVIDIA/AMD/Intel),跨厂商;适合 Windows 部署。
  • CoreML(Apple)、OpenVINO(Intel)、NNAPI(Android)等:针对特定平台。选择时按部署环境与性能需求选;多 EP 可组合(如 CUDA + TensorRT,部分 op fallback)。

三、使用方式

创建 session 时指定 provider 列表:ort.InferenceSession(model_path, providers=['TensorRTExecutionProvider', 'CUDAExecutionProvider', 'CPUExecutionProvider']);按序 fallback:先试 TensorRT,再 CUDA,再 CPU。可传 EP 专属选项(如 TensorRT 的 fp16、cache 路径)。


面试要点

  • EP = 执行后端;常见有 CPU、CUDA、TensorRT、DirectML、CoreML、OpenVINO 等。
  • GPU 上常用 CUDA 或 TensorRT;Windows 多 GPU 可用 DirectML;按平台与性能选。
  • Session 指定 providers 列表,按序 fallback;可传各 EP 的选项。

记忆要点

  1. EP = 后端;CPU/CUDA/TensorRT/DirectML 等。
  2. GPU 首选 CUDA 或 TensorRT;TensorRT 更优但依赖重。
  3. providers 列表决定优先级与 fallback。

返回模块 | 返回总览

09-推理引擎/100-torch.compile的推理优化模式.md

第 100 题:torch.compile的推理优化模式?reduce-overhead vs max-autotune

题目

torch.compile的推理优化模式?reduce-overhead vs max-autotune


完整讲解

一、torch.compile 的推理模式

torch.compile 对模型做图捕获与优化(TorchDynamo + Inductor 等)。推理时可指定 modemode="reduce-overhead" 侧重降低 Python 与调度开销(如减少 Python 调用、融合 kernel);mode="max-autotune" 侧重 极致性能,会做更多 kernel 搜索与选型,编译更慢、运行时更快。

二、reduce-overhead vs max-autotune

  • reduce-overhead:优化目标 = 减少 overhead(Python、dispatch、小 kernel launch),适合 batch 不大、推理延迟敏感 的场景;编译较快,适合迭代与部署平衡。
  • max-autotune:允许 更激进的 autotune(如更多 matmul/cuda 配置),编译时间长,适合 离线编译、追求峰值吞吐或大 batch;可能增加显存与编译时间。
  • 默认(无 mode 或 mode="default"):介于两者之间。推理常用 reduce-overhead 做延迟优化,或 max-autotune 做吞吐优化;训练一般不用 max-autotune(编译与显存成本高)。

三、使用建议

  • 推理延迟优先:torch.compile(model, mode="reduce-overhead");大 batch 或离线优化:mode="max-autotune"
  • 需配合 fullgraph=True(若可行)减少 Python 回退;首次运行会编译,可做 warmup。

面试要点

  • reduce-overhead:降 Python/调度开销,适合推理延迟;max-autotune:激进 kernel 搜索,适合吞吐、编译慢。
  • 推理常用 reduce-overhead 或 max-autotune;默认介于两者之间。
  • 配合 fullgraph、warmup 使用。

记忆要点

  1. reduce-overhead = 低延迟、少 overhead;max-autotune = 高吞吐、慢编译。
  2. 推理延迟用 reduce-overhead;吞吐用 max-autotune。
  3. 首次运行编译,需 warmup。

返回模块 | 返回总览

09-推理引擎/101-vLLM的PagedAttention核心思想.md

第 101 题:vLLM的PagedAttention核心思想?block table的数据结构?

题目

vLLM的PagedAttention核心思想?block table的数据结构?


完整讲解

一、PagedAttention 核心思想

PagedAttention 借鉴 OS 的分页内存:把 KV cache 按「块」(block)管理,每块固定大小(如 16/64 token 的 KV),物理上不连续;逻辑上每个序列的 KV 用 block 指针列表 串联。这样可 按需分配/回收块、减少外部碎片、便于不同序列共享前缀块(prefix caching)。

二、Block 与 Block Table

  • Block:固定 token 数的 KV 存储单元;所有 block 组成 全局 block 池,按需分配给请求。
  • Block table:每个序列维护一张表,记录「该序列的 KV 由哪些 block 组成、顺序如何」;即 逻辑 KV 序列 → 物理 block 列表 的映射。解码时根据 block table 找到对应 block,再做 attention 计算;支持非连续、共享块(前缀共享时多序列指向同一组 block)。

三、收益

  • 显存利用率高:按块分配,减少碎片;可回收已结束序列的 block 给新请求。
  • 前缀共享:相同 prefix 的请求共享同一组 block,省显存与算力。
  • 与 continuous batching 自然结合:新请求随时要新 block、结束请求释放 block,block 池统一调度。

面试要点

  • PagedAttention = KV 按块(page)管理,逻辑序列用 block 指针表串联;类似 OS 分页。
  • Block table = 每序列的「逻辑 KV → 物理 block 列表」;支持非连续与共享。
  • 收益:显存利用率高、碎片少、前缀共享、易与 continuous batching 结合。

记忆要点

  1. KV 分块存储;每序列 block table 记录 block 列表。
  2. 块可复用、可共享(前缀);减少碎片。
  3. 与 continuous batching 配合,按需分配/回收 block。

返回模块 | 返回总览

09-推理引擎/102-vLLM的continuous-batching如何实现.md

第 102 题:vLLM的continuous batching如何实现?和static batching的吞吐对比?

题目

vLLM的continuous batching如何实现?和static batching的吞吐对比?


完整讲解

一、Static Batching 的问题

Static batching:凑满一个 batch(或超时)后一起跑一次 decode,本 batch 全部完成再接下一批。问题:序列长短不一,短序列先结束却要等长序列,GPU 空转;batch 内 padding 多则算力浪费,吞吐与延迟都不理想。

二、Continuous Batching 的做法

Continuous batching(vLLM 等):不固定 batch 边界,每轮 decode 时只对「当前步仍需生成」的请求做一次前向;某请求生成完 EOS 就立即移出,新请求可立即加入。即 batch 在时间维上「流动」:每轮参与的是「in-flight」的请求子集,完成即退出、新请求即进入。这样 GPU 始终有活干,短序列不拖长序列,吞吐高、尾延迟低。

三、实现要点与吞吐对比

  • 调度:每轮选「未完成」的请求组成当前 batch(受 max_batch、显存约束);与 PagedAttention 结合,按 block 分配与回收。
  • 吞吐:在相同 QPS 与延迟约束下,continuous batching 通常比 static 高 数倍(尤其长短混合、高方差场景);static 的「等最慢」导致利用率低,continuous 的「即出即进」拉高利用率。vLLM 的 benchmark 常见 2~10x 提升(视负载而定)。

面试要点

  • Static:凑 batch、等整批完成再下一批;短等长、利用率低。
  • Continuous:每轮只算「未完成」请求,完成即出、新请求即入;batch 流动,利用率高。
  • 吞吐上 continuous 常比 static 高数倍,尤其长短混合;与 PagedAttention 配合实现。

记忆要点

  1. Static = 整批进整批出;continuous = 每步只算 in-flight,出即入。
  2. Continuous 避免「短等长」,GPU 利用率高。
  3. vLLM 用 continuous + PagedAttention,吞吐显著优于 static。

返回模块 | 返回总览

09-推理引擎/103-vLLM的prefix-caching机制.md

第 103 题:vLLM的prefix caching机制?命中率如何提升?

题目

vLLM的prefix caching机制?命中率如何提升?


完整讲解

一、Prefix Caching 机制

Prefix caching:多个请求若共享相同前缀(如 system prompt、长 context),则只算一次该前缀的 KV,并缓存起来;后续请求直接复用这些 KV block,只算「前缀之后」的 decode。与 PagedAttention 的 block 结合:共享前缀对应同一组 block,多请求引用同一 block 表前缀部分,省显存与算力。

二、命中率提升

  • 请求路由:把相同 prefix 的请求尽量路由到同一实例或同一 block 池,使缓存可复用;多实例时可用一致性 hash 或 prefix 指纹路由。
  • Prefix 规范化:对 system prompt、模板做归一化(去空格、统一格式),提高「相同 prefix」的匹配率;或对长 prefix 做分段指纹,允许部分命中。
  • 缓存策略:LRU 或 TTL;保留热点 prefix(如常见 prompt),淘汰冷门;显存允许时可多保留一些 prefix block。
  • 业务设计:鼓励复用同一套 system/context 模板,或把超长 context 做成「可引用」的 prefix id,从设计上提高命中。

三、与 PagedAttention 的关系

PagedAttention 的 block 表天然支持「多序列指向同一 block」;prefix caching 就是在逻辑上识别「相同前缀」并复用这些 block,实现上即多序列的 block table 前缀段指向同一组物理 block。


面试要点

  • Prefix caching = 相同前缀的 KV 只算一次、多请求复用;与 PagedAttention block 共享一致。
  • 命中率:路由到同实例、prefix 规范化、LRU/TTL、业务复用模板或 prefix id。
  • 多实例时用路由与指纹提高跨请求命中。

记忆要点

  1. 共享前缀 = 共享 KV block;只算一次前缀,后续复用。
  2. 命中率 = 路由 + 规范化 + 缓存策略 + 业务复用。
  3. Block 表前缀段指向同一物理 block 即实现 prefix cache。

返回模块 | 返回总览

09-推理引擎/104-TensorRT-LLM的in-flight-batching原理.md

第 104 题:TensorRT-LLM的in-flight batching原理?

题目

TensorRT-LLM的in-flight batching原理?


完整讲解

一、In-Flight Batching 的含义

In-flight batching:与 continuous batching 同义——当前在执行的请求 组成一个「在飞」的 batch,每轮 decode 只对这些请求做一次前向;某请求生成完就离开 batch,新请求可加入。Batch 成员随时间变化,不等到「整批完成」再换批,从而提高 GPU 利用率、降低尾延迟。

二、TensorRT-LLM 的实现要点

  • 调度器:每轮根据 max_num_seqsmax_tokens、显存与 block 池,决定本轮参与 decode 的请求集合;已 EOS 的请求释放 KV、退出,新请求分配 block、加入。
  • 与 KV cache 管理结合:TensorRT-LLM 也有类似 PagedAttention 的 block 或 chunk 管理,in-flight 的请求按需占 block,结束即还回;保证显存与调度一致。
  • 性能:通过「即出即入」避免 static batch 的等待,吞吐与 P99 延迟通常优于固定 batch;与 vLLM 的 continuous batching 思想一致,实现上可能用不同 kernel 与调度策略。

三、与 Static 的对比

Static:batch 固定到整批完成;in-flight/continuous:batch 每轮更新,完成即出、可进新请求。TensorRT-LLM 的 in-flight batching 是其在 LLM 服务上对标 vLLM 的核心能力之一。


面试要点

  • In-flight batching = 每轮只算「当前未完成」的请求,完成即出、新请求即入;即 continuous batching。
  • TensorRT-LLM 通过调度器 + KV/block 管理实现;与 PagedAttention 类思路一致。
  • 相对 static:利用率高、尾延迟低;与 vLLM 思想一致、实现各异。

记忆要点

  1. In-flight = continuous batching,batch 成员动态变化。
  2. 调度器每轮选 in-flight 请求;结束即释放、新请求即加入。
  3. 与 KV/block 管理结合,提高利用率与延迟。

返回模块 | 返回总览

09-推理引擎/105-FasterTransformer的decoder优化技术.md

第 105 题:FasterTransformer的decoder优化技术?memory layout优化?

题目

FasterTransformer的decoder优化技术?memory layout优化?


完整讲解

一、FasterTransformer Decoder 的优化方向

FasterTransformer(NVIDIA)对 Transformer decoder(如 GPT、T5 decoder)做 kernel 融合、内存布局、批处理 等优化,目标低延迟与高吞吐。Decoder 特点:自回归、每步只生成 1 token、强依赖 KV cache 与 attention。

二、Decoder 优化技术

  • Kernel 融合:把 QKV 投影 + attention + output 投影 融合成少量 kernel,减少 launch 与显存读写;类似 fused attention。
  • KV cache 布局:KV 按 batch×head×seq×dimbatch×seq×head×dim 等布局;选择 缓存友好、与 attention kernel 一致 的 layout,减少转置与访存。有时按 block 或 chunk 管理,便于变长与批处理。
  • Batch 与变长:支持 paddingpacking;或类似 in-flight batching,不同长度用 mask 或变长 kernel 处理,减少无效计算。
  • FP16/INT8:权重量化与低精度 matmul,降低带宽与算力;配合 calibration 或量化感知推理。

三、Memory Layout

Memory layout 优化:使 连续访问计算顺序 一致(如 batch 维连续、或 KV 按 step 连续写),减少 bank conflict 与 cache miss;或把 KV 与权重按「分块」排布,配合 tiled attention。文档与源码中的「memory layout」多指 KV cache 与中间 buffer 的排布选择,以适配其 fused kernel。


面试要点

  • FasterTransformer decoder:fused QKV+attention+O、KV cache 布局、batch/变长、FP16/INT8。
  • Memory layout = KV 与 buffer 排布,追求缓存友好、与 kernel 一致;减少转置与访存。
  • 与 TensorRT-LLM、vLLM 等思路类似,实现与生态不同。

记忆要点

  1. 融合 kernel + KV layout + 批处理/变长 + 低精度。
  2. Layout 优化 = 访存顺序与计算一致、减少冲突与 miss。
  3. 针对 decoder 自回归、KV cache 密集的特点优化。

返回模块 | 返回总览

09-推理引擎/106-Hugging-Face的text-generation-inference.md

第 106 题:Hugging Face的text-generation-inference(TGI)架构?

题目

Hugging Face的text-generation-inference(TGI)架构?


完整讲解

一、TGI 的定位

Text Generation Inference(TGI) 是 Hugging Face 开源的 LLM 推理服务,面向生产部署:支持 continuous batching、Tensor Parallelism、FlashAttention、量化(bitsandbytes)、流式输出等,与 HuggingFace 模型生态无缝对接(从 Hub 拉模型、用 Transformers 加载)。

二、架构要点

  • 服务层:基于 Rust 的 HTTP/gRPC 服务,请求队列与调度;支持流式 SSE 与 non-streaming。
  • 推理引擎:底层用 CUDA/custom kernel 或与 FlashAttention、FasterTransformer 等集成;continuous batching 类似 vLLM,请求动态进出 batch;TP 支持多卡张量并行。
  • 模型加载:从 Hub 或本地加载 SafeTensors/PyTorch;支持 int8/int4 量化(bitsandbytes)、FlashAttention-2;可选 speculative decodingprefix caching(部分版本)。
  • 部署:Docker 镜像、可配 max_batch_size、max_input_length、TP 度等;常与 Kubernetes/负载均衡配合做水平扩展。

三、与 vLLM / TensorRT-LLM 的对比

TGI 与 HuggingFace 生态绑定紧、易用;vLLM 的 PagedAttention 与吞吐在部分 benchmark 更优;TensorRT-LLM 在 NVIDIA 栈上延迟与吞吐都强。选型看生态(HF vs 通用)、性能与部署环境(Docker/K8s、多框架)。


面试要点

  • TGI = HuggingFace 的 LLM 推理服务;Rust 服务层 + continuous batching + TP + FlashAttention/量化。
  • 从 Hub/本地加载模型;支持流式、量化、prefix cache(部分);Docker 部署。
  • 与 vLLM、TensorRT-LLM 对比:生态(HF)、性能与部署需求选型。

记忆要点

  1. TGI = HF 官方推理服务;Rust + continuous batching + TP。
  2. 支持 FlashAttention、量化、流式;Docker/K8s 部署。
  3. 选型看 HF 生态 vs 极致性能(vLLM/TRT-LLM)。

返回模块 | 返回总览

09-推理引擎/107-llama.cpp的量化策略.md

第 107 题:llama.cpp的量化策略?Q4_0Q5_K_M的区别?

题目

llama.cpp的量化策略?Q4_0Q5_K_M的区别?


完整讲解

一、llama.cpp 的量化体系

llama.cpp 支持多种 权重量化 格式,用于在 CPU/低显存 GPU 上跑大模型。命名规则通常为 Q<位数>_<子类型>:位数表示权重的 bit 数,子类型表示分组、对称/非对称、scale 等。

二、Q4_0 与 Q5_K_M 等

  • Q4_0:4 bit 量化,单组 scale(每块共用一个 scale),实现简单、速度较快,精度一般;适合追求速度与显存、对精度要求不极高的场景。
  • Q5_K_M:「5 bit」+ K(通常指 block 内更细分组)+ M(medium,中等精度/速度折中)。Q5 比 Q4 多 1 bit,K 表示更细的 scale 或分组,M 表示在「快/准」谱系里取中间档;精度优于 Q4_0,速度略慢、显存略大。
  • 其他常见:Q4_K_M、Q4_K_S、Q6_K、Q8_0 等;数字越大一般精度越高、体积与算力越大;_S/M/L 表示 speed/medium/quality 档位。文档与代码中有完整列表与推荐(如 7B 常用 Q4_K_M、Q5_K_M)。

三、选择建议

  • 极致省显存/速度:Q4_0、Q4_K_S。
  • 平衡:Q4_K_M、Q5_K_M。
  • 更高精度:Q6_K、Q8_0 或更高。实际按模型大小、设备与可接受精度选;llama.cpp 支持运行时指定 -q 或加载对应 gguf 文件。

面试要点

  • llama.cpp 量化格式:Q_<子类型>;Q4_0 = 4bit 单 scale、快、精度一般;Q5_K_M = 5bit 细分组、中档精度与速度。
  • K = 更细分组/scale;S/M/L = 速度/平衡/质量档。
  • 按显存与精度需求选 Q4_0~Q8_0 及 K/S/M/L 变体。

记忆要点

  1. Q4_0 = 4bit 简单快;Q5_K_M = 5bit 中等精度与速度。
  2. 数字大 = 更准更重;K/S/M/L 为细档位。
  3. 省显存用 Q4 系;平衡用 Q5_K_M。

返回模块 | 返回总览

09-推理引擎/108-移动端推理框架选择.md

第 108 题:移动端推理框架选择?MNNTNNPaddle Lite对比?

题目

移动端推理框架选择?MNNTNNPaddle Lite对比?


完整讲解

一、移动端推理的特点

移动端 算力与功耗 受限,常用 CPU + NPU/DSP/GPU;模型需 量化、剪枝、小模型;框架要 轻量、低依赖、多后端(ARM Neon、OpenCL、Vulkan、厂商 NPU 等)。

二、MNN、TNN、Paddle Lite 概览

  • MNN(阿里):轻量、跨平台(iOS/Android/嵌入式),支持 TensorFlow/Caffe/ONNX;算子全、优化多(Neon、OpenCL、Vulkan、Metal);文档与社区活跃,适合多端统一部署。
  • TNN(腾讯):高性能、多后端(CPU、OpenCL、Metal、NPU 等);支持 ONNX、TFLite、Caffe;算子融合与量化 做得好,适合对延迟与功耗要求高的 App。
  • Paddle Lite(百度):来自 PaddlePaddle 的端侧推理;支持 Paddle、ONNX、Caffe;硬件适配广(ARM、NPU、FPGA),与 Paddle 生态集成紧;若模型来自 Paddle 可选。

三、对比与选型

  • 生态:Paddle 模型选 Paddle Lite;通用 ONNX/TF 选 MNN 或 TNN。
  • 性能:三者均在 ARM/GPU 上有优化;具体设备上需 benchmark;TNN 在部分机型上延迟更优。
  • 易用与维护:MNN 文档与开源活跃;TNN 性能导向;Paddle Lite 与 Paddle 绑定。选型看模型来源、目标设备与团队技术栈。

面试要点

  • MNN:轻量跨平台、算子全、多后端;TNN:高性能、多后端、融合与量化好;Paddle Lite:Paddle 生态、端侧、硬件适配广。
  • 移动端需量化与多后端;按模型来源(ONNX/Paddle)与目标设备选型。
  • 具体延迟与功耗需真机 benchmark。

记忆要点

  1. MNN = 轻量跨平台;TNN = 高性能多后端;Paddle Lite = Paddle 端侧。
  2. 选型看模型格式与生态;真机测延迟与功耗。
  3. 移动端必备:量化、多后端、算子融合。

返回模块 | 返回总览

09-推理引擎/109-推理引擎的warmup为什么重要.md

第 109 题:推理引擎的warmup为什么重要?如何设计warmup策略?

题目

推理引擎的warmup为什么重要?如何设计warmup策略?


完整讲解

一、Warmup 为何重要

  • 首次推理 常包含:CUDA 初始化、kernel JIT、显存分配、图优化/编译(如 TensorRT、torch.compile)等,第一次 会明显偏慢;若用这次耗时做 SLA 或容量规划会高估延迟、低估容量
  • Warmup:在正式接流量前,用 若干次假请求(或小 batch)把上述开销「跑完」,使 cache、显存、编译状态 稳定,后续请求的延迟才代表真实水平;同时可 预分配显存、触发 lazy 初始化,避免首包慢。

二、如何设计 Warmup 策略

  • 次数与 shape:做 多轮 warmup(如 10~100 次),覆盖 典型 input shape(如常见 batch、seq_len);若用 dynamic shape,应对 min/opt/max 或几种典型 shape 各跑若干次,让 TensorRT/引擎针对这些 shape 完成优化与缓存。
  • 内容:可用 空或随机输入,只要走通完整前向;有时需 真实 shape + 占位 token,避免某些引擎对异常输入做特殊路径。
  • 时机:进程启动后、接流量前 必须完成;健康检查应在 warmup 之后,避免把「未 warmup」的实例标为 ready。若模型/配置变更,需重新 warmup。
  • 监控:记录 warmup 前后几次的延迟,确认稳定后再开放流量;或设 warmup 完成 的 readiness 条件(如 P99 低于某阈值)。

三、与编译/缓存的配合

TensorRT、torch.compile、ONNX 等 首次 shape 可能触发 build/compile;warmup 应覆盖这些 shape,使正式请求命中缓存。多模型/多实例时,每个模型与实例都需独立 warmup。


面试要点

  • Warmup 消除首次推理的初始化/JIT/编译/显存分配等开销,使延迟稳定、容量评估准确。
  • 策略:多轮、覆盖典型 shape(含 dynamic 的 min/opt/max);进程启动后、接流量前完成;健康检查在 warmup 后。
  • 与 TensorRT/compile 缓存配合,覆盖会触发编译的 shape。

记忆要点

  1. 首次推理含初始化与编译,必须 warmup 再接流量。
  2. 多轮 + 典型 shape;dynamic 要覆盖多种 shape。
  3. 健康检查在 warmup 之后;模型/配置变更需重 warmup。

返回模块 | 返回总览

09-推理引擎/110-多stream推理的实现.md

第 110 题:多stream推理的实现?CUDA stream的同步机制?

题目

多stream推理的实现?CUDA stream的同步机制?


完整讲解

一、多 Stream 推理的目的

多 stream:用多条 CUDA stream 并行执行多路推理(如多 batch、多请求),使 kernel 与拷贝 在时间上重叠,提高 GPU 利用率与吞吐。单 stream 时推理串行;多 stream 时不同 stream 上的 kernel 可被调度器交错执行,隐藏延迟、填满 GPU

二、实现要点

  • Stream 分配:为每个「逻辑并发单元」(如每路 batch、每 worker)分配独立 stream;或维护 stream 池,请求到来时取空闲 stream、执行完归还。
  • 依赖与同步:同一 stream 内顺序执行;跨 streamcudaEventRecord + cudaStreamWaitEvent 表达「A 在 stream1 完成后,stream2 再继续」;避免多 stream 同时写同一显存(需加锁或分 buffer)。
  • 与推理引擎结合:TensorRT/ONNX Runtime 等支持 enqueue 时传入 stream;多请求分别 enqueue 到不同 stream,由 CUDA 调度器并行;需保证每个请求的输入/输出 buffer 独立,避免数据竞争。

三、同步机制小结

  • cudaStreamSynchronize(stream):当前 host 等该 stream 全部完成;会 stall,少用。
  • cudaEventRecord(event, stream):在该 stream 上打点;cudaStreamWaitEvent(other_stream, event):另一 stream 等到该 event 再执行。用 event 做 流间依赖 即可实现「A 算完再算 B」或「拷贝完再算」,而不必全局 sync。
  • 多 stream 推理:每路请求绑定 stream,用 event 保证「输入就绪→推理→输出就绪」的依赖;host 侧可用 callback 或轮询 event 得知完成。

面试要点

  • 多 stream = 多路推理并行,提高 GPU 利用率;每路独立 stream,buffer 独立。
  • 同步:同 stream 内顺序;跨 stream 用 event(Record + WaitEvent),避免全局 sync。
  • 推理引擎 enqueue 时传 stream;用 event 表达输入/输出依赖。

记忆要点

  1. 多 stream 并行填满 GPU;每路一线程/stream,buffer 独立。
  2. 跨 stream 依赖用 Event(Record + WaitEvent)。
  3. 少用 StreamSynchronize,多用 event 精细同步。

返回模块 | 返回总览

09-推理引擎/111-推理batching的padding和packing策略.md

第 111 题:推理batching的paddingpacking策略?FlashAttention的变长支持?

题目

推理batching的paddingpacking策略?FlashAttention的变长支持?


完整讲解

一、Padding 策略

Padding:batch 内序列长短不一时,把短序列 pad 到同一长度(如 max_len),再一起做矩阵运算。优点:实现简单、与固定-shape kernel 兼容好。缺点算力浪费(对 pad 位置做无效计算);batch 内长度方差大时浪费大。可通过 attention mask 屏蔽 pad 位置,不参与 softmax 与输出。

二、Packing 策略

Packing(如 FlashAttention 的 packing):把多个短序列 拼成一条长序列,用 segment 或 position 偏移 区分不同序列;attention 时只在同一 segment 内做,避免跨序列。优点:无 pad 浪费、有效 token 数高。缺点:实现复杂、需变长 kernel 或自定义 attention;部分引擎对 packing 支持有限。适合 长短混合、追求吞吐 的场景。

三、FlashAttention 的变长支持

FlashAttention 通过 cu_seqlens(每个序列的起始位置)或 segment 划分 支持 变长:一次 forward 中不同 segment 对应不同序列,attention 只在 segment 内计算。这样可 不 padding轻量 padding,结合 packing 提高有效算力。vLLM、FasterTransformer 等在变长 batch 中会结合 mask 或 packing + FlashAttention 减少浪费。


面试要点

  • Padding:pad 到同长、实现简单、有算力浪费;mask 屏蔽 pad。
  • Packing:多序列拼成一条、按 segment 做 attention,无 pad 浪费、实现复杂。
  • FlashAttention 用 cu_seqlens/segment 支持变长;与 packing 结合可提高有效算力。

记忆要点

  1. Padding = 简单有浪费;Packing = 无浪费、实现难。
  2. FlashAttention 变长 = segment/cu_seqlens,只段内 attention。
  3. 长短混合、高吞吐场景倾向 packing + FlashAttention。

返回模块 | 返回总览

09-推理引擎/112-如何评估推理引擎的延迟分布.md

第 112 题:如何评估推理引擎的延迟分布?P50、P90、P99的优化重点?

题目

如何评估推理引擎的延迟分布?P50、P90、P99的优化重点?


完整讲解

一、延迟分布与 P50/P90/P99

P50(中位数):一半请求低于该值;P90:90% 请求低于该值;P99:99% 低于该值。P99 反映 长尾延迟,常用于 SLA(如「P99 < 500ms」)。评估时需在稳定负载下采集足够样本(如数万次请求),按延迟排序取百分位;区分 首 token 延迟(TTFT)每 token 延迟(流式场景)。

二、优化重点

  • P50:代表「典型」请求;优化 主路径:kernel 效率、batch 大小、无多余拷贝、warmup 充分。P50 好说明引擎与调度正常。
  • P90/P99:代表 长尾;常见原因:排队(高负载时等待)、冷启动/编译(未 warmup 或新 shape)、显存不足/碎片(偶发 OOM 或重分配)、GC/调度(CPU 侧停顿)、网络/跨进程。优化:限流/排队策略预编译与 warmup显存预留与碎片控制隔离 noisy neighbor(多模型/多租户时)。
  • 评估方式:打流测 P50/P90/P99,并看 分布直方图时间线(是否周期性 spike);结合 trace 定位 P99 对应的请求特征(大 batch、长 seq、新 shape 等)。

三、指标与 SLA

  • 业务常约定 P99 或 P95 作为 SLA;评估引擎时同时报 P50/P90/P99 与 throughput,便于权衡「平均」与「长尾」。优化顺序:先稳 P99(消除冷启动、排队、OOM),再压 P50(主路径性能)。

面试要点

  • P50 = 中位数,P90/P99 = 长尾;评估需足够样本,区分 TTFT 与 per-token。
  • P50 优化主路径;P99 优化排队、冷启动、显存、GC、noisy neighbor。
  • 评估时看分布与时间线;SLA 常用 P99/P95。

记忆要点

  1. P50 典型、P99 长尾;SLA 常用 P99。
  2. P99 差:排队、冷启动、显存、GC、新 shape;先稳 P99 再压 P50。
  3. 打流 + 直方图 + trace 定位长尾请求特征。

返回模块 | 返回总览

09-推理引擎/113-推理服务的auto-scaling策略.md

第 113 题:推理服务的auto-scaling策略?基于GPU利用率还是请求队列?

题目

推理服务的auto-scaling策略?基于GPU利用率还是请求队列?


完整讲解

一、基于 GPU 利用率的扩缩容

思路:监控实例的 GPU 利用率(如 nvidia-smi、DCGM);当 均值或 P95 高于阈值(如 80%)时 扩容,低于某阈值(如 30%)时 缩容优点:直接反映「算力是否吃满」。缺点:利用率高可能来自 少量大请求,此时扩容未必改善延迟;利用率低可能是 请求少batch 未填满,缩容可能增加排队。适用:吞吐优先、负载较平稳时;需设上下界与冷却时间,避免抖动。

二、基于请求队列的扩缩容

思路:监控 排队长度等待时间;队列超过某长度或等待时间超过 SLA 时 扩容,队列空且持续一段时间后 缩容优点:与 延迟/SLA 直接相关,更贴近「用户等多久」。缺点:需暴露队列指标、与负载均衡配合;短时尖峰可能触发过度扩容。适用:延迟敏感、有明确 SLA 时;常与 最大排队长度、超时 配合。

三、策略组合与建议

  • 混合:队列为主(保证延迟),利用率为辅(避免空跑过多实例);例如「队列深度 > N 或 P99 超 SLA 则扩容」「利用率持续低且队列空则缩容」。
  • 预热与冷却:扩容后新实例需 warmup 再接流量;缩容前设 cooldown,避免刚缩又扩。HPA/KEDA 等可根据 queue length、GPU 利用率、自定义 metric 做扩缩容;推理服务常用 队列深度 + 延迟 作为主指标,GPU 利用率 作参考与成本控制。

面试要点

  • GPU 利用率:反映算力是否吃满;高则扩容、低则缩容;易受少数大请求影响,需防抖动。
  • 请求队列:反映等待与 SLA;队列长或超时则扩容,更贴近延迟目标。
  • 建议:队列/延迟为主、利用率为辅;配合 warmup、cooldown 与 HPA/KEDA。

记忆要点

  1. 利用率 = 算力维度;队列/延迟 = 用户体验维度。
  2. 延迟敏感以队列为主;吞吐/成本以利用率为参考。
  3. 扩缩容需 warmup 与 cooldown,避免抖动。

返回模块 | 返回总览

09-推理引擎/114-多模型混部的资源隔离.md

第 114 题:多模型混部的资源隔离?MPS(Multi-Process Service)?

题目

多模型混部的资源隔离?MPS(Multi-Process Service)?


完整讲解

一、多模型混部的挑战

多模型混部:同一 GPU(或同一节点)上同时跑 多个模型/多路推理,共享硬件。挑战:资源争抢(显存、算力、带宽)、互相干扰(某一路卡顿拖慢其他)、隔离与公平性(保证各模型有可预测的延迟与吞吐)。

二、资源隔离手段

  • 显存:各进程/模型 预分配显存 或设 上限(如 CUDA 的 per-process limit、或容器 limit),避免单模型吃满导致 OOM 影响其他。
  • 算力MPS(Multi-Process Service)允许 多进程共享同一 GPU,由驱动做时间片调度;可配合 CUDA MPSMIG(多实例 GPU)做更细粒度隔离。MPS 下多进程共享 context,可减少显存重复占用,但算力仍共享,需限流或优先级。
  • 进程/容器:每模型 独立进程独立容器,用 cgroup 限制 CPU/内存;GPU 侧用 MPS 或 MIG 做共享与隔离。Kubernetes 上可用 GPU 分片、资源 request/limit 做配额。
  • 调度与限流:每模型 独立队列并发上限,避免某模型突发占满 GPU;或按 优先级/权重 分配算力。

三、MPS 的 role

MPS:NVIDIA 的 Multi-Process Service,让 多进程 共享同一 GPU context,减少每个进程单独占用的显存与启动开销;算力由驱动在进程间调度。适合 多小模型/多路推理 混部;需注意 公平性与长尾(某进程大 kernel 会阻塞其他),可配合 流优先级限流 使用。


面试要点

  • 混部 = 多模型共享 GPU;需显存与算力隔离、队列与限流。
  • MPS = 多进程共享 GPU context,省显存与启动;算力共享,需限流/优先级。
  • 手段:显存上限、MPS/MIG、进程/容器隔离、每模型队列与并发限制。

记忆要点

  1. 混部要隔离显存与算力;MPS 共享 context、算力由驱动调度。
  2. 每模型独立队列与并发上限,防单模型打满。
  3. MIG 可做更细 GPU 分片;MPS 适合多进程共享一卡。

返回模块 | 返回总览

09-推理引擎/115-推理引擎的debug模式.md

第 115 题:推理引擎的debug模式?如何定位精度下降问题?

题目

推理引擎的debug模式?如何定位精度下降问题?


完整讲解

一、推理引擎的 Debug 模式

  • 精度/数值:以 FP32 或高精度 跑同一输入,与「优化/量化版本」逐层或逐 tensor 对比(diff),定位从哪一层开始误差变大;TensorRT/ONNX 等可关掉部分优化(如 fp16、int8)做 baseline。
  • Dump 与比对:在关键层 dump 输入输出(FP32 与优化版),用脚本算 max/mean abs diff、相对误差;或导出 ONNX 用 ONNX Runtime 的 reference 实现对比。
  • 逐层/逐 op:在引擎中 禁用融合单 op 执行,缩小范围;或用 torch/ONNX 的逐层执行 与引擎结果对比,找到第一个不一致的 op。
  • 环境:设置 CUDA_LAUNCH_BLOCKING=1 保证同步执行,便于复现与断点;或用 cuda-gdb / Nsight 做 GPU 侧调试。

二、精度下降的常见原因

  • FP16/INT8:舍入与溢出;检查 scale/calibrationclip 范围;对比 FP32 baseline。
  • 图优化/融合:融合或改写导致等价性破坏(如 reassociation);逐层关优化或对比中间结果。
  • Plugin 或自定义 op:实现错误或与框架约定不一致;单独测 plugin、对比参考实现。
  • 量化:per-tensor vs per-channel、symmetric vs asymmetric;校准数据与真实分布不一致会掉点;用代表性数据重新 calibration 或提高精度档位。

三、定位流程

  1. 确定 golden:FP32 或 PyTorch/ONNX 高精度结果作为标准。
  2. 同输入 跑优化引擎,逐层或按 block dump 对比,找到 首次显著偏差 的层/op。
  3. 对该层 关优化、提精度、或替换为参考实现 再测,确认是否该点导致。
  4. 若为量化,检查 scale、校准集、量化配置;若为融合,检查该融合的数学等价性。
  5. 修复后做 回归测试(多输入、多 shape),避免再次退化。

面试要点

  • Debug 模式:高精度 baseline、dump 对比、逐层/逐 op 缩小范围、必要时 CUDA_LAUNCH_BLOCKING。
  • 精度下降常见:FP16/INT8、图融合、plugin、量化配置与校准。
  • 定位流程:golden → 同输入对比 → 找首次偏差层 → 单点修复 → 回归。

记忆要点

  1. 用 FP32/高精度做 golden;dump 对比找首次偏差层。
  2. 关优化、提精度、单 op 测试缩小范围。
  3. 量化问题查 scale 与 calibration;融合问题查等价性。

返回模块 | 返回总览

10-量化与压缩/README.md

10-量化与压缩(第 116–130 题)

题号 主题 文章
116 INT8量化的symmetricasymmetric区别?… 116-INT8量化的symmetric和asymmetric区别.md
117 SmoothQuant的原理?为什么能同时保持权重和激活的量化精度? 117-SmoothQuant的原理.md
118 AWQ(Activation-aware Weight Quanti… 118-AWQ(Activation-aware-Weight-Quantizati.md
119 GPTQone-shot量化流程?OBQ(Optimal … 119-GPTQ的one-shot量化流程.md
120 GGUF格式的量化级别?Q4_K_M适合什么场景? 120-GGUF格式的量化级别.md
121 FP8量化的硬件支持?H100的`Transformer Eng… 121-FP8量化的硬件支持.md
122 量化校准(calibration)的数据集选择?多少样本足够? 122-量化校准(calibration)的数据集选择.md
123 量化后的精度损失如何快速定位?layer-wise的sensitivit… 123-量化后的精度损失如何快速定位.md
124 k-means量化和非均匀量化的应用场景? 124-k-means量化和非均匀量化的应用场景.md
125 二值化网络(BNN)在推理优化中的实际价值? 125-二值化网络(BNN)在推理优化中的实际价值.md
126 知识蒸馏在推理优化中的作用?MiniLLMDistilBERT 126-知识蒸馏在推理优化中的作用.md
127 结构化剪枝和非结构化剪枝的硬件友好性? 127-结构化剪枝和非结构化剪枝的硬件友好性.md
128 动态量化(Dynamic Quantization)和静态量化的runt… 128-动态量化(Dynamic-Quantization)和静态量化的runtim.md
129 量化算子的融合?quantize-linear + matmul 129-量化算子的融合.md
130 混合精度推理的策略?哪些层必须保持FP16 130-混合精度推理的策略.md

返回总览

10-量化与压缩/116-INT8量化的symmetric和asymmetric区别.md

第 116 题:INT8量化的symmetricasymmetric区别?per-tensor vs `per-cha…

题目

INT8量化的symmetricasymmetric区别?per-tensor vs per-channel


完整讲解

一、Symmetric vs Asymmetric

Symmetric:零点固定在 0,量化公式为 scale * (x/scale).round(),正负范围对称(如 INT8 为 -128~127)。实现简单、推理时无需存 zero_point,适合权重和激活分布较对称的情形(如 ReLU 后)。

Asymmetric:引入 zero_point,公式为 round(x/scale) + zero_point,可把真实范围映射到 [0,255],更好地拟合非对称分布(如激活多非负),精度通常更好,但推理需多一次减 zero_point 的运算与存储。

二、Per-tensor vs Per-channel

Per-tensor:整个 tensor 共用一个 scale(和可选 zero_point),计算与存储开销最小,但若通道间分布差异大(如 Conv 各 output channel),易产生较大误差。

Per-channel(或 per-axis):对某一维(如 Conv 的 output channel)各用一套 scale/zero_point,表达能力更强、精度更高,尤其对权重;代价是多组量化参数与逐 channel 的缩放逻辑,推理实现稍复杂。

三、工程取舍

权重常用 per-channel symmetric(兼顾精度与实现);激活可选 per-tensor 或 per-channel、asymmetric 更稳。PTQ 时根据校准数据选 scheme;QAT 可端到端学 scale/zero_point。


面试要点

  • Symmetric:零点为 0,实现简单、无 zero_point 存储,适合对称分布;Asymmetric:有 zero_point,非对称分布精度更好,推理多一次减法。
  • Per-tensor:全 tensor 一套 scale,省算力与存储;per-channel:按轴(如 channel)多套参数,精度高、实现稍复杂。
  • 权重常用 per-channel symmetric;激活可选 per-tensor/per-channel + asymmetric;PTQ 按校准选,QAT 可学参数。

记忆要点

  1. Symmetric = 零点 0,无 zero_point;Asymmetric = 有 zero_point,非对称分布更准。
  2. Per-tensor = 一套 scale;per-channel = 按轴多套 scale,精度高、开销略大。
  3. 工程上:权重 per-channel symmetric,激活可 asymmetric;PTQ/QAT 决定具体 scheme。

返回模块 | 返回总览

10-量化与压缩/117-SmoothQuant的原理.md

第 117 题:SmoothQuant的原理?为什么能同时保持权重和激活的量化精度?

题目

SmoothQuant的原理?为什么能同时保持权重和激活的量化精度?


完整讲解

一、问题背景

权重通常分布平滑、易量化;激活(尤其大模型里)动态范围大、 outlier 多,直接 INT8 量化激活会严重掉点。SmoothQuant 通过「迁移」一部分数值范围到权重,让激活更平滑、权重略「变难」但仍在可量化范围内,从而同时保持权重与激活的量化精度。

二、核心做法

数学等价变换:把激活的 scale 乘到权重上。设 Y = XW,令 X' = X/diag(s)W' = diag(s)W,则 X'W' = XW 不变。选 s(per-channel 或 per-token)使得 X' 的幅值变小(平滑激活)、W' 的幅值变大但在可接受范围,再对 X'W' 分别量化,推理时先 dequant 再乘或直接 INT8 乘后按 scale 还原。

三、实现与效果

s 的选取常用激活的绝对值最大值或百分位数估计,有时结合一层内权重范数做平衡。实现上在量化前对线性层做一次离线或校准阶段的 scaling,推理仍是标准 linear + 量化。大模型 LLM 里 SmoothQuant 常与 per-channel 权重量化、per-token 激活量化配合,显著降低激活量化误差。


面试要点

  • 动机:激活难量化(动态范围大、outlier 多),权重好量化;SmoothQuant 用等价变换把「难度」从激活迁到权重,二者都可 INT8。
  • 做法:Y=XW 改写为 X'W',X'=X/s、W'=s*W,选 s 使 X' 平滑、W' 仍可量化;再对 X'、W' 分别量化。
  • 实现:s 按 channel 或 token 用激活幅值(如 max|X|)估计;推理保持数学等价,可与 per-channel/per-token 量化组合。

记忆要点

  1. SmoothQuant = 激活难量化 → 用线性变换把 scale 迁到权重,激活变平滑、权重略放大仍可量化。
  2. 数学:X'=X/s, W'=sW,X'W'=XW;选 s 平衡 X' 与 W' 的幅值。
  3. 工程:s 由校准数据估计;与 per-channel/per-token 量化配合,常用于 LLM。

返回模块 | 返回总览

10-量化与压缩/118-AWQ(Activation-aware-Weight-Quantizati.md

第 118 题:AWQ(Activation-aware Weight Quantization)的核心思想?

题目

AWQ(Activation-aware Weight Quantization)的核心思想?


完整讲解

一、核心思想

AWQ(Activation-aware Weight Quantization)认为:权重量化时不应一视同仁,而应根据激活的尺度对权重做保护。对激活幅值大的通道(或 group),对应权重更敏感,应少量化或用更高精度;对激活小的通道,权重可压得更狠。这样在相同比特预算下,重要通道保留更多信息,整体精度更好。

二、做法简述

通过激活统计(如 calibration 时各 channel 的 scale 或重要性)得到一个 per-channel 的保护因子,在量化前对权重做 scaling:重要 channel 的权重放大(相当于量化时用更细的步长),不重要的缩小。量化后还原,或把 scale 融进后续的 linear 计算。可选地配合「混合精度」:少量关键 channel 保持 FP16/W8,其余 INT4,在显存与精度间折中。

三、与 GPTQ/SmoothQuant 的区分

GPTQ 是逐层基于 Hessian 的权重量化;SmoothQuant 是激活-权重的等价缩放迁移。AWQ 是按激活重要性对权重量化做非均匀保护,不改变前向数学形式,而是选「量化谁、压多少」,工程上常与 per-group 量化、KV cache 量化等一起用在大模型部署。


面试要点

  • AWQ = 按激活重要性保护权重量化:激活大的 channel 权重量化更保守,激活小的可压更狠。
  • 实现:用校准得到 per-channel 重要性/scale,对权重做 scaling 再量化,或混合精度保留关键 channel。
  • 与 GPTQ(Hessian 权重量化)、SmoothQuant(激活-权重 scale 迁移)区分开;常与 per-group、W4 等用于 LLM。

记忆要点

  1. AWQ = activation-aware:看激活幅值决定权重量化力度,重要 channel 少压。
  2. 做法:校准得 per-channel 重要性 → 权重量化前 scaling 或混合精度。
  3. 与 GPTQ/SmoothQuant 互补;常用于 LLM 的 W4/W8 部署。

返回模块 | 返回总览

10-量化与压缩/119-GPTQ的one-shot量化流程.md

第 119 题:GPTQone-shot量化流程?OBQ(Optimal Brain Quantization)?

题目

GPTQone-shot量化流程?OBQ(Optimal Brain Quantization)?


完整讲解

一、GPTQ 的 one-shot 流程

GPTQ 是逐层、逐 block 的权重量化方法,one-shot 指用一层(或 block)的校准数据一次性求解量化参数,无需端到端微调。流程大致:对某一层,给定校准输入(若干真实激活或合成数据),在该层输出重建误差(如 MSE)约束下,按 Hessian 逆对权重量化做二阶优化——即 OBQ 思想在 Transformer 上的扩展,按权重对损失的影响顺序逐个或逐组量化,并即时更新未量化权重以补偿误差,使整层量化后输出与 FP 尽量一致。

二、OBQ(Optimal Brain Quantization)

OBQ 是更早的「最优脑量化」思路:把权重量化视为在约束下的最优删除/舍入问题。用 Hessian 刻画权重对损失的影响,按影响从小到大的顺序量化权重,每量化一个就用闭式解更新其余权重以最小化当前误差,相当于贪心 + 局部最优。GPTQ 把 OBQ 从单层全连接推广到分 block、支持 per-channel/group,并针对 GPU 做了批量化与实现优化,成为 LLM 权重量化的常用基线。

三、工程要点

GPTQ 需校准数据(几百条序列即可)、逐层跑一遍;量化后可直接推理或再配激活量化(如 SmoothQuant)。与 AWQ(激活感知)、QAT(训练中量化)相比,GPTQ 无训练、速度快,精度在 W4 上表现好,是离线 PTQ 的代表方法之一。


面试要点

  • GPTQ one-shot:逐层用校准数据 + Hessian 逆做权重量化,一次性求量化参数,无需微调;按对输出的影响顺序量化并更新未量化权重。
  • OBQ:用 Hessian 决定量化顺序,贪心+闭式更新,最小化重建误差;GPTQ 是 OBQ 在 Transformer 上的 block 化、工程化。
  • 工程:校准几百条即可、逐层跑、可与激活量化组合;无训练、适合 W4 等离线 PTQ。

记忆要点

  1. GPTQ = one-shot 权重量化,逐层校准 + Hessian 逆,按影响顺序量化并补偿。
  2. OBQ = Hessian 顺序 + 闭式更新;GPTQ 是 OBQ 的 block/Transformer 版。
  3. 无训练、校准即用;常与 SmoothQuant 等配合,W4 常用。

返回模块 | 返回总览

10-量化与压缩/120-GGUF格式的量化级别.md

第 120 题:GGUF格式的量化级别?Q4_K_M适合什么场景?

题目

GGUF格式的量化级别?Q4_K_M适合什么场景?


完整讲解

一、GGUF 与量化级别

GGUF 是 llama.cpp 等使用的模型格式,支持多种量化类型(如 Q4_0、Q4_K_M、Q5_K_S、Q8_0 等)。数字表示权重的有效比特(如 4/5/8),后缀表示「粒度」或版本:_0 多为旧版 per-block 简单量化,_K_S / _K_M / _K_L 等为 K-quant 系列,对 block 内权重做更细的分组或非均匀量化,在相同比特下精度更好。

二、Q4_K_M 含义与场景

Q4_K_M 一般指 4-bit 的 K-quant 中等粒度(M = medium):比 Q4_0 更精细的分块或 scale 设计,推理时略多一点计算,但同尺寸下精度更高。适合显存紧张、又要较好效果的本地或边缘部署:例如 7B 模型用 Q4_K_M 可在 4~6GB 显存跑推理,效果明显好于 Q4_0,略逊于 Q5 或 Q8;若追求极致速度或兼容性可选 Q4_0,追求更好精度可上 Q5_K_M 或 Q8_0。

三、选型建议

按「显存 vs 精度 vs 速度」权衡:Q4_0 最快、兼容广;Q4_K_M 平衡;Q5/Q8 更准、更大。服务端可考虑 Q8 或 FP16;端侧、单卡小显存首选 Q4_K_M 或 Q5_K_S。


面试要点

  • GGUF:llama.cpp 等用的格式,支持 Q4_0、Q4_K_M、Q5_K_、Q8_0 等;K 为 K-quant 更细粒度,同比特下更准。
  • Q4_K_M:4-bit 中等粒度 K-quant,比 Q4_0 精度高、略多算力,适合显存紧张又要较好效果的本地/边缘部署。
  • 选型:Q4_0 最快兼容好;Q4_K_M 平衡;Q5/Q8 更准更大;端侧常用 Q4_K_M。

记忆要点

  1. GGUF = 格式 + 多级量化;Qx_K_S/M/L = K-quant 细粒度,同比特更准。
  2. Q4_K_M = 4bit 中等粒度,显存与精度平衡,适合本地/边缘 7B 等。
  3. 选型:显存紧 → Q4_K_M;要速度 → Q4_0;要精度 → Q5/Q8。

返回模块 | 返回总览

10-量化与压缩/121-FP8量化的硬件支持.md

第 121 题:FP8量化的硬件支持?H100Transformer Engine

题目

FP8量化的硬件支持?H100Transformer Engine


完整讲解

一、FP8 与硬件支持

FP8(8-bit 浮点)在保持一定动态范围与精度的同时,比 FP16 省一半显存与带宽,适合大模型训练与推理。硬件支持:NVIDIA Hopper(H100)及后续架构在 Tensor Core 中原生支持 FP8(E4M3、E5M2 等格式),可做 FP8 矩阵乘与累加,无需软件模拟,吞吐高、能效好;Ampere 及更早 GPU 无原生 FP8,需用 FP16 或 INT8 替代。

二、H100 Transformer Engine

Transformer Engine(TE) 是 NVIDIA 在 H100 上提供的库与内核,针对 Transformer 的线性、LayerNorm、注意力等提供 FP8 训练与推理支持。核心思路:在部分线性层用 FP8 计算(权重与激活用 FP8),用缩放因子与可选的反量化在关键位置与 FP16 衔接,在保证收敛的前提下显著提升吞吐、降低显存。TE 与 PyTorch/JAX 集成,用户通过换层或配置即可启用 FP8,无需手写 kernel。

三、工程要点

启用 TE 需 H100(或支持 FP8 的卡)、对应 CUDA/cuDNN;训练时通常与混合精度(FP16 master 权重 + FP8 计算)配合。推理也可用 FP8 降低带宽与计算量。面试可强调:FP8 硬件加速是 Hopper 的重要卖点,TE 是落地的软件栈。


面试要点

  • FP8:8-bit 浮点,省显存与带宽;Hopper(H100)Tensor Core 原生支持,Ampere 及以前无原生 FP8。
  • Transformer Engine:NVIDIA 在 H100 上的 FP8 库,为 Transformer 提供 FP8 线性/注意力等,与 PyTorch/JAX 集成,混合精度训练与推理。
  • 工程:需 H100 级硬件;训练用 FP8 计算 + FP16 master;推理可全 FP8 降带宽。

记忆要点

  1. FP8 硬件 = Hopper(H100)Tensor Core 原生;更早架构无。
  2. Transformer Engine = H100 上 FP8 Transformer 库,线性/注意力等 FP8 + 缩放与混合精度。
  3. 用途:训练与推理省带宽与算力;需对应 GPU 与 CUDA 栈。

返回模块 | 返回总览

10-量化与压缩/122-量化校准(calibration)的数据集选择.md

第 122 题:量化校准(calibration)的数据集选择?多少样本足够?

题目

量化校准(calibration)的数据集选择?多少样本足够?


完整讲解

一、校准的目的

量化校准(calibration)指在 PTQ 中,用一批无标签或带标签数据跑一遍前向,统计激活(及可选权重)的分布(min/max、直方图、分位数等),据此确定每层或每 channel 的 scale、zero_point 等量化参数。校准数据不需要与下游任务完全一致,但分布应接近真实推理输入,否则 scale 会偏,导致 clipping 或分辨率浪费。

二、数据集选择

常用做法:从训练集或公开语料中随机采样若干条(或句子/段落),保证覆盖不同长度与类型即可;有时用验证集子集。无训练数据时可用通用文本(如 Wikipedia 片段)。关键不是「任务标签」而是激活分布有代表性;若模型有多模态或多场景,可每类采样一些。避免只用极短或极长序列,以免分布偏颇。

三、多少样本足够

经验上 几百条(如 128~512 条)序列往往足够让 per-tensor 或 per-channel 的 min/max 或分位数稳定;更多(如 1024~2048)收益递减。若用 MSE 等更复杂校准(如选最优 clip 百分位),可适当增加。大模型 PTQ 常见 256~512 条;校准时间远小于训练,不必追求海量数据。


面试要点

  • 校准目的:用前向统计激活(及可选权重)分布,确定 scale/zero_point;数据分布应接近真实推理输入。
  • 数据选择:训练集/验证集/通用语料随机采样,覆盖长度与类型;无标签即可,重分布不重标签。
  • 数量:通常 128~512 条即可稳定;256~512 常用于 LLM;更多收益递减。

记忆要点

  1. 校准 = 前向统计激活分布 → 定 scale/zero_point;数据分布要接近推理。
  2. 数据 = 随机采样、覆盖长度与类型;可不带任务标签。
  3. 样本数:几百条常用,256~512 足够;更多收益有限。

返回模块 | 返回总览

10-量化与压缩/123-量化后的精度损失如何快速定位.md

第 123 题:量化后的精度损失如何快速定位?layer-wise的sensitivity分析?

题目

量化后的精度损失如何快速定位?layer-wise的sensitivity分析?


完整讲解

一、快速定位思路

量化后精度损失可从三方面排查:层/模块敏感度(哪几层量化后掉点最多)、激活/权重分布(是否 outlier 多、动态范围大)、校准与配置(scale、比特数、per-channel 等)。快速定位常用「逐层或逐模块量化」:先只量化某一层(或某几层),其余保持 FP,看验证指标变化;或反过来,逐层恢复 FP,看恢复哪几层后指标明显回升,从而锁定敏感层。

二、Layer-wise sensitivity 分析

Sensitivity 分析:对每一层(或每一类算子)单独做量化,在验证集上测 loss 或任务指标,得到每层的「量化敏感度」排序。敏感度高的层可保留更高精度(如 FP16、W8)或更细粒度(per-channel、更小 group);敏感度低的可压到 W4 或 per-tensor。可结合梯度或 Hessian 近似做重要性估计,但直接逐层量化测指标最直观、工程上常用。

三、工程实践

实现上可写脚本:遍历层或 block,仅对当前层量化、其余 FP,跑一遍验证并记录;最后得到 sensitivity 曲线或排序表,据此定混合精度策略(如 embedding、最后一层用 FP16,中间部分层 W8 其余 W4)。可与剪枝、结构搜索结合,形成「敏感层少量化、不敏感层狠量化」的配置。


面试要点

  • 快速定位:逐层(或逐模块)量化、其余 FP,看指标变化;或逐层恢复 FP 看哪几层恢复后明显回升。
  • Layer-wise sensitivity:每层单独量化测验证指标,排序得到敏感度;高敏感层保留高精度或 per-channel,低敏感层可 W4/per-tensor。
  • 工程:脚本遍历层做单层量化+验证,得到敏感度表,用于混合精度与比特分配。

记忆要点

  1. 定位 = 逐层量化/逐层恢复 FP,看指标变化锁定敏感层。
  2. Sensitivity = 每层单独量化测指标排序;高敏感→高精度,低敏感→低比特。
  3. 输出 = 混合精度配置表(哪层 FP16/W8/W4、per-channel 等)。

返回模块 | 返回总览

10-量化与压缩/124-k-means量化和非均匀量化的应用场景.md

第 124 题:k-means量化和非均匀量化的应用场景?

题目

k-means量化和非均匀量化的应用场景?


完整讲解

一、K-means 量化

K-means 量化:把权重量化视为聚类问题,用 K 个中心(码本)表示权重,每个权重映射到最近中心,推理时用码本索引或查表计算。K=2^b 即 b-bit 量化。优点是可适应非均匀分布(中心由数据学出),在低比特下比均匀量化更准;缺点是推理需查表或额外解码,且码本更新(如微调)成本高,硬件上不如均匀 scale/zero_point 通用,多用于压缩、剪枝后的权重量化或研究。

二、非均匀量化

非均匀量化:量化步长不相等,在值密集区步长小、稀疏区步长大,从而在总比特数有限下更贴合分布、降低量化误差。实现方式包括:对数/指数刻度、K-means 码本、学习得到的 codebook 等。适合激活或权重分布明显非均匀、且有条件做校准或学习的场景;代价是推理时需非均匀查表或分段计算,通用 GPU 上不如均匀 INT8/INT4 高效,多用于专用芯片或极致压缩。

三、应用场景

K-means/非均匀量化常用于:极低比特(如 2~3 bit)权重量化、压缩优先的存储与传输、分布极不均匀的某一层或 channel;或与剪枝结合做「稀疏+非均匀量化」。生产推理更常用均匀 per-channel INT8/INT4 + 硬件友好 kernel;非均匀作为补充手段在特定场景使用。


面试要点

  • K-means 量化:权重量化为 K 个中心,非均匀适应分布,低比特可更准;缺点查表/码本、硬件通用性差。
  • 非均匀量化:步长不等,密集区细、稀疏区粗;实现有对数刻度、码本等;适合非均匀分布,推理稍复杂。
  • 场景:极低比特、压缩优先、分布极不均匀或研究;生产常用均匀 INT8/INT4。

记忆要点

  1. K-means = 码本聚类量化,非均匀、低比特准,查表与硬件支持是瓶颈。
  2. 非均匀 = 不等步长,贴合分布;实现有对数/码本等。
  3. 应用:极低比特、压缩、特殊分布;生产多用均匀量化。

返回模块 | 返回总览

10-量化与压缩/125-二值化网络(BNN)在推理优化中的实际价值.md

第 125 题:二值化网络(BNN)在推理优化中的实际价值?

题目

二值化网络(BNN)在推理优化中的实际价值?


完整讲解

一、二值化网络(BNN)是什么

BNN 将权重与(或)激活二值化为 +1/-1(或 0/1),前向用 XNOR + popcount 等位运算替代乘加,理论上有巨大算力与带宽节省(32× 相比 FP32),且硬件可实现为纯逻辑门。但二值化带来极大精度损失,大模型与复杂任务上很难达到可用精度,训练也不稳定(梯度近似、尺度等问题)。

二、在推理优化中的实际价值

实际价值有限:在通用 GPU/CPU 上,二值化推理需要大量位运算或专用 kernel,当前主流框架与硬件对 INT8/INT4 支持更好,二值化的「理论加速」在通用硬件上往往发挥不出来;精度又明显不如 W4/W8。因此 BNN 更多出现在嵌入式、FPGA、专用 ASIC 等对功耗与面积极度敏感、且任务相对简单(如小 CNN、二分类)的场景;或作为混合二值(部分层二值)的研究方向。大模型推理优化中一般不把 BNN 作为主方案,而是 INT4/INT8 + 剪枝、蒸馏等。

三、面试可说的点

能说清「二值化理论省算力但精度与硬件支持是瓶颈」「通用推理多用 INT8/INT4,BNN 适合边缘/专用硬件与简单任务」即可;若做过 FPGA/嵌入式可举具体例子。


面试要点

  • BNN:权重/激活二值化,XNOR+popcount 替代乘加,理论省算力与带宽,但精度损失大、训练难。
  • 推理价值:通用 GPU 上 INT8/INT4 更实用;BNN 适合嵌入式/FPGA/ASIC、简单任务或混合二值研究。
  • 大模型推理主流是 W4/W8+剪枝/蒸馏,BNN 不作为主方案。

记忆要点

  1. BNN = 二值 + 位运算,理论省算力,精度与训练是瓶颈。
  2. 通用推理多用 INT8/INT4;BNN 适合边缘、专用硬件、简单任务。
  3. 大模型推理优化以 W4/W8 为主,BNN 仅特定场景。

返回模块 | 返回总览

10-量化与压缩/126-知识蒸馏在推理优化中的作用.md

第 126 题:知识蒸馏在推理优化中的作用?MiniLLMDistilBERT

题目

知识蒸馏在推理优化中的作用?MiniLLMDistilBERT


完整讲解

一、知识蒸馏在推理优化中的作用

知识蒸馏用大模型(教师)的软标签或表示指导小模型(学生)训练,学生在相同或更低算力下逼近教师表现,从而在推理时用更小、更快的模型替代大模型,直接带来延迟与显存下降。因此蒸馏是「推理优化」的一种:不改变单次前向的量化或 kernel,而是用更小模型达到可接受精度,属于模型级优化。

二、MiniLLM、DistilBERT 代表什么

DistilBERT:对 BERT 做蒸馏,学生层数/宽度更小,用教师 logits + 隐层 MSE 等损失训练,推理时参数量与计算量明显小于 BERT,适合资源受限部署。MiniLLM 等针对 LLM:用大 LLM 的生成分布(或 reward)蒸馏到小 LLM,减少幻觉、保持能力的同时缩小规模;可与量化、剪枝叠加,进一步加速推理。共同点:教师→学生、软标签/分布、小模型推理更快。

三、与量化、剪枝的配合

推理优化可组合:先蒸馏得到小模型,再对小模型做 INT8/INT4 量化或剪枝,进一步减显存与算力;或先量化大模型做「快但略逊」的基线,再用蒸馏小模型在同等延迟下追平/超越。面试可强调:蒸馏解决「模型规模」,量化/剪枝解决「单模型计算与存储」,三者互补。


面试要点

  • 蒸馏作用:用小模型(学生)逼近大模型(教师),推理时用更小更快模型,属模型级推理优化。
  • DistilBERT:BERT 蒸馏、小层数/宽度;MiniLLM:LLM 生成分布蒸馏,小模型减幻觉、保能力。
  • 可与量化、剪枝叠加:先蒸馏再量化,或量化大模型+蒸馏小模型双路线。

记忆要点

  1. 蒸馏 = 教师→学生,小模型推理更快,属推理优化中的「缩模型」。
  2. DistilBERT = BERT 蒸馏;MiniLLM = LLM 蒸馏,小模型保能力。
  3. 与量化/剪枝互补:蒸馏缩规模,量化/剪枝降单模型算力与显存。

返回模块 | 返回总览

10-量化与压缩/127-结构化剪枝和非结构化剪枝的硬件友好性.md

第 127 题:结构化剪枝和非结构化剪枝的硬件友好性?

题目

结构化剪枝和非结构化剪枝的硬件友好性?


完整讲解

一、非结构化剪枝

非结构化剪枝:按元素将权重置零,稀疏模式任意(每个位置独立)。可达到很高稀疏度且对精度友好(保留重要单权),但得到的稀疏矩阵在通用 GPU 上难以加速:常规 GEMM 和内存布局假设稠密或块稀疏,随机稀疏导致不规则访存与计算,实际加速比远低于理论零占比,甚至更慢。多用于压缩存储、与稀疏 kernel(需专用库或硬件)结合,或作为结构化剪枝的预处理。

二、结构化剪枝

结构化剪枝:按剪枝,如整 channel、整 head、整块 N×M 为零。剪枝后仍为规整矩阵或更小的稠密块,硬件友好:可用标准 GEMM、减小 shape,真正减少 FLOPs 与带宽,推理加速明显。代价是自由度低,同稀疏度下精度通常不如非结构化;需在「结构约束」下做重要性估计与训练。

三、工程取舍

推理优化优先选结构化(channel/head 剪枝等),以便在现有框架与 GPU 上落地加速;非结构化适合存储压缩或配合专用稀疏硬件。也可「结构化+非结构化」:先做 channel 剪枝再对剩余权重做元素级稀疏,在支持稀疏算子的环境下进一步压缩。


面试要点

  • 非结构化:按元素稀疏,模式任意;精度潜力大但通用 GPU 难加速,多用于存储或专用稀疏 kernel。
  • 结构化:按 channel/head/块剪枝,规整、硬件友好,真正减 FLOPs 与带宽;自由度低、精度略逊。
  • 推理优化优先结构化;非结构化配合稀疏库或专用硬件。

记忆要点

  1. 非结构化 = 元素级稀疏,灵活但通用 GPU 不友好;结构化 = 块级,硬件友好、真加速。
  2. 推理落地多用结构化(channel/head);非结构化用于压缩或稀疏硬件。
  3. 可组合:先结构化再非结构化,在支持稀疏时进一步压。

返回模块 | 返回总览

10-量化与压缩/128-动态量化(Dynamic-Quantization)和静态量化的runtim.md

第 128 题:动态量化(Dynamic Quantization)和静态量化的runtime开销?

题目

动态量化(Dynamic Quantization)和静态量化的runtime开销?


完整讲解

一、动态量化(Dynamic Quantization)

动态量化:权重量化在加载时完成(或预量化好),激活的 scale/zero_point 在每次前向时根据当前输入的 min/max(或分位数)现场计算并量化。优点是不需要校准集、适应输入分布变化(如不同 domain 的请求);缺点是运行时多一次统计与量化,有额外开销,且激活量化在 batch 或 sequence 上做统计可能增加延迟,适合权重占主导、激活量化简单或可选的场景(如 LSTM、部分 Linear)。

二、静态量化(Static Quantization)

静态量化:权重与激活的 scale/zero_point 均在离线校准阶段确定,推理时只做固定公式的 quantize/dequant,无额外统计,延迟与实现最稳定,吞吐高。缺点是对分布偏移敏感,校准数据需有代表性;若输入分布变化大,可能需重新校准或多套参数。适合推理输入分布稳定、追求极致延迟与吞吐的场景(如 CV、固定格式的 NLP)。

三、Runtime 开销对比

动态量化 runtime 多:每层或每次前向要做激活的 min/max 或直方图、再算 scale;静态量化 runtime 仅查表与乘加。因此高 QPS、低延迟服务倾向静态;输入分布多变、或模型以权重计算为主时可用动态。大模型推理常见「权重静态 + 激活静态或 per-token 动态」的折中。


面试要点

  • 动态量化:激活 scale 运行时按当前输入计算,无需校准、适应分布变化;缺点运行时多统计与量化,有额外开销。
  • 静态量化:权重与激活 scale 校准阶段定死,推理无额外统计,延迟低、吞吐高;对分布偏移敏感。
  • 高 QPS/低延迟用静态;分布多变或权重为主可用动态;大模型常权重静态+激活静态或 per-token 动态。

记忆要点

  1. 动态 = 激活 scale 运行时算,无校准、有 runtime 开销;静态 = scale 校准定死,推理无统计。
  2. 静态延迟低、适合稳定分布;动态适应变化、适合权重为主或分布多变。
  3. 大模型常见:权重静态 + 激活静态或 per-token 动态。

返回模块 | 返回总览

10-量化与压缩/129-量化算子的融合.md

第 129 题:量化算子的融合?quantize-linear + matmul + dequantize

题目

量化算子的融合?quantize-linear + matmul + dequantize


完整讲解

一、典型量化线性层的数据流

推理时线性层常拆成:quantize(激活 FP→INT8)、matmul(INT8×INT8 或 INT8×INT8 累加)、dequantize(结果 INT→FP 或直接按 scale 还原)。若这三步各自成 kernel,会有多次读写与多次遍历,带宽与 launch 开销大;且 quantize/dequant 可与相邻运算合并,减少中间结果落地。

二、融合的意义与做法

融合:把 quantize-linear + matmul + dequantize 合成一个或少量 kernel,使激活只读一次、量化后立即参与乘加、结果在寄存器或共享内存中按 scale 还原后再写回或交给下一层。这样减少全局内存访问与 kernel launch,提升吞吐、降低延迟。实现方式:手写 CUDA/ Triton kernel、或依赖框架/库(如 ONNX Runtime 的 QLinearMatMul、TensorRT 的 INT8 层、cuBLASLt 的 scaled matmul)自动融合。

三、工程要点

融合是量化推理的常规优化;需保证数值与分离实现一致(scale 传递、round 方式)。面试可提:Q-DQ 与 matmul 融合是 INT8 推理的标配优化;TensorRT/ONNX Runtime 等都会做此类融合;手写 kernel 时可进一步与激活、LayerNorm 等前后算子融合。


面试要点

  • 量化线性层 = quantize(激活) + matmul(INT8) + dequantize(结果);分离实现导致多次读写与 launch。
  • 融合:三合一或与前后算子合并,减少访存与 launch,提升吞吐与延迟。
  • 实现:TensorRT/ONNX Runtime 等自动融合;手写 kernel 可再与 LayerNorm 等融合。

记忆要点

  1. 量化线性 = Q + matmul + DQ;融合 = 合并为少 kernel,减访存与 launch。
  2. 融合是 INT8 推理标配;框架或手写 kernel 均可做。
  3. 数值需与分离实现一致(scale、round)。

返回模块 | 返回总览

10-量化与压缩/130-混合精度推理的策略.md

第 130 题:混合精度推理的策略?哪些层必须保持FP16

题目

混合精度推理的策略?哪些层必须保持FP16


完整讲解

一、混合精度推理的目的

混合精度指模型中部分层或张量用 FP16(或 BF16/FP8),部分保持 FP32 或更高精度,在精度与速度/显存间折中。推理时用 FP16 可减带宽与算力、加速;但某些层(如 softmax、LayerNorm 的方差、敏感输出)若全 FP16 可能数值不稳或掉点,需保留高精度。

二、策略与必须 FP16 的层

常见策略:默认 FP16,敏感处保留 FP32。通常可全 FP16 的:大部分 Linear、Conv、激活;常需保留 FP32 或局部高精度的:softmax 分母与指数(防溢出与精度)、LayerNorm 的 mean/var 计算(方差对精度敏感)、累加项很多时的 reduction(避免 FP16 累加误差)、首尾层(embedding 输出、logits)若敏感也可 FP32。具体可结合 sensitivity 分析:逐层切 FP16 看指标,掉点层保留高精度。

三、实现方式

框架级:PyTorch 的 autocast、TensorRT 的 layer precision 设置、ONNX 的 mixed precision 等;或手写时对指定 op 用 FP32 kernel。FP8 可用时,可进一步做 FP8+FP16 混合(如 TE),策略类似:敏感层或敏感 op 用 FP16,其余 FP8。


面试要点

  • 混合精度 = 部分层 FP16 加速,部分层 FP32 保精度;根据 sensitivity 或经验定。
  • 常保留高精度:softmax(分母/指数)、LayerNorm 的 mean/var、大累加 reduction、首尾层若敏感。
  • 实现:autocast、TensorRT layer precision、手写指定 op;可结合 FP8 做 FP8+FP16 混合。

记忆要点

  1. 混合精度 = 大部分 FP16,敏感处 FP32;目的省带宽与算力且保精度。
  2. 必须/建议 FP32:softmax、LayerNorm 统计、大累加、首尾层(按 sensitivity 定)。
  3. 实现靠框架精度设置或手写 kernel;可与 FP8 组合。

返回模块 | 返回总览

11-服务化与调度/README.md

11-服务化与调度(第 131–145 题)

题号 主题 文章
131 Triton Inference Server的`model ensem… 131-Triton-Inference-Server的model-ensemble.md
132 Triton的dynamic batching和`preferred… 132-Triton的dynamic-batching和preferred-batc.md
133 推理服务的A/B testing如何实现?模型版本管理? 133-推理服务的A-B-testing如何实现.md
134 Kubernetes + NVIDIA GPU Operator 134-Kubernetes-+-NVIDIA-GPU-Operator的部署经验.md
135 GPU虚拟化方案?MIG(Multi-Instance GPU)的配… 135-GPU虚拟化方案.md
136 推理请求的priority scheduling实现?`weight… 136-推理请求的priority-scheduling实现.md
137 长文本请求的preemption策略?KV cache的swap o… 137-长文本请求的preemption策略.md
138 推理服务的health check和`graceful degrad… 138-推理服务的health-check和graceful-degradation.md
139 如何监控推理服务的GPU memory泄漏? 139-如何监控推理服务的GPU-memory泄漏.md
140 推理模型的hot reload如何实现?零停机更新? 140-推理模型的hot-reload如何实现.md
141 gRPC vs REST for inference?性能差异和… 141-gRPC-vs-REST-for-inference.md
142 推理批处理的timeout处理?部分结果返回? 142-推理批处理的timeout处理.md
143 多租户场景下的资源配额管理?quotalimit、`reque… 143-多租户场景下的资源配额管理.md
144 推理服务的cost optimization策略?Spot inst… 144-推理服务的cost-optimization策略.md
145 Edge deployment的挑战?模型加密、设备兼容性? 145-Edge-deployment的挑战.md

返回总览

11-服务化与调度/131-Triton-Inference-Server的model-ensemble.md

第 131 题:Triton Inference Server的model ensemble如何使用?

题目

Triton Inference Server的model ensemble如何使用?


完整讲解

一、Model Ensemble 是什么

Triton 的 model ensemble 把多个模型(或同一模型不同阶段)组成一个推理流水线:请求依次经过 A→B→C,前一个模型的输出作为后一个的输入,在 server 内部完成多步推理,对客户端暴露为一个模型接口。典型用途:预处理模型 + 主模型、主模型 + 后处理/重排序、多阶段检索+生成等。

二、如何使用

config.pbtxt 中定义 ensemble_scheduling 类型的模型,在 ensemble_scheduling 里声明 step 列表:每个 step 指定用哪个模型、输入来自上一 step 的哪几个输出、输出名到下一 step 的映射。输入/输出名需与各子模型的 config 一致。部署时各子模型需先单独加载(或作为 dependency 声明);请求发往 ensemble 模型名,Triton 按 step 顺序调度、在 GPU/CPU 间传递中间 tensor。

三、注意点

Step 间数据在进程内传递,避免网络往返;可配置各 step 的 instance 数与设备。调试时先确保各子模型单独可调通,再组 ensemble;版本更新时需保证各子模型版本兼容(输入输出 shape/名一致)。


面试要点

  • Ensemble = 多模型组成流水线 A→B→C,对客户端暴露为一个模型;用于预处理+主模型、多阶段生成等。
  • 使用:config 里定义 ensemble 模型、声明 step 与各 step 的 model、输入输出映射;子模型先部署,请求发往 ensemble 名。
  • 数据在进程内传递;注意子模型输入输出名与 shape 一致、版本兼容。

记忆要点

  1. Ensemble = 多模型流水线,一步推理多阶段,对外一个接口。
  2. 配置 = ensemble 类型 + step 列表(model、输入输出映射);子模型先加载。
  3. 进程内传中间结果;部署时保证各子模型 config 与版本兼容。

返回模块 | 返回总览

11-服务化与调度/132-Triton的dynamic-batching和preferred-batc.md

第 132 题:Triton的dynamic batchingpreferred batch size配置?

题目

Triton的dynamic batchingpreferred batch size配置?


完整讲解

一、Dynamic Batching

Dynamic batching:服务端在有限时间窗口内把多个到达的请求攒成一批,再一起送进模型推理,从而提高 GPU 利用率与吞吐。请求不会无限等待,通常有 max_queue_delay_microseconds:从第一个请求进队到凑批或超时即执行。这样在 QPS 高时自动形成较大 batch,QPS 低时小 batch 或单条,延迟可控。

二、Preferred Batch Size

Preferred batch size:提示 Triton 优先凑成的 batch 大小列表(如 [1, 2, 4, 8])。当队列中请求数达到某一 preferred size 时立即执行该 batch,不必等到 max_queue_delay;若一直凑不齐则到时间后按当前队列执行。作用:在延迟与吞吐间折中——preferred 越大越利于吞吐,但等待时间可能变长;通常设成模型或 kernel 较优的 batch(如 2、4、8),避免总是 1 或总是很大 batch。

三、配置要点

在 model 的 dynamic_batching 中配置 max_queue_delay_microsecondspreferred_batch_size、可选 preserve_ordering 等。LLM 生成场景下有时用 continuous batching(每步可不同 batch)而非单纯 dynamic batching,需看后端与版本支持。


面试要点

  • Dynamic batching:在时间窗口内攒多个请求成一批推理,提高吞吐;max_queue_delay 控制最大等待时间。
  • Preferred batch size:优先凑成的 batch 列表,达到即执行;用于在延迟与吞吐间折中,常设 1/2/4/8 等。
  • 配置在 dynamic_batching 里;LLM 生成可能用 continuous batching,需看后端支持。

记忆要点

  1. Dynamic batching = 时间窗口内攒批,max_queue_delay 限等待。
  2. Preferred batch size = 优先凑成的 batch 列表,凑齐即跑;常设 1/2/4/8。
  3. 配置在 model config 的 dynamic_batching;生成场景注意 continuous batching。

返回模块 | 返回总览

11-服务化与调度/133-推理服务的A-B-testing如何实现.md

第 133 题:推理服务的A/B testing如何实现?模型版本管理?

题目

推理服务的A/B testing如何实现?模型版本管理?


完整讲解

一、A/B Testing 实现思路

A/B testing:将流量按比例分到不同模型版本(如 A 90%、B 10%),比较延迟、准确率、业务指标。实现方式:(1)网关/负载均衡层:按请求头、用户 ID 哈希或随机数把请求路由到不同后端或同一后端的不同模型版本;(2)推理服务自身:同一 endpoint 支持多版本,由请求参数或 header 指定版本,内部路由到对应 model instance;(3)流量镜像:主流量走 A,复制一部分到 B 做影子测试,对比结果。需保证同一用户或 session 尽量稳定在同一版本(一致性),并打日志/打点做指标对比。

二、模型版本管理

版本管理:模型文件按版本号或标签组织(如 model_v1/model_v2/),部署时通过 Triton 的 model_version_policy、K8s 的 deployment 标签、或配置中心指定当前生效版本。支持多版本并存:新旧版本同时加载,通过路由做灰度或 A/B;支持回滚:切回上一版本配置并重载。版本与配置(batch、instance 数等)一起管理,便于复现与审计。

三、工程要点

版本命名建议语义化或带时间戳;CI/CD 产出物与版本绑定;A/B 的流量比例与周期可配置,结果用统一监控与实验平台分析。


面试要点

  • A/B 实现:网关/负载均衡按比例或哈希路由到不同版本;或推理服务内按 header/参数选版本;可加流量镜像做影子测试。
  • 版本管理:模型按版本目录或标签部署;多版本并存、路由灰度;支持回滚与配置绑定。
  • 同一用户/session 尽量同版本;打点与监控做指标对比。

记忆要点

  1. A/B = 流量按比例路由到不同模型版本;网关或服务内路由,可加镜像。
  2. 版本管理 = 多版本并存、路由/灰度、回滚;配置与版本绑定。
  3. 一致性(同用户同版本)、打点与监控必备。

返回模块 | 返回总览

11-服务化与调度/134-Kubernetes-+-NVIDIA-GPU-Operator的部署经验.md

第 134 题:Kubernetes + NVIDIA GPU Operator的部署经验?

题目

Kubernetes + NVIDIA GPU Operator的部署经验?


完整讲解

一、K8s + GPU 的痛点与 Operator

K8s 默认不识别 GPU,需安装驱动、CUDA、设备插件等,并正确配置 resources.limits.nvidia.com/gpuNVIDIA GPU Operator 把 GPU 相关组件的安装与生命周期自动化:在集群中部署 Operator 后,它会在有 GPU 的节点上安装 NVIDIA 驱动(或依赖节点已有驱动)、container toolkit、device plugin、DCGM exporter 等,并通过 NodeFeatureDiscovery 等给节点打标签,便于用 nodeSelector 调度到 GPU 节点。

二、部署经验要点

(1)节点准备:若用 Operator 管理驱动,需满足其要求的 OS 与内核;否则预装驱动再让 Operator 只装 toolkit 与 plugin。(2)资源声明:Pod 中 limits.nvidia.com/gpu: 1 等,request 通常与 limit 同以保证独占。(3)调度:用 nodeSelector/taint/toleration 把推理或训练任务固定到 GPU 节点。(4)监控:Operator 可选装 DCGM、Prometheus 指标,便于看显存与利用率。(5)多卡与 MIG:多卡节点可配 MIG 或按卡数分片部署;升级与故障时注意 driver 与 CUDA 版本兼容。

三、常见问题

镜像需带 CUDA 与对应 cuDNN;K8s 与 driver 版本要匹配;OOM 或 device 未找到时查 device plugin 日志与节点条件。


面试要点

  • GPU Operator 自动化:驱动(可选)、container toolkit、device plugin、监控等,并给节点打 GPU 相关标签。
  • 部署:节点满足 OS/驱动要求;Pod 声明 limits.nvidia.com/gpu;用 nodeSelector/taint 调度;可选 DCGM 监控。
  • 注意镜像 CUDA 版本、driver 与 K8s 兼容;多卡/MIG 按需配置。

记忆要点

  1. GPU Operator = 自动装驱动/toolkit/device plugin + 节点标签,便于调度。
  2. Pod 声明 limits.nvidia.com/gpu;调度靠 nodeSelector/taint。
  3. 镜像带 CUDA;版本兼容;多卡/MIG 按需。

返回模块 | 返回总览

11-服务化与调度/135-GPU虚拟化方案.md

第 135 题:GPU虚拟化方案?MIG(Multi-Instance GPU)的配置?

题目

GPU虚拟化方案?MIG(Multi-Instance GPU)的配置?


完整讲解

一、GPU 虚拟化方案概览

物理独占:一卡一任务,无虚拟化。时间片/分时:多任务共享一卡,由调度器切换,上下文切换有开销。MIG(Multi-Instance GPU):A100 及以后部分卡支持将一块 GPU 切成多个小实例,每个实例有独立显存与算力,隔离性好,适合小模型多实例部署。vGPU(如 vGPU 软件方案):将单卡虚拟成多块「小卡」,多用于云与多租户。容器 + 设备分配:K8s 下用 limits 分配整卡或 MIG 实例给不同 Pod,逻辑隔离。

二、MIG 配置

MIG 将 GPU 按「slice」划分,如 A100 可配成 7×1g.5gb(7 个 1/7 算力+显存实例)或 3×2g.10gb 等。配置步骤:在节点上启用 MIG mode(需支持 MIG 的卡与驱动),用 nvidia-smi mig 创建实例规格,再通过 device plugin 或 K8s 资源(如 nvidia.com/mig-1g.5gb)把实例暴露给 Pod。每个 MIG 实例有独立 UUID,调度时按资源名申请即可。注意:启用 MIG 后整卡不再作为单设备使用,需规划好切分与实例数。

三、选型

小模型、多实例、强隔离用 MIG;大模型单卡或多卡用物理卡;云上多租户常结合 vGPU 或 MIG + 配额。


面试要点

  • 方案:物理独占、分时、MIG(硬件切分)、vGPU、容器设备分配;MIG 适合小模型多实例、强隔离。
  • MIG 配置:启用 MIG mode、nvidia-smi mig 创建实例规格、device plugin 暴露 MIG 资源名给 K8s。
  • 选型:小模型多实例用 MIG;大模型用物理卡;多租户可 MIG 或 vGPU。

记忆要点

  1. MIG = 一块 GPU 切成多实例,独立显存与算力,A100+ 支持。
  2. 配置 = MIG mode + mig 实例规格 + device plugin 暴露资源名。
  3. 小模型多实例、隔离选 MIG;大模型用整卡。

返回模块 | 返回总览

11-服务化与调度/136-推理请求的priority-scheduling实现.md

第 136 题:推理请求的priority scheduling实现?weighted fair queuing

题目

推理请求的priority scheduling实现?weighted fair queuing


完整讲解

一、Priority Scheduling

Priority scheduling:请求带优先级(如高优 VIP、低优批量),调度器按优先级决定谁先获得 GPU 或先入批。实现方式:(1)多队列:按优先级分队列,高优队列先被取;(2)抢占:高优请求可抢占低优(需支持中断或分批,推理中较难);(3)加权轮询:按权重从各优先级取请求,高权高优多占资源。推理服务常采用多队列 + 从高优队列优先取批,无抢占则通过「高优队列等待时间更短」体现优先级。

二、Weighted Fair Queuing(WFQ)

WFQ:按流或按优先级给不同权重,调度时按「虚拟完成时间」或权重分配带宽/算力,使各流在长期上按权重获得公平份额,同时高权流更快。在推理中可抽象为:不同租户或优先级对应不同权重,batch 调度时按权重决定每类请求进入 batch 的比例或顺序,避免某类请求长期饿死。实现可用虚拟时间戳:每类维护 virtual finish time,按最小 virtual time 选下一个请求或 batch。

三、工程要点

结合 dynamic batching:高优请求可设更短 max_queue_delay 或单独队列;WFQ 需按租户/优先级打标签并在调度逻辑中算权重与 virtual time。监控上区分各优先级的延迟与吞吐。


面试要点

  • 优先级调度:多队列按优先级取、或加权轮询;高优先得资源,无抢占时通过排队时间体现。
  • WFQ:按权重分配算力,虚拟完成时间或权重轮询,避免饿死、保证公平与优先级。
  • 实现:请求打优先级/租户标签;调度器多队列或 WFQ 选批;监控分优先级指标。

记忆要点

  1. 优先级 = 多队列或加权轮询,高优先服务;推理少用抢占。
  2. WFQ = 按权重公平分配,虚拟时间或权重;防饿死、可体现优先级。
  3. 与 dynamic batching 结合:高优短等待或单独队列;打标签与监控。

返回模块 | 返回总览

11-服务化与调度/137-长文本请求的preemption策略.md

第 137 题:长文本请求的preemption策略?KV cache的swap out?

题目

长文本请求的preemption策略?KV cache的swap out?


完整讲解

一、长文本与 Preemption 需求

长文本请求占用的 KV cache 大、耗时长,若一直占着显存不释放,会阻塞新请求或导致 OOM。Preemption(抢占):在资源紧张或高优请求到达时,暂停或挂起当前长请求,释放其 KV cache 与算力,先服务高优或短请求,之后再恢复被挂起请求。难点在于:生成是状态化的(已生成 token、KV 状态),挂起需保存状态、恢复需还原,且要保证正确性与延迟体验。

二、KV Cache Swap Out

KV cache swap out:把当前不需要参与计算的 KV 块从 GPU 显存换出到 CPU 内存(或 SSD),腾出显存给其他请求或同一请求的后续计算;需要时再换入回显存。这样长上下文不必一次性占满显存,可按「当前窗口」+ 换出历史实现长序列。实现要点:按 block 或 chunk 管理 KV,LRU 或按 attention 范围决定谁换出;换入时可能造成一次 stall,需与调度配合(如 preemption 时整请求 swap out,恢复时 swap in)。

三、Preemption 策略

策略可组合:时间片到则挂起长请求、swap out KV,让出 GPU;高优到达时挂起低优长请求;显存水位超阈值时对最不「划算」的请求(如已生成很多、剩余少)做 swap out 或终止。恢复时按 checkpoint 或 swap 回来的 KV 继续生成。PagedAttention、vLLM 等已支持类似逻辑,面试可结合具体系统说。


面试要点

  • 长文本抢占:挂起长请求、释放 KV 与算力,先服务高优/短请求,再恢复;需保存与还原生成状态。
  • KV swap out:把 KV 块从 GPU 换到 CPU/SSD,腾显存;需要时换入;按 block 管理、LRU 或按范围决策。
  • 策略:时间片、高优到达、显存水位触发;与 PagedAttention/vLLM 等实现结合。

记忆要点

  1. Preemption = 挂起长请求、释放资源,再恢复;状态需保存与还原。
  2. KV swap out = 显存→CPU/SSD,按块管理;换入换出与调度配合。
  3. 触发:时间片、优先级、显存阈值;可结合 PagedAttention 等。

返回模块 | 返回总览

11-服务化与调度/138-推理服务的health-check和graceful-degradation.md

第 138 题:推理服务的health checkgraceful degradation

题目

推理服务的health checkgraceful degradation


完整讲解

一、Health Check

Health check:外部或负载均衡定期探测服务是否存活、是否可接受请求。常见:Liveness(进程是否在、端口是否监听):失败则重启实例;Readiness(是否就绪接流):模型是否加载完、是否过载,失败则从 LB 摘除、不再分新流量。实现方式:HTTP 指定 path(如 /health/ready)返回 200 或 503;或 gRPC health 协议。探测频率与超时要合理,避免误判;GPU 推理可在 ready 中加「模型加载完成」与可选「显存可用」检查。

二、Graceful Degradation

Graceful degradation:在部分故障或过载时降级而非直接挂掉。策略包括:限流:超 QPS 时返回 429 或排队;降级响应:超时或错误时返回缓存、默认回复或简化模型结果;关闭部分功能:如关闭重排序、只用检索结果;实例级:单实例异常时由 LB 摘除,其他实例继续服务。目标是在部分失败下尽量保证可用性与用户体验,并配合告警与自动恢复。

三、工程要点

Health 与 LB、K8s readiness/liveness 配合;降级策略可配置(开关、阈值);监控记录 5xx、超时、降级次数,便于定位与容量规划。


面试要点

  • Health check:Liveness(存活/重启)、Readiness(就绪/摘流);HTTP 或 gRPC health;可含模型加载与显存检查。
  • Graceful degradation:限流、超时降级(缓存/默认/简化)、关部分功能、实例摘除;保证部分故障时仍可用。
  • 与 LB、K8s 配合;降级策略可配置;监控 5xx、超时、降级次数。

记忆要点

  1. Health = liveness(重启)+ readiness(摘流);就绪可含模型与显存。
  2. 降级 = 限流、超时降级、关功能、摘实例;目标部分故障仍可用。
  3. 配合 LB/K8s;可配置;监控必备。

返回模块 | 返回总览

11-服务化与调度/139-如何监控推理服务的GPU-memory泄漏.md

第 139 题:如何监控推理服务的GPU memory泄漏?

题目

如何监控推理服务的GPU memory泄漏?


完整讲解

一、GPU 显存泄漏表现

推理服务长时间运行后显存持续增长、最终 OOM,或 nvidia-smi 显示进程占用显存只增不减,多为显存泄漏。常见原因:每请求分配临时 buffer 或 KV cache 未释放、CUDA graph 或缓存未清理、模型推理中创建中间 tensor 未释放、第三方库或 driver 层泄漏。

二、监控手段

(1)进程级:定期采集 nvidia-smi 或 DCGM 的 per-process 显存,看随时间是否单调增;设告警阈值与增长率。(2)框架级:PyTorch 用 torch.cuda.memory_allocated()memory_reserved() 在请求前后或周期打点,对比是否回落;Triton 等看 backend 提供的内存统计。(3)请求级:对单次请求前后打显存快照,定位是否某类请求导致增长。(4)工具:Nsight Systems、cuda-memcheck 做长时间或单次追踪,看分配栈与未释放块。

三、定位与修复

结合监控确定是「每请求涨一点」还是「偶发大涨」;再通过请求类型、模型路径、版本缩小范围。修复:确保每次推理后释放临时 buffer、正确管理 KV cache 生命周期、避免在热路径上重复建大 tensor;升级框架或 driver 以修已知泄漏。


面试要点

  • 表现:长时间运行显存持续增、OOM;原因多为 buffer/KV 未释放、缓存未清、框架或 driver 问题。
  • 监控:nvidia-smi/DCGM 进程显存趋势;PyTorch memory_allocated 打点;请求前后快照;cuda-memcheck/Nsight 追踪。
  • 定位:看是否每请求涨或偶发涨;修复:保证释放、管理 KV 生命周期、升级已知修复版本。

记忆要点

  1. 泄漏 = 显存只增不减、最终 OOM;原因 buffer/KV/缓存/框架。
  2. 监控 = 进程显存趋势 + 请求前后打点 + 工具追踪分配栈。
  3. 修复 = 释放临时、管理 KV、避免热路径重复分配、升级版本。

返回模块 | 返回总览

11-服务化与调度/140-推理模型的hot-reload如何实现.md

第 140 题:推理模型的hot reload如何实现?零停机更新?

题目

推理模型的hot reload如何实现?零停机更新?


完整讲解

一、Hot Reload 与零停机目标

Hot reload:不重启进程、不中断正在处理的请求,用新版本模型替换旧版本,新请求 thereafter 使用新模型。零停机:用户无感知、无 5xx、无连接断开。难点:模型可能很大、加载耗时长;正在进行的请求必须用旧模型跑完;新模型与旧模型接口需兼容(shape、配置等)。

二、实现思路

(1)多版本并存:新模型加载到新目录或新 version,加载完成后通过配置或路由把新流量切到新版本,旧请求仍用旧 version;旧请求结束后可卸载旧版本(可选)。(2)双 buffer/双实例:维护 A/B 两套实例,当前流量走 A;后台把 B 更新为新模型并预热,切换时流量切到 B,再更新 A,轮流替换。(3)Triton 等:支持 model_version_policy 与 load/unload API,先 load 新 version,再改 policy 或路由指向新 version,旧 request 仍用原 version 直到完成。关键:新模型加载与切换原子化或通过「版本切换」一步完成,避免半新半旧状态。

三、注意点

加载期间显存可能双倍(旧+新),需预留或先 unload 再 load;接口兼容性要在发布流程里保证;可做金丝雀(先切少量流量到新版本)。


面试要点

  • Hot reload = 不重启进程、新模型替换旧模型,新请求用新版本;零停机 = 无 5xx、无断连。
  • 实现:多版本并存 + 流量切换;或双实例轮流更新;Triton 用 version policy + load 新 version 后切路由。
  • 加载期可能双倍显存;保证接口兼容;可金丝雀发布。

记忆要点

  1. Hot reload = 进程内换模型、新请求用新版本;零停机 = 无感知。
  2. 实现 = 多版本/双实例 + 流量切换;旧请求用旧版本跑完。
  3. 显存预留、接口兼容、金丝雀。

返回模块 | 返回总览

11-服务化与调度/141-gRPC-vs-REST-for-inference.md

第 141 题:gRPC vs REST for inference?性能差异和适用场景?

题目

gRPC vs REST for inference?性能差异和适用场景?


完整讲解

一、gRPC vs REST 概览

REST:HTTP/JSON(或其它序列化),无状态、易调试、浏览器与 curl 直接支持,生态广。gRPC:基于 HTTP/2、默认 Protobuf 二进制,支持流、多路复用、强类型接口,延迟与序列化开销通常更小,但需要 client 库与 IDL 定义。

二、性能差异与推理场景

延迟与吞吐:gRPC 二进制序列化更小、HTTP/2 多路复用减少连接开销,高 QPS 下通常延迟更低、吞吐更高;REST/JSON 序列化与解析成本大,大 payload 时差异明显。流式:gRPC 原生双向流,适合长上下文、流式生成(token 级推流);REST 需 SSE 或 chunked 等,实现与生态略逊。调试与兼容:REST 用 curl/Postman 即可;gRPC 需工具或代码,对开放 API、多语言轻量调用更友好的是 REST。

三、适用场景

选 gRPC:内部推理服务、高 QPS、低延迟、流式生成、多语言强类型契约。选 REST:对外 API、需要简单调试、浏览器或脚本直接调用、对延迟不极端敏感。实践中内部多 gRPC,对外或简单调用用 REST;也有网关将 REST 转 gRPC 后端。


面试要点

  • gRPC:HTTP/2 + Protobuf,低延迟、高吞吐、原生流;REST:HTTP/JSON,易调试、兼容好。
  • 推理高 QPS、流式生成倾向 gRPC;对外、简单调用、调试友好用 REST。
  • 可组合:内部 gRPC、网关对外 REST。

记忆要点

  1. gRPC = 二进制+多路复用+流,性能好;REST = 易调试、兼容广。
  2. 推理内部、流式、高 QPS 用 gRPC;对外、简单用 REST。
  3. 内部 gRPC + 网关 REST 常见。

返回模块 | 返回总览

11-服务化与调度/142-推理批处理的timeout处理.md

第 142 题:推理批处理的timeout处理?部分结果返回?

题目

推理批处理的timeout处理?部分结果返回?


完整讲解

一、Batch 与 Timeout 问题

推理批处理为凑满 batch 会等待一段时间;若某请求等待过久推理执行过久,需要 timeout 控制:超时则不再等待该请求、或中止其推理,并给客户端明确反馈(超时错误或部分结果),避免长时间挂住连接与资源。

二、Timeout 处理策略

(1)排队超时:从请求进队到开始执行的上限时间;超时则直接返回 408/503 或「排队超时」错误,不进入推理。(2)推理超时:从开始推理到返回的上限;超时可选:中止当前 batch 中该请求(若后端支持 per-request 取消)、或等整批完成但对该请求标记超时并返回错误。(3)部分结果返回:对生成类任务,可设「最大等待时间」,到点则返回已生成部分(如已生成的 token)+ 超时标记,让客户端决定是否继续轮询或放弃。这样既不白算、又给用户部分可用结果。

三、实现要点

在队列与执行层设 timeout 参数;超时后释放该请求占用的 slot 或 KV;响应中区分「排队超时」与「推理超时」;流式场景可每 chunk 检查 deadline、超时则停止生成并返回已生成部分。


面试要点

  • Batch 需控制排队与推理超时;超时后返回明确错误或部分结果,释放资源。
  • 排队超时:不进推理、直接 408/503;推理超时:中止或等批完成并标记该请求超时。
  • 部分结果:生成类可返回已生成 token + 超时标记,供客户端决定是否继续。

记忆要点

  1. Timeout = 排队超时 + 推理超时;超时必返回明确状态并释放资源。
  2. 生成类可支持「部分结果」:已生成 token + 超时标记。
  3. 实现:队列与执行层设 deadline;区分排队/推理超时;流式可按 chunk 检查。

返回模块 | 返回总览

11-服务化与调度/143-多租户场景下的资源配额管理.md

第 143 题:多租户场景下的资源配额管理?quotalimitrequest

题目

多租户场景下的资源配额管理?quotalimitrequest


完整讲解

一、Quota、Limit、Request 含义

Request:Pod/容器向 K8s 声明的「期望资源」,用于调度器决策(能否找到满足 request 的节点);Limit:该 Pod 最多可用资源上限,超限可能被 throttled 或 OOM kill。Quota:多租户场景下,对某 namespace 或某租户的总资源上限(如总 GPU 数、总 CPU),防止单租户占满集群。

二、多租户资源配额管理

(1)Namespace 级:每租户一个 namespace,设 ResourceQuota(总 CPU/内存/GPU)与 LimitRange(单 Pod 默认 limit)。(2)Request = Limit:对 GPU 推理常设 request 等于 limit,保证独占、避免超卖导致性能抖动。(3)Quota 与优先级:高优租户可配更大 quota 或单独资源池;结合优先级调度保证高优租户的 request 优先满足。(4)监控与告警:按租户统计实际使用与 quota 使用率,超配额则拒绝新调度或告警。

三、工程要点

Quota 要略大于各租户 request 之和以允许碎片;GPU 可细到「每租户最大 GPU 数」;配合 RBAC 与计费做租户隔离与审计。


面试要点

  • Request = 调度用期望资源;Limit = 单 Pod 上限;Quota = 某租户/namespace 总资源上限。
  • 多租户:每租户 namespace + ResourceQuota + LimitRange;GPU 推理常 request=limit 独占。
  • 配额与优先级、监控使用率、超配额拒绝或告警。

记忆要点

  1. Request/Limit = 单 Pod;Quota = 租户/namespace 总上限。
  2. 多租户 = namespace + Quota + LimitRange;GPU 常 request=limit。
  3. 监控、优先级、超配额处理必备。

返回模块 | 返回总览

11-服务化与调度/144-推理服务的cost-optimization策略.md

第 144 题:推理服务的cost optimization策略?Spot instance的使用?

题目

推理服务的cost optimization策略?Spot instance的使用?


完整讲解

一、Cost Optimization 思路

推理成本 = 算力(GPU/CPU)× 时长 + 存储与网络。优化方向:提高利用率(批处理、弹性伸缩、混部)、选用更便宜算力(Spot/抢占式实例、自建与云结合)、模型与推理优化(量化、剪枝、小模型)减少单请求算力与时长、按需伸缩避免常驻大容量。

二、Spot Instance 的使用

Spot(抢占式)实例:价格低但可能被回收,适合可中断、可恢复的负载。推理场景:批处理/离线推理可用 Spot 大幅降本;在线推理若要求高可用则需策略:如用 Spot 做弹性扩容、与 on-demand 混用(基线 on-demand,峰值 Spot),或多可用区/多实例冗余,单点被回收时流量切到其它实例。可配合 K8s 的 spot 节点池、中断通知与 Pod 迁移,尽量在回收前排空或迁移请求。

三、其它策略

预留实例/节省计划包年降单价;自动伸缩按 QPS 或队列深度扩缩容;多模型共享 GPU(MIG、多实例);监控单请求成本与利用率,持续优化。


面试要点

  • 成本优化:提利用率(批处理、弹性、混部)、便宜算力(Spot)、模型与推理优化、按需伸缩。
  • Spot:低价可回收;适合批处理/离线;在线需混用 on-demand 或多实例冗余,配合中断通知与迁移。
  • 预留/节省计划、自动伸缩、多模型共享 GPU、单请求成本监控。

记忆要点

  1. 成本 = 算力×时长+存储;优化 = 利用率+算力选型+模型优化+伸缩。
  2. Spot = 低价可回收;批处理用 Spot;在线可 Spot 弹性+on-demand 基线。
  3. 预留、伸缩、共享、监控单请求成本。

返回模块 | 返回总览

11-服务化与调度/145-Edge-deployment的挑战.md

第 145 题:Edge deployment的挑战?模型加密、设备兼容性?

题目

Edge deployment的挑战?模型加密、设备兼容性?


完整讲解

一、Edge 部署的挑战

算力与功耗:边缘设备 CPU/NPU 有限,大模型需裁剪、量化或小模型。延迟与离线:网络不稳定或离线时需本地推理,模型与数据需预置。安全与合规:模型与数据在端侧,需防逆向、防篡改、满足隐私合规。设备碎片化:ARM/x86、不同 NPU、不同 OS 与驱动,兼容性与测试成本高。

二、模型加密与保护

模型加密:分发时模型文件加密存储,运行时在安全环境(TEE、安全区)内解密加载,防止被直接拷贝或逆向。权重混淆/水印:在不严重影响精度下做混淆或嵌入水印,便于溯源与防滥用。访问控制:端侧 API 鉴权、调用频率与权限控制,防止未授权使用。

三、设备兼容性

格式与运行时:ONNX、TFLite、OpenVINO 等跨平台格式;针对 ARM、NPU 的优化与算子支持。分层策略:强设备用较大模型、弱设备用蒸馏小模型或更强量化;同一服务根据设备能力返回不同模型或配置。CI 与真机:多设备、多 OS 的自动化构建与真机测试,覆盖主流机型与版本。


面试要点

  • Edge 挑战:算力/功耗有限、延迟与离线、安全合规、设备碎片化。
  • 模型保护:加密分发与 TEE 内解密、混淆/水印、端侧鉴权与访问控制。
  • 兼容性:ONNX/TFLite 等格式、多设备分层策略(大/小模型)、多设备 CI 与真机测试。

记忆要点

  1. Edge = 算力有限、离线、安全、设备碎片化;模型需裁剪/量化/小模型。
  2. 加密 = 分发加密 + TEE 解密;兼容 = 跨平台格式 + 多设备分层。
  3. 分层策略:强设备大模型、弱设备小模型;多设备 CI 必备。

返回模块 | 返回总览

12-训练框架/README.md

12-训练框架(第 146–160 题)

题号 主题 文章
146 Megatron-LM的代码结构?megatron/core的新设计… 146-Megatron-LM的代码结构.md
147 DeepSpeed的ZeRO-Infinity和`ZeRO-Offl… 147-DeepSpeed的ZeRO-Infinity和ZeRO-Offload的代.md
148 Colossal-AI的GeminiPatrickStar的异… 148-Colossal-AI的Gemini和PatrickStar的异同.md
149 FairScale的FullyShardedDataParallel 149-FairScale的FullyShardedDataParallel(FSD.md
150 Hugging Face的Accelerate如何简化分布式训练? 150-Hugging-Face的Accelerate如何简化分布式训练.md
151 torch.distributed.fsdp的`limit_all_… 151-torch.distributed.fsdp的limit_all_gathe.md
152 大模型训练的checkpoint格式?`sharded checkp… 152-大模型训练的checkpoint格式.md
153 训练恢复的consistency问题?如何确保resume后的los… 153-训练恢复的consistency问题.md
154 大模型训练的data pipeline优化?WebDataset 154-大模型训练的data-pipeline优化.md
155 多模态大模型的训练基础设施挑战?图文数据的加载? 155-多模态大模型的训练基础设施挑战.md
156 RLHF训练的infra设计?PPO的分布式实现? 156-RLHF训练的infra设计.md
157 MoE模型的all-to-all通信优化?Tutel、`Fast… 157-MoE模型的all-to-all通信优化.md
158 长上下文训练(100K+ tokens)的显存优化?`Ring Atte… 158-长上下文训练(100K+-tokens)的显存优化.md
159 训练任务的fault tolerance?`elastic trai… 159-训练任务的fault-tolerance.md
160 大模型训练的experiment tracking?`Weights… 160-大模型训练的experiment-tracking.md

返回总览

12-训练框架/146-Megatron-LM的代码结构.md

第 146 题:Megatron-LM的代码结构?megatron/core的新设计?

题目

Megatron-LM的代码结构?megatron/core的新设计?


完整讲解

一、Megatron-LM 代码结构概览

Megatron-LM 是 NVIDIA 的大模型训练框架,核心包括:模型并行(Tensor Parallel、Pipeline Parallel)实现、Transformer 块(Self-Attention、MLP 的切分与通信)、数据加载与 checkpoint配置与启动脚本。目录上常见 megatron/ 下按功能分:model、training、data、inference 等;配置与入口通过 YAML 或命令行指定模型规模、并行度、数据路径等。

二、megatron/core 新设计

megatron/core 是较新的模块化设计:把核心算子与并行逻辑从原先与训练脚本强耦合中拆出,形成可复用的「core」库。包括:transformer(attention、MLP 的 fused kernel 与并行版)、tensor_parallel(列/行切分与 all-reduce)、pipeline_parallel(stage 划分与通信)、distributed(通信原语封装)等。这样其它项目(如 NeMo、自定义训练)可直接依赖 megatron/core 做 TP/PP,而不必拉整个 Megatron 训练流程;同时 core 内测试与升级更清晰。

三、面试可说的点

能说出「Megatron 负责大模型 TP/PP、transformer 切分」「megatron/core 是抽出的核心库、便于复用与集成」即可;若看过代码可提 attention 的 column/row parallel、MLP 的切分方式。


面试要点

  • Megatron-LM:大模型训练框架,含 TP/PP、Transformer 切分、数据与 checkpoint、配置入口。
  • megatron/core:核心算子与并行逻辑模块化,可单独复用;含 transformer、tensor_parallel、pipeline_parallel、distributed 等。
  • 便于其它项目集成 TP/PP;core 与训练脚本解耦,测试与升级更清晰。

记忆要点

  1. Megatron = TP/PP + Transformer 切分 + 数据/checkpoint;目录按功能分。
  2. megatron/core = 核心库抽离,transformer、TP、PP、distributed 可复用。
  3. 其它框架可依赖 core 做并行,不必用全套 Megatron。

返回模块 | 返回总览

12-训练框架/147-DeepSpeed的ZeRO-Infinity和ZeRO-Offload的代.md

第 147 题:DeepSpeed的ZeRO-InfinityZeRO-Offload的代码入口?

题目

DeepSpeed的ZeRO-InfinityZeRO-Offload的代码入口?


完整讲解

一、ZeRO-Infinity 与 ZeRO-Offload 简述

ZeRO-Offload:把优化器状态与梯度 offload 到 CPU 内存,GPU 只保留参数与激活,用 CPU-GPU 异步拷贝与计算重叠,实现单卡或少量卡训练大模型。ZeRO-Infinity:在 Offload 基础上进一步把参数也 offload 到 CPU(或 NVMe),仅计算时按需把参数块换入 GPU,突破单机 GPU 显存上限,支持极大模型。

二、代码入口与关键模块

DeepSpeed 中与 ZeRO 相关的入口与配置:deepspeed.initialize() 时传入 config 中的 zero_optimization;其中 stage 3 表示 ZeRO-3(参数分片),offload_optimizeroffload_param 对应 CPU/NVMe offload。代码路径deepspeed/runtime/zero/ 下,stage2.pystage3.py 等实现分片与通信;offload 逻辑在 offload_config.py 与 optimizer/parameter 的 CPU 侧管理;partition_parameters.pygather_parameters.py 等实现参数的分片与 all-gather。查「ZeRO-Infinity」时可搜 offload_paraminfinity;查「Offload」时可搜 offload_optimizercpu_optimizer

三、使用方式

用户通过 ds_config.json 或 API 开启 zero_optimization.stage=3offload_optimizer/offload_param 的 device 与 buffer 配置;训练脚本用 deepspeed.initialize(model=..., config=...) 即可,无需改模型结构,仅改配置与启动命令。


面试要点

  • ZeRO-Offload = 优化器/梯度 offload 到 CPU;ZeRO-Infinity = 参数也 offload 到 CPU/NVMe,按需换入 GPU。
  • 代码:deepspeed.initialize + zero_optimization 配置;deepseed/runtime/zero/ 下 stage2/3、offload 相关;offload_param、partition/gather 等。
  • 使用:ds_config 里 stage、offload_optimizer、offload_param;无需改模型。

记忆要点

  1. Offload = 优化器/梯度→CPU;Infinity = 参数→CPU/NVMe,按需换入。
  2. 入口 = deepspeed.initialize + config;实现 = runtime/zero/ + offload 与 partition。
  3. 配置 stage、offload_optimizer、offload_param 即可启用。

返回模块 | 返回总览

12-训练框架/148-Colossal-AI的Gemini和PatrickStar的异同.md

第 148 题:Colossal-AI的GeminiPatrickStar的异同?

题目

Colossal-AI的GeminiPatrickStar的异同?


完整讲解

一、Gemini 与 PatrickStar 定位

二者都是 Colossal-AI 中的异构内存管理方案,目标是在有限 GPU 显存下训练更大模型:把暂时不用的张量放到 CPU 或 NVMe,需要时再换回 GPU。PatrickStar:更早的方案,按「张量生命周期」做分层存储与换入换出,参数、优化器状态等按使用时机在 GPU/CPU/NVMe 间调度。Gemini:后续设计,强调统一内存视图与更细粒度的 chunk 管理、更高效的换入换出与重叠,并更好与 ZeRO 风格的分片结合。

二、异同概览

相同:都是 CPU/NVMe 做扩展显存、按需换入 GPU;都面向单机或小规模多卡上的大模型训练;都需处理换入换出与计算重叠以降低 stall。不同:Gemini 在内存抽象(chunk、统一管理)、与 ZeRO 的集成、以及换入换出策略上做了迭代,通常比 PatrickStar 更高效、接口更统一;PatrickStar 更偏「按张量类型与生命周期」的早期异构方案。具体 API 与默认策略需看 Colossal-AI 当前文档。

三、面试可说的点

能说清「都是 Colossal 的 CPU/NVMe 扩展显存方案」「Gemini 是更新一代、chunk 管理与 ZeRO 集成更好」「PatrickStar 偏早期按生命周期调度」即可。


面试要点

  • 二者均为 Colossal-AI 的异构内存方案:GPU+CPU/NVMe,按需换入换出,扩展可训模型规模。
  • PatrickStar:按张量生命周期分层与调度;Gemini:统一内存视图、chunk 管理、与 ZeRO 集成更好,通常更高效。
  • 相同目标与思路;Gemini 为迭代版,管理与策略更成熟。

记忆要点

  1. 都是 Colossal 的 CPU/NVMe 扩展显存;PatrickStar 较早,Gemini 迭代版。
  2. PatrickStar = 按生命周期分层;Gemini = chunk + 统一管理 + ZeRO 集成。
  3. Gemini 一般更高效、接口更统一;具体以文档为准。

返回模块 | 返回总览

12-训练框架/149-FairScale的FullyShardedDataParallel(FSD.md

第 149 题:FairScale的FullyShardedDataParallel(FSDP)实现细节?

题目

FairScale的FullyShardedDataParallel(FSDP)实现细节?


完整讲解

一、FSDP 做什么

FullyShardedDataParallel(FSDP):把模型参数、梯度、优化器状态按 rank 分片,每 rank 只存 1/world_size,前向与反向时按需 all-gather 参数,计算完再释放或转为分片,从而把显存从「每卡一份完整副本」降为「每卡 1/N」,可训更大模型或更大 batch。

二、FairScale 实现要点

FairScale 的 FSDP(后并入 PyTorch 的 torch.distributed.fsdp)核心实现:(1)分片策略:按 parameter 或 submodule 为单位分片,每 rank 只保留一部分;(2)前向:进入某层前 all-gather 该层参数,算完该层后可立刻释放(或保留到反向);(3)反向:同样 all-gather 该层参数算梯度,梯度按分片 reduce-scatter 回各 rank;(4)优化器:每 rank 只更新本 rank 持有的分片,优化器状态也分片。包装方式:用 FullyShardedDataParallel 包装子模块或整模型,内部 hook 在 forward 前后做 all-gather/释放;可与 auto_wrap_policy 配合,按 transformer block 等自动包装以平衡通信与显存。

三、与 DDP、ZeRO 的关系

DDP 每卡完整参数;FSDP 参数分片、按需 all-gather,显存更省、通信量在 all-gather。ZeRO-3 与 FSDP 思路一致,DeepSpeed 实现;PyTorch 官方 FSDP 吸收 FairScale 设计并持续优化。


面试要点

  • FSDP = 参数/梯度/优化器状态分片,前向反向按需 all-gather,算完释放;显存约 1/N。
  • FairScale 实现:按 parameter/submodule 分片、forward/backward 时 all-gather、梯度 reduce-scatter、优化器只更新本分片;auto_wrap_policy 按 block 包装。
  • 与 DDP(每卡完整)、ZeRO-3(同思路)对比;PyTorch 已收 FSDP。

记忆要点

  1. FSDP = 分片 + 按需 all-gather + 梯度 reduce-scatter;显存 1/N。
  2. 实现 = 分片单位、forward/backward 时 gather、释放;auto_wrap 按 block。
  3. FairScale 并入 PyTorch FSDP;与 ZeRO-3 思路一致。

返回模块 | 返回总览

12-训练框架/150-Hugging-Face的Accelerate如何简化分布式训练.md

第 150 题:Hugging Face的Accelerate如何简化分布式训练?

题目

Hugging Face的Accelerate如何简化分布式训练?


完整讲解

一、Accelerate 的定位

Hugging Face Accelerate 提供统一接口屏蔽分布式与设备差异:同一套训练脚本可在单卡、多卡、多机、CPU、混合精度、DeepSpeed/FSDP 等不同配置下运行,用户主要写「单卡逻辑」,通过配置或命令行指定并行方式与设备,Accelerate 负责初始化进程组、包装模型与优化器、调度 dataloader 与 gradient accumulation 等。

二、如何简化分布式训练

(1)统一入口accelerate launchAccelerator() 初始化,根据 config 或环境自动设 backend、rank、world_size。(2)模型与优化器accelerator.prepare(model, optimizer, dataloader) 自动做 DDP/FSDP/DeepSpeed 包装、混合精度、dataloader 分片。(3)训练循环accelerator.backward(loss)accelerator.gather() 等统一 API,无需手写 all-reduce 或判断 rank。(4)配置accelerate config 交互式生成配置文件,或 YAML 指定 device、mixed_precision、fsdp_config、deepspeed_config 等,换配置即换运行方式,脚本基本不动。这样研究者只需关心模型与 loss,分布式与设备细节由 Accelerate 抽象。

三、典型用法

单卡脚本加 Accelerator()prepare(),多卡时用 accelerate launch --num_processes N script.py;要切 FSDP 或 DeepSpeed 时改 config 或传对应 config 文件即可。


面试要点

  • Accelerate = 统一接口,同一脚本跑单卡/多卡/多机/混合精度/FSDP/DeepSpeed;用户写单卡逻辑。
  • 简化方式:accelerate launch + prepare(model, optimizer, dataloader);backward/gather 等统一 API;config 指定并行与设备。
  • 换配置即换运行方式,脚本基本不改;适合快速尝试多种并行。

记忆要点

  1. Accelerate = 统一入口 + prepare + 统一 API,屏蔽 backend 与设备。
  2. 简化 = launch + prepare + config;DDP/FSDP/DeepSpeed 通过 config 切换。
  3. 研究者写单卡逻辑即可,分布式由库负责。

返回模块 | 返回总览

12-训练框架/151-torch.distributed.fsdp的limit_all_gathe.md

第 151 题:torch.distributed.fsdplimit_all_gathers参数作用?

题目

torch.distributed.fsdplimit_all_gathers参数作用?


完整讲解

一、FSDP 中的 All-Gather

FSDP 在前向与反向时需要对当前层的参数做 all-gather,把各 rank 持有的分片拼成完整参数再计算。若多个层或多次 all-gather 同时进行,会并发占用大量显存(多份完整参数临时存在),容易 OOM;且 all-gather 是集体通信,过多并发也会增加调度与同步开销。

二、limit_all_gathers 的作用

limit_all_gathers(或等价选项):限制同一时刻处于「已 all-gather、未释放」状态的参数量,即对并发 all-gather 做限流。实现上通常通过调度:只有当前「未释放的 all-gathered 参数」占用的显存低于某阈值或数量时,才允许下一层执行 all-gather;否则等待前面某层释放后再进行。这样用少量额外同步换显存峰值下降,避免因多段同时全量参数而 OOM,特别在层数多、参数大的模型上有效。

三、使用建议

显存紧张或大模型时建议开启;会略微增加通信与调度序列化,但能显著提高可训模型规模或 batch 上限。具体参数名与默认值以当前 PyTorch FSDP 文档为准(如 limit_all_gathers=True 或带数值的配置)。


面试要点

  • FSDP 按层 all-gather 参数,多段同时 all-gather 会拉高显存峰值、易 OOM。
  • limit_all_gathers:限制同一时刻「已 gather 未释放」的 all-gather 数量/显存,用限流换峰值降低。
  • 显存紧张时建议开;会略增调度与序列化,但能训更大模型或更大 batch。

记忆要点

  1. 多段同时 all-gather → 显存峰值高、易 OOM。
  2. limit_all_gathers = 限流 all-gather,控制并发 gather 数量/显存。
  3. 开后可训更大模型或 batch;以 PyTorch 文档为准。

返回模块 | 返回总览

12-训练框架/152-大模型训练的checkpoint格式.md

第 152 题:大模型训练的checkpoint格式?sharded checkpoint的合并?

题目

大模型训练的checkpoint格式?sharded checkpoint的合并?


完整讲解

一、大模型 Checkpoint 格式

常见有 PyTorch 原生torch.save(state_dict).pt/.bin)、safetensors(见下题)、分片格式(如 model-00001-of-00005.safetensors)等。Sharded checkpoint:参数按 rank 或按层分片存成多文件,每文件只含一部分参数,便于多卡/多机保存时各写各的、且单机加载时可按需只加载部分;合并后可得完整 state_dict。

二、Sharded Checkpoint 的合并

合并目的:推理或单卡加载时需要完整参数,要把多份分片合并成一份。做法:(1)按约定顺序读入各分片文件(如按 rank 或按 shard 编号);(2)按 key 或元数据把同一参数名的分片拼成完整 tensor;(3)写出为单文件或统一 state_dict。工具上:Hugging Face 的 safe_convert、各框架的 checkpoint 工具(如 Megatron 的 merge 脚本)都支持;需注意分片时的切分方式(按层、按 rank、按参数量)与合并顺序一致,以及 dtype、device 等元信息一致。

三、注意点

合并后单文件可能很大,注意磁盘与内存;若仅做推理可考虑不合并、用分片加载(见存储与 IO 题)。版本与键名要兼容,避免漏键或重复。


面试要点

  • 大模型 checkpoint 有 .pt/.bin、safetensors、分片多文件;sharded 便于多卡各写各的、按需加载。
  • 合并:按分片顺序读入、按 key 拼成完整 tensor、写出单文件;工具如 HF 的 convert、各框架 merge 脚本。
  • 分片方式与合并顺序一致;合并后单文件大,可按需只合并或保留分片加载。

记忆要点

  1. Sharded = 多文件分片存;合并 = 按序读入、按 key 拼接、写出单文件。
  2. 工具:HF、Megatron 等有现成合并脚本;注意分片约定一致。
  3. 推理也可不合并,用分片加载。

返回模块 | 返回总览

12-训练框架/153-训练恢复的consistency问题.md

第 153 题:训练恢复的consistency问题?如何确保resume后的loss一致?

题目

训练恢复的consistency问题?如何确保resume后的loss一致?


完整讲解

一、Resume 的 Consistency 问题

训练恢复(resume)需恢复:模型参数、优化器状态、随机数状态、当前 step/epoch、以及可选的学习率调度、dataloader 位置等。若漏掉或错恢复某一项,恢复后的 loss 曲线与未中断时不一致:例如优化器动量未恢复会导致下一步更新方向不同;RNG 未恢复会导致 dropout/data shuffle 不同;step 未恢复会导致 lr schedule 错位;分布式时各 rank 的 dataloader 需从同一逻辑位置恢复,否则数据顺序错乱。

二、如何确保 Loss 一致

(1)Checkpoint 内容完整:至少包含 model state、optimizer state、step(或 epoch)、RNG states(torch、numpy、random);分布式时还有 rank0 的 step 与 dataloader 的 sampler 状态。(2)加载顺序与设备:按相同设备与 key 加载,避免 half/full 或 key 不匹配。(3)Dataloader:用 sampler.set_epoch(epoch) 或保存/恢复 sampler 状态,保证各 rank 恢复后读到同一顺序的数据。(4)验证:恢复后跑若干 step 与「未中断时同 step」的 loss 对比(或与上次 checkpoint 的 loss 衔接),不一致则排查漏项。

三、工程要点

Checkpoint 设计时就把 step、optimizer、RNG、dataloader 状态纳入;恢复脚本与保存脚本对称;大规模训练建议定期验证 resume 后的 loss 衔接。


面试要点

  • Consistency 指 resume 后 loss 与未中断时一致;漏恢复 optimizer、step、RNG、dataloader 任一都会导致不一致。
  • 做法:checkpoint 含 model、optimizer、step、RNG、dataloader/sampler 状态;加载顺序与设备一致;恢复后验证 loss 衔接。
  • 分布式时各 rank 的 step 与 sampler 状态一致;验证用若干 step 对比或看曲线衔接。

记忆要点

  1. 一致 = 恢复后 loss 曲线衔接;漏 optimizer/step/RNG/dataloader 会错。
  2. Checkpoint 要全:model、optimizer、step、RNG、sampler;加载对称。
  3. 恢复后做验证;分布式注意各 rank 的 step 与 sampler。

返回模块 | 返回总览

12-训练框架/154-大模型训练的data-pipeline优化.md

第 154 题:大模型训练的data pipeline优化?WebDatasettfrecord

题目

大模型训练的data pipeline优化?WebDatasettfrecord


完整讲解

一、Data Pipeline 瓶颈

大模型训练数据量大、预处理复杂(tokenize、pack、augment),若 DataLoader 跟不上,GPU 会空转、吞吐下降。瓶颈常在:磁盘 IO、CPU 预处理、Python GIL、数据从 CPU 到 GPU 的拷贝与排队。优化目标:让数据预取充足与计算重叠减少主线程阻塞

二、WebDataset、tfrecord 等格式

WebDataset:基于 tar 的流式格式,按 shard 存储样本,训练时流式读、按需解压与解码,无需先全部解压到磁盘,适合超大规模数据集与对象存储。tfrecord:TensorFlow 的二进制序列格式,支持压缩、可随机访问或顺序读,多用于 CV/NLP 的预处理好结果缓存。Parquet/Arrow:列存、便于按列过滤与并行读,适合表格型或需过滤的 metadata。共同点:二进制、可压缩、利于顺序或并行 IO,减少小文件与解析开销。

三、Pipeline 优化手段

多 worker DataLoader、pin_memoryprefetch_factor;数据存 SSD 或高带宽存储、用多进程读;预处理放 DataLoader worker 或独立进程、与 GPU 计算重叠;大语料用 WebDataset 流式 + 多 shard 并行;tfrecord/parquet 做预处理好缓存,训练时只做轻量解码。


面试要点

  • 瓶颈:磁盘 IO、CPU 预处理、GIL、CPU→GPU 拷贝;目标预取充足、与计算重叠。
  • WebDataset = tar 流式、按 shard、无需全量解压;tfrecord = 二进制缓存、可压缩;Parquet/Arrow = 列存、过滤友好。
  • 优化:多 worker、pin_memory、prefetch;高带宽存储;预处理与计算重叠;流式+多 shard。

记忆要点

  1. 瓶颈 = IO + 预处理 + 拷贝;目标 = 预取 + 重叠。
  2. WebDataset 流式;tfrecord 缓存;Parquet 列存;均利于大规模与并行。
  3. 多 worker、pin_memory、prefetch、高带宽存储、预处理重叠。

返回模块 | 返回总览

12-训练框架/155-多模态大模型的训练基础设施挑战.md

第 155 题:多模态大模型的训练基础设施挑战?图文数据的加载?

题目

多模态大模型的训练基础设施挑战?图文数据的加载?


完整讲解

一、多模态训练的基础设施挑战

数据异构:图像、视频、文本、音频等格式与大小差异大,存储、索引与采样策略需统一抽象。加载与解码:图像/视频解码耗 CPU、耗内存,高分辨率时更明显;需与 GPU 计算流水线重叠、避免成为瓶颈。对齐与打包:图文对、视频-文本等需按 pair 或 sequence 打包,tokenization 与 padding 策略复杂(如图像 patch、变长序列)。规模:数据量常更大、单样本更大,对 IO 带宽、缓存与 sharding 要求高。

二、图文数据加载要点

存储:常用对象存储 + 索引(JSON/Parquet 等)存 path 与 caption;或 WebDataset 式 tar 内嵌图像与文本。解码:图像用 PIL/decord 等多进程解码,或预解码成 tensor 存 tfrecord/WebDataset 减少训练时 CPU;视频按帧或 clip 采样、控制分辨率与帧数。Batch:同 batch 内图像尺寸不一需 padding 或 resize,或按 bucket 分组;文本侧 tokenize 后与图像 tensor 一起组成 batch,注意 max_len 与 padding。流水线:多 worker、预取、可选 DALI 等 GPU 解码,与 backbone 计算重叠。

三、与单模态的差异

多模态需统一 dataloader 返回 (image, text, ...);存储与 metadata 设计要支持多类型与过滤;解码与打包逻辑更重,常单独模块化;监控上区分图像/视频/文本的 IO 与解码耗时。


面试要点

  • 挑战:数据异构、解码重、对齐与打包复杂、规模大;需统一抽象与高带宽。
  • 图文加载:存储用对象存储+索引或 WebDataset;解码多进程或预解码;batch 需 padding/bucket;流水线多 worker、预取、可选 GPU 解码。
  • 与单模态比:统一 dataloader、多类型 metadata、解码与打包模块化、监控分类型耗时。

记忆要点

  1. 多模态 = 异构数据 + 重解码 + 对齐打包 + 大规模 IO。
  2. 图文 = 存储+索引、多进程/预解码、padding/bucket、多 worker 预取。
  3. 统一 dataloader、metadata、解码模块化;监控分类型。

返回模块 | 返回总览

12-训练框架/156-RLHF训练的infra设计.md

第 156 题:RLHF训练的infra设计?PPO的分布式实现?

题目

RLHF训练的infra设计?PPO的分布式实现?


完整讲解

一、RLHF 与 PPO 的 Infra 需求

RLHF(人类反馈强化学习)通常包含:监督微调 SFT奖励模型 RM 训练PPO 等策略优化。其中 PPO 阶段:要跑策略模型(actor)、价值模型(critic)、参考模型(reference)、以及奖励模型 的多次前向,且需要大批量 rollout(多 env、多 step)收集轨迹,再多轮更新,对显存、通信与数据流要求高。

二、PPO 分布式实现要点

数据并行:rollout 与 batch 可按数据并行划分,多卡/多机各自生成轨迹、再汇总或分片做 PPO 更新。模型并行:若单卡放不下 actor+critic+ref+RM,可对部分模型做 TP/PP 或 offload。Rollout 并行:多个 worker 独立做 rollout(每 worker 若干 env),收集 (state, action, reward, ...) 后汇总成大 batch 做 PPO 更新;或异步地一边 rollout 一边更新。通信:需同步或汇总 trajectory、梯度;大 batch 时 all-gather/reduce 要优化。Checkpoint:需保存 actor、critic、optimizer、以及可选 ref 与 RM,便于 resume 与部署。

三、工程要点

框架上 TRL、DeepSpeed-Chat、Colossal-AI 等有 RLHF/PPO 实现;关键是把「rollout 生成」与「PPO 更新」的流水线设计好、显存与通信可控;多节点时注意 rollout 数据与模型分片的协同。


面试要点

  • RLHF infra:SFT、RM、PPO 三阶段;PPO 需 actor、critic、ref、RM 多模型前向 + 大批量 rollout。
  • PPO 分布式:rollout 并行(多 worker 多 env)、数据并行或模型并行按需;通信汇总 trajectory 与梯度;checkpoint 含多模型与 optimizer。
  • 框架:TRL、DeepSpeed-Chat 等;重点 rollout 与更新流水线、显存与通信。

记忆要点

  1. RLHF = SFT + RM + PPO;PPO = actor+critic+ref+RM + rollout。
  2. 分布式 = rollout 并行 + 数据/模型并行 + 通信汇总;checkpoint 多模型。
  3. 流水线设计、显存与通信优化;可用 TRL、DeepSpeed-Chat 等。

返回模块 | 返回总览

12-训练框架/157-MoE模型的all-to-all通信优化.md

第 157 题:MoE模型的all-to-all通信优化?TutelFasterMoE

题目

MoE模型的all-to-all通信优化?TutelFasterMoE


完整讲解

一、MoE 与 All-to-All

MoE(Mixture of Experts):每层有多个「专家」子网络,按路由只激活部分专家,计算与通信模式与稠密层不同。前向时需根据 token 的 routing 把各 token 发到对应 expert,算完再按 token 顺序收回来,即 all-to-all:每个 rank 持有部分 token,要把自己的 token 按目标 expert 发到对应 rank,并接收其它 rank 发来的、目标为自己所持 expert 的 token。All-to-all 是 MoE 的通信瓶颈,量级与 expert 数、token 数相关。

二、Tutel、FasterMoE 等优化

Tutel(微软):针对 MoE 的 kernel 与通信优化,包括高效 all-to-all、expert 内并行、以及与 CUDA 的融合。FasterMoE:类似地优化 MoE 的 dispatch 与 all-to-all,减少通信次数与显存拷贝。思路共性:通信与计算重叠合并小消息按 expert 或 token 的智能分片以降低 all-to-all 的 volume 与次数、以及 kernel fusion(dispatch + 计算 + combine)减少往返。与 NCCL 的 all-to-all 原语配合,或自定义 collective 以更好匹配 MoE 的拓扑。

三、面试可说的点

MoE 的 all-to-all 是 token↔expert 的分布与汇总;Tutel/FasterMoE 做通信优化、kernel 融合与分片策略;目标降低延迟与带宽占用。


面试要点

  • MoE 前向需按 routing 把 token 发到各 expert、再按序收回,通信模式为 all-to-all,是瓶颈。
  • Tutel/FasterMoE:优化 all-to-all(重叠、合并、分片)、expert 内并行、dispatch+计算+combine 的 kernel 融合。
  • 目标:减少通信次数与 volume、降低延迟与带宽。

记忆要点

  1. MoE 通信 = token↔expert 的 all-to-all;是 MoE 训练/推理的主要瓶颈。
  2. Tutel/FasterMoE = all-to-all 优化 + kernel 融合 + 分片策略。
  3. 重叠、合并小消息、智能分片、融合 kernel。

返回模块 | 返回总览

12-训练框架/158-长上下文训练(100K+-tokens)的显存优化.md

第 158 题:长上下文训练(100K+ tokens)的显存优化?Ring Attention

题目

长上下文训练(100K+ tokens)的显存优化?Ring Attention


完整讲解

一、长上下文显存瓶颈

序列长度 L 时,注意力与 KV cache 的显存约为 O(L²)O(L)(依实现);100K+ token 时单机单卡难以放下完整 attention 与 KV。优化方向:稀疏/近似 attention(只算部分位置)、分块与通信(把序列切块分布到多卡,通过通信拼出 attention)、重计算(用激活重计算换显存)、外存换入换出(KV 或中间结果放 CPU/NVMe)。

二、Ring Attention 思路

Ring Attention:把序列在长度维切块,每块分布到不同 rank,形成「环」;计算 attention 时,每 rank 持有当前块与部分其它块(通过沿环传递逐步拿到全部块),在本地做局部 attention 或与传递来的 key/value 做计算,再传递下一段。这样每 rank 只需 O(L/P) 的显存(P 为 rank 数),总显存与通信在长序列下可控;通信是沿环的流水线式,可与计算重叠。变体有 Ring Attention、Blockwise Transformer 等,核心都是「序列分块 + 通信拼全」以突破单卡显存。

三、其它手段

FlashAttention 等省显存 attention kernel;线性 attention 或 state space 把复杂度降到 O(L);结合 offload 把部分 KV 放 CPU。面试可强调:长上下文 = 显存 O(L) 或 O(L²);Ring Attention = 序列分块 + 环上传递,显存与通信可扩展。


面试要点

  • 长上下文显存 O(L) 或 O(L²);100K+ 需稀疏/分块/重计算/offload 等手段。
  • Ring Attention:序列按长度切块分布到多 rank,沿环传递块以拼全 attention,每 rank 显存 O(L/P);通信可与计算重叠。
  • 配合 FlashAttention、线性 attention、offload 等进一步省显存。

记忆要点

  1. 长上下文瓶颈 = 显存与 attention 规模;Ring Attention = 序列分块 + 环上传递。
  2. 每 rank 显存 O(L/P);通信流水线、可重叠。
  3. 可与 FlashAttention、线性 attention、offload 组合。

返回模块 | 返回总览

12-训练框架/159-训练任务的fault-tolerance.md

第 159 题:训练任务的fault toleranceelastic training的实现?

题目

训练任务的fault toleranceelastic training的实现?


完整讲解

一、Fault Tolerance 需求

长时训练(数天到数周)中节点、网络、磁盘可能故障;容错目标:故障发生后从最近一致状态恢复不重头开训,且恢复后与未中断时行为一致(见 checkpoint consistency 题)。手段核心:定期 checkpoint + 可恢复的 dataloader 与 RNG + 弹性或固定拓扑的进程组

二、Elastic Training 实现

Elastic training:允许训练过程中 worker 数变化(节点加入或退出),通过协调器(如 PyTorch Elastic、TorchX)管理 rank 与 world_size 的变更、重新分配数据分片、并从一致 checkpoint 恢复。实现要点:(1)协调器:监控进程存活、发现新节点或失效节点,触发 resize;(2)Checkpoint:在已知一致点(如 step 边界)保存,恢复时所有存活 rank 加载同一 checkpoint 并同步 step;(3)Rendezvous:重新做一次进程组组建,新 world_size 与 rank 分配;(4)Data:sampler 按新 world_size 重新分片,保证不重不漏。固定规模时也可不用弹性,仅用「故障时从 checkpoint 重启」的容错。

三、与普通容错的区别

普通容错 = 固定规模 + 故障则全组重启 + 从 checkpoint 恢复。Elastic = 支持规模变化、动态 rendezvous、数据与状态按新规模重分配;实现更复杂,适合云上节点可能缩容/扩容的场景。


面试要点

  • 容错 = 故障后从一致 checkpoint 恢复、不重头训、行为一致;依赖定期 checkpoint + 可恢复的 dataloader/RNG。
  • Elastic = 支持 worker 数变化;协调器监控、resize 时 rendezvous、checkpoint 恢复、数据按新规模重分片。
  • 固定规模可仅「故障全组重启+checkpoint」;弹性适合云上扩缩容。

记忆要点

  1. 容错 = checkpoint + 可恢复 dataloader/RNG + 一致恢复。
  2. Elastic = 动态 worker 数 + rendezvous + checkpoint + 数据重分片。
  3. 协调器、一致 checkpoint、新 world_size 下的 sampler 是关键。

返回模块 | 返回总览

12-训练框架/160-大模型训练的experiment-tracking.md

第 160 题:大模型训练的experiment trackingWeights & BiasesMLflow

题目

大模型训练的experiment trackingWeights & BiasesMLflow


完整讲解

一、Experiment Tracking 做什么

大模型训练实验多、超参与配置复杂,实验追踪记录:每个 run 的 config(模型、lr、batch、并行度等)、metrics(loss、accuracy、 throughput 等随时间或 step)、artifacts(checkpoint、日志、生成样例)、代码与环境(git commit、依赖版本),便于对比、复现与选型。

二、Weights & Biases(W&B)

W&B:云端实验管理,与 PyTorch/TF 等集成简单,wandb.init()wandb.log(metrics)wandb.save() 即可上报 config、曲线与文件。支持多 run 对比、表格与可视化、报告与协作;可自建 server 或用其云。适合大规模实验、团队协作与可视化;注意数据与 checkpoint 上传带宽与存储成本。

三、MLflow

MLflow:开源实验与模型管理,含 Tracking(metrics、params、artifacts)、Projects(可复现运行)、Models(模型注册与部署)。可本地或自建 server,与主流框架集成;适合自托管、合规要求高的场景。与 W&B 相比更偏自建与模型全生命周期;W&B 在可视化与协作上更丰富。


面试要点

  • 实验追踪 = config + metrics + artifacts + 代码/环境;便于对比、复现与选型。
  • W&B:云端、集成简单、可视化与协作强;wandb.init/log/save;注意带宽与存储。
  • MLflow:开源、Tracking+Projects+Models;可自建、偏模型全生命周期;W&B 偏实验与协作。

记忆要点

  1. 追踪 = config + metrics + artifacts + 可复现;大模型实验必备。
  2. W&B = 云端、易集成、可视化好;MLflow = 开源、自建、模型全周期。
  3. 选型:要协作与云端用 W&B;要自建与模型注册用 MLflow。

返回模块 | 返回总览

13-存储与IO/README.md

13-存储与IO(第 161–170 题)

题号 主题 文章
161 大模型checkpoint的存储格式?safetensors vs … 161-大模型checkpoint的存储格式.md
162 分布式文件系统的选择?LustreGPFSAlluxio 162-分布式文件系统的选择.md
163 训练数据的caching策略?SSD作为`burst buffe… 163-训练数据的caching策略.md
164 大模型权重的高效加载?memory mapping、`lazy lo… 164-大模型权重的高效加载.md
165 多节点间的checkpoint同步?`asynchronous chec… 165-多节点间的checkpoint同步.md
166 数据加载的bottleneck诊断?`nvidia-smi dmon… 166-数据加载的bottleneck诊断.md
167 DALI(NVIDIA Data Loading Library)的… 167-DALI(NVIDIA-Data-Loading-Library)的使用场景.md
168 训练数据的sharding策略?按文件vs按样本? 168-训练数据的sharding策略.md
169 云存储(S3、OSS)与本地存储的性能差异?s3fs 169-云存储(S3、OSS)与本地存储的性能差异.md
170 大规模数据集的metadata管理?parquet、`arrow… 170-大规模数据集的metadata管理.md

返回总览

13-存储与IO/161-大模型checkpoint的存储格式.md

第 161 题:大模型checkpoint的存储格式?safetensors vs pytorch.bin

题目

大模型checkpoint的存储格式?safetensors vs pytorch.bin


完整讲解

一、常见 Checkpoint 存储格式

PyTorch 原生.pt/.pth/.bin):torch.save(state_dict, path),内部为 pickle + 张量二进制,不安全——反序列化可执行任意代码,且无校验,易损坏。safetensors:Hugging Face 推动的格式,仅存张量(无代码)、内存映射友好、带简单校验,安全且多语言可读;文件为头信息(shape、dtype、offset)+ 裸张量数据,便于 mmap 与按 key 懒加载。

二、safetensors vs pytorch.bin

安全:safetensors 不执行代码,适合不可信来源;.bin 反序列化有风险。加载方式:safetensors 支持 mmap,大文件可映射不一次性读入内存;.bin 通常整文件读入再反序列化。跨语言:safetensors 有 Rust/Python 等实现,易被其它栈读取;.bin 强依赖 PyTorch。体积与速度:二者张量存储类似;safetensors 头信息紧凑,多 key 时按 key 加载更省内存。生产与开源分发更推荐 safetensors;需兼容旧脚本或仅 PyTorch 时可保留 .bin。

三、使用建议

新项目与模型分发用 safetensors;加载大模型时用 safetensors.torch.load_file(..., device_map="cpu") 等做懒加载或 mmap,控制内存峰值。


面试要点

  • .bin/.pt:torch.save、pickle+张量,反序列化不安全、无校验;safetensors:仅张量、安全、可 mmap、多语言。
  • safetensors 适合不可信来源、大文件 mmap、按 key 加载;.bin 兼容旧脚本。
  • 新项目与分发推荐 safetensors;大模型加载用 mmap/懒加载控内存。

记忆要点

  1. .bin = pickle 不安全;safetensors = 安全、mmap、多语言。
  2. 大模型加载:safetensors 可 mmap/按 key;.bin 常整文件读入。
  3. 推荐 safetensors;兼容时保留 .bin。

返回模块 | 返回总览

13-存储与IO/162-分布式文件系统的选择.md

第 162 题:分布式文件系统的选择?LustreGPFSAlluxio

题目

分布式文件系统的选择?LustreGPFSAlluxio


完整讲解

一、Lustre、GPFS、Alluxio 定位

Lustre:开源并行分布式文件系统,面向 HPC,高聚合带宽、大文件顺序 IO 优,适合超算与大规模训练集群的共享 home/数据集;部署与运维复杂,小规模不划算。GPFS(现 Spectrum Scale):商业并行文件系统,高可靠、高带宽,多用于企业 HPC 与存储;成本高。Alluxio内存/SSD 层缓存,架在现有存储(HDFS、S3、本地盘)之上,对应用呈现为统一命名空间,热数据缓在 Alluxio 层以加速读;适合「冷数据在对象存储、热数据加速」的训练与迭代。

二、选择考量

大规模、高带宽、共享数据集:Lustre 或 GPFS 做共享存储,训练多节点直接挂载读数据。云上或混合:对象存储(S3/OSS)为主,用 Alluxio 或 s3fs + 本地缓存做加速层,减少重复拉取与延迟。成本与运维:Lustre/GPFS 需专业运维;Alluxio 相对轻量、可与 K8s 集成。小规模单机:本地 SSD/NVMe 或 NFS 即可。选型看规模、带宽需求、是否已有 HPC 存储、是否云上对象存储为主。

三、面试可说的点

Lustre/GPFS = 并行共享文件系统、高带宽、适合大规模训练共享;Alluxio = 缓存层、加速对象存储与混合存储;云上常用对象存储 + Alluxio 或本地缓存。


面试要点

  • Lustre/GPFS:并行分布式文件系统,高带宽、共享存储,适合 HPC 与大规模训练;部署复杂。
  • Alluxio:缓存层,架在 HDFS/S3 等之上,热数据加速;适合云上或混合、训练数据加速。
  • 选型:大规模共享用 Lustre/GPFS;云上/混合用对象存储+Alluxio 或本地缓存;小规模用本地/NFS。

记忆要点

  1. Lustre/GPFS = 并行共享、高带宽;Alluxio = 缓存层、加速冷存储。
  2. 大规模训练共享选 Lustre/GPFS;云上选 S3+Alluxio 或缓存。
  3. 成本与运维:Lustre 复杂;Alluxio 相对轻量。

返回模块 | 返回总览

13-存储与IO/163-训练数据的caching策略.md

第 163 题:训练数据的caching策略?SSD作为burst buffer

题目

训练数据的caching策略?SSD作为burst buffer


完整讲解

一、训练数据 Caching 目的

数据反复读自远程或慢盘会成为瓶颈;Caching 把热数据放在更快介质(内存、本地 SSD),减少重复 IO 与延迟。策略:全量缓存(数据集可放入内存或本地 SSD 时)、LRU 等淘汰(部分缓存、按访问热度)、预取(训练前或后台把即将用到的 shard 拉到本地)。

二、SSD 作为 Burst Buffer

Burst buffer:在计算节点与慢存储(如 Lustre、对象存储)之间加一层高速缓冲(常为 SSD/NVMe),写时先落缓冲、后台异步刷回慢存储,读时优先从缓冲取。这样训练过程主要与 SSD 交互,削峰填谷、减轻对共享存储的瞬时压力,并降低读延迟。多节点训练时可在每节点配本地 SSD 做节点级 cache,或共享的 SSD 池做 burst buffer;数据生命周期管理(预热、淘汰、持久化)需与作业与存储策略配合。

三、工程要点

缓存一致性:多进程/多节点时注意 invalidation;预取与 DataLoader 的 worker 数、shard 划分配合;监控 cache hit 与 IO 延迟,评估是否仍为瓶颈。


面试要点

  • Caching 目的:热数据放快介质,减重复 IO;策略有全量、LRU、预取。
  • SSD burst buffer:计算与慢存储间的 SSD 缓冲层,写先落缓冲再刷回、读优先走缓冲;削峰、降延迟。
  • 多节点可节点级 SSD 或共享 SSD 池;注意一致性、预取与监控。

记忆要点

  1. Caching = 热数据放内存/SSD;全量/LRU/预取。
  2. Burst buffer = SSD 缓冲层,写先缓冲、读优先缓冲;削峰降延迟。
  3. 多节点节点级或共享池;一致性、预取、监控。

返回模块 | 返回总览

13-存储与IO/164-大模型权重的高效加载.md

第 164 题:大模型权重的高效加载?memory mappinglazy loading

题目

大模型权重的高效加载?memory mappinglazy loading


完整讲解

一、大模型权重加载的难点

参数量大(数十 GB 到数百 GB),若一次性读入内存再搬到 GPU,会占满内存或显存、启动慢且可能 OOM。需要按需、分块、低峰值的加载方式。

二、Memory Mapping(mmap)

mmap:把 checkpoint 文件映射到进程地址空间,不立刻读入物理内存;访问某段时由 OS 按需调页。这样多进程或多次访问同一文件可共享物理页,且峰值内存接近「当前用到的部分」而非整个文件。safetensors 与部分格式支持按 key 的 offset 做 mmap,加载时只映射、实际张量在首次访问或拷贝到 GPU 时才读入,适合单机多卡或推理时按层加载。

三、Lazy Loading

Lazy loading:不一次性加载全部参数,而是按层或按模块在首次前向用到时再加载并可选地释放已用层(如流水线推理)。实现上:state_dict 按 key 或按层组织;加载器只建「占位」或只读 meta,实际 tensor 在 forward 到该层时从磁盘读入并填到设备。可结合 mmap:文件 mmap,按需读对应 offset 到 GPU。这样显存峰值约为「单层或若干层」而非全模型,适合超大模型推理与多卡分片加载。


面试要点

  • 难点:权重大、一次性加载易 OOM、启动慢;需按需、分块、低峰值。
  • mmap:文件映射到地址空间、按需调页;峰值低、可共享页;safetensors 等支持按 key mmap。
  • Lazy loading:按层或按用到的 key 在首次使用时加载;可结合 mmap;显存峰值约为部分层。

记忆要点

  1. 大模型加载 = 避免整文件进内存;mmap = 按需调页、峰值低。
  2. Lazy loading = 按层/按 key 用时再加载;可释放已用层;适合推理与分片。
  3. safetensors + mmap + 按 key 加载是常见组合。

返回模块 | 返回总览

13-存储与IO/165-多节点间的checkpoint同步.md

第 165 题:多节点间的checkpoint同步?asynchronous checkpoint

题目

多节点间的checkpoint同步?asynchronous checkpoint


完整讲解

一、多节点 Checkpoint 的挑战

分布式训练时参数与优化器状态分片在各 rank,保存需把各分片写出(每 rank 写自己的或汇总到少数 rank);加载时需按相同分片方式读回并恢复通信组。若同步写:所有 rank 写完才继续,慢的 rank 拖累整体;若异步写:各 rank 独立写本地或共享存储,不互相等待,但需保证「恢复时能凑齐所有分片」且一致性(同一 step、同一全局状态)。

二、Asynchronous Checkpoint

异步 checkpoint:各 rank 独立、并行地把自己的分片写入存储(本地盘或共享存储),不阻塞其它 rank,也不做跨 rank 的「等大家都写完」。优点:写入阶段不因最慢 rank 而拉长,训练停顿时间短。要点:(1)命名与布局:约定分片文件名与目录(如 rank_0/, rank_1/),恢复时按 rank 读自己的分片;(2)元数据:在某一处(如 rank 0)写一份全局元数据(step、world_size、各分片 path),恢复时先读元数据再各 rank 读自己的分片;(3)一致性:异步下要保证「这次 checkpoint 对应同一 step」,通常在约定 step 同步一次后再各自写,避免写一半有 rank 已进入下一步。

三、与同步的取舍

同步 checkpoint 实现简单、语义清晰;异步牺牲一点实现复杂度换更短的 checkpoint 停顿,适合大规模、checkpoint 频繁的场景。恢复时仍需所有分片可用;存储可用性与故障处理需单独考虑。


面试要点

  • 多节点 checkpoint:分片各 rank 写;同步写则最慢 rank 拖累;异步写则各 rank 独立写、不互相等。
  • 异步 checkpoint:各 rank 并行写自己的分片、约定命名与元数据;恢复时按元数据与 rank 读回;缩短停顿时间。
  • 一致性:约定 step 后同步一次再各自写;恢复需所有分片与元数据可用。

记忆要点

  1. 同步 = 等所有 rank 写完;异步 = 各写各的、不互相等,缩短停顿。
  2. 异步要点:分片命名、元数据(step、path)、恢复时按 rank 读。
  3. 约定 step 再写,保证同一 step 的全局一致。

返回模块 | 返回总览

13-存储与IO/166-数据加载的bottleneck诊断.md

第 166 题:数据加载的bottleneck诊断?nvidia-smi dmon

题目

数据加载的bottleneck诊断?nvidia-smi dmon


完整讲解

一、数据加载 Bottleneck 表现

GPU 利用率低吞吐上不去而 CPU 或 IO 占用高,多半是数据侧瓶颈:DataLoader 供不上 batch,GPU 在等数据。可能原因:磁盘 IO 慢、预处理(decode、tokenize)重、DataLoader worker 少、GIL、网络存储延迟等。

二、诊断思路

(1)时间线:用 PyTorch Profiler 或 Nsight Systems 看 CPU 与 GPU 时间线:若 GPU 有大量「等待」或空档、而 CPU 在忙解码/读盘,则瓶颈在数据。(2)Worker 与 prefetch:看 DataLoader 的 num_workers、prefetch_factor;过小则预取不足。(3)磁盘与 IO:iostat、存储带宽;若从网络盘读,看延迟与带宽。(4)nvidia-smi dmondmon 是 nvidia-smi 的持续监控模式,可看 GPU 利用率、显存、功耗等随时间变化;若 GPU 利用率周期性掉下去、与 batch 边界对齐,常说明 GPU 在等数据;配合 CPU 侧 profiling 可确认是「等数据」而非「等通信」。

三、nvidia-smi dmon 用法

nvidia-smi dmon -s u -c 10:每 1 秒采样一次、共 10 次,-s u 表示 utilization;可看 gpu 列与 sm 列(计算利用率)。若 sm 经常为 0 或很低而训练在跑,多半是 CPU/IO 瓶颈。


面试要点

  • 瓶颈表现:GPU 利用率低、吞吐上不去;原因常为 IO、预处理、worker 不足。
  • 诊断:Profiler 看 CPU/GPU 时间线;DataLoader worker/prefetch;iostat/存储;nvidia-smi dmon 看 GPU 利用率随时间。
  • dmon:持续看利用率;周期性掉到 0 且与 batch 对齐 → 等数据;配合 CPU 侧确认。

记忆要点

  1. 数据瓶颈 = GPU 等数据;表现利用率低、CPU/IO 忙。
  2. 诊断 = 时间线 + worker/prefetch + IO + nvidia-smi dmon。
  3. dmon 看利用率曲线;周期掉 0 → 常为等数据。

返回模块 | 返回总览

13-存储与IO/167-DALI(NVIDIA-Data-Loading-Library)的使用场景.md

第 167 题:DALI(NVIDIA Data Loading Library)的使用场景?

题目

DALI(NVIDIA Data Loading Library)的使用场景?


完整讲解

一、DALI 是什么

NVIDIA DALI(Data Loading Library):在 GPU 上做数据解码与预处理(解码、resize、crop、normalize 等),数据从存储或 CPU 进入后由 DALI pipeline 在 GPU 上完成解码与 augments,输出 GPU tensor 直接供训练,减少 CPU-GPU 拷贝与 CPU 瓶颈,并可与训练计算流水线重叠

二、使用场景

图像/视频训练:解码(JPEG、视频帧)、resize、crop、flip、normalize 等放在 GPU,CPU 只做 IO 或轻量调度;适合 CV 与多模态里解码重的场景。高吞吐需求:当 DataLoader 的 CPU 解码成为瓶颈、GPU 利用率上不去时,用 DALI 把解码迁到 GPU 或专用线程,提高吞吐。多模态与复杂 augment:DALI 支持多种 op 与组合,可在同一 pipeline 里做图像+文本的预处理。不适合:纯文本、或数据已预处理好只需简单 tensor 化时,DALI 收益有限且增加依赖;小数据集或 IO 非瓶颈时不必上 DALI。

三、工程要点

DALI 与 PyTorch/TF 通过 iterator 或 DataLoader 适配器对接;需保证 GPU 显存能同时容纳 DALI buffer 与模型;调试时先确认 CPU 解码确实是瓶颈再引入 DALI。


面试要点

  • DALI = GPU 上解码与预处理,减少 CPU 瓶颈与 CPU-GPU 拷贝,可与训练计算重叠。
  • 场景:图像/视频解码重、高吞吐 CV、多模态预处理;纯文本或已预处理好则收益小。
  • 与框架通过 iterator/DataLoader 对接;注意显存;先确认瓶颈再引入。

记忆要点

  1. DALI = GPU 解码与预处理;减 CPU 瓶颈、增吞吐。
  2. 适合解码重的 CV/多模态;不适合纯文本或非瓶颈。
  3. 对接 PyTorch/TF;显存与瓶颈确认。

返回模块 | 返回总览

13-存储与IO/168-训练数据的sharding策略.md

第 168 题:训练数据的sharding策略?按文件vs按样本?

题目

训练数据的sharding策略?按文件vs按样本?


完整讲解

一、Sharding 的目的

分布式训练时每个 rank 只应消费数据的一个子集,避免重复与遗漏;Sharding 即把数据集划分成多份,每 rank 一份(或按 rank 取子集)。划分策略影响负载均衡IO 分布可恢复性

二、按文件 vs 按样本

按文件 sharding:每个 rank 分配不同文件集合(如 rank 0 读 file_0, file_4, ...,rank 1 读 file_1, file_5, ...)。优点:实现简单、每个 rank 读不同文件、IO 易并行;缺点:若文件大小或样本数差异大,各 rank 负载不均,有的先跑完要等别的 rank。按样本 sharding:把全体样本视为序列,按 rank 数切分(rank i 取 sample_id % world_size == i)。优点:负载更均衡(每 rank 样本数相同);缺点:若数据按文件存储,可能多个 rank 读同一文件的不同偏移,需要支持按 offset 读或先做「按样本索引」的元数据(如样本→文件+offset),实现稍复杂。大模型训练常用按样本或「按文件但做大小感知的分配」以均衡;小文件多时也可按文件并做动态负载均衡。

三、实现要点

PyTorch 的 DistributedSampler 默认按样本(每个 rank 取 dataset 的 1/N);若数据按大文件存,可建索引(样本→文件+offset)再按样本 shard。恢复训练时 sampler 的 epoch/seed 要与 checkpoint 一致,保证恢复后各 rank 读到的顺序与未中断时一致。


面试要点

  • Sharding = 每 rank 消费数据子集;按文件简单但易负载不均;按样本均衡但需索引或按 offset 读。
  • 按文件:rank 读不同文件集;按样本:rank 取 sample_id % world_size,负载匀。
  • 大模型常用按样本或大小感知的文件分配;恢复时 sampler 状态一致。

记忆要点

  1. 按文件 = 简单、IO 并行,易负载不均;按样本 = 均衡,需索引或 offset。
  2. DistributedSampler 默认按样本;大文件可建样本→(文件,offset) 索引。
  3. 恢复时 sampler/epoch 与 checkpoint 一致。

返回模块 | 返回总览

13-存储与IO/169-云存储(S3、OSS)与本地存储的性能差异.md

第 169 题:云存储(S3、OSS)与本地存储的性能差异?s3fs

题目

云存储(S3、OSS)与本地存储的性能差异?s3fs


完整讲解

一、云存储与本地存储的差异

本地存储(NVMe/SSD 直连):低延迟、高带宽、无网络抖动,适合热数据与高 IOPS;容量与扩展受单机限制。云存储(S3、OSS、Azure Blob):容量弹性、持久性与可用性高,但延迟与带宽受网络限制:首字节延迟通常毫秒级、带宽受实例与 bucket 限制,大量小文件或随机读时性能明显差于本地盘。

二、性能差异与 s3fs

差异:云存储适合顺序大块读、批量 list;高 QPS 小文件、随机读、或训练时「每个 step 读不同小 chunk」会拉高延迟与成本。s3fs(或 s3fs-fuse):把 S3 bucket 挂载为文件系统,应用按普通文件路径访问;底层仍是 HTTP 请求,延迟与带宽特性不变,且 FUSE 有额外开销,不适合高吞吐训练数据直接读;适合偶尔访问、脚本与工具兼容。更好做法:训练数据预拉到本地盘或 SSD(拉一次、多 epoch 复用),或使用云上的「本地盘 + 生命周期」;或用 Alluxio 等缓存层在计算节点缓存 S3 数据。

三、选型建议

热数据、高吞吐训练用本地/NVMe 或缓存层;冷数据与归档用 S3/OSS;s3fs 适合兼容性与轻量访问,不作为训练主存储路径。


面试要点

  • 本地:低延迟高带宽;云存储:弹性与持久,但延迟与带宽受网络限制,小文件/随机读性能差。
  • s3fs:S3 挂成文件系统,兼容性好但性能与 FUSE 开销限制,不适合高吞吐训练直读。
  • 训练数据建议预拉到本地或缓存层;冷数据存 S3;s3fs 做兼容与轻量访问。

记忆要点

  1. 云存储 = 高延迟、带宽受限;本地 = 低延迟高带宽。
  2. s3fs = 挂载 S3 为文件系统;不适合训练主路径,适合兼容与轻量。
  3. 训练用本地/缓存;冷数据 S3;预拉或 Alluxio 等缓存。

返回模块 | 返回总览

13-存储与IO/170-大规模数据集的metadata管理.md

第 170 题:大规模数据集的metadata管理?parquetarrow

题目

大规模数据集的metadata管理?parquetarrow


完整讲解

一、大规模数据集 Metadata 需求

海量样本(图像、文本、多模态)需要索引、过滤、分片与采样,不能只靠「列目录」;Metadata 存样本路径、标签、长度、分组等,便于按条件过滤、按 rank shard、做 bucket 与负采样等。格式要可扩展、可并行读、支持列式过滤

二、Parquet、Arrow 的作用

Parquet:列存格式,schema 清晰、支持按列读取与谓词下推(只读需要的列、按条件过滤),压缩友好;适合存「样本路径 + 标签 + 长度」等表格型 metadata,训练时按 shard 或按条件读 Parquet 得到本 rank 的样本列表,再按 path 或 key 拉数据。Arrow:内存列式格式与 IPC/文件格式,零拷贝、多语言、与 Pandas/Spark 等互通;可做「内存中的 metadata 表」、或 Arrow 文件做 metadata 存储,训练时用 Arrow 读入过滤与 shard,再驱动 DataLoader。二者常一起用:Parquet 做持久化、Arrow 做内存表示与处理;或直接用 Arrow 的 Parquet 读写。

三、工程要点

Metadata 与数据分离:大文件或对象存数据,Parquet/Arrow 存索引与属性;DataLoader 先读 metadata(或按需读列)、再按 path/key 取数据。大规模时 metadata 也分片(多 Parquet 文件),按 rank 或按 key 范围读对应分片。


面试要点

  • 大规模数据需 metadata 做索引、过滤、shard、采样;要可扩展、可并行、支持列式与过滤。
  • Parquet:列存、schema 清晰、谓词下推、压缩;适合存样本表(path、label、len 等)。
  • Arrow:内存列式、零拷贝、多语言;做内存表或 Arrow 文件;常与 Parquet 配合(持久化+内存处理)。

记忆要点

  1. Metadata = 索引、过滤、shard;Parquet = 列存、过滤友好;Arrow = 内存列式、零拷贝。
  2. 数据与 metadata 分离;metadata 用 Parquet 持久、Arrow 处理。
  3. 大规模时 metadata 也分片;DataLoader 先读 metadata 再取数据。

返回模块 | 返回总览

14-集群调度/README.md

14-集群调度(第 171–180 题)

题号 主题 文章
171 Slurm的sbatch脚本编写?gres资源申请? 171-Slurm的sbatch脚本编写.md
172 Kubernetes的volcano调度器在AI场景的应用? 172-Kubernetes的volcano调度器在AI场景的应用.md
173 训练任务的gang schedulingPyTorchJob的… 173-训练任务的gang-scheduling.md
174 多租户集群的resource quota和`priority cla… 174-多租户集群的resource-quota和priority-class.md
175 GPU集群的topology awareness调度?`NVLink… 175-GPU集群的topology-awareness调度.md
176 训练任务的preemption和`checkpoint & resu… 176-训练任务的preemption和checkpoint-&-resume.md
177 集群的utilization监控?Prometheus + `G… 177-集群的utilization监控.md
178 多集群的federated learning基础设施? 178-多集群的federated-learning基础设施.md
179 训练任务的cost accounting?按GPU小时计费? 179-训练任务的cost-accounting.md
180 集群的heterogeneous GPU管理?A100、`H10… 180-集群的heterogeneous-GPU管理.md

返回总览

14-集群调度/171-Slurm的sbatch脚本编写.md

第 171 题:Slurm的sbatch脚本编写?gres资源申请?

题目

Slurm的sbatch脚本编写?gres资源申请?


完整讲解

一、sbatch 脚本结构

sbatch 是 Slurm 的批处理提交命令,脚本中通过 #SBATCH directive 指定资源与行为。常用项:--job-name--partition--nodes/--ntasks-per-node--cpus-per-task--time--output/--error;GPU 通过 gres 申请。脚本体为实际要执行的命令(如 srun 启动 MPI、或直接跑 Python)。

二、gres 资源申请

gres(Generic Resource):在 Slurm 中表示 GPU、FPGA 等设备。典型写法:#SBATCH --gres=gpu:2(2 块任意 GPU)、#SBATCH --gres=gpu:a100:4(4 块 A100)。需集群配置 GresTypes=gpu 及每节点 Gres=gpu:8 等。申请后任务内通过 CUDA_VISIBLE_DEVICES(由 Slurm 自动设置)使用对应 GPU。

三、工程要点

脚本内用 srun 做多进程/多节点时,通常每个 task 对应一进程;配合 --gres 保证每进程可见的 GPU 与 task 绑定。超时用 --time 避免长占;大作业用 --exclusive 独占节点时可减少干扰。生产环境常把 partition、account、qos 等写进脚本或通过环境/模板注入。

面试要点

  • sbatch 用 #SBATCH 指定 partition、nodes、cpus、time、output;GPU 用 --gres=gpu[:type]:数量
  • gres 需集群配置 GresTypes 与节点 Gres;任务内通过 CUDA_VISIBLE_DEVICES 使用 GPU。
  • 多任务时 srun 与 gres 配合;可结合 --exclusive、--account、--qos 做资源与计费控制。

记忆要点

  1. sbatch = 批处理脚本;#SBATCH 写资源,脚本体写执行命令。
  2. gres=gpu:2 或 gres=gpu:a100:4;集群需配置 Gres。
  3. 任务内用 CUDA_VISIBLE_DEVICES;srun 多任务时注意 GPU 与 task 绑定。

返回模块 | 返回总览

14-集群调度/172-Kubernetes的volcano调度器在AI场景的应用.md

第 172 题:Kubernetes的volcano调度器在AI场景的应用?

题目

Kubernetes的volcano调度器在AI场景的应用?


完整讲解

一、Volcano 的定位

Volcano 是 Kubernetes 上面向批处理与高性能计算的调度器,支持 gang scheduling(一组 Pod 要么全调度成功要么不调度)、队列与优先级资源预留与抢占等,弥补默认 kube-scheduler 对「多 Pod 协同、公平共享」支持不足的问题,适合 AI 训练、MPI 等 All-or-Nothing 作业。

二、AI 场景的应用

Gang scheduling:训练 job 的多个 worker Pod 必须同时就绪再一起跑,否则部分先起会挂起或死锁;Volcano 的 PodGroupminAvailable 保证「凑齐再调度」。队列:按团队/项目设 queue,配合 priorityClasscap 做公平与限流。GPU 等扩展资源:通过 CRD 或 device plugin 暴露 GPU,Volcano 按 request/limit 调度;可与 NVIDIA K8s Device Plugin 等配合。抢占与回收:高优任务可抢占低优,被抢占方可做 checkpoint 后重排。

三、与 PyTorchJob / Kubeflow 的关系

PyTorchJob 等 CRD + controller 负责生成 Pod、定义 role(master/worker);调度策略由 Volcano(或 kube-scheduler)执行。通常集群启用 Volcano 作为调度器、为训练 Job 的 Pod 打 schedulerName: volcanoPodGroup,即可获得 gang 调度与队列能力。

面试要点

  • Volcano 提供 gang scheduling(PodGroup/minAvailable)、队列、优先级与抢占,适合批处理与 AI 训练。
  • AI 场景:多 worker 必须同时就绪;配合 GPU device plugin、队列与 priority 做资源与公平控制。
  • PyTorchJob 等负责 Pod 编排,Volcano 负责调度;Pod 需指定 schedulerName 与 PodGroup。

记忆要点

  1. Volcano = K8s 批处理调度器;gang、队列、抢占。
  2. PodGroup + minAvailable 实现「全有或全无」调度。
  3. 与 PyTorchJob/GPU plugin 配合;schedulerName: volcano。

返回模块 | 返回总览

14-集群调度/173-训练任务的gang-scheduling.md

第 173 题:训练任务的gang schedulingPyTorchJoboperator

题目

训练任务的gang schedulingPyTorchJoboperator


完整讲解

一、Gang scheduling 的含义

Gang scheduling:一组进程/ Pod 要么全部同时调度运行,要么都不运行。分布式训练中多个 worker 若只部分启动,先起的会等未起的或超时失败,造成资源空占与死锁;因此需要「凑齐 N 个再一起跑」。

二、实现方式

Volcano:通过 PodGroup CRD 将多个 Pod 归为一组,设 minAvailable;调度器只有在能一次性满足 minAvailable 时才调度该组,否则不调度其中任何 Pod。Slurm:对 MPI/多节点作业本身即「一起分配节点再启动」,天然 gang。K8s 默认 scheduler:无原生 gang 语义,可配合 KubeBatch(已并入 Volcano 思路)或自研 scheduler plugin 实现「预留 + 一次性绑定」。

三、PyTorchJob 与 Operator

PyTorchJob 是 Kubeflow 的 CRD,定义 Master/Worker 的 replica 数与镜像、命令等;Operator 根据 spec 创建对应 Deployment/ReplicaSet 或裸 Pod,并注入环境变量(RANK、WORLD_SIZE 等)。调度由 K8s/Volcano 完成;Operator 不负责「凑齐再跑」,需集群提供 gang 调度(如 Volcano PodGroup)。Operator 还负责状态同步、失败重试、与 ML 元数据集成等。

面试要点

  • Gang scheduling:一组 Pod 全有或全无,避免分布式训练部分起、部分等导致的死锁与空占。
  • Volcano 用 PodGroup + minAvailable 实现;Slurm 多节点作业天然 gang;K8s 默认需插件或 Volcano。
  • PyTorchJob Operator 负责生成 Pod 与注入 rank;调度策略由 Volcano/kube-scheduler 执行。

记忆要点

  1. Gang = 全起或不起;训练多 worker 必须同时就绪。
  2. Volcano:PodGroup、minAvailable;K8s 需 Volcano 或等价插件。
  3. PyTorchJob Operator 管 Pod 编排与 rank;调度器管 gang 与资源。

返回模块 | 返回总览

14-集群调度/174-多租户集群的resource-quota和priority-class.md

第 174 题:多租户集群的resource quotapriority class

题目

多租户集群的resource quotapriority class


完整讲解

一、Resource quota 的作用

Resource quota(K8s 的 ResourceQuota):在 namespace 维度限制该命名空间内所有资源的总和(如总 CPU、内存、GPU 数量、PVC 容量等),防止某租户占满集群。多租户下为每个团队/项目分配独立 namespace 并设 quota,实现硬上限

二、Priority class

PriorityClass:为 Pod 指定调度优先级(数字越大越优先);高优 Pod 可抢占低优 Pod 的节点,被抢占的 Pod 可被 evict 后重调度。多租户场景:生产/紧急任务用高 priority,批处理/实验用低 priority;配合 preemption policy(Never 可禁止被抢占)。注意:高优任务过多仍会排队,quota 与 capacity 是硬约束。

三、与队列、公平共享的配合

Quota 管「最多能用多少」;谁先谁后由队列与 priority 决定。Volcano 的 Queue 可设置 cap、weight,与 namespace/quota 结合:例如每队列对应若干 namespace、每 namespace 设 quota;priority 用于同一队列内或跨队列的抢占与排序。这样实现「租户隔离 + 公平共享 + 紧急优先」。

面试要点

  • ResourceQuota 在 namespace 级别限制 CPU/内存/GPU 等总和,多租户下每团队一 namespace + quota。
  • PriorityClass 决定调度与抢占顺序;高优可抢占低优,配合 preemption policy 控制是否可被抢占。
  • Quota 管上限,队列与 priority 管顺序;可与 Volcano Queue 结合做公平与紧急优先。

记忆要点

  1. Quota = namespace 级资源上限;多租户按 namespace 隔离。
  2. PriorityClass = 调度/抢占优先级;高优可抢占低优。
  3. Quota + Queue + Priority 一起实现隔离与公平。

返回模块 | 返回总览

14-集群调度/175-GPU集群的topology-awareness调度.md

第 175 题:GPU集群的topology awareness调度?NVLink拓扑?

题目

GPU集群的topology awareness调度?NVLink拓扑?


完整讲解

一、Topology awareness 的意义

拓扑感知调度:在分配 GPU(或 NUMA、网卡)时,考虑硬件拓扑(如 NVLink 连接、PCIe 树、NUMA 节点),优先把同一作业的 GPU 安排在通信延迟低、带宽高的组内,从而提升 all-reduce 等通信效率、缩短训练时间。

二、NVLink 与拓扑

NVLink:GPU 间高速直连;同一节点内多卡可能通过 NVLink 全连接(如 8×A100 全连)或部分连接。调度时若「尽量把同一 job 的 8 卡放在同一节点、且选 NVLink 拓扑最优的节点」,可最大化带宽。多节点:节点间通过 IB/RoCE;同一 job 的节点宜在相近拓扑(同 rack、同 leaf)以减少跨级跳数。

三、实现方式

设备插件 + 调度:NVIDIA DCGMGPU Feature Discovery 可暴露拓扑信息(如 nvidia.com/nvlink);调度器在 Score 阶段对「请求多 GPU 的 Pod」优先选 NVLink 带宽高的节点。K8s:可扩展 scheduler plugin 或使用 Volcano 的 binpack / topology 策略;Slurm 的 cons_restopology/tree 可做类似约束。CRI/容器:保证分配到的 GPU 与上报拓扑一致,避免跨 NUMA 或远距离 PCIe。

面试要点

  • 拓扑感知:按 NVLink/PCIe/NUMA 等把同一 job 的 GPU 放在通信最优的位置,提升 all-reduce 等性能。
  • NVLink 同节点内高带宽;多节点看 IB/RoCE 与网络拓扑(同 rack 等)。
  • 通过设备插件暴露拓扑、调度器 Score 或 Volcano 策略做拓扑感知;Slurm 可用 cons_res/topology。

记忆要点

  1. 拓扑感知 = 按 NVLink/NUMA 等优化放置,减少通信延迟与带宽瓶颈。
  2. 同节点 NVLink、多节点 IB/RoCE + 同 rack 有利于通信。
  3. 设备插件暴露拓扑;调度器 Score/Volcano/Slurm 做拓扑感知。

返回模块 | 返回总览

14-集群调度/176-训练任务的preemption和checkpoint-&-resume.md

第 176 题:训练任务的preemptioncheckpoint & resume

题目

训练任务的preemptioncheckpoint & resume


完整讲解

一、Preemption(抢占)

抢占:高优先级任务需要资源时,调度器可终止或驱逐低优先级任务、回收其资源后再调度高优任务。被抢占的作业若未做 checkpoint 会丢失进度;因此训练任务需要周期性 checkpoint 并在被抢占后能从最新 checkpoint 恢复

二、Checkpoint & Resume

Checkpoint:训练过程中定期将模型参数、优化器状态、步数、随机数状态等写入存储(分布式时各 rank 写分片或汇总)。Resume:重新提交作业时,从存储加载 checkpoint,恢复 step 与状态,继续训练。这样被抢占或故障后只需「重新排队、重新调度」,从断点续训,不重头跑。

三、工程要点

调度侧:Volcano/K8s 的 preemption 会发 SIGTERM 或 evict;训练框架需捕获信号、写完当前 checkpoint 再退出,或依赖已有周期 checkpoint。存储:checkpoint 存共享存储(如 NFS、对象存储)以便任意节点恢复。作业描述中需带「checkpoint 路径、step」等,重提时由启动脚本或平台自动加载并 resume。

面试要点

  • 抢占下低优任务被终止;训练必须依赖周期 checkpoint 与 resume 避免进度丢失。
  • Checkpoint 含模型、优化器、step、RNG;存共享存储;resume 时加载后继续训练。
  • 框架需处理 SIGTERM/evict,写完 checkpoint 再退;重提作业时自动指定 checkpoint 路径并 resume。

记忆要点

  1. Preemption = 高优抢低优资源;被抢占任务会中断。
  2. Checkpoint = 周期保存状态;Resume = 从 checkpoint 恢复继续训。
  3. 共享存储存 checkpoint;重提时加载并 resume。

返回模块 | 返回总览

14-集群调度/177-集群的utilization监控.md

第 177 题:集群的utilization监控?Prometheus + Grafana

题目

集群的utilization监控?Prometheus + Grafana


完整讲解

一、Utilization 指标

集群利用率:GPU/CPU 的使用率(如 nvidia-smi 的 GPU-Util、或基于 DCGM 的 SM 利用率)、显存占用节点/卡在线与空闲比例等。高利用率表示资源被有效使用;长期低利用率说明空闲多、可做弹性或混部。需区分「分配率」(已分配/总资源)与「使用率」(实际算力/显存占用)。

二、Prometheus + Grafana

Prometheus:拉取并存储时序指标;通过 exporter(如 DCGM Exporter 暴露 GPU 指标、node_exporter 暴露节点 CPU/内存/磁盘)采集各节点与 GPU 的 utilization、memory、temperature 等。Grafana:连接 Prometheus 做看板:曲线图、单值、表格,按节点/作业/队列聚合,设告警阈值。典型面板:集群总 GPU 利用率、每节点利用率、每作业占用、排队时长、失败率等。

三、工程要点

调度器或作业系统可暴露「已分配/已使用」到 Prometheus;结合 labels(job_id、user、queue)做多维度查询与公平性分析。告警:利用率长期异常、节点故障、作业大量失败时触发;与工单或自动化恢复联动。

面试要点

  • 利用率包括 GPU 算力利用率、显存占用、分配率;用于评估集群效率与容量。
  • Prometheus 拉取 DCGM/node_exporter 等指标;Grafana 做看板与告警。
  • 指标带 job/queue/user 等 label,便于按维度分析与做公平性/容量规划。

记忆要点

  1. Utilization = 使用率/分配率;GPU 常用 DCGM、nvidia-smi 采集。
  2. Prometheus 存时序;Grafana 画图与告警。
  3. 多维度 label + 告警,支撑容量与公平性分析。

返回模块 | 返回总览

14-集群调度/178-多集群的federated-learning基础设施.md

第 178 题:多集群的federated learning基础设施?

题目

多集群的federated learning基础设施?


完整讲解

一、多集群与联邦学习

联邦学习(FL):数据保留在各参与方本地,仅交换梯度或模型更新,不在中心汇聚原始数据。多集群:参与方可能是多个独立集群(不同地域、不同机构),各自有调度、存储与安全边界;需要「跨集群的任务编排、通信与一致性」基础设施。

二、基础设施要点

编排与调度:中心或各站点有 FL 协调器,下发训练配置、轮次与聚合策略;各集群内按本地调度器(K8s/Slurm)启动训练任务,在约定轮次完成后上传梯度/模型到聚合服务(或采用安全聚合协议)。通信:跨集群通常走公网或专线,需 TLS、认证与访问控制;带宽与延迟比单集群差,设计时需减少通信轮次、压缩更新(梯度压缩、稀疏化)。

三、安全与一致性

隐私:仅传梯度/更新,不传原始数据;可叠加 差分隐私、安全聚合(Secure Aggregation)进一步保护。一致性:多集群下节点故障、网络分区常见;需容错聚合(部分节点掉线仍可聚合)、版本与轮次对齐,避免某一方长期落后拖慢全局。

面试要点

  • 多集群 FL:数据在各集群本地,只交换梯度/更新;需跨集群编排、通信与安全。
  • 基础设施:中心协调器 + 各集群本地调度;跨集群通信需 TLS、认证与压缩。
  • 安全与容错:差分隐私/安全聚合;容错聚合与轮次对齐应对故障与延迟。

记忆要点

  1. 多集群 FL = 数据不出域,只传梯度/更新;需跨集群编排与通信。
  2. 协调器下发配置、各集群本地跑训练、约定轮次上传/聚合。
  3. 通信安全 + 压缩;容错聚合与轮次一致。

返回模块 | 返回总览

14-集群调度/179-训练任务的cost-accounting.md

第 179 题:训练任务的cost accounting?按GPU小时计费?

题目

训练任务的cost accounting?按GPU小时计费?


完整讲解

一、Cost accounting 的目的

成本核算:按谁用了多少资源计费或摊成本,用于内部 chargeback、预算控制与优化决策。训练任务通常按 GPU 小时(或卡时)、CPU 小时存储与网络等计量;需区分「按量计费」与「包时/预留」的折算方式。

二、按 GPU 小时计费

GPU 小时:每块 GPU 使用 1 小时计 1 单位(可再按机型加权,如 A100×1.5、H100×2)。调度器或作业系统在任务结束时统计:分配到的 GPU 数 × 实际运行时长(或 wall time);若有抢占,可按「实际占用时长」计。数据来源:Slurm 的 sacct、K8s 的 usage 统计(需 metrics-server 或自定义 exporter);与计费系统对接生成账单或报表。

三、扩展与公平

多维度:除 GPU 小时外可加 存储 I/O、跨节点流量、队列溢价 等。公平共享:与 quota、priority、fair sharing 结合,避免单用户占满;成本数据也可驱动「预算用尽则降优先级或暂停提交」。Spot/抢占实例:若使用抢占式资源,计费单价可打折,但需与 checkpoint 与重跑成本权衡。

面试要点

  • Cost accounting 用于按用户/项目/队列统计资源消耗并计费或摊成本。
  • GPU 小时 = 卡数 × 运行时长;数据来自 sacct、K8s usage 或自定义 exporter。
  • 可与 quota、priority、fair sharing 结合;Spot 资源可打折计费。

记忆要点

  1. Cost accounting = 按资源使用量计费/摊成本。
  2. GPU 小时 = 卡数 × 时长;sacct / usage 提供数据。
  3. 多维度计费 + 与配额/优先级结合。

返回模块 | 返回总览

14-集群调度/180-集群的heterogeneous-GPU管理.md

第 180 题:集群的heterogeneous GPU管理?A100H1004090混部?

题目

集群的heterogeneous GPU管理?A100H1004090混部?


完整讲解

一、Heterogeneous GPU 的挑战

异构:集群中同时存在 A100、H100、4090 等不同型号,算力、显存、NVLink 与驱动/库支持不同。调度:需识别每块卡的类型与能力,按任务需求(如「必须 A100 80G」「可接受 4090」)做匹配与放置;避免大模型任务被分到显存不足的卡、或混部导致驱动/CUDA 版本冲突。

二、资源抽象与标签

设备插件:NVIDIA K8s Device Plugin 等可暴露 nvidia.com/gpu 及扩展标签(如 gpu-type=a100memory=80Gi)。Slurm 的 gres 可配置多种类型(如 gpu:a100:2,gpu:h100:1)。调度器按 node label / resource request 做筛选:例如 Pod 请求 nvidia.com/gpu: 1 且 nodeSelector gpu-type=a100,则只调度到 A100 节点。

三、混部策略

分区:按机型划分 partition 或 namespace,不同任务提交到不同分区,简单清晰。统一池 + 选择:所有 GPU 进一池,任务通过 request/selector 指定机型或「任意」;调度器做 binpack 或 spread。驱动与镜像:异构节点可能需不同驱动/CUDA 版本;用 节点亲和 + 镜像 tag 或统一基础镜像兼容多卡型,减少运维复杂度。

面试要点

  • 异构 GPU:不同型号能力不同,调度需按类型与需求匹配(显存、算力、NVLink)。
  • 通过 device plugin/label、gres 类型暴露卡型;request + nodeSelector 做筛选。
  • 分区或统一池 + 选择;注意驱动与镜像兼容多卡型。

记忆要点

  1. 异构 = 多型号混部;调度要类型感知与需求匹配。
  2. 设备插件/label、gres 暴露类型;request + selector 选节点。
  3. 分区或统一池;驱动与镜像需兼容。

返回模块 | 返回总览

15-性能分析工具/README.md

15-性能分析工具(第 181–195 题)

题号 主题 文章
181 nvidia-smidmonpmon模式区别? 181-nvidia-smi的dmon、pmon模式区别.md
182 Nsight Systems的timeline分析?如何识别gap 182-Nsight-Systems的timeline分析.md
183 Nsight Compute的roofline model分析? 183-Nsight-Compute的roofline-model分析.md
184 PyTorch Profiler的memory profiling功… 184-PyTorch-Profiler的memory-profiling功能.md
185 torch.autograd.profiler的`record_sh… 185-torch.autograd.profiler的record_shapes和.md
186 Chrome Trace Viewer解读PyTorch profile… 186-Chrome-Trace-Viewer解读PyTorch-profiler输.md
187 perfeBPF在CPU侧的profiling? 187-perf和eBPF在CPU侧的profiling.md
188 网络性能分析?iperfqperf 188-网络性能分析.md
189 存储IO分析?fioiostat 189-存储IO分析.md
190 如何构建端到端的性能监控dashboard? 190-如何构建端到端的性能监控dashboard.md
191 训练速度的scaling efficiency计算?理想vs实际? 191-训练速度的scaling-efficiency计算.md
192 通信时间的breakdown分析?all-reduce、`all… 192-通信时间的breakdown分析.md
193 算子级别的耗时分析?torch.ops.aten的dispatch? 193-算子级别的耗时分析.md
194 Python层面的profiling?cProfile、`py-sp… 194-Python层面的profiling.md
195 性能回归(regression)的自动化检测? 195-性能回归(regression)的自动化检测.md

返回总览

15-性能分析工具/181-nvidia-smi的dmon、pmon模式区别.md

第 181 题:nvidia-smidmonpmon模式区别?

题目

nvidia-smidmonpmon模式区别?


完整讲解

一、dmon 模式

nvidia-smi dmon持续监控模式,按固定间隔(如每秒)采样并输出 GPU 的 utilization(sm、mem)、功耗、温度 等到终端或日志。常用:nvidia-smi dmon -s u -c 10 表示采 utilization、共 10 次。适合观察一段时间内的波动(如训练时 GPU 是否周期性掉下去、是否在等数据),或脚本化采集做简单监控。

二、pmon 模式

nvidia-smi pmon:按 进程 维度显示 GPU 使用,输出每个进程的 PID、进程名、对应 GPU、显存占用、计算占用 等。适合看「哪几个进程在用哪块卡、各占多少」,用于排查多进程争卡、显存泄漏、混部时的占用归属。采样也是周期性的,可加 -c N 控制次数。

三、区别与使用场景

dmon:以 GPU 为维度,看整卡利用率和状态,适合看负载与瓶颈(如 GPU 是否跑满、是否在等 CPU)。pmon:以 进程为维度,看谁在用卡、用多少,适合多任务/多用户时的归属与隔离排查。二者可结合:先用 dmon 看卡是否忙,再用 pmon 看是哪些进程在占用。

面试要点

  • dmon:按 GPU 维度持续采样利用率、显存、功耗等;看整卡负载与时间序列。
  • pmon:按进程维度显示每进程占用的 GPU 与显存/算力;看谁在用哪块卡。
  • dmon 看瓶颈与波动,pmon 看归属与多进程;可配合使用。

记忆要点

  1. dmon = GPU 维度、持续采样;pmon = 进程维度、谁在用卡。
  2. dmon 适合看利用率曲线与瓶颈;pmon 适合多进程/多用户排查。
  3. 常用:dmon -s u -c N;pmon -c N。

返回模块 | 返回总览

15-性能分析工具/182-Nsight-Systems的timeline分析.md

第 182 题:Nsight Systems的timeline分析?如何识别gap

题目

Nsight Systems的timeline分析?如何识别gap


完整讲解

一、Nsight Systems 与 timeline

Nsight Systems:NVIDIA 的系统级性能分析工具,采集 CPU、GPU、CUDA API、kernel、内存拷贝、NCCL 等在同一时间轴上的活动,生成 timeline。可看到 CPU 与 GPU 的并行与串行关系、kernel 起止、拷贝与计算重叠情况,是定位「GPU 等 CPU、等数据、等通信」的首选。

二、如何识别 gap

Gap:timeline 上 GPU 没有 kernel 或拷贝在执行 的空白段,表示 GPU 在该段时间空闲。常见原因:(1)等 CPU:数据未准备好或下一批未提交;(2)等通信:all-reduce 等未完成、同步点;(3)等 kernel 启动:launch 延迟、小 kernel 过多;(4)调度/驱动:上下文切换、排队。识别方法:在 timeline 上找连续空白区间,看其前后是 CPU 活动、NCCL 调用还是 CUDA API;对应到代码的 dataloader、通信或 launch 位置,再针对性优化(如加 prefetch、重叠通信、kernel 融合)。

三、使用要点

采集时用 nsys profile 跑训练/推理,导出 timeline;用 Nsight Systems GUI 或 Chrome trace 打开。关注 GPU 利用率gap 占比;若 gap 多则优先减 gap(数据、通信、launch),再考虑单 kernel 优化。

面试要点

  • Nsight Systems 做系统级 timeline,看 CPU/GPU/通信在时间轴上的分布。
  • Gap = GPU 无 kernel/拷贝的空白;多表示等 CPU、等通信或 launch 延迟。
  • 看 gap 前后活动定位原因;优先减 gap 再优化单 kernel。

记忆要点

  1. Nsight Systems = 系统级 timeline;CPU/GPU/NCCL 同轴。
  2. Gap = GPU 空闲段;原因多为等 CPU、等通信、launch。
  3. 看 gap 前后对应代码;减 gap 优先于单 kernel 优化。

返回模块 | 返回总览

15-性能分析工具/183-Nsight-Compute的roofline-model分析.md

第 183 题:Nsight Compute的roofline model分析?

题目

Nsight Compute的roofline model分析?


完整讲解

一、Roofline model 概念

Roofline:以 算术强度(Arithmetic Intensity,AI = FLOPs/Byte,即每字节数据能做的浮点运算数)为横轴、可达性能(GFLOPS 等)为纵轴;曲线由算力上限(ridge point 左侧)和带宽上限(右侧)组成,形成「屋顶」。AI 小时受内存带宽限制(带宽 bound);AI 大时受算力限制(compute bound)。用于判断 kernel 或算子落在哪一侧、优化方向是省带宽还是提算力。

二、Nsight Compute 中的 roofline

Nsight Compute(ncu)可对单 kernel 做详细分析,并给出 Roofline 图:标出该 kernel 的 AI实际达到的吞吐在屋顶上的位置。若在带宽 roof 下方,说明内存受限,优化方向为减少全局内存访问、合并访问、用共享内存等;若在算力 roof 下方,说明计算受限,可考虑提高 occupancy、更多算术等。ncu 还提供 Memory Workload AnalysisCompute Workload Analysis 与具体瓶颈建议。

三、工程用法

先跑 ncu --set full -o report python train.py 等采集 kernel;在 Nsight Compute 中打开,看 Roofline 与 Top Recommendations。结合 Nsight Systems 的 timeline 确定要重点看的 kernel(热点或 gap 附近),再用 ncu 做单 kernel roofline 与建议优化。

面试要点

  • Roofline:AI = FLOPs/Byte;左侧带宽 bound、右侧算力 bound,判断优化方向。
  • Nsight Compute 对单 kernel 画 Roofline,标出 AI 与达到的吞吐;给 Memory/Compute 瓶颈建议。
  • 带宽 bound 减访存、合并、共享内存;算力 bound 提 occupancy、算力利用。

记忆要点

  1. Roofline:横轴 AI,纵轴性能;左带宽右算力。
  2. ncu 给单 kernel Roofline + 瓶颈建议。
  3. 带宽 bound → 减访存;算力 bound → 提算力利用。

返回模块 | 返回总览

15-性能分析工具/184-PyTorch-Profiler的memory-profiling功能.md

第 184 题:PyTorch Profiler的memory profiling功能?

题目

PyTorch Profiler的memory profiling功能?


完整讲解

一、Memory profiling 的目的

显存分析:看分配与释放发生在何时、哪段代码,以及峰值与泄漏。训练 OOM 或推理显存不稳时,需知道是哪些 tensor、哪几层导致峰值;是否有未释放的中间结果或缓存。

二、PyTorch Profiler 的 memory 功能

torch.profilertorch.autograd.profiler 可开启 profile_memory=True(或 with torch.profiler.profile(profile_memory=True)),记录 alloc 与 free 事件、每 operator 的 显存增量。导出后可在 Chrome tracePyTorch Profiler 表格 中按时间线看「某 step 内哪些 op 分配了多少」、峰值时刻 对应的调用栈。memory_profile=True(新 API)会生成更细的显存时间线。

三、使用要点

需在足够代表的 step 上采集(如一个完整 step 或若干 step);注意 CUDA 缓存(allocator 会预留池),看到的「已分配」可能高于当前 tensor 实际需求。结合 torch.cuda.memory_summary()memory_allocated() 做点状检查;profiler 做时间维度的分配归属与峰值定位。

面试要点

  • Memory profiling 用于定位显存峰值、泄漏与各 op 的分配贡献。
  • PyTorch Profiler 开 profile_memory / memory_profile,看 alloc/free 时间线与 per-op 增量。
  • 结合 memory_summary、memory_allocated 做点状检查;在代表 step 上采足够长。

记忆要点

  1. 显存分析:分配/释放时间线、峰值、per-op 贡献。
  2. torch.profiler profile_memory=True;导出看 Chrome trace 或表格。
  3. 代表 step 采集;注意 CUDA cache 与真实 tensor 区别。

返回模块 | 返回总览

15-性能分析工具/185-torch.autograd.profiler的record_shapes和.md

第 185 题:torch.autograd.profilerrecord_shapesprofile_memory

题目

torch.autograd.profilerrecord_shapesprofile_memory


完整讲解

一、record_shapes

record_shapes:在 torch.autograd.profilertorch.profiler 中开启后,会记录每个 operator 的输入/输出 tensor 的 shape。便于在分析结果中看到「某 op 是在什么 shape 下被调用的」(如 batch、seq_len、hidden),用于判断是否因动态 shape 导致多次编译、或某 shape 特别耗时,以及做容量与优化决策。

二、profile_memory

profile_memory:记录 CUDA 显存分配与释放 事件及归属到哪个 op。可看到每个 op 的 显存增量(正为分配、负为释放)、时间线上的分配峰值,用于定位 OOM 对应的 op 与 tensor、以及显存泄漏(某 op 只增不释)。需在代表性 step 上采集足够长;注意 PyTorch 的 caching allocator 会复用块,看到的「分配」可能包含池化。

三、使用场景

record_shapes:排查动态 shape、大 tensor、异常 batch 维;与 torch.compile 或 TensorRT 的 shape 相关问题时常用。profile_memory:OOM、显存峰值优化、多模型/多阶段共享显存时理清谁在何时占用多少。二者可同时开,在同一个 profile 里既看耗时又看 shape 与显存。

面试要点

  • record_shapes:记录每 op 的输入/输出 shape,用于动态 shape、异常 batch、编译次数分析。
  • profile_memory:记录显存 alloc/free 与 per-op 增量,用于峰值与泄漏定位。
  • 二者可同开;在代表 step 上采集,结合 trace 与表格分析。

记忆要点

  1. record_shapes = 记录 op 的 tensor shape;查动态 shape、大 tensor。
  2. profile_memory = 记录显存分配与归属;查峰值与泄漏。
  3. 同开可同时看耗时、shape 与显存。

返回模块 | 返回总览

15-性能分析工具/186-Chrome-Trace-Viewer解读PyTorch-profiler输.md

第 186 题:Chrome Trace Viewer解读PyTorch profiler输出?

题目

Chrome Trace Viewer解读PyTorch profiler输出?


完整讲解

一、PyTorch Profiler 与 Chrome Trace

PyTorch Profiler 导出 trace 时可选择 Chrome trace 格式(.json),用 Chrome 浏览器打开 chrome://tracing 加载该文件。Trace 中每条横条代表一段时间内的活动(CPU op、CUDA kernel、内存拷贝等),纵轴为线程或 stream,可看到 CPU 与 GPU 的并行与依赖、gap、重叠情况。

二、如何解读

时间轴:从左到右为时间;找 GPU stream 上的空白(gap)即 GPU 空闲。层级:PyTorch 会按 op、kernel、cudaLaunch 等分层;展开可看到具体算子与 kernel 名。颜色与长度:长度表耗时;不同类型用不同颜色。关联:CPU 上「某 op」与 GPU 上「对应 kernel」可通过名称或时间对齐,判断是等数据、等启动还是等通信。

三、常用操作

缩放时间轴聚焦到单 step 或单次迭代;按名称搜索关键 op 或 kernel;看 gap 前后是哪个 CPU 或 CUDA 活动,对应回代码(dataloader、通信、launch)。与 Nsight Systems 互补:Chrome trace 偏 PyTorch 视角、易对回 Python;Nsight 更偏系统与 NCCL。

面试要点

  • PyTorch Profiler 可导出 Chrome trace 格式,用 chrome://tracing 打开。
  • 横条=活动、纵轴=线程/stream;看 CPU/GPU 并行、gap、op 与 kernel 对应关系。
  • 找 gap、按名搜 op/kernel、对齐到代码;与 Nsight 互补使用。

记忆要点

  1. 导出 .json → chrome://tracing 加载。
  2. 横轴时间、纵轴线程;空白=gap。
  3. 按名搜、看前后活动,对应回代码。

返回模块 | 返回总览

15-性能分析工具/187-perf和eBPF在CPU侧的profiling.md

第 187 题:perfeBPF在CPU侧的profiling?

题目

perfeBPF在CPU侧的profiling?


完整讲解

一、perf 在 CPU 侧的作用

perf(Linux perf_events):采样 CPU 上的热点(函数、指令、cache miss、分支预测等),通过 perf record / perf report 得到调用栈与占比。训练/推理若 CPU 成为瓶颈(如 dataloader、预处理、Python 解释器),可用 perf 看哪些函数占 CPU 多、是否有不必要的系统调用或锁竞争。

二、eBPF 在 CPU profiling 的应用

eBPF:在内核中运行安全沙箱程序,可挂载到各类事件(系统调用、tracepoint、kprobe)做低开销的统计与过滤。用于 CPU 侧:CPU 采样(如 BCC 的 profile)、off-CPU 分析(看进程在等什么)、锁与调度 分析。相比 perf 可做更定制化的过滤与聚合(如按 PID、按调用栈标签),且通常无需改应用、开销小。

三、与 GPU 分析的配合

GPU 瓶颈时用 Nsight/CUDA profiler;CPU 瓶颈(数据加载、Python、通信的 CPU 侧)用 perf 或 eBPF 定位。off-CPU:若 GPU 在等 CPU,用 eBPF 看 CPU 进程在等什么(等 IO、等锁、等调度),可精确定位到系统调用或内核路径。

面试要点

  • perf:CPU 热点采样、调用栈、cache/分支;用于 dataloader、Python、系统调用瓶颈。
  • eBPF:内核可编程、低开销;可做 CPU 采样、off-CPU、锁与调度分析,定制过滤。
  • CPU 瓶颈用 perf/eBPF;与 GPU 分析配合,off-CPU 可看「等什么」。

记忆要点

  1. perf = CPU 热点、调用栈、cache;perf record/report。
  2. eBPF = 内核挂载、低开销、可定制;CPU/off-CPU/锁分析。
  3. CPU 瓶颈用二者;off-CPU 看等待原因。

返回模块 | 返回总览

15-性能分析工具/188-网络性能分析.md

第 188 题:网络性能分析?iperfqperf

题目

网络性能分析?iperfqperf


完整讲解

一、网络性能分析的目的

分布式训练与推理依赖节点间带宽与延迟;若网络成为瓶颈,需测量 带宽、延迟、丢包、重传 等。工具用于裸机或容器网络的基准测试与故障排查,不依赖具体训练框架。

二、iperf

iperf(iperf2/iperf3):TCP/UDP 带宽测试。一端起 server(iperf3 -s),另一端 client(iperf3 -c <server>),测量端到端吞吐。可调包长、并行流、时长;常用于验证链路最大带宽、多流聚合、以及不同节点/路径差异。局限:测的是「裸」传输能力,不直接反映 NCCL/MPI 的实际表现,但可作网络健康与上限参考。

三、qperf

qperf:除带宽外还可测 RDMA(InfiniBand/RoCE)的 latency 与 bandwidth(如 qperf <server> tcp_bw tcp_latrc_* 等 RDMA 测试)。在 IB/RoCE 集群中用于验证 verbs 层 的延迟与带宽,比 iperf 更贴近 NCCL 底层使用的通信方式。用法:一端 qperf & 待连,另一端 qperf <server> <tests>

面试要点

  • 网络分析用于测带宽、延迟、丢包;支撑分布式训练/推理的瓶颈判断。
  • iperf:TCP/UDP 带宽测试,client-server 模式;验证链路与多流吞吐。
  • qperf:可测 TCP 与 RDMA 的 bw/lat;IB/RoCE 环境常用 qperf 测 verbs 性能。

记忆要点

  1. iperf = 带宽测试;iperf3 -s / -c。
  2. qperf = 带宽 + 延迟,支持 RDMA;IB/RoCE 常用。
  3. 二者测链路能力;实际训练还看 NCCL/拓扑。

返回模块 | 返回总览

15-性能分析工具/189-存储IO分析.md

第 189 题:存储IO分析?fioiostat

题目

存储IO分析?fioiostat


完整讲解

一、存储 IO 分析的意义

训练与推理的数据加载、checkpoint、日志都依赖存储;若 IO 成为瓶颈(GPU 等数据、吞吐上不去),需测量读写的带宽、IOPS、延迟,以及各设备/分区的实际使用情况

二、fio

fio(Flexible I/O Tester):可配置的 IO 压测,支持多种 IO 引擎、顺序/随机、块大小、队列深度、多线程。常用场景:顺序读/写带宽(模拟大文件读)、随机读 IOPS(模拟小文件或随机访问)、混合负载。通过 fio 配置文件 或命令行指定 job,得到带宽、IOPS、延迟分布(如 clat)。用于评估单机或共享存储的极限能力、与训练时的 DataLoader 行为对比,判断是否 IO 瓶颈。

三、iostat

iostat(sysstat 包):实时或周期 查看各块设备的 读写吞吐(r/s, w/s)、带宽(rkB/s, wkB/s)、利用率(%util) 等。iostat -x 2 每 2 秒刷新。用于运行时观察训练/推理期间哪些盘在忙、利用率是否打满、是否有某块盘成为瓶颈。结合 df、mount 确认被测路径对应设备;iostat 看设备级,fio 做可控压测。

面试要点

  • 存储 IO 分析用于判断数据加载、checkpoint 是否成为瓶颈。
  • fio:可配置压测,测顺序/随机带宽与 IOPS、延迟;评估存储能力与上限。
  • iostat:实时看各设备吞吐、利用率;运行时观察哪块盘忙、是否打满。

记忆要点

  1. fio = 压测;顺序/随机、带宽/IOPS、可配。
  2. iostat = 实时设备级统计;iostat -x 2。
  3. fio 定上限,iostat 看运行时负载。

返回模块 | 返回总览

15-性能分析工具/190-如何构建端到端的性能监控dashboard.md

第 190 题:如何构建端到端的性能监控dashboard?

题目

如何构建端到端的性能监控dashboard?


完整讲解

一、端到端监控的目标

端到端:从作业提交/请求进入训练 step 或推理完成的全链路,包含调度等待、数据加载、计算、通信、存储等。监控目标:吞吐、延迟、利用率、排队、失败率 等可观测指标,用于容量规划、SLA 与故障定位。

二、数据来源与指标

指标来源:调度器(排队时长、分配资源、开始/结束时间);训练/推理进程(通过 Prometheus exporter、日志解析、或框架 callback 上报 step 耗时、loss、GPU 利用率、通信时间);节点与 GPU(DCGM、node_exporter);存储与网络(可选)。关键指标:job 级(排队时间、运行时长、吞吐 samples/s、通信占比);集群级(GPU 利用率、队列深度、失败率);推理级(QPS、P99 延迟、错误率)。

三、Dashboard 设计

Grafana 等连接 Prometheus(或其它时序库),按层级组织:总览(集群利用率、队列、今日完成 job 数);单 job/单服务(该 job 的 step 时间、通信、loss 曲线);单节点/单卡(GPU 利用率、显存、温度)。告警:利用率异常、排队超时、失败率突增、P99 超 SLA 等。链路:若需 request 级追踪,可集成 trace(如 OpenTelemetry)做从请求到各阶段的 span。

面试要点

  • 端到端监控覆盖从提交/请求到完成的全链路;指标含吞吐、延迟、利用率、排队、失败。
  • 数据来自调度器、框架 callback、DCGM、node_exporter、日志等;统一到时序库(如 Prometheus)。
  • Dashboard 分层:总览、job/服务、节点;告警 + 可选 trace 做链路追踪。

记忆要点

  1. 端到端 = 全链路;调度、计算、通信、存储都要可观测。
  2. 指标:job 级 + 集群级 + 推理级;Prometheus + exporter/callback。
  3. Grafana 分层看板 + 告警;可选 trace。

返回模块 | 返回总览

15-性能分析工具/191-训练速度的scaling-efficiency计算.md

第 191 题:训练速度的scaling efficiency计算?理想vs实际?

题目

训练速度的scaling efficiency计算?理想vs实际?


完整讲解

一、Scaling efficiency 定义

Scaling efficiency实际加速比理想加速比 之比。理想情况:N 卡相对 1 卡,吞吐应接近 N 倍(线性扩展);实际因通信、负载不均、数据/调度开销等往往低于 N 倍。效率 = (实际吞吐 / 单卡吞吐) / N,或等价地 实际吞吐 / (单卡吞吐 × N);常用百分数表示(如 8 卡达到 6× 单卡则效率约 75%)。

二、如何计算

单卡基线:在相同模型、batch、数据下测单卡吞吐(samples/s 或 step/s)。N 卡实际:同配置下 N 卡分布式训练,测全局吞吐效率 = (N 卡全局吞吐 / 单卡吞吐) / N。若还要看强扩展(固定总 batch,卡数翻倍则 step 时间应约减半),可算 理想 step 时间 / 实际 step 时间 作为 step 维度的扩展效率。

三、瓶颈分析

效率低时,用 profiler(Nsight Systems、PyTorch Profiler)看 通信占比、gap、负载均衡。通信占比高或 gap 多,说明通信或数据是瓶颈;可做通信重叠、更大 batch、或拓扑优化。报告时同时给单卡吞吐、N 卡吞吐、效率,便于评估扩展性与性价比。

面试要点

  • Scaling efficiency = 实际加速比 / 理想加速比;(实际吞吐/单卡吞吐)/N。
  • 单卡测基线吞吐,N 卡测全局吞吐,代入公式得效率(常用百分数)。
  • 效率低时用 profiler 看通信、gap、负载;优化后复测。

记忆要点

  1. 效率 = (N 卡吞吐/单卡吞吐)/N;理想 100%。
  2. 单卡基线 + N 卡实际吞吐即可算。
  3. 低效率查通信、gap、负载。

返回模块 | 返回总览

15-性能分析工具/192-通信时间的breakdown分析.md

第 192 题:通信时间的breakdown分析?all-reduceall-gather占比?

题目

通信时间的breakdown分析?all-reduceall-gather占比?


完整讲解

一、通信 breakdown 的意义

分布式训练中 all-reduce、all-gather、reduce-scatter 等集体通信常占相当比例;优化前需知道各通信原语分别占多少时间、是否某一种特别突出(如 all-gather 在流水线中成为瓶颈),从而针对性优化(重叠、换算法、调拓扑)。

二、如何做 breakdown

PyTorch Profiler:开启后可在 trace 或表格 中看到 NCCL 调用(如 nccl:all_reduce、nccl:all_gather)及其耗时;按名称聚合可得各集体通信的总时间或占比Nsight Systems:timeline 上 NCCL 区段会标出通信类型;可手动或脚本统计各类型总时长。NCCL 自带:部分版本或环境可打开 NCCL_DEBUGNCCL 日志 得到每次调用的耗时;再按 op 类型聚合。DCGM:可看 GPU 侧「等通信」的占比,与 profiler 的 NCCL 时间交叉验证。

三、解读与优化

all-reduce 占比高:梯度同步;可考虑梯度压缩、更大 batch 减少次数、或通信重叠。all-gather 高:常见于流水线或 tensor parallel 的激活/权重收集;可重叠或减少 gather 量。reduce-scatter:与 all-gather 成对出现;同样看能否重叠与减量。Breakdown 结果与 通信量、带宽、拓扑 结合判断是带宽瓶颈还是延迟/次数瓶颈。

面试要点

  • 通信 breakdown:区分 all-reduce、all-gather、reduce-scatter 等各自耗时与占比。
  • 工具:PyTorch Profiler(NCCL 调用)、Nsight Systems(timeline)、NCCL 日志、DCGM。
  • 根据占比与类型做重叠、压缩、减次数或拓扑优化。

记忆要点

  1. Breakdown = 各集体通信(all-reduce/all-gather 等)的耗时与占比。
  2. Profiler/Nsight/NCCL 日志可得到;按名称聚合。
  3. 高占比类型针对性优化:重叠、压缩、拓扑。

返回模块 | 返回总览

15-性能分析工具/193-算子级别的耗时分析.md

第 193 题:算子级别的耗时分析?torch.ops.aten的dispatch?

题目

算子级别的耗时分析?torch.ops.aten的dispatch?


完整讲解

一、算子级耗时分析的目的

算子级:将耗时归因到具体算子(如 aten::linear、aten::mm、cuDNN 的 conv),用于定位热点、判断是框架 op 还是 kernel 实现问题、以及为融合与替换提供依据。PyTorch 中多数 op 会 dispatch 到 aten(torch.ops.aten.*),再到底层 backend(CUDA、cuDNN 等)。

二、PyTorch Profiler 与 aten

torch.profiler 记录的 op 名称 多为 aten::torch::;表格或 trace 中可按 op 名排序、聚合,得到每个 aten op 的总耗时与占比。record_shapes=True 可看到该 op 的输入 shape,便于判断是否某 shape 特别慢。dispatch:aten 是 PyTorch 的 C++ 算子库,Python 调用会经 torch.dispatcher** 到 aten 再到底层;profiler 在 dispatch 边界打点,所以看到的是「aten 层」的耗时,其下可能对应多个 CUDA kernel(如 linear = matmul + bias)。

三、深入与优化

若某 aten op 占比较高,可用 Nsight Compute 对该 op 触发的 kernel 做单 kernel 分析(roofline、memory);或查是否可融合(如 linear+relu)、换实现(如用 FlashAttention 替代手写 attention)。torch.compileTensorRT 会改写/融合 op,profiler 中可能看到融合后的名字(如 torch._inductor.*),需对应回原始逻辑。

面试要点

  • 算子级分析:把耗时归到具体 op(aten::*);用于热点定位与融合/替换依据。
  • PyTorch Profiler 记录 aten 层;record_shapes 看 shape;aten 下可能多 kernel。
  • 高占比 op 用 ncu 看 kernel、考虑融合或换实现;compile 后 op 名可能变化。

记忆要点

  1. 算子级 = 按 aten/op 聚合耗时;Profiler 表格或 trace 按名排序。
  2. aten = PyTorch C++ 算子库;dispatch 到 CUDA/cuDNN。
  3. 高占比 → ncu 看 kernel、融合或换实现。

返回模块 | 返回总览

15-性能分析工具/194-Python层面的profiling.md

第 194 题:Python层面的profiling?cProfilepy-spy

题目

Python层面的profiling?cProfilepy-spy


完整讲解

一、Python 层成为瓶颈时

Python 侧:解释器开销、GIL、过多 Python 调用(如逐元素操作)、数据预处理与 dataloader 在 Python 中执行等,可能拖慢整体。需要在 Python 层做 profiling,看哪些函数、哪行代码占 CPU 多,而不是只看 GPU。

二、cProfile

cProfile(Python 标准库):确定性 profiler,记录每个函数的调用次数与累计耗时。用法:python -m cProfile -o out.prof train.py 或代码内 cProfile.run('func()');用 pstatssnakeviz 查看。可看到 Python 调用栈 与热点函数;适合找「谁在占 CPU」——如某个 dataloader 的 collate、或某段预处理。注意:会拖慢执行,且主要反映 CPU 时间,不直接反映 GPU 等待。

三、py-spy

py-spy采样式 profiler,无需改代码、无需重启,通过 ptrace(或类似机制)定期采样 Python 进程的调用栈。py-spy top 实时看热点;py-spy record -o profile.svg 生成火焰图。优点:低侵入、可对已运行进程采样、开销小。适用:生产或长时间运行时的现场采样,看当前 Python 热点;与 cProfile 互补(cProfile 更精确、py-spy 更轻量、可事后挂载)。

面试要点

  • Python 层瓶颈时需做 Python 侧 profiling(热点函数、调用栈)。
  • cProfile:确定性、每函数调用次数与耗时;python -m cProfile 或 run();看 pstats/snakeviz。
  • py-spy:采样式、无需改代码、可挂载运行中进程;top/record 火焰图;低侵入。

记忆要点

  1. cProfile = 标准库、确定性;看 Python 函数耗时与次数。
  2. py-spy = 采样、可挂载、火焰图;低侵入。
  3. 二者配合:cProfile 精确,py-spy 现场采样。

返回模块 | 返回总览

15-性能分析工具/195-性能回归(regression)的自动化检测.md

第 195 题:性能回归(regression)的自动化检测?

题目

性能回归(regression)的自动化检测?


完整讲解

一、性能回归的含义

回归:代码或环境变更后,性能变差(吞吐下降、延迟上升、显存增加等)而未及时发现。自动化检测:在 CI/CD 或定期任务中,对固定 benchmark(固定模型、数据、配置)跑性能测试,将当前结果与基线对比,若超出阈值则告警或阻断,要求排查后再合入或发布。

二、如何实现

基线:在「已知良好」的 commit 或版本上跑 benchmark,记录 吞吐、延迟、显存峰值 等作为基线(可存为 CI 产物或数据库)。每次变更:在 PR 或 nightly 中跑同一 benchmark,得到当前指标。比较:当前 vs 基线;若 回归超过阈值(如吞吐降 >5%、P99 升 >10%)则失败。环境:尽量固定硬件与驱动(同一 runner 或同一机型),减少噪声;或多次跑取中位数/均值。维度:可对多配置(batch、模型规模)各设基线,避免只测单一场景。

三、工程要点

Benchmark 要稳定、可复现(固定 seed、数据量、warmup);CI 里可设 allowlist(已知回归待修)或 只告警不阻断。结果可写入 Prometheus/Grafana 做趋势图;与代码 commit 关联便于定位引入回归的变更。

面试要点

  • 性能回归:变更导致性能变差;自动化检测 = CI 中跑固定 benchmark、与基线对比、超阈值告警/阻断。
  • 基线来自已知良好版本;同一 benchmark、固定环境;多配置可多基线。
  • Benchmark 需稳定可复现;结果可存时序库、关联 commit。

记忆要点

  1. 回归 = 性能变差;自动检测 = benchmark + 基线对比 + 阈值。
  2. 基线固定;CI 每次跑同一 benchmark;环境尽量固定。
  3. 稳定可复现;结果可做趋势与 commit 关联。

返回模块 | 返回总览

16-优化技术/README.md

16-优化技术(第 196–215 题)

题号 主题 文章
196 FlashAttentionIO-aware优化原理?`til… 196-FlashAttention的IO-aware优化原理.md
197 FlashAttention-2FlashAttention的… 197-FlashAttention-2和FlashAttention的改进点.md
198 xFormers的`memory_efficient_attenti… 198-xFormers的memory_efficient_attention使用.md
199 cuDNNfused attention如何调用? 199-cuDNN的fused-attention如何调用.md
200 算子融合的边界判断?融合后register pressure过高? 200-算子融合的边界判断.md
201 内存带宽bound vs 计算bound的判断?`arithmetic … 201-内存带宽bound-vs-计算bound的判断.md
202 kernel fusion的手动实现 vs 编译器自动生成? 202-kernel-fusion的手动实现-vs-编译器自动生成.md
203 CUDA Graph的捕获和重放?`torch.cuda.make_… 203-CUDA-Graph的捕获和重放.md
204 动态shape的优化困境?torch.compile的`dynami… 204-动态shape的优化困境.md
205 torch.backends.cudnn.benchmark的作用和… 205-torch.backends.cudnn.benchmark的作用和副作用.md
206 CPU offload的pin_memory和`non_blocki… 206-CPU-offload的pin_memory和non_blocking.md
207 数据预处理的multi-processing优化?`num_work… 207-数据预处理的multi-processing优化.md
208 DALIGPU decodingaugmentation 208-DALI的GPU-decoding和augmentation.md
209 混合精度训练的numerical stability问题? 209-混合精度训练的numerical-stability问题.md
210 gradient accumulation的`effective b… 210-gradient-accumulation的effective-batch-.md
211 大batch训练的learning rate scaling规则? 211-大batch训练的learning-rate-scaling规则.md
212 LARSLAMB优化器在大batch场景的应用? 212-LARS、LAMB优化器在大batch场景的应用.md
213 模型并行的communication hiding技术? 213-模型并行的communication-hiding技术.md
214 pipeline bubble的数学分析和优化? 214-pipeline-bubble的数学分析和优化.md
215 稀疏attention的优化?Sparse Transformer、… 215-稀疏attention的优化.md

返回总览

16-优化技术/196-FlashAttention的IO-aware优化原理.md

第 196 题:FlashAttentionIO-aware优化原理?tilingrecomputation

题目

FlashAttentionIO-aware优化原理?tilingrecomputation


完整讲解

一、IO-aware 的问题背景

标准 attention 的 QKV 与 softmax 需要多次读写 HBM(显存),带宽成为瓶颈;算力往往吃不满。IO-aware 优化:从「减少对 HBM 的读写、提高算术强度」出发设计算法与实现,使 attention 更贴近算力上限而非带宽上限。

二、Tiling 与分块

Tiling:不一次性把整块 Q、K、V 从 HBM 读入,而是按(tile)处理。每次只把 Q 的一小块K、V 的对应块 读入 SRAM/共享内存,在片上算完该块的 attention 与输出,再写回 HBM。这样重复利用片上数据,减少 HBM 往返次数,即降低 IO 量、提高有效算术强度。

三、Recomputation

Recomputation:前向时不存完整的 attention 中间结果(如 softmax 前的 scores、softmax 结果)回 HBM,只存为反向所需的最少信息(如 softmax 归一化因子、或分块时的块级统计)。反向时按需重新计算部分前向(用存下的统计量快速重算),用算换存,降低显存占用与带宽,避免 OOM 并利于更大 batch 或更长序列。

面试要点

  • FlashAttention 的 IO-aware:从减少 HBM 读写出发,提高算术强度、逼近算力上限。
  • Tiling:按块在片上算 QK^T/softmax/OV,减少 HBM 往返;分块复用数据。
  • Recomputation:前向少存中间结果,反向时重算;用算换存、降带宽与显存。

记忆要点

  1. IO-aware = 减 HBM 访问、提算术强度。
  2. Tiling = 分块、片上算、少往返。
  3. Recomputation = 少存、反向重算;算换存。

返回模块 | 返回总览

16-优化技术/197-FlashAttention-2和FlashAttention的改进点.md

第 197 题:FlashAttention-2FlashAttention的改进点?

题目

FlashAttention-2FlashAttention的改进点?


完整讲解

一、FlashAttention 核心思想

FlashAttention:通过 tiling + recomputationIO-aware 的 attention,减少 HBM 读写、提高带宽利用率;使用 online softmax 等数学技巧在分块下保持数值等价。FlashAttention-2 在保持上述思想下做了实现与调度上的大幅优化。

二、FlashAttention-2 的改进

并行与调度:(1)更细的并行:在 sequence 维 做切分与并行,而不仅 batch 维,更好利用 GPU;(2)work partitioning:让每个 block 负责的 Q 块与 K/V 块划分更均衡,减少 warp 间空闲。(3)单 pass:在 FA-1 中部分场景需多 pass,FA-2 通过改进 online softmax 与分块策略做到单 pass 完成,进一步减 IO。数值与兼容:支持 head 维度 不整除 8 等、与 causal mask 的融合更好;backward 同样做 tiling 与重算,显存与速度都优于 FA-1。

三、使用与选型

FA-2 是当前默认推荐的 attention 实现(如 vLLM、HuggingFace 中常用);接口上通常替换 sdpascaled_dot_product_attention 的后端即可。FA-1 仍可用于旧环境或对比;FA-2 在 A100/H100 上性能与显存都更优。

面试要点

  • FlashAttention:tiling + recomputation、IO-aware;FlashAttention-2 在并行、调度与单 pass 上大幅改进。
  • FA-2:sequence 维并行、work 划分更均衡、单 pass、更好的 causal 与 head 维兼容。
  • 选型优先 FA-2;接口多为替换 SDPA 后端。

记忆要点

  1. FA-2 保持 IO-aware,改进并行与单 pass。
  2. 序列维并行、均衡划分、单 pass;backward 同样优化。
  3. 优先用 FA-2;接口替换 SDPA 后端。

返回模块 | 返回总览

16-优化技术/198-xFormers的memory_efficient_attention使用.md

第 198 题:xFormersmemory_efficient_attention使用?

题目

xFormersmemory_efficient_attention使用?


完整讲解

一、xFormers 与 memory_efficient_attention

xFormers(Meta):提供 memory_efficient_attention 等算子,背后可走 FlashAttention、cutlass 等实现,用于省显存、提速的 attention。接口统一,可根据硬件与可用后端自动选择最优实现(如 A100 上选 FlashAttention)。

二、使用方式

安装pip install xformers(需对应 CUDA/PyTorch 版本)。调用from xformers.ops import memory_efficient_attention;传入 Q、K、V(以及可选的 attn_bias、mask),得到与标准 attention 数学等价的输出。mask:支持 causal、自定义 mask;与 FlashAttention 的 causal 融合一致。适用:替换 F.scaled_dot_product_attention 或手写 attention 循环,在长序列、大 batch 下显存与速度优势明显。

三、与 PyTorch SDPA 的关系

PyTorch 2.0+ 的 torch.nn.functional.scaled_dot_product_attention 在支持的后端下也会调用 FlashAttention/xFormers;若已用 SDPA 且后端选对,效果接近。xFormers 仍可用于更细控制(如指定 backend)、或 PyTorch 版本较旧 时作为独立依赖;部分特殊 mask 或 bias 在 xFormers 中支持更全。

面试要点

  • xFormers 提供 memory_efficient_attention,背后可走 FlashAttention 等;省显存、提速。
  • 使用:from xformers.ops import memory_efficient_attention;传 Q/K/V 与可选 mask。
  • 与 SDPA 可二选一;xFormers 可做后端细控或旧版 PyTorch 替代。

记忆要点

  1. xFormers = memory_efficient_attention;可走 FlashAttention。
  2. 传 Q/K/V + mask;替换手写或 SDPA。
  3. SDPA 新版本也可用;xFormers 做细控或兼容。

返回模块 | 返回总览

16-优化技术/199-cuDNN的fused-attention如何调用.md

第 199 题:cuDNNfused attention如何调用?

题目

cuDNNfused attention如何调用?


完整讲解

一、cuDNN fused attention 的定位

cuDNN 从 8.x 起提供 fused attention 实现:将 QKV 投影、attention score、softmax、与 value 乘 等融合为少量 kernel,减少 launch 与显存往返,并针对 A100 等做优化。适合固定或常见 shape 的 transformer attention,作为 backend 被 PyTorch/TensorRT 等调用。

二、如何调用

直接调用:多数用户通过 框架 使用,而非直接调 cuDNN C API。PyTorchtorch.nn.functional.scaled_dot_product_attentionbackend="flash_attention"backend="sdpa" 且环境有 cuDNN 时,底层可走 cuDNN fused attention(取决于 PyTorch 与 cuDNN 版本)。启用:需 cuDNN 8+、对应 CUDA、且 PyTorch 编译时启用;运行时通常无需改代码,只要不用 backend="eager" 等强制关闭即可。TensorRT:plugin 或 built-in 中会选用 cuDNN attention;用户通过 ONNX/TRT 图表达 attention 即可。

三、与 FlashAttention 的取舍

cuDNN fused 与 FlashAttention 思路类似(融合、减 IO);FlashAttention 开源、可定制、在长序列与 causal 上优化多;cuDNN 与 NVIDIA 栈集成紧、驱动/库升级即用。实际中 PyTorch SDPA 会按可用性在 FlashAttention、cuDNN、math 等间选择;若已用 SDPA 且环境正常,通常已间接用到 cuDNN 或 FlashAttention。

面试要点

  • cuDNN fused attention:融合 QKV/score/softmax/OV,减少 kernel 与 IO;通过框架间接调用。
  • PyTorch:SDPA 在支持环境下可走 cuDNN;需 cuDNN 8+、对应 CUDA,一般无需改代码。
  • 与 FlashAttention 二选一或由 SDPA 自动选;cuDNN 集成、FlashAttention 可定制。

记忆要点

  1. cuDNN fused = 融合 attention kernel;通过 SDPA/TRT 等调用。
  2. PyTorch SDPA 可走 cuDNN;需 cuDNN 8+。
  3. 与 FlashAttention 由框架按可用性选择。

返回模块 | 返回总览

16-优化技术/200-算子融合的边界判断.md

第 200 题:算子融合的边界判断?融合后register pressure过高?

题目

算子融合的边界判断?融合后register pressure过高?


完整讲解

一、融合的边界

算子融合:把多个小 kernel(如 add + relu、linear + bias + gelu)合并成一个大 kernel,减少 launch 开销与显存往返边界:并非「越融越多越好」;融合后单 kernel寄存器、共享内存 占用会上升,若超过 GPU 限制会导致 occupancy 下降(并行 block 数减少),反而可能变慢;或触发 spilling,增加局部内存访问。

二、Register pressure 过高

Register pressure:每个 thread 使用的寄存器数量过多时,GPU 能同时驻留的 thread block 数 减少(由每个 block 的寄存器总需求与 SM 寄存器总量决定),即 occupancy 低。后果:延迟隐藏能力变差(更多时间在等内存)、利用率下降。判断:用 Nsight Compute 看 kernel 的 OccupancyRegister usage;若融合后 occupancy 明显下降、且 kernel 非带宽极限,可考虑拆开减少单 kernel 内的中间变量(如用更少寄存器、或部分放 shared memory 折中)。

三、工程策略

融合前先 profile 看 launch 与带宽占比;融合后用 ncu 看 occupancy 与 register。若「小 kernel 过多、launch 占主导」则融合收益大;若「单 kernel 已很大、occupancy 已低」则谨慎再融。编译器/自动融合(如 torch.compile)也会做类似权衡;手写时可参考其生成的 kernel 大小与 occupancy。

面试要点

  • 融合有边界:过大会导致 register pressure 升高、occupancy 下降,可能变慢或 spilling。
  • 用 Nsight Compute 看 Occupancy、Register usage;融合后若 occupancy 明显降则考虑拆或减寄存器。
  • 先 profile 看 launch vs 计算;再决定融合粒度;编译器也会做权衡。

记忆要点

  1. 融合边界 = 不能无限融;寄存器/共享内存有限。
  2. Register pressure 高 → occupancy 低 → 可能变慢。
  3. ncu 看 occupancy/register;按需拆或减中间变量。

返回模块 | 返回总览

16-优化技术/201-内存带宽bound-vs-计算bound的判断.md

第 201 题:内存带宽bound vs 计算bound的判断?arithmetic intensity

题目

内存带宽bound vs 计算bound的判断?arithmetic intensity


完整讲解

一、Compute bound vs memory bound

Compute bound:算力是瓶颈,增加的计算能转化为性能提升;GPU 算力吃满、内存带宽有余。Memory bound:内存带宽是瓶颈,减少的访存能转化为性能提升;算力有余、带宽吃满。判断后即可决定优化方向:算力瓶颈 → 提高并行度、算力利用、或减无效计算;带宽瓶颈 → 融合、复用、合并访问、用共享内存等。

二、Arithmetic intensity(算术强度)

Arithmetic intensityAI = FLOPs / Byte,即该 kernel(或算子)每从内存读/写 1 字节能做多少次浮点运算Roofline:设备有「算力屋顶」与「带宽屋顶」;ridge point 对应的 AI 为临界值:AI 低于该值多为 memory bound高于该值多为 compute bound。因此算 AI 即可初步判断:AI 小(如逐元素 op)多为 memory bound;AI 大(如大矩阵乘)多为 compute bound。

三、如何算与用

FLOPs:根据 op 类型与 shape 算(如 matmul M×K × K×N 约 2MNK FLOPs);Byte:该 op 读写的 输入+输出 张量字节数。AI = FLOPs / Byte。与设备 ridge point(带宽/算力比)比较;或直接用 Nsight Compute 的 Roofline 图看该 kernel 落在屋顶哪一侧。优化:memory bound → 提高 AI(融合、复用、减少读写);compute bound → 提高 occupancy、更多有效算力。

面试要点

  • Compute bound = 算力瓶颈;memory bound = 带宽瓶颈;决定优化方向。
  • Arithmetic intensity AI = FLOPs/Byte;与 roofline ridge point 比,低则多 memory bound、高则多 compute bound。
  • 用 ncu Roofline 或手算 AI;memory bound 提 AI,compute bound 提 occupancy。

记忆要点

  1. Compute bound = 算力瓶颈;memory bound = 带宽瓶颈。
  2. AI = FLOPs/Byte;小 AI 多 memory bound,大 AI 多 compute bound。
  3. Roofline 看位置;按 bound 类型选优化手段。

返回模块 | 返回总览

16-优化技术/202-kernel-fusion的手动实现-vs-编译器自动生成.md

第 202 题:kernel fusion的手动实现 vs 编译器自动生成?

题目

kernel fusion的手动实现 vs 编译器自动生成?


完整讲解

一、Kernel fusion 的两种来源

手动实现:用 CUDA(或 Triton)手写一个 kernel,把多个 op 的数学在一个 kernel 里完成(如 linear + bias + relu);完全控制寄存器与共享内存使用、循环与访存模式。编译器自动生成:由 torch.compile、XLA、TensorRT 等根据计算图做 pattern 匹配 + 代码生成,自动把多个 op 合并成融合 kernel;用户无感、覆盖广,但融合策略由编译器决定,未必最优。

二、手动 vs 自动的取舍

手动性能上限高、可针对热点做极致优化(如 FlashAttention);成本高、维护难、覆盖有限,适合极热点、框架/库级自动开发效率高、全图可融、随图变化自动适应;可能 register pressure 或调度不如手写、或未识别某些 pattern。实践:通用 op 融合交给 torch.compile 或 TRT;极热点(如 attention、norm)用手写或成熟库(FlashAttention、cuDNN);二者结合。

面试要点

  • 融合可手写(CUDA/Triton)或由编译器(torch.compile、XLA、TRT)自动做。
  • 手写:性能上限高、成本高,适合极热点;自动:覆盖广、开发效率高,可能非最优。
  • 实践:通用融合用编译器;极热点用手写/成熟库。

记忆要点

  1. 手写 = CUDA/Triton,完全可控;自动 = 编译器按图融合。
  2. 手写适合极热点;自动适合全图、快速迭代。
  3. 结合:通用用 compile,热点用 FlashAttention 等。

返回模块 | 返回总览

16-优化技术/203-CUDA-Graph的捕获和重放.md

第 203 题:CUDA Graph的捕获和重放?torch.cuda.make_graphed_callables

题目

CUDA Graph的捕获和重放?torch.cuda.make_graphed_callables


完整讲解

一、CUDA Graph 的作用

CUDA Graph:将一段 CUDA 调用序列(kernel + 拷贝等)录制成一张「图」,之后通过 重放 一次性提交整图,减少 host 侧 launch 次数与同步,降低延迟与 CPU 开销。适合小 kernel 多、重复执行的推理或训练 step。

二、捕获与重放

捕获:在 cudaStreamBeginCapture / cudaStreamEndCapture 之间执行要录制的 CUDA 操作(同一 stream),得到 cudaGraph_t重放cudaGraphLaunch(graph, stream) 一次性提交整图。约束:捕获期间不能做 host 同步、不能 动态分配、不能某些无法捕获的 API;图内 指针与 size 固定,若输入输出地址或 shape 变化需重新捕获或使用 graph 的 updatable 节点(部分 API 支持)。

三、torch.cuda.make_graphed_callables

PyTorch 提供 make_graphed_callables:对给定的 callable(如 model forward)做 warmup 运行 + 捕获,返回一个可重放的 callable,内部用 CUDA Graph 执行。适合 固定 shape 的推理或训练 step;动态 shape 需多套 graph 或 fallback。使用时可把 forward 与 loss backward 分别做 graphed callable,或整 step 一图(若满足捕获约束)。

面试要点

  • CUDA Graph:录制一段 CUDA 序列为图,重放时一次提交,减 launch 与 host 开销。
  • 捕获:BeginCapture/EndCapture;重放:GraphLaunch;约束:无 host sync、指针/size 固定等。
  • make_graphed_callables:对 callable 做 warmup+捕获,返回可重放版本;适合固定 shape。

记忆要点

  1. Graph = 录制成图 + 重放;减 launch 与 CPU 开销。
  2. 捕获约束:无 host sync、固定指针/size;变 shape 需重捕或多图。
  3. make_graphed_callables 封装了 warmup+捕获;固定 shape 推理/step 适用。

返回模块 | 返回总览

16-优化技术/204-动态shape的优化困境.md

第 204 题:动态shape的优化困境?torch.compiledynamic=True

题目

动态shape的优化困境?torch.compiledynamic=True


完整讲解

一、动态 shape 的困境

动态 shape:batch、seq_len 等维度在运行时变化(如不同请求不同长度)。困境:(1)编译/优化:TensorRT、torch.compile 等常针对固定 shape 做 kernel 选择与融合,动态时需为多种 shape 编译或 runtime 选择,增加编译时间与缓存复杂度;(2)CUDA Graph:图内 size 固定,shape 变需重捕或多图;(3)性能:同一 kernel 在不同 shape 下效率不同,动态难以「每 shape 最优」。

二、torch.compile 的 dynamic=True

torch.compile(..., dynamic=True):告诉编译器 batch 或某些维是动态的,生成的代码会保留动态分支参数化 shape,在运行时按实际 shape 执行,而非为单一 shape 特化。好处:一套编译结果可应对多种 shape,减少 recompile。代价:可能无法做某些强依赖固定 shape 的优化(如部分融合、静态分配),性能可能略逊于固定 shape 的专门编译。适用:推理请求 batch/seq 多变、或训练中 batch 不固定时使用。

三、工程取舍

固定 shape:推理时 padding 到固定长度batch 固定,便于极致优化与 CUDA Graph;动态 shape:少 padding 浪费、接口灵活,用 dynamic=True 或多 shape 编译。长尾 shape 可 fallback 到 eager按桶(bucket) 编译几种典型 shape。

面试要点

  • 动态 shape 导致编译/优化复杂、CUDA Graph 难用、难以每 shape 最优。
  • torch.compile(..., dynamic=True) 生成适应动态维的代码,一套编译多 shape;可能牺牲部分优化。
  • 取舍:固定 shape 利于极致优化;动态 + dynamic=True 或按桶编译折中。

记忆要点

  1. 动态 shape:编译多、Graph 难、性能难每 shape 最优。
  2. dynamic=True:一套编译应对多 shape;可能少部分优化。
  3. 固定 vs 动态:按业务选;可 bucket 或 fallback。

返回模块 | 返回总览

16-优化技术/205-torch.backends.cudnn.benchmark的作用和副作用.md

第 205 题:torch.backends.cudnn.benchmark的作用和副作用?

题目

torch.backends.cudnn.benchmark的作用和副作用?


完整讲解

一、cudnn.benchmark 的作用

torch.backends.cudnn.benchmark = True:让 cuDNN 在首次遇到某组 (op, shape, dtype) 时,自动跑多种卷积/RNN 等算法,选其中最快的并缓存,后续同配置直接用该算法。目的:在 shape 固定 的训练或推理中,减少「每次都试一遍」的开销,并选到当前硬件上更优的算法,往往能明显提速(尤其卷积多、shape 不变时)。

二、副作用

首次迭代变慢:第一次遇到新 shape 会做 benchmark 试跑,该 step 会偏慢。显存:某些「更快」的算法可能显存更大(如用更多 workspace),极端情况下可能 OOM;若遇 OOM 可尝试关 benchmark 或限制 cuDNN workspace。非确定性:不同 run 可能选到不同算法(若多算法性能接近),数值结果可能略有差异;若需严格可复现(如论文、合规),可设 benchmark=False 并配合 cudnn.deterministic

三、使用建议

训练/推理 shape 固定:默认开 benchmark=True 即可。shape 多变:每次新 shape 都会触发一次 benchmark,可能反而不划算,可关或按需开。严格复现:benchmark=False + deterministic。

面试要点

  • cudnn.benchmark=True:cuDNN 对每类 (op,shape) 试多种算法、选最快并缓存;shape 固定时提速明显。
  • 副作用:首次新 shape 慢、可能更占显存、算法选择可能导致非确定性。
  • shape 固定可开;shape 多变或要严格复现时可关或加 deterministic。

记忆要点

  1. benchmark = 自动选最快算法并缓存;固定 shape 提速。
  2. 副作用:首 iter 慢、显存可能增、非确定性。
  3. 固定 shape 开;要复现时关 + deterministic。

返回模块 | 返回总览

16-优化技术/206-CPU-offload的pin_memory和non_blocking.md

第 206 题:CPU offload的pin_memorynon_blocking

题目

CPU offload的pin_memorynon_blocking


完整讲解

一、CPU-GPU 拷贝与 pin_memory

CPU 到 GPU 的数据拷贝若走 pinned memory(页锁定内存),DMA 可直接访问、带宽更高,且可与 GPU 计算异步进行。pin_memory=True(在 DataLoader 的 tensor 或 torch.Tensor.pin_memory()):把 tensor 放在 pinned 页,拷贝到 GPU 时用 async copy,减少阻塞与总时间。

二、non_blocking

non_blocking=True(在 .to(device, non_blocking=True)):表示 CPU→GPU 拷贝异步的,当前 CPU 流不等待拷贝完成就返回;GPU 侧在使用该 tensor 前需保证拷贝已完成(通常由 CUDA 流依赖自动保证,或后续 kernel 在同一 stream 上会等待)。这样 CPU 可继续 准备下一批或做其它事,与 GPU 计算重叠,提高吞吐。

三、配合使用

DataLoader 里 pin_memory=True 使取出的 tensor 在 pinned 区;训练循环里 .to(device, non_blocking=True) 做异步拷贝。需保证使用前拷贝已完成:同一 stream 上后续 kernel 会自动等;若多 stream 需 event 同步。典型场景:数据加载与上一 batch 的 GPU 计算重叠,减少「GPU 等数据」的 gap。

面试要点

  • pin_memory:tensor 放页锁定内存,CPU→GPU 拷贝更快、可异步;DataLoader 或 tensor.pin_memory()。
  • non_blocking=True:.to(device) 异步,CPU 不等待拷贝完成;与 GPU 计算重叠需流/event 保证顺序。
  • 配合:DataLoader pin_memory + to(device, non_blocking=True);重叠加载与计算。

记忆要点

  1. pin_memory = 页锁定、DMA 友好、异步拷贝。
  2. non_blocking = 异步 to(device);用流/event 保证使用前拷贝完成。
  3. 二者配合重叠 IO 与计算。

返回模块 | 返回总览

16-优化技术/207-数据预处理的multi-processing优化.md

第 207 题:数据预处理的multi-processing优化?num_workers调优?

题目

数据预处理的multi-processing优化?num_workers调优?


完整讲解

一、多进程加载的目的

DataLoader多进程(num_workers>0)在多个 CPU 进程里并行做 读数据、解码、增强,通过 队列 把 batch 送给主进程,减少「主进程串行做 IO + 预处理」导致的 GPU 等数据。多进程可把数据加载与 GPU 计算重叠,提高吞吐。

二、num_workers 调优

过小:预取不足,GPU 常等数据;过大:CPU 与内存争抢、进程切换开销、可能反而变慢,且 共享内存 占用增加。经验:从 4~8 起调,看 GPU 利用率吞吐;若 GPU 利用率已高、再增 workers 无提升则可停。与 batch 关系:通常 workers 略大于或等于「能填满 GPU 的 pipeline 深度」(如 2×batch 预取),不必远大于。Windows:多进程有 spawn 限制,有时 num_workers=0 或 1 更稳,可配合 prefetch_factor。

三、其它要点

persistent_workers=True:worker 进程不随 epoch 结束而销毁,避免每 epoch 重新 fork;适合多 epoch 训练。pin_memory + non_blocking:与 206 题配合。GIL:解码与 Python 逻辑在 worker 里执行,若 Python 侧过重可考虑 DALI 或 C++ 扩展把重活迁出。

面试要点

  • 多进程 DataLoader:并行读与预处理,与 GPU 计算重叠;num_workers>0。
  • num_workers 从 4~8 起调,看 GPU 利用率与吞吐;过大反而可能变慢或占内存。
  • persistent_workers 多 epoch 可开;配合 pin_memory、non_blocking;重活可迁 DALI。

记忆要点

  1. 多进程 = 并行加载与预处理;减 GPU 等数据。
  2. num_workers 适度;过小等数据、过大争资源。
  3. persistent_workers、pin_memory、non_blocking 配合。

返回模块 | 返回总览

16-优化技术/208-DALI的GPU-decoding和augmentation.md

第 208 题:DALIGPU decodingaugmentation

题目

DALIGPU decodingaugmentation


完整讲解

一、DALI 的 GPU decoding

NVIDIA DALI:在 GPU 上做解码(如 JPEG、视频帧),数据从存储或 CPU 传到 GPU 后,由 DALI 的 GPU 解码算子 在 GPU 上完成 decode,输出 GPU tensor。这样 CPU 解码 不再是瓶颈,且解码与后续 增强、训练计算 可在 GPU 上流水线重叠,减少 CPU-GPU 拷贝与等待。

二、GPU augmentation

DALI 还提供 GPU 上的数据增强:crop、resize、flip、normalize、color jitter 等可在 GPU pipeline 里做,输出直接供训练。与「CPU 解码 + CPU 增强 + 再拷到 GPU」相比,省去一次 CPU→GPU 的 batch 拷贝,并可与训练 kernel 重叠(DALI 产出下一 batch 时 GPU 在算上一 batch)。

三、使用场景与注意点

适合:图像/视频训练、解码与增强 占 CPU 较多、GPU 利用率上不去时。集成:通过 DALI iteratorPyTorch DataLoader 适配 与训练循环对接;需保证 GPU 显存能同时容纳 DALI 的 buffer 与模型。不适合:纯文本、或数据已预处理好只需简单 tensor 化时,DALI 收益有限;小数据集或 IO 非瓶颈不必上。

面试要点

  • DALI GPU decoding:解码在 GPU 上做,减轻 CPU 瓶颈;与训练计算可重叠。
  • DALI GPU augmentation:crop/resize 等在 GPU pipeline;省 CPU→GPU batch 拷贝。
  • 适合解码/增强重的 CV;与 PyTorch 通过 iterator 对接;显存与 pipeline 需兼顾。

记忆要点

  1. GPU decoding = 解码在 GPU;减 CPU 瓶颈。
  2. GPU augmentation = 增强在 GPU pipeline;省拷贝、可重叠。
  3. 适合 CV、解码重;对接 PyTorch;注意显存。

返回模块 | 返回总览

16-优化技术/209-混合精度训练的numerical-stability问题.md

第 209 题:混合精度训练的numerical stability问题?

题目

混合精度训练的numerical stability问题?


完整讲解

一、混合精度的数值风险

FP16/BF16 范围与精度低于 FP32:溢出(大数变 inf)、下溢(小数变 0)、舍入误差累积。在 loss scaling、梯度、某些层 上可能表现为 loss NaN、梯度爆炸/消失、训练不稳

二、常见问题与对策

Loss scaling:梯度在 FP16 下容易下溢;用 动态或静态 scale 放大梯度再做 backward,还原后再 unscale 更新;可避免梯度变 0。敏感层LayerNorm、Softmax、loss 等保持 FP32(或 BF16)计算,仅部分 linear/matmul 用 FP16,即 混合精度 而非全 FP16。BF16:指数域与 FP32 同,范围大,不易溢出,可减少 scaling 与 cast;精度略逊 FP16,通常训练更稳。检查:训练中监控 梯度 norm、loss;若出现 NaN 可先关混合精度做 baseline,再逐层或逐 op 放宽精度定位。

三、工程实践

PyTorch AMP(autocast + GradScaler):autocast 自动选 op 精度,GradScaler 做 loss scale 与 unscale;一般够用。自定义:对已知敏感 op 用 torch.amp.autocast(..., enabled=False) 包一层保持 FP32。数值稳定性速度 需权衡;BF16 在 A100 等上推荐为首选。

面试要点

  • 混合精度有溢出/下溢/舍入风险;loss scaling、敏感层 FP32、BF16 可缓解。
  • Loss scaling(GradScaler);LayerNorm/Softmax/loss 等保持 FP32;BF16 范围大更稳。
  • AMP:autocast + GradScaler;敏感 op 可局部关 autocast。

记忆要点

  1. 风险:溢出、下溢、舍入;loss scaling + 敏感层 FP32。
  2. BF16 范围大、不易溢出;AMP 常用 GradScaler。
  3. 监控梯度/loss;NaN 时先关 AMP 再逐层排查。

返回模块 | 返回总览

16-优化技术/210-gradient-accumulation的effective-batch-.md

第 210 题:gradient accumulationeffective batch size计算?

题目

gradient accumulationeffective batch size计算?


完整讲解

一、Gradient accumulation 的含义

Gradient accumulation:把 N 个 mini-batch 的梯度累加后再做一次 optimizer.step(),等价于用 N×mini-batch_size 的「大 batch」做一次更新,但显存只需容纳 一个 mini-batch 的前向与反向。用于 显存不够 直接跑大 batch、但又希望 effective batch size 较大时。

二、Effective batch size 计算

Effective batch size = mini_batch_size × accumulation_steps。例如 mini_batch_size=8、accumulation_steps=4,则每 4 个 step 做一次更新,effective batch size = 8×4 = 32等价:与「一次前向 32 个样本再 backward」在梯度与更新上等价(若无 BN 等依赖 batch 统计的层,或 BN 用 running stat);时间上约为 4 倍小 step 的前向+反向 + 1 次优化器,显存约 1 倍小 batch。

三、与学习率等配合

大 effective batch 通常要配合 learning rate scaling(线性或 sqrt 放大);以及 warmup总 step 数 按 effective batch 折算(如总样本数 / effective_batch_size 为 epoch 内更新次数)。BN:若用 BN,当前实现下每 mini-batch 的 mean/var 仍按小 batch 算,与「真大 batch」略有差异;可改用 SyncBNLayerNorm 减轻对 batch 的依赖。

面试要点

  • Gradient accumulation:多 mini-batch 梯度累加再一步更新;显存按 mini-batch,等效大 batch 更新。
  • Effective batch size = mini_batch_size × accumulation_steps。
  • 配合 lr scaling、warmup、总 step 折算;BN 时注意 batch 统计与小 batch 差异。

记忆要点

  1. 累加 N 次梯度再 step;effective = mini_batch × N。
  2. 显存省、等效大 batch;与 lr scaling 配合。
  3. BN 时每 mini-batch 统计;可 SyncBN 或 LayerNorm。

返回模块 | 返回总览

16-优化技术/211-大batch训练的learning-rate-scaling规则.md

第 211 题:大batch训练的learning rate scaling规则?

题目

大batch训练的learning rate scaling规则?


完整讲解

一、大 batch 与学习率

大 batch:单步更新用更多样本,梯度估计更准,但单步更新次数减少。若保持与小 batch 相同总样本数,大 batch 的 总 step 数 会少;若 学习率不变,可能欠拟合或收敛慢。经验上大 batch 需要 更大学习率 以补偿「每步更新更准、步数更少」。

二、Linear scaling 规则

Linear scaling:batch 扩大 k 倍,学习率也扩大 k 倍(如 batch 从 256 到 1024,lr 从 0.1 到 0.4)。依据:梯度是 mini-batch 平均,方差约与 batch 成反比;步长(lr×grad)若与 batch 同比例放大,每步「有效进展」大致相当。适用:在 一定范围内(如 8~64 倍)有效;过大 batch(如 8k+)时线性可能过激,需 warmupsqrt scaling(lr ∝ √batch)更稳。

三、Warmup 与 fine-tuning

Warmup:大 batch 训练前期用 小学习率 若干 step 再升到目标 lr,避免初期大更新导致不稳定。LARS/LAMB 等优化器针对大 batch 做了 per-layer 或自适应 scaling,可减少纯线性规则的副作用。实践:先在小 batch 上找合适 lr,再按 linear(或 sqrt)乘上 batch 比,加 warmup;大 batch 时可用 LARS/LAMB 或调低 scaling 系数。

面试要点

  • 大 batch 步数少、梯度更准;通常需更大 lr 补偿;linear scaling:lr ∝ batch。
  • 过大 batch 可用 sqrt scaling 或 warmup;LARS/LAMB 做 per-layer/自适应。
  • 先小 batch 定 lr,再按比例放大 + warmup;大 batch 可试 LARS/LAMB。

记忆要点

  1. 大 batch → 更大 lr;linear:lr 随 batch 线性增。
  2. 过大 batch:warmup、sqrt scaling;LARS/LAMB 可辅助。
  3. 小 batch 定 lr → 按比例 + warmup。

返回模块 | 返回总览

16-优化技术/212-LARS、LAMB优化器在大batch场景的应用.md

第 212 题:LARSLAMB优化器在大batch场景的应用?

题目

LARSLAMB优化器在大batch场景的应用?


完整讲解

一、大 batch 的难点

大 batch 时常用 大学习率(linear scaling),易导致训练不稳泛化变差LARS(Layer-wise Adaptive Rate Scaling)、LAMB(Layer-wise Adaptive Moments for Batching)通过 逐层逐参数自适应缩放 学习率,使大 batch 下各层更新幅度更合理,便于稳定训练扩展 batch

二、LARS 思路

LARS:对每层(或每参数组)计算 梯度范数权重范数 的比,用该比 缩放 该层的有效学习率;梯度大的层相对「压一压」、梯度小的层相对「抬一抬」,避免某层更新过大或过小。公式上常为 trust_coef × (weight_norm / grad_norm) 再乘全局 lr;实现时在 optimizer 里 per-param 或 per-group 做 scaling。

三、LAMB 与使用场景

LAMB:在 Adam 类(一阶+二阶矩)基础上,对 update 做 L2 norm 约束 再与 weight norm 比,做 layer-wise 的 adaptive learning rate;兼顾 Adam 的适应性与大 batch 稳定性。应用:大 batch BERT 等预训练、超大 batch(如 64k)分布式训练;PyTorch 无内置时可从 NVIDIA ApexDeepSpeed 等取 LAMB 实现,或自写 optimizer。

面试要点

  • LARS/LAMB:逐层(或逐参数)自适应缩放学习率,大 batch 下更稳、易扩展。
  • LARS:用梯度范数与权重范数比缩放每层 lr;LAMB:Adam + norm 约束的 layer-wise 缩放。
  • 大 batch 预训练、超大 batch 分布式常用;实现见 Apex/DeepSpeed 或自写。

记忆要点

  1. LARS/LAMB = 大 batch 下逐层自适应 lr。
  2. LARS = grad_norm/weight_norm 比;LAMB = Adam + norm 约束。
  3. 大 batch 预训练、超大 batch 常用。

返回模块 | 返回总览

16-优化技术/213-模型并行的communication-hiding技术.md

第 213 题:模型并行的communication hiding技术?

题目

模型并行的communication hiding技术?


完整讲解

一、Communication hiding 的含义

Communication hiding:在模型并行(含流水线、张量并行)中,让 计算与通信在时间上重叠,用 计算 去「藏」通信延迟,使通信不单独占用 wall-clock 时间,从而提高整体效率。若不重叠,总时间 ≈ 计算时间 + 通信时间;重叠后总时间 ≈ max(计算, 通信) 或略多。

二、常见手段

预取(overlap):在 需要某数据之前 就发起 recv 或 all-reduce,在后续计算进行时通信在后台完成;到真正用该数据时已就绪。例如:下一层的 all-reduce 与当前层计算重叠;或 send 本层结果的同时做下一层计算双缓冲 / 多 buffer:用 两套(或多套)buffer 轮转:一套在算、一套在通信,下一轮交换。异步通信:用 非阻塞 collective(如 ncclAllReduce 异步版)或 point-to-point 的 isend/irecv,不阻塞计算流;用 event/stream 保证「用数据前通信完成」。

三、与流水线、张量并行的结合

流水线:各 stage 间 send/recv 与 backward/forward 重叠;micro-batch 调度使「算」与「传」并行。张量并行:all-reduce 与 matmul 重叠(如 Megatron 中 column/row 并行后的 all-reduce 与后续层计算重叠)。实现:依赖 CUDA stream、NCCL 非阻塞 API、以及计算图切分 使通信与计算在不同 stream 或不同阶段交错。

面试要点

  • Communication hiding:计算与通信重叠,用计算藏通信延迟;总时间 ≈ max(计算,通信)。
  • 手段:预取、双缓冲、异步 collective/point-to-point;event/stream 保证依赖。
  • 流水线中 stage 间传与算重叠;张量并行中 all-reduce 与 matmul 重叠。

记忆要点

  1. Hiding = 计算与通信重叠;总时间 ≈ max(算,通信)。
  2. 预取、双缓冲、异步通信;stream/event 保证顺序。
  3. 流水线/张量并行中与层间通信重叠。

返回模块 | 返回总览

16-优化技术/214-pipeline-bubble的数学分析和优化.md

第 214 题:pipeline bubble的数学分析和优化?

题目

pipeline bubble的数学分析和优化?


完整讲解

一、Pipeline bubble 的含义

流水线 把模型按 layer 或 stage 分到多设备,micro-batch 依次流过各 stage。Bubble:在 填满管道排空管道 的阶段,部分 stage 空闲(在等前/后 micro-batch),这段时间没有有效计算,即 pipeline bubble,造成 利用率损失

二、数学上对 bubble 的刻画

S = stage 数M = micro-batch 数理想:所有 stage 一直满负荷时,总 step 约为 S + M - 1(或按 backward 再乘约 2)。Bubble 占比:约 (S-1)/M(填满+排空阶段约 2(S-1) 个「半满」步,相对总步数)。结论M 越大,bubble 占比越小;S 越大,bubble 绝对量越大。因此 增加 micro-batch 数 可降低 bubble 比例;减少 stage 数(在显存允许下)也可减 bubble。

三、优化方向

多 micro-batch:在显存与调度允许下增大 M,使 bubble/(S+M) 变小。非对称或 1F1B1F1B(One Forward One Backward)等调度让各 stage 尽早做 backward,减少「只等 forward」的空闲。Re-materialization:少存激活、用重算换显存,从而支持更多 micro-batch。Stage 划分:尽量让各 stage 计算量均衡,避免某 stage 特别长拖慢整管。

面试要点

  • Pipeline bubble:填满/排空管道时部分 stage 空闲;bubble 占比约与 (S-1)/M 相关。
  • M 大则 bubble 占比小;S 大则 bubble 绝对量多;1F1B 等调度可减空闲。
  • 优化:多 micro-batch、1F1B、均衡 stage、recompute 换显存增 M。

记忆要点

  1. Bubble = 管道未满时 stage 空闲;占比约 (S-1)/M。
  2. M↑ 占比↓;S↑ 绝对量↑;1F1B 减空闲。
  3. 多 M、均衡 stage、recompute。

返回模块 | 返回总览

16-优化技术/215-稀疏attention的优化.md

第 215 题:稀疏attention的优化?Sparse TransformerLongformer

题目

稀疏attention的优化?Sparse TransformerLongformer


完整讲解

一、稀疏 attention 的动机

全连接 attention 的复杂度是 O(L²)(L 为序列长),长序列时显存与算力都贵。稀疏 attention:只对 部分位置局部+全局 做 attention,使复杂度降为 O(L√L)O(L log L) 等,在长序列上可训、可推。

二、Sparse Transformer、Longformer

Sparse Transformer(OpenAI):通过 strided / fixed稀疏 pattern,每个位置只 attend 到 局部窗口 + 若干 stride 的全局点,用 稀疏矩阵分块计算 实现,减少计算与显存。Longformer局部窗口 + 全局 token(如 [CLS] 或若干 global position);局部用滑动窗口、全局用少量 token 做全局 attention,实现 O(L) 的线性复杂度。二者都需 自定义 attention mask 或 kernel,与标准 dense attention 接口不同。

三、实现与优化

实现:可在 PyTorch 中 mask 掉 不 attend 的位置(稀疏 mask),或调用 FlashAttention 等对稀疏 pattern 的支持;Longformer 有官方实现与 HuggingFace 集成。优化:稀疏后 访存与计算 模式不规则,需专用 kernel 或 block-sparse 以达高效;否则稀疏 mask 在 dense kernel 上仍可能做无效计算。

面试要点

  • 稀疏 attention:只对部分位置/局部+全局计算,复杂度低于 O(L²);适合长序列。
  • Sparse Transformer:strided/fixed pattern;Longformer:局部窗口+全局 token、O(L)。
  • 实现:稀疏 mask 或专用 kernel;需 block-sparse/专用实现才能高效。

记忆要点

  1. 稀疏 = 非全连接;降复杂度与显存。
  2. Sparse Transformer = 稀疏 pattern;Longformer = 局部+全局、线性。
  3. 专用 kernel 或 block-sparse 才能高效。

返回模块 | 返回总览

17-训练平台设计/README.md

17-训练平台设计(第 216–235 题)

题号 主题 文章
216 设计一个支持1000卡规模的训练平台,核心组件有哪些? 216-设计一个支持1000卡规模的训练平台,核心组件有哪些.md
217 训练平台的job scheduler如何设计?FIFO vs `… 217-训练平台的job-scheduler如何设计.md
218 分布式存储的选择?CephJuiceFSGPFS对比? 218-分布式存储的选择.md
219 训练容器的镜像管理?layer cachingregistry 219-训练容器的镜像管理.md
220 网络架构设计?InfiniBand vs RoCE?`fat-t… 220-网络架构设计.md
221 故障检测和自动恢复机制?heartbeatwatchdog 221-故障检测和自动恢复机制.md
222 训练数据的global shuffle实现?`shuffle buf… 222-训练数据的global-shuffle实现.md
223 模型仓库的设计?版本管理血缘追踪 223-模型仓库的设计.md
224 超参搜索(HPO)的基础设施?OptunaRay Tune集成… 224-超参搜索(HPO)的基础设施.md
225 训练平台的multi-tenancy隔离?namespace、`… 225-训练平台的multi-tenancy隔离.md
226 资源碎片整理(defragmentation)策略? 226-资源碎片整理(defragmentation)策略.md
227 训练任务的dry-runprofiling模式? 227-训练任务的dry-run和profiling模式.md
228 模型压缩服务的集成?量化剪枝流水线? 228-模型压缩服务的集成.md
229 训练平台的cost model?预测任务耗时和资源需求? 229-训练平台的cost-model.md
230 如何支持异构计算?CPUGPUTPU统一调度? 230-如何支持异构计算.md
231 训练平台的SLA定义?job completion time保证… 231-训练平台的SLA定义.md
232 数据隐私和合规?联邦学习基础设施? 232-数据隐私和合规.md
233 训练平台的disaster recovery?跨地域备份? 233-训练平台的disaster-recovery.md
234 模型CI/CD流水线?自动化测试、benchmark? 234-模型CI-CD流水线.md
235 训练平台的observability?日志、指标、链路追踪? 235-训练平台的observability.md

返回总览

17-训练平台设计/216-设计一个支持1000卡规模的训练平台,核心组件有哪些.md

第 216 题:设计一个支持1000卡规模的训练平台,核心组件有哪些?

题目

设计一个支持1000卡规模的训练平台,核心组件有哪些?


完整讲解

一、规模与挑战

1000 卡 意味着数百节点、数千进程的协同调度、网络与存储;需支持 gang scheduling拓扑感知故障恢复多租户。核心组件围绕 资源管理、作业调度、通信与存储、可观测与运维 设计。

二、核心组件

调度与资源Job scheduler(如 Volcano 或自研)支持 gang、队列、优先级、抢占资源抽象(K8s Device Plugin 或 Slurm gres)暴露 GPU 与拓扑;Quota / 多租户(namespace、PriorityClass、队列 cap)。计算与通信容器/运行时(K8s + containerd 或 Slurm);高速网络(IB/RoCE)与 NCCL 拓扑感知;训练框架(PyTorch/Megatron 等)与 分布式启动(torchrun、elastic)。存储共享存储(Lustre/JuiceFS/Ceph)存数据与 checkpoint;元数据与配置(etcd、配置中心)。可观测监控(Prometheus + DCGM/node_exporter)、日志与 trace成本与利用率 看板。

三、扩展与高可用

控制面:scheduler、API、etcd 等 多副本与高可用存储 多副本与故障域。弹性:支持 弹性扩缩(如 Ray、Kueue)时需与 gang 与 checkpoint 配合。安全与计费:认证/授权、网络策略、GPU 小时计费 与 quota。

面试要点

  • 1000 卡需 gang、拓扑、故障恢复、多租户;组件:调度、资源、网络、存储、可观测。
  • 调度器(Volcano 等)+ 设备插件 + 队列/quota;IB/RoCE + NCCL;共享存储 + checkpoint。
  • 控制面高可用、存储多副本;计费与安全。

记忆要点

  1. 核心:调度(gang/队列)、资源抽象、网络(IB/NCCL)、存储、监控。
  2. 多租户:quota、priority、队列;可观测:DCGM、Prometheus、日志。
  3. 高可用、计费、安全。

返回模块 | 返回总览

17-训练平台设计/217-训练平台的job-scheduler如何设计.md

第 217 题:训练平台的job scheduler如何设计?FIFO vs priority vs `fair shari…

题目

训练平台的job scheduler如何设计?FIFO vs priority vs fair sharing


完整讲解

一、FIFO

FIFO(先来先服务):按提交顺序排队,先提交的先调度。优点:实现简单、公平、无饥饿。缺点:大 job 会堵住后面小 job(head-of-line blocking);紧急任务无法插队;不适合多租户与混合负载。

二、Priority

Priority:每个 job 有优先级(数字或等级),高优先调度;可配合抢占(高优可抢占低优资源)。优点:紧急/生产任务可优先;适合多租户(付费高优、实验低优)。缺点:低优可能饥饿;需设 priority 上限、quota、或 fairness 约束。

三、Fair sharing

Fair sharing:按用户或队列历史使用量权重 分配资源,使长期占用趋于公平(用得多的优先级随时间下降)。优点:多用户下公平、防止单用户占满。缺点:实现复杂(需 usage 统计与动态权重);可能与 deadline、SLA 冲突。实践:三者常组合:队列内 fair sharing、队列间 priority;或 FIFO + priority 覆盖(高优可插队);再配 quota 防单用户占满。

面试要点

  • FIFO:先来先服务;简单公平但易 head-of-line blocking。
  • Priority:高优先调、可抢占;需防低优饥饿、配 quota。
  • Fair sharing:按使用/权重公平分;可组合:队列内 fair、队列间 priority。

记忆要点

  1. FIFO = 顺序;Priority = 高优先、可抢占;Fair = 按使用公平。
  2. 组合:fair 队列内 + priority 队列间;quota 限单用户。
  3. 按业务选:简单用 FIFO;多租户用 priority + fair。

返回模块 | 返回总览

17-训练平台设计/218-分布式存储的选择.md

第 218 题:分布式存储的选择?CephJuiceFSGPFS对比?

题目

分布式存储的选择?CephJuiceFSGPFS对比?


完整讲解

一、Ceph

Ceph:开源 分布式存储,提供 对象、块、文件 接口;可扩展、自愈,适合大规模。训练:RBD 或 CephFS 做 共享盘(数据、checkpoint);带宽与延迟 依赖网络与配置,大顺序读可调 pool 与 PG。运维:部署与调优复杂;需专业运维。

二、JuiceFS

JuiceFS元数据与数据分离;元数据在 Redis/MySQL 等,对象数据在 S3/OSS/本地。对计算节点呈现为 POSIX 文件系统(FUSE 或 CSI),兼容性好训练:数据与 checkpoint 放 JuiceFS;缓存(本地 SSD/内存)可加速热数据;适合 云上 + 对象存储 或混合存储。运维:相对轻量;需维护元数据服务与对象后端。

三、GPFS(Spectrum Scale)

GPFS:商业 并行文件系统高带宽、高可靠,多用于 HPC 与金融。训练:共享 home、数据集、checkpoint;性能与特性 强,成本高选型大规模 HPC/企业 有预算选 GPFS;开源、自建 选 Ceph 或 JuiceFS;云上、对象存储为主 选 JuiceFS + 对象存储;小规模 可用 NFS 或单机盘。

面试要点

  • Ceph:对象/块/文件、可扩展;适合自建大规模;运维复杂。
  • JuiceFS:元数据+对象分离、POSIX、可缓存;适合云上、对象存储。
  • GPFS:商业、高带宽高可靠;有预算的 HPC/企业。

记忆要点

  1. Ceph = 开源分布式、对象/块/文件;JuiceFS = 元数据+对象、POSIX。
  2. GPFS = 商业、高性能;选型看规模、预算、是否云上。
  3. 训练共享:数据+checkpoint;JuiceFS 可做缓存加速。

返回模块 | 返回总览

17-训练平台设计/219-训练容器的镜像管理.md

第 219 题:训练容器的镜像管理?layer cachingregistry优化?

题目

训练容器的镜像管理?layer cachingregistry优化?


完整讲解

一、镜像管理需求

训练任务需统一环境(CUDA、PyTorch、依赖);镜像 大(数十 GB)、拉取慢 会拖慢任务启动。需 layer 复用、就近拉取、版本与安全 管理。

二、Layer caching

Layer caching:镜像由 多层 组成;相同 layer 只拉一次,后续任务复用本地缓存。实现:节点本地 image cache(如 containerd 的 snapshot、Dragonfly 的 P2P 缓存);registry 返回 layer digest,节点按需拉缺失层。多节点P2P 分发(如 Dragonfly、Kraken)让节点间互拉 layer,减轻 registry 与带宽压力;首拉仍可能慢,可 预热 常用镜像到节点。

三、Registry 优化

Registry:用 Harbor 或云厂商 镜像仓库,支持 多副本、CDN、就近 region优化:训练镜像 按基础层与业务层 拆分,基础层(CUDA、PyTorch)大但复用高,业务层小且常变;这样多数任务只拉增量层安全:镜像扫描、签名与准入;避免不可信镜像进生产。

面试要点

  • 训练镜像大、拉取慢;layer caching 使相同层复用,P2P 可加速多节点拉取。
  • Registry 就近、多副本、CDN;镜像按基础/业务分层,减少拉取量。
  • 预热常用镜像;安全扫描与签名。

记忆要点

  1. Layer cache = 同层复用;P2P 多节点互拉。
  2. Registry 就近、分层镜像(基础+业务)。
  3. 预热、安全扫描。

返回模块 | 返回总览

17-训练平台设计/220-网络架构设计.md

第 220 题:网络架构设计?InfiniBand vs RoCEfat-tree拓扑?

题目

网络架构设计?InfiniBand vs RoCEfat-tree拓扑?


完整讲解

一、InfiniBand vs RoCE

InfiniBand:专用 HPC 网络低延迟、高带宽、无损NCCL 与 MPI 支持好;成本高、运维专,多用于超算与大规模训练。RoCE(RDMA over Converged Ethernet):在 以太网 上跑 RDMA硬件与布线 可与现有以太网共用,成本与兼容 更好;需 PFC/ECN 等做无损有损配置,否则拥塞时可能丢包、影响 NCCL。选型极致性能与规模 选 IB;成本与已有以太网 选 RoCE,并做好 DCQCN/PFC 与交换机配置。

二、Fat-tree 拓扑

Fat-tree多级 交换机(spine-leaf 或三层),上行与下行带宽 逐级收敛,使 任意两节点 间有多路径、无 oversubscription(或可控)。训练:all-reduce 等多对多 通信依赖无阻塞或低阻塞 网络;fat-tree 便于 ECMP拓扑感知 调度(同 job 放同 leaf/rack)。规模:千卡级常用 spine-leafclos;需与 NCCL 拓扑发现 配合做 最优 rank 映射

面试要点

  • IB:低延迟高带宽、专用、成本高;RoCE:以太网+RDMA、成本低,需无损/拥塞控制。
  • Fat-tree:多级、无/低阻塞、多路径;适合 all-reduce 与拓扑感知调度。
  • 千卡级 spine-leaf/clos;NCCL 拓扑与 rank 映射配合。

记忆要点

  1. IB = 专用、高性能;RoCE = 以太网 RDMA、需 PFC/ECN。
  2. Fat-tree = 多级、无阻塞、多路径。
  3. 拓扑感知 + rank 映射。

返回模块 | 返回总览

17-训练平台设计/221-故障检测和自动恢复机制.md

第 221 题:故障检测和自动恢复机制?heartbeatwatchdog

题目

故障检测和自动恢复机制?heartbeatwatchdog


完整讲解

一、故障检测

Heartbeat:训练进程或 agent 定期向 scheduler/controller 上报「存活」;超时未报则判为故障(进程挂、节点宕、网络分区)。Watchdog:节点或容器内 看门狗 监控 主进程;主进程卡死或退出时 watchdog 触发(如重启容器、上报失败)。多级进程级(worker 向 master 心跳)、节点级(kubelet、Slurm 的 slurmd)、集群级(scheduler 与 API 健康);任一级发现异常即可触发恢复或告警。

二、自动恢复

策略:(1)重启:单进程/单 Pod 失败则 restartPolicy 或 controller 重建;(2)从 checkpoint 恢复:训练任务加载最新 checkpoint 后继续,由平台或启动脚本指定 checkpoint 路径;(3)弹性:Ray、PyTorch elastic 等可 替换故障节点、重新组通信继续跑;(4)重提:无法原地恢复时,自动重新提交 同配置 job(带 checkpoint),由调度器重新分配资源。

三、与调度的配合

Gang 作业:任一 worker 失败需全组感知(通过 controller 或 NCCL abort);统一退出 后由平台做「从 checkpoint 重提」或「替换节点后重启」。存储:checkpoint 存共享存储,任意新节点可读;元数据(step、world_size)一致才能正确 resume。

面试要点

  • 故障检测:heartbeat(进程/节点向控制面)、watchdog(监控主进程);多级检测。
  • 自动恢复:重启、从 checkpoint 恢复、弹性替换节点、自动重提 job。
  • Gang 作业需全组感知失败;checkpoint 在共享存储、元数据一致。

记忆要点

  1. 检测:heartbeat、watchdog;多级(进程/节点/集群)。
  2. 恢复:重启、checkpoint resume、弹性、重提。
  3. Gang + checkpoint 共享存储。

返回模块 | 返回总览

17-训练平台设计/222-训练数据的global-shuffle实现.md

第 222 题:训练数据的global shuffle实现?shuffle buffer大小?

题目

训练数据的global shuffle实现?shuffle buffer大小?


完整讲解

一、Global shuffle 的目的

Global shuffle:在 多 epoch多 worker 下,让整个数据集全局视角下打乱,避免每个 epoch 或每个 worker 看到相同顺序,从而提高泛化、减少顺序偏差。若只做本地 shuffle(每 worker 自己 shuffle 自己的 shard),全局上仍可能存在跨 shard 的顺序相关性;global shuffle 使不同 epoch 间、不同 rank 间的样本顺序更随机。

二、实现思路

中心式:由 单节点或服务 生成「全局随机排列」的 index 或 sample_id 列表,各 worker 按 rank 取自己那一段;每 epoch 重新生成一次排列。分布式:各 worker 约定 seed + epoch,用 相同算法 生成全局排列(如 shuffle 0..N-1 的索引),再按 shard 划分 各取一段;无需中心节点,但需确定性(同一 seed+epoch 得到同一排列)。DataLoader:PyTorch 的 DistributedSamplershuffle=True 时会对全量 index 做 shuffle(基于 seed+epoch),再按 rank 切分,等价于 global shuffle。

三、Shuffle buffer 大小

Shuffle buffer:若数据流式读、无法一次性载入全量,可用 buffer:先填满 buffer,从 buffer 中随机抽 一个输出,再补一个新样本;buffer 越大 随机性越强、但内存与延迟越大。经验:与 dataset 大小内存 权衡;常见 几万到几十万 样本;过小则 shuffle 效果弱,过大则内存与首包延迟高。Global:若用 buffer,可 每 worker 独立 buffer按 shard 做全局索引 shuffle 再流式读。

面试要点

  • Global shuffle:全数据集在全局打乱,多 epoch/多 worker 下顺序更随机;利于泛化。
  • 实现:中心生成全局排列、或分布式 seed+epoch 确定性生成;DistributedSampler 即一种。
  • Shuffle buffer:流式时用 buffer 随机抽;buffer 大小权衡随机性与内存。

记忆要点

  1. Global shuffle = 全局打乱;中心或分布式确定性生成排列。
  2. DistributedSampler shuffle=True 即 global shuffle。
  3. Buffer 大小:大则随机性好、内存高;按数据集与内存权衡。

返回模块 | 返回总览

17-训练平台设计/223-模型仓库的设计.md

第 223 题:模型仓库的设计?版本管理血缘追踪

题目

模型仓库的设计?版本管理血缘追踪


完整讲解

一、模型仓库的职责

模型仓库:存 训练产出的模型(checkpoint、导出格式)、版本与元数据(config、metric、数据集/代码快照),支持 检索、回滚、对比、下发。需与 训练作业、推理服务、CI 打通,便于「训完即存、按版部署、可追溯」。

二、版本管理

版本:每次训练产出对应 唯一版本(如 commit_sha + timestamp、或自增 version_id);元数据 含:config、hyper-param、dataset version、metric(loss、accuracy)、git/dataset 快照。检索:按 metric、时间、tag 筛选;回滚:按版本拉取历史 checkpoint 或 artifact。存储:大文件(权重)可放 对象存储,元数据放 DB 或索引;或统一用 MLflow、Weights & Biases 等做 artifact + 版本。

三、血缘追踪

血缘:记录 模型版本 ← 训练 job ← 代码/数据/配置溯源;某模型由哪次 job、哪份数据、哪段代码产出,可追溯。实现:训练 job 提交时带 code snapshot、dataset version、config;产出时写回 model registry 并关联;推理/下游 消费时记录「用的哪个模型版本」,形成 lineage 图。便于 复现、审计、合规

面试要点

  • 模型仓库:存 checkpoint/导出、版本与元数据;支持检索、回滚、下发。
  • 版本:唯一 ID、config/metric/dataset 快照;检索按 metric/tag;大文件对象存储。
  • 血缘:模型←job←代码/数据/配置;便于复现与审计。

记忆要点

  1. 仓库 = 模型 + 版本 + 元数据;检索、回滚。
  2. 版本含 config、metric、数据集/代码快照。
  3. 血缘 = 模型→job→代码/数据;可追溯。

返回模块 | 返回总览

17-训练平台设计/224-超参搜索(HPO)的基础设施.md

第 224 题:超参搜索(HPO)的基础设施?OptunaRay Tune集成?

题目

超参搜索(HPO)的基础设施?OptunaRay Tune集成?


完整讲解

一、HPO 基础设施需求

超参搜索(HPO):在 超参空间采样或搜索(网格、随机、贝叶斯、NAS 等),并发 跑多组训练,按 metric 选优。基础设施需:任务编排(多 trial 的提交、排队、资源)、metric 收集与早停搜索策略结果存储

二、Optuna、Ray Tune 集成

OptunaPython 库,定义 objectivesuggest 超参;scheduler(如 MultiObjective、Pruning)做早停与多目标;storage 存 trial 与 metric。与平台:Optuna 可 backend 到 DB/Redis每个 trial 可提交为 平台上的训练 job(如 K8s Job、Ray task),平台负责调度与资源;callback轮询 把 job 的 metric 回填 Optuna,供下一轮 suggest。Ray Tune分布式 HPO,trial 以 Ray task 跑在 Ray 集群;scheduler(ASHA、HyperBand 等)与 search_algorithm 内置;与 训练脚本 通过 config + report 对接。集成:平台提供 Ray 集群K8s + Optuna executor,训练镜像与资源由平台统一管;HPO 只负责「生成 trial、收 metric、选优」。

面试要点

  • HPO 需:多 trial 编排与资源、metric 收集与早停、搜索策略、结果存储。
  • Optuna:objective + suggest + storage;trial 可提交为平台 job,metric 回填。
  • Ray Tune:trial 即 Ray task;scheduler + search 内置;与平台通过 Ray 或 K8s 集成。

记忆要点

  1. HPO = 多 trial 编排 + metric + 搜索策略。
  2. Optuna = 库;trial 可映射平台 job;Ray Tune = trial 即 Ray task。
  3. 平台提供资源与训练环境;HPO 负责 suggest 与选优。

返回模块 | 返回总览

17-训练平台设计/225-训练平台的multi-tenancy隔离.md

第 225 题:训练平台的multi-tenancy隔离?namespacecgroup

题目

训练平台的multi-tenancy隔离?namespacecgroup


完整讲解

一、多租户隔离需求

多租户:多团队/多项目共享同一集群;需 资源隔离(某租户不能占满)、故障与噪声隔离(某任务异常不影响他人)、安全与权限(只能看/用自己资源)。

二、Namespace 与 cgroup

Namespace(K8s):逻辑隔离;每个租户一个 namespace,Pod、PVC、ConfigMap 等归属其下;RBAC 限制谁只能操作哪些 namespace。ResourceQuota 在 namespace 级限 CPU/内存/GPU 总量LimitRange 限单 Pod 上下界。Cgroup内核级 资源限制;K8s 通过 requests/limits 落到 CPU/memory cgroup;可扩展 GPU、IO 等。隔离效果:CPU/内存/GPU 硬限、避免某 Pod 吃满节点;网络 可配 NetworkPolicy存储 可按 namespace 或 PVC 隔离。

三、与调度、计费配合

队列:租户对应 queuenamespace;调度器按 queue 做 fair share 或 cap计费:按 namespace/queue 统计 GPU 小时 等,做 chargeback。噪声:多租户同节点时可能 CPU/内存/网络 争抢;GPU 独占MIG 可做更细 GPU 隔离;优先级与抢占 保证高优租户不受低优拖累。

面试要点

  • 多租户:资源隔离、故障隔离、权限;Namespace 做逻辑隔离 + Quota/LimitRange。
  • Cgroup 做 CPU/内存等硬限;K8s 通过 requests/limits 落 cgroup。
  • 队列 + 计费按 namespace;GPU 独占/MIG 做细粒度隔离。

记忆要点

  1. Namespace = 逻辑隔离 + Quota;cgroup = 内核资源限。
  2. ResourceQuota、LimitRange、RBAC 配合。
  3. 队列、计费、GPU 隔离(MIG/独占)。

返回模块 | 返回总览

17-训练平台设计/226-资源碎片整理(defragmentation)策略.md

第 226 题:资源碎片整理(defragmentation)策略?

题目

资源碎片整理(defragmentation)策略?


完整讲解

一、资源碎片问题

碎片:集群中 空闲资源 分散在多个节点上,单节点 不足以满足「需要 N 卡同节点」的 gang 作业,导致 有总资源却无法调度(如总共有 64 卡空闲但每节点最多 4 卡空闲,无法满足 8 卡同节点)。碎片化 降低实际可用率、拉长排队。

二、Defragmentation 策略

整理思路:(1)迁移/驱逐:将 低优或可迁移 的已运行任务 迁到更少节点,腾出 整节点 给大 job;需与 checkpoint、迁移成本 权衡。(2)预留与预留池:预留若干 整节点 专供大 job,小 job 用零散资源;或 定时 将小 job 收拢到部分节点。(3)调度策略Bin packing 优先「填满已有节点」再开新节点,减少碎片;Spread 则相反,易产生碎片;大集群常 bin pack 为主。(4)队列与优先级:大 job 高优时可 抢占 若干小 job、腾出整节点;被抢占方 checkpoint 后重排。

三、与 Gang 的关系

Gang 作业要求 多卡/多节点同时;碎片化直接导致 gang 无法满足。Defrag 目标就是 凑出连续/整节点 资源块;监控 上可看「碎片率」「无法调度的大 job 数」等指标,驱动 defrag 策略与参数。

面试要点

  • 碎片 = 空闲资源分散,无法凑出 gang 所需整块;defrag = 整理出连续/整节点资源。
  • 手段:迁移/驱逐低优任务、预留整节点、bin pack 调度、抢占腾节点。
  • 与 gang 强相关;监控碎片率与无法调度的大 job 数。

记忆要点

  1. 碎片 = 总资源够但单节点不够;defrag = 凑整块。
  2. 迁移、预留、bin pack、抢占。
  3. Gang 依赖整块资源;监控驱动 defrag。

返回模块 | 返回总览

17-训练平台设计/227-训练任务的dry-run和profiling模式.md

第 227 题:训练任务的dry-runprofiling模式?

题目

训练任务的dry-runprofiling模式?


完整讲解

一、Dry-run 模式

Dry-run不真正跑训练,只做 资源配置校验、依赖检查、启动命令与环境模拟。例如:检查 GPU/节点数 是否满足、镜像与数据路径 是否存在、启动脚本 能否解析 rank/world_size;可 打印 将要执行的命令与 env,便于用户确认。用于 提交前自检CI 校验、避免占资源却因配置错误秒挂。

二、Profiling 模式

Profiling 模式:以 少量 step 或短时间 跑训练,打开 profiler(PyTorch Profiler、Nsight)采集 耗时、通信、显存 等,不追求收敛。目的:性能基线瓶颈定位资源预估(如显存峰值、建议 GPU 数)。平台可提供「profiling job 类型」:自动注入 profiler、限制 step 数、产出 trace 或报告;与正式长训共享同一镜像与配置,仅运行时参数不同。

三、与正式任务的衔接

Dry-run 通过后可 一键转正式(同一配置、去掉 dry-run 标志)。Profiling 结果可 回填到 job 模板(如建议 batch、GPU 数)、或供 cost model 做耗时预测;正式任务可引用「某次 profiling job」的配置与建议。

面试要点

  • Dry-run:不跑训练,只校验资源、依赖、命令与环境;提交前自检、CI。
  • Profiling 模式:短时/少 step + profiler,采性能数据;做基线、瓶颈分析、资源预估。
  • 与正式任务衔接:dry-run 通过转正式;profiling 结果驱动配置与 cost model。

记忆要点

  1. Dry-run = 校验不执行;Profiling = 短跑 + profiler。
  2. Dry-run 查资源、依赖、命令;Profiling 出 trace、显存、建议。
  3. 衔接:转正式、配置建议、cost model。

返回模块 | 返回总览

17-训练平台设计/228-模型压缩服务的集成.md

第 228 题:模型压缩服务的集成?量化剪枝流水线?

题目

模型压缩服务的集成?量化剪枝流水线?


完整讲解

一、模型压缩服务定位

模型压缩量化、剪枝、蒸馏 等,在保持精度前提下 减小模型体积与算力,便于部署与推理。平台集成:训练产出 全精度模型 后,通过 压缩流水线 自动或按需生成 量化/剪枝版本,并做 精度与性能评估,再写入模型仓库或下发推理。

二、量化流水线

量化:PTQ(训练后量化)或 QAT(量化感知训练)。流水线:输入 checkpoint + 校准数据/配置校准或 QAT导出(ONNX/TRT 等)→ 验证(精度、延迟、显存)→ 入库或下发。平台可提供 量化 job 模板:指定模型版本、校准集、目标精度(INT8/FP16);跑完产出压缩后 artifact 与报告。

三、剪枝与流水线编排

剪枝:按 权重重要性结构 剪枝;可接在训练后或与训练交替。流水线:剪枝 → 微调/再训 → 评估 → 导出。编排:与 CI/CD模型仓库 联动:新模型版本触发「压缩流水线」;或用户在前台选择「为该版本生成 INT8 与剪枝版」。统一:量化与剪枝可共用 评估与回归测试(精度、latency、throughput);失败则告警、不覆盖生产版本。

面试要点

  • 压缩服务:训练产出全精度模型后,通过流水线做量化/剪枝,并做精度与性能评估。
  • 量化流水线:校准或 QAT → 导出 → 验证 → 入库;剪枝可接微调与评估。
  • 与模型仓库、CI 联动;统一评估与回归,失败不覆盖生产。

记忆要点

  1. 压缩 = 量化/剪枝;流水线 = 输入模型 → 压缩 → 评估 → 入库。
  2. 量化:PTQ/QAT、校准、导出、验证;剪枝:剪枝+微调+评估。
  3. 与仓库/CI 联动;统一评估与回归。

返回模块 | 返回总览

17-训练平台设计/229-训练平台的cost-model.md

第 229 题:训练平台的cost model?预测任务耗时和资源需求?

题目

训练平台的cost model?预测任务耗时和资源需求?


完整讲解

一、Cost model 的目的

Cost model:根据 任务配置(模型规模、batch、GPU 数、数据量等)预测「运行时长、资源占用、费用」。用于 排队预估、预算控制、资源建议(如「建议 8 卡、预计 10 小时」)、以及 调度与优先级 的辅助决策。

二、预测任务耗时与资源

耗时:可基于 历史同配置 jobwall time 做回归(如按参数量、batch、卡数建简单模型);或 profiling 得到单 step 时间,再乘以 总 step 数(由数据量、batch、epoch 推出)。资源显存 可由 profiling 或公式(按模型结构、batch、优化器状态)估算;GPU 数 由「总显存需求 / 单卡显存」或「目标吞吐与单卡吞吐」推导。数据:需 历史 job 的 config + 实际耗时/资源 做训练或拟合;新配置 可插值或用相似 job 的统计。

三、工程要点

特征:模型参数量、batch、seq_len、GPU 类型与数量、数据量、是否混合精度等。更新:随新 job 完成 持续更新 统计或模型;不确定性 可给出区间(如 P50/P90 耗时)。与 调度器 结合:预估时长用于 backfill预留;与 计费 结合做预算告警。

面试要点

  • Cost model:根据任务配置预测耗时、资源、费用;用于排队预估、预算、资源建议。
  • 耗时:历史回归或 profiling×总 step;资源:显存公式或 profiling、GPU 数按需求推导。
  • 特征:参数量、batch、卡数等;持续用新 job 更新;可与调度、计费联动。

记忆要点

  1. Cost model = 预测耗时/资源/费用。
  2. 耗时:历史或 profiling×step;资源:显存、GPU 数。
  3. 特征+更新;与调度、计费联动。

返回模块 | 返回总览

17-训练平台设计/230-如何支持异构计算.md

第 230 题:如何支持异构计算?CPUGPUTPU统一调度?

题目

如何支持异构计算?CPUGPUTPU统一调度?


完整讲解

一、异构计算类型

CPU、GPU、TPU算力类型不同;任务可能指定「仅 GPU」「仅 TPU」或「CPU 兜底」。统一调度:资源池中 同时存在 多种设备类型;调度器按 job 的 request(如 nvidia.com/gpu、tpu.googleapis.com/v3)做 匹配与放置,并保证 同一 job 内 设备类型一致(或显式支持混合时再细说)。

二、统一调度设计

资源抽象:每种设备通过 device plugin自定义 resource 暴露(如 gpu、tpu、npux);request/limit 统一为「某 resource 的数量」。调度:scheduler 在 Filter 阶段排除不满足 resource 与 node label(如 accelerator=tpu-v3)的节点;Score 时可按类型、拓扑、利用率打分。运行时训练代码按设备类型 选后端(CUDA、XLA/TPU、CPU);平台通过 环境变量或注入 告知当前分配类型,或 同一镜像 内多后端并存、按 env 选择。

三、多集群与统一队列

GPU 与 TPU 分属不同 集群或 region,可 统一队列/API:用户提交时指定「偏好 GPU 或 TPU」或「任意」;上层调度 将 job 路由到对应集群,或 联邦 多集群资源视图后由统一 scheduler 分配。计费与 quota 需按设备类型分别统计与限制。

面试要点

  • 异构:CPU/GPU/TPU 等并存;统一调度 = 资源抽象一致、按 request 与 label 匹配与放置。
  • Device plugin 暴露各类型;scheduler Filter/Score;运行时按分配类型选后端。
  • 多集群时统一队列/API 路由到对应集群;计费与 quota 按类型分。

记忆要点

  1. 异构 = 多设备类型;统一 request + label 匹配。
  2. 调度 Filter/Score;运行时按类型选 CUDA/XLA/CPU。
  3. 多集群可统一 API/队列;计费按类型。

返回模块 | 返回总览

17-训练平台设计/231-训练平台的SLA定义.md

第 231 题:训练平台的SLA定义?job completion time保证?

题目

训练平台的SLA定义?job completion time保证?


完整讲解

一、SLA 定义

SLA(服务等级协议):对训练任务可约定 job completion time(从提交到完成的时间上限)、排队时间上限可用率(如 99%)等。定义方式:按 队列或用户 设「P95 完成时间 ≤ T」「排队不超过 Q 分钟」;或「关键 job 带 SLA 标签,未满足则告警或补偿」。

二、Job completion time 保证

含义:在 资源充足、无故障 前提下,预计承诺 某 job 在 T 内完成(含排队 + 运行)。实现:(1)预估:用 cost model 预测运行时长;排队 由调度策略与容量保证(如预留、优先级)控制。(2)预留与优先级:SLA job 高优、或 预留资源 减少排队;抢占 低优任务腾资源。(3)监控与告警:实际 排队+运行 超 T 时告警、或触发 扩容/加资源。(4)弹性:若运行超预期,可 自动加卡(弹性训练)或 checkpoint 后重提更大规模,尽量在 T 内完成。

三、与容量、公平的权衡

保证 completion time 常需 过量供给高优抢占,与 公平共享、成本 冲突。实践上多对 少量关键 job 做 SLA、其余按 best-effort;或 SLA 与队列 cap 结合,避免 SLA 占满集群。

面试要点

  • SLA 可定义:完成时间上限、排队上限、可用率等;按队列或 job 标签。
  • Job completion 保证:cost model 预估 + 排队控制;预留、优先级、抢占;超时告警或弹性。
  • 与容量、公平权衡;多对关键 job 做 SLA、cap 控制。

记忆要点

  1. SLA = 完成时间/排队/可用率等约定。
  2. 保证:预估+预留+优先级;监控与弹性。
  3. 与公平、成本权衡;关键 job + cap。

返回模块 | 返回总览

17-训练平台设计/232-数据隐私和合规.md

第 232 题:数据隐私和合规?联邦学习基础设施?

题目

数据隐私和合规?联邦学习基础设施?


完整讲解

一、数据隐私与合规

隐私:训练数据可能含 个人、敏感、受监管 信息;合规 要求数据 不出域、最小使用、可审计。平台需 访问控制、加密、审计日志数据目录 标注敏感级别与用途限制;训练作业 仅能访问其 授权 的数据集。

二、联邦学习基础设施

联邦学习(FL):数据 保留在各参与方,仅交换 梯度或模型更新,不集中原始数据。基础设施协调服务(中心或去中心)下发配置、轮次与聚合策略;各参与方 在本地跑训练、按轮次上传 加密或脱敏的更新安全聚合(Secure Aggregation)可选,使中心只得到「聚合结果」而看不到单方更新。通信:跨方 TLS、认证、访问控制差分隐私梯度压缩 可叠加。多集群:参与方多为独立集群,需 跨集群任务与通信版本与轮次一致故障与掉线 处理。

三、与平台集成

平台提供 FL 作业类型:指定参与方列表、聚合方式、轮次;权限与网络 仅开放 FL 所需;审计 记录谁在何时用何数据与模型版本。合规:满足「数据不出域」;审计 满足监管与内控。

面试要点

  • 数据隐私:访问控制、加密、审计、数据目录与敏感标注;训练仅用授权数据。
  • 联邦学习:数据不出域、只传梯度/更新;需协调、安全聚合、跨集群通信与容错。
  • 平台提供 FL 作业类型、权限与审计;满足合规与隐私。

记忆要点

  1. 隐私:访问控制、加密、审计;合规要求不出域、可审计。
  2. FL = 数据留本地、传更新;协调、安全聚合、跨集群。
  3. 平台 FL 作业 + 权限 + 审计。

返回模块 | 返回总览

17-训练平台设计/233-训练平台的disaster-recovery.md

第 233 题:训练平台的disaster recovery?跨地域备份?

题目

训练平台的disaster recovery?跨地域备份?


完整讲解

一、Disaster recovery 目标

灾难恢复(DR):在 地域级故障(机房/区域不可用)时,能 在另一地域恢复 关键服务与数据,RTO(恢复时间目标)与 RPO(恢复点目标)满足业务要求。训练平台需考虑 控制面、数据与 checkpoint、配置与元数据 的跨地域备份与恢复。

二、跨地域备份

数据训练数据checkpoint异步复制 到另一 region(如对象存储跨 region 复制、Ceph/JuiceFS 多站点);RPO 取决于复制延迟(如分钟级)。元数据与配置etcd、DB、配置中心跨地域复制(异步或同步);或 定期快照 到对象存储,恢复时从快照拉起。控制面API、scheduler 可在 多 region 部署,主区故障时 DNS/流量 切到备区;或 冷备:备区平时不跑、灾备时用备份数据与镜像恢复服务。

三、训练任务恢复

已跑 job:checkpoint 若已跨区复制,可在 备区 重新提交「从 checkpoint resume」的 job;未复制 的 checkpoint 可能丢失,RPO 内完成的 job 需在备区重训。新 job:备区需有 调度与资源队列与元数据 从备份恢复或最终一致。演练:定期 DR 演练(切流量、从备份恢复)验证 RTO/RPO。

面试要点

  • DR:地域级故障时在另一地域恢复;RTO/RPO 目标。
  • 跨地域备份:数据与 checkpoint 异步复制;元数据/DB 复制或快照;控制面多区或冷备。
  • 训练恢复:checkpoint 在备区 resume;演练验证 RTO/RPO。

记忆要点

  1. DR = 跨地域恢复;RTO/RPO。
  2. 数据/checkpoint 跨区复制;元数据复制或快照。
  3. 备区 resume + 演练。

返回模块 | 返回总览

17-训练平台设计/234-模型CI-CD流水线.md

第 234 题:模型CI/CD流水线?自动化测试、benchmark?

题目

模型CI/CD流水线?自动化测试、benchmark?


完整讲解

一、模型 CI/CD 含义

模型 CI/CD:像代码一样对 模型与训练流水线持续集成与部署CI:代码/配置变更触发 构建、测试、训练或压缩流水线CD:通过测试与 benchmark 的 模型版本 自动或审批后 部署到推理/下线。保证 可重复、可审计、质量可控

二、自动化测试与 benchmark

测试单元测试(数据加载、config、单步 forward/backward);集成测试(小规模多卡/多节点跑若干 step);回归测试(精度、loss 曲线与基线对比)。Benchmark固定配置 下跑 吞吐、延迟、显存;与 基线 对比,性能回归 则告警或阻断。触发:代码/数据/配置 PR 或 merge 触发 CI;定时新模型版本 触发 benchmark 与回归。

三、流水线编排

流水线代码 build → 镜像 → 训练(或跳过用缓存)→ 评估 → 压缩(可选)→ 入库/部署。用 Tekton、Argo、GitHub Actions 等编排;artifact(镜像、checkpoint、报告)在阶段间传递。门控:仅 通过测试与 benchmark 的版本可 进模型仓库推推理;失败则告警、不自动发布。

面试要点

  • 模型 CI/CD:训练与模型流水线持续集成与部署;可重复、可审计。
  • 自动化测试:单元、集成、回归(精度/性能);benchmark 与基线对比、回归告警。
  • 流水线:build→训练→评估→压缩→入库/部署;门控:通过才发布。

记忆要点

  1. CI/CD = 训练与模型流水线自动化;测试 + benchmark。
  2. 测试:单元、集成、回归;benchmark 固定配置、与基线比。
  3. 流水线编排 + 门控;通过才入库/部署。

返回模块 | 返回总览

17-训练平台设计/235-训练平台的observability.md

第 235 题:训练平台的observability?日志、指标、链路追踪?

题目

训练平台的observability?日志、指标、链路追踪?


完整讲解

一、Observability 的三大支柱

可观测性(Observability):通过 日志、指标、链路追踪 理解系统行为、排查故障、优化性能。日志结构化日志(JSON)含 job_id、rank、时间、级别、消息;集中收集(如 Loki、ELK)便于检索与告警。指标时序指标(Prometheus)— GPU 利用率、吞吐、排队长度、失败率等;看板(Grafana)与 告警链路追踪(Tracing):请求/job 级 从提交到各阶段(排队、调度、运行、写 checkpoint)的 span,便于看延迟分布与瓶颈。

二、训练平台具体指标

作业级:排队时长、运行时长、吞吐、loss、通信占比、显存峰值。集群级:GPU 利用率、队列深度、成功率、成本与利用率趋势。节点级:DCGM、node_exporter、磁盘与网络。与业务:模型版本、数据集版本、实验 ID 等 label 便于按实验/用户/队列下钻。

三、工程实践

统一采集:日志与 trace 带 trace_id/job_id,便于关联。采样:高 QPS 时 trace 可采样、日志可按级别过滤。保留与成本:指标可长期聚合;日志与 trace 按策略保留或归档。SLO:基于指标定义 SLA/SLO(如 P99 完成时间)、告警与 on-call。

面试要点

  • Observability = 日志 + 指标 + 链路追踪;理解行为、排障、优化。
  • 训练平台:作业/集群/节点级指标;日志集中、trace 做 job 级链路。
  • 统一 job_id/trace_id;采样与保留策略;SLO 与告警。

记忆要点

  1. 三支柱:日志、指标、trace。
  2. 作业/集群/节点指标;日志集中、trace 链路。
  3. 关联 ID、采样、保留、SLO。

返回模块 | 返回总览

18-推理平台设计/README.md

18-推理平台设计(第 236–255 题)

题号 主题 文章
236 设计一个支持10万QPS的大模型推理服务? 236-设计一个支持10万QPS的大模型推理服务.md
237 推理服务的auto-scaling策略?HPAVPA、`K… 237-推理服务的auto-scaling策略.md
238 多模型multi-tenancy的GPU共享?MPS vs `M… 238-多模型multi-tenancy的GPU共享.md
239 推理请求的routing策略?least loaded、`con… 239-推理请求的routing策略.md
240 边缘推理的model caching策略?CDN for mod… 240-边缘推理的model-caching策略.md
241 推理服务的A/B testing和`canary deploymen… 241-推理服务的A-B-testing和canary-deployment.md
242 长文本生成的streaming实现?`Server-Sent Eve… 242-长文本生成的streaming实现.md
243 推理结果的caching策略?prompt级别的deduplic… 243-推理结果的caching策略.md
244 多模态推理的pipeline设计?图文、视频? 244-多模态推理的pipeline设计.md
245 推理服务的safety guardrails?内容过滤、速率限制? 245-推理服务的safety-guardrails.md
246 模型fine-tuning as a service的架构? 246-模型fine-tuning-as-a-service的架构.md
247 推理服务的cost optimization?`spot insta… 247-推理服务的cost-optimization.md
248 模型on-device部署的infra支持?Core ML、`T… 248-模型on-device部署的infra支持.md
249 推理服务的latency SLO保证?p99 < 100ms如何… 249-推理服务的latency-SLO保证.md
250 推理请求的admission control?防止过载? 250-推理请求的admission-control.md
251 模型ensemblecascade的架构设计? 251-模型ensemble和cascade的架构设计.md
252 推理服务的debuggability?`request tracin… 252-推理服务的debuggability.md
253 实时推理和离线推理的统一架构? 253-实时推理和离线推理的统一架构.md
254 推理服务的security?模型加密、API认证? 254-推理服务的security.md
255 推理平台的carbon footprint优化?绿色AI? 255-推理平台的carbon-footprint优化.md

返回总览

18-推理平台设计/236-设计一个支持10万QPS的大模型推理服务.md

第 236 题:设计一个支持10万QPS的大模型推理服务?

题目

设计一个支持10万QPS的大模型推理服务?


完整讲解

一、10 万 QPS 的挑战

高 QPS 要求 高吞吐、低延迟、可扩展、高可用。单实例 GPU 推理有限(数千 QPS 量级);需 水平扩展:多实例 + 负载均衡自动扩缩容批处理与动态 batching 提高单卡吞吐,以及 缓存、限流、降级 保护与成本控制。

二、核心组件

网关与路由负载均衡(L4/L7)把请求分到多实例;路由 按模型/版本、canary 等;限流与熔断 防过载。推理服务多副本 无状态;动态 batching(vLLM、Triton 等)聚多请求为一 batch 提高 GPU 利用率;连续批处理(continuous batching)流式场景下边生成边输出。扩缩容HPA/KEDA 按 QPS、队列、延迟扩缩;预热冷却 避免抖动。可观测延迟(P50/P99)、QPS、错误率 监控与告警;trace 做请求级排查。

三、存储、缓存与成本

模型:从 模型仓库 拉取或 挂载;大模型可 多副本加载按需加载缓存结果缓存(相同 prompt 直接返回)、KV cache 复用(vLLM 等);降低重复计算与延迟。成本:10 万 QPS 需 数十到数百 GPU 实例;Spot、混部、批处理缓存 控成本;多 region 做就近与容灾。

面试要点

  • 10 万 QPS:水平扩展 + 负载均衡、动态/连续 batching、扩缩容、限流与熔断。
  • 推理服务多副本、动态 batch;HPA/KEDA + 预热;延迟/QPS/错误率监控与 trace。
  • 模型仓库、结果与 KV 缓存;Spot/混部/多 region 控成本。

记忆要点

  1. 高 QPS = 多实例 + LB + 批处理 + 扩缩容。
  2. 动态/连续 batching;HPA/KEDA;可观测。
  3. 缓存、限流、成本控制。

返回模块 | 返回总览

18-推理平台设计/237-推理服务的auto-scaling策略.md

第 237 题:推理服务的auto-scaling策略?HPAVPAKEDA

题目

推理服务的auto-scaling策略?HPAVPAKEDA


完整讲解

一、Auto-scaling 目标

自动扩缩容:根据 负载(QPS、队列深度、延迟)自动增加或减少 推理实例数,在 保证 SLA 前提下 控制成本。负载高时扩容减排队与延迟;负载低时缩容省资源。

二、HPA、VPA、KEDA

HPA(Horizontal Pod Autoscaler):K8s 原生,按 CPU/内存自定义 metric(如 QPS、请求数)水平 扩缩 Pod 副本数。需 metrics-servercustom metrics adapter(如 Prometheus adapter)提供 QPS 等;target 设为「平均每 Pod 的 QPS 或利用率」。VPA(Vertical Pod Autoscaler):垂直 调整 单 Pod 的 request/limit(CPU、内存),适合「单实例规格不固定」;推理场景更常用 HPA 做副本数伸缩。KEDA:基于 Kubernetes Event-Driven Autoscaling,用 多种 trigger(队列长度、Prometheus、HTTP 等)驱动扩缩容;从 0 扩到 N 支持好,适合 队列消费、定时或事件触发 的推理与批处理。

三、策略与注意

指标:推理常用 QPS、队列深度、P99 延迟 作为 scale 依据;多指标 可设「满足任一即扩容」。冷却与预热:扩容后 warmup 再接流量(模型加载、编译);缩容前 cooldown 避免抖动。最小/最大副本资源 quota 防止过度扩缩。

面试要点

  • Auto-scaling:按负载扩缩实例;HPA 水平扩缩副本、VPA 垂直调单 Pod 资源、KEDA 事件驱动。
  • 推理常用 HPA/KEDA;指标:QPS、队列、P99;custom metrics 或 Prometheus adapter。
  • 预热与冷却;最小/最大副本与 quota。

记忆要点

  1. HPA = 水平扩副本;VPA = 垂直调资源;KEDA = 事件驱动、可缩到 0。
  2. 推理指标:QPS、队列、P99;warmup、cooldown。
  3. 多指标、min/max、quota。

返回模块 | 返回总览

18-推理平台设计/238-多模型multi-tenancy的GPU共享.md

第 238 题:多模型multi-tenancy的GPU共享?MPS vs MIG

题目

多模型multi-tenancy的GPU共享?MPS vs MIG


完整讲解

一、多模型多租户 GPU 共享

多模型/多租户 共享同一 GPU:提高利用率、降成本;需 隔离(显存、算力、延迟)避免互相干扰。手段MPS(多进程共享一卡)、MIG(多实例 GPU,硬件分区)、多进程/多容器 各占部分显存与时间片。

二、MPS vs MIG

MPS(Multi-Process Service):多进程共享同一 GPU context,由 驱动做时间片调度显存 各进程分配但共享设备,算力 共享。优点:实现简单、无需硬件分区;缺点:无硬隔离,某进程大 kernel 会阻塞其他、公平性与长尾 难保证。MIG(Multi-Instance GPU):A100 等 可将单卡 硬件划分 为多份 MIG 实例,每实例有 独立显存与算力强隔离优点:隔离好、可预测;缺点:仅部分型号支持、分区粒度固定、总利用率可能略降。

三、选型与使用

小模型、多路推理、对隔离要求不高:可用 MPS,配合 限流或优先级 减轻互相影响。多租户、需 SLA 与隔离:优先 MIG单卡单模型(不共享)。K8s:MIG 可通过 device plugin 暴露为多「小 GPU」资源;MPS 下多 Pod 共享同卡,需 显存 limit并发控制

面试要点

  • 多模型/多租户共享 GPU:MPS(时间片共享)、MIG(硬件分区);或单卡单模型。
  • MPS:多进程共享、无硬隔离、简单;MIG:强隔离、可预测、仅部分卡支持。
  • 按隔离与 SLA 需求选;K8s 上 MIG 可暴露为多资源、MPS 需 limit 与并发控制。

记忆要点

  1. MPS = 多进程共享、时间片;MIG = 硬件分区、强隔离。
  2. MPS 简单无硬隔离;MIG 隔离好、部分卡支持。
  3. 按需求选;K8s 配合 device plugin 与 limit。

返回模块 | 返回总览

18-推理平台设计/239-推理请求的routing策略.md

第 239 题:推理请求的routing策略?least loadedconsistent hashing

题目

推理请求的routing策略?least loadedconsistent hashing


完整讲解

一、Routing 的目的

路由:把 入站请求 分到 多个推理实例,实现 负载均衡、灰度、就近。策略影响 延迟、吞吐、故障隔离。常见:轮询、随机、最少连接、加权,以及 least loaded、一致性哈希

二、Least loaded

Least loaded:把请求发到 当前负载最低 的实例(如 正在处理的请求数最少、或 队列最短)。优点均衡、避免某实例过载而其他空闲。实现:需 实时定期 上报各实例的 负载指标(活跃请求数、队列深度);LB 或路由层 查表选最小。注意长尾请求(如长生成)会长时间占住实例,新请求可能仍选到「看起来少但即将变忙」的实例;可结合 超时与重试

三、Consistent hashing

一致性哈希:按 请求的 key(如 user_id、session_id、model+version)哈希环上,选 顺时针最近 的实例。优点同一 key 总到同一实例,利于 缓存亲和(同一用户/会话的请求命中同实例的 KV cache 或结果缓存);实例扩缩 时仅影响环上相邻段,迁移量小缺点:可能 负载不均(某些 key 热);可加 虚节点(virtual node)打散。适用:有状态或强缓存亲和时;无状态、纯均衡可用 least loaded。

面试要点

  • Routing:负载均衡、灰度、就近;策略有 least loaded、一致性哈希等。
  • Least loaded:选当前负载最低实例;需实时/定期负载上报;长尾需结合超时。
  • Consistent hashing:同 key 同实例、缓存亲和、扩缩迁移小;可加虚节点均衡。

记忆要点

  1. Least loaded = 选负载最低;consistent hashing = 同 key 同实例。
  2. Least loaded 需负载指标;hashing 利于缓存亲和。
  3. 按有状态/缓存需求选;虚节点可均衡。

返回模块 | 返回总览

18-推理平台设计/240-边缘推理的model-caching策略.md

第 240 题:边缘推理的model caching策略?CDN for models?

题目

边缘推理的model caching策略?CDN for models?


完整讲解

一、边缘推理的特点

边缘:在 靠近数据源或用户 的节点(机房、基站、设备侧)部署推理,低延迟、省带宽、隐私;但 资源有限模型需适配(小模型、量化、剪枝)。Model caching:模型 从中心下发到边缘本地缓存,避免每次请求都回源;版本更新 时再拉新模型或增量。

二、Model caching 策略

拉取按需(首次请求某模型时拉取)、预拉(部署时或定时从中心拉)、推送(中心按策略推送到边缘)。存储:边缘节点 本地盘或内存 存模型文件;容量有限 时需 淘汰(LRU、按版本、按热度)。一致性版本号或 digest 校验;更新时 原子替换蓝绿,避免推理用旧版。多边缘CDN 思路— 中心为源、边缘为缓存;P2P 边缘间互拉减少回源。

三、CDN for models

CDN for models:把 模型文件 当静态资源,通过 CDN 分发到边缘节点;就近 拉取、减轻中心带宽加速冷启动。与 对象存储 + 边缘节点缓存 类似;CDN 提供 全球分布、缓存策略、失效 等。注意:模型大、更新频率低,CDN 缓存命中高;权限与加密 需与 CDN 能力结合(如 signed URL、私有 bucket)。

面试要点

  • 边缘推理:就近、低延迟;model caching 使模型本地可用、减少回源。
  • 策略:按需/预拉/推送;本地存储与淘汰(LRU、版本);版本一致与原子更新。
  • CDN for models:模型当静态资源、CDN 分发;就近、减中心带宽;注意权限与加密。

记忆要点

  1. 边缘 = 就近;caching = 本地存模型、减少回源。
  2. 按需/预拉/推送;淘汰与版本一致。
  3. CDN 分发模型;权限与加密。

返回模块 | 返回总览

18-推理平台设计/241-推理服务的A-B-testing和canary-deployment.md

第 241 题:推理服务的A/B testingcanary deployment

题目

推理服务的A/B testingcanary deployment


完整讲解

一、A/B testing

A/B 测试流量按比例 分到 多版本(如模型 A vs 模型 B、或同一模型不同参数),收集 延迟、准确率、业务指标统计比较 后决定是否全量切到某版本。实现路由层user_id、request_id 哈希或随机将请求分到 variant A/B指标 带 variant 标签上报;分析 看 A/B 的 P99、准确率、转化等差异。

二、Canary deployment

Canary新版本先上少量流量(如 5%),观察 错误率、延迟 无异常后再 逐步放量 至全量;若有问题则 回滚实现路由/网关权重(如 95% 老版本、5% 新版本)或 按用户/地域 切流量;监控 新版本实例的指标;自动或人工 判断是否继续放量或回滚。与 A/B 区别:Canary 侧重 稳妥发布;A/B 侧重 效果对比。可结合:先 canary 放量,再 A/B 对比新旧模型效果。

三、与推理平台集成

模型版本路由规则 绑定(如 10% 流量到 v2);平台 提供 流量比例配置、指标按版本聚合、回滚接口金丝雀 可配 自动回滚(错误率或延迟超阈值即回滚);A/B统计显著性 与业务决策后再全量。

面试要点

  • A/B testing:流量分多版本、收集指标、统计比较后决策;路由按 user/request 分 variant。
  • Canary:新版本少量流量、观察无异常后放量;有问题回滚;路由按权重或用户。
  • 平台:版本与路由绑定、比例配置、按版本聚合指标、回滚与自动回滚。

记忆要点

  1. A/B = 多版本对比、统计决策;Canary = 少量流量、逐步放量、可回滚。
  2. 路由分流量;指标带版本;Canary 可自动回滚。
  3. 可结合:canary 发布 + A/B 效果对比。

返回模块 | 返回总览

18-推理平台设计/242-长文本生成的streaming实现.md

第 242 题:长文本生成的streaming实现?Server-Sent Events

题目

长文本生成的streaming实现?Server-Sent Events


完整讲解

一、长文本生成的流式需求

长文本生成(如大模型对话、摘要):逐 token 输出,若等全部生成完再返回首包延迟 高、用户体验差。流式:每生成若干 token 就 立即推给客户端,降低 TTFT(Time To First Token)感知、提升体验。

二、Server-Sent Events(SSE)

SSEHTTP 长连接,服务端 单向 向客户端 持续推送 文本事件(event stream)。格式Content-Type: text/event-stream;每条为 data: ...\n\n优点简单、基于 HTTP,易与现有网关与前端集成;自动重连(浏览器 EventSource)。适用流式生成— 每生成一段就 data: chunk 推送;客户端边收边展示。与 WebSocket:SSE 单向、HTTP;WebSocket 双向、独立协议;若只需「服务端推生成结果」SSE 足够。

三、实现要点

后端:推理引擎 流式输出(如 vLLM 的 streaming、OpenAI 兼容的 stream=True);每 token 或每 N token 通过 SSE 写回。超时与断开:长连接需设 keepalive、超时;客户端断线时服务端应 停止生成 或做清理。网关:需支持 流式透传(不缓冲整响应);负载均衡 在流式场景下通常 sticky 到同一实例。

面试要点

  • 长文本生成流式:边生成边返回,降低 TTFT、提升体验;常用 SSE。
  • SSE:HTTP 长连接、服务端单向推送;Content-Type: text/event-stream;简单易集成。
  • 后端流式输出 + SSE 写回;超时与断开清理;网关流式透传、sticky。

记忆要点

  1. 流式 = 边生成边返回;SSE = HTTP 单向推送。
  2. text/event-stream;data: chunk。
  3. 超时、断开清理;网关透传、sticky。

返回模块 | 返回总览

18-推理平台设计/243-推理结果的caching策略.md

第 243 题:推理结果的caching策略?prompt级别的deduplication?

题目

推理结果的caching策略?prompt级别的deduplication?


完整讲解

一、推理结果缓存的目的

相同或相近请求 的推理结果可 复用,减少 重复计算降延迟与成本。尤其 大模型 单次推理贵,高重复(如相同 prompt、模板化问答)时缓存收益大。

二、Caching 策略

Key:常用 完整 prompt(或 prompt 的 hash)作 key;多轮对话 可用 session_id + 轮次对话摘要存储Redis/Memcached 等做 分布式缓存TTL 控制过期(如 1 小时、1 天)。命中:请求先 查 cache;命中则 直接返回、不调模型;未命中则 推理后写入 cache 再返回失效:模型版本更新时 按 prefix 或全量失效;或 版本号 写进 key,自然隔离。

三、Prompt 级 deduplication

Deduplication相同 prompt并发请求合并为一次推理,多路复用 结果(即 request coalescing)。实现:短时间窗口 内相同 prompt 的请求 排队只跑一次 推理,结果 广播 给所有等待者。与 cache 区别:cache 是 跨请求、持久;dedup 是 同批请求 合并。二者可同时用:先 dedup 再查 cache,再未命中则推理。

面试要点

  • 结果缓存:相同/相近请求复用结果;key 常用 prompt 或 hash;Redis 等、TTL。
  • 命中则直接返回;未命中推理后写 cache;模型更新时失效或版本号进 key。
  • Prompt 级 dedup:并发相同 prompt 合并为一次推理、结果复用;与 cache 可叠加。

记忆要点

  1. Cache key = prompt/hash;存储 Redis、TTL。
  2. 命中直接返回;版本更新失效。
  3. Dedup = 并发同 prompt 合并一次推理;与 cache 叠加。

返回模块 | 返回总览

18-推理平台设计/244-多模态推理的pipeline设计.md

第 244 题:多模态推理的pipeline设计?图文、视频?

题目

多模态推理的pipeline设计?图文、视频?


完整讲解

一、多模态推理场景

多模态图文、视频、语音 等混合输入或输出;需 多模型/多阶段 协同(如 图像编码 → 文本生成视频抽帧 → 图像理解 → 文本)。Pipeline:把多步串成 有向图,每步为 一个服务或模型数据与格式 在步间传递。

二、Pipeline 设计

阶段划分:按 模态与模型 拆成 stage(如 preprocess、image_encoder、fusion、llm、postprocess)。数据流:上游输出为下游输入;格式 统一(如 tensor、JSON、base64 图);大对象(图、视频)可 传 URL 或 ID,下游再拉取,避免经网关传大 body。调度同步 串行调用各 stage,或 异步 队列 + worker;错误与重试 在 stage 边界处理。资源:不同 stage 可能 不同硬件(如 GPU 编码、CPU 后处理);扩缩容 可按 stage 独立。

三、图文、视频示例

图文图 → 图像编码器 → 向量文本 + 向量 → 多模态 LLM → 文本;可拆为 encode 服务 + LLM 服务,网关或编排层串起来。视频视频 → 抽帧 → 图像编码 → 序列时序模型或 LLM;抽帧与编码可单独服务、可批处理。统一:用 DAG 编排(如 K8s Workflow、Argo、自研)描述 pipeline;每节点为 HTTP/gRPC 服务任务

面试要点

  • 多模态:图文、视频等;pipeline = 多阶段有向图,阶段间数据传递。
  • 阶段划分按模态与模型;数据格式统一、大对象传 URL/ID;错误与重试在 stage 边界。
  • 图文/视频示例:编码器 + LLM 等;DAG 编排、每节点为服务或任务。

记忆要点

  1. 多模态 = 多阶段;pipeline = 有向图、数据在 stage 间传递。
  2. 格式统一、大对象传引用;按 stage 扩缩容。
  3. DAG 编排、节点即服务。

返回模块 | 返回总览

18-推理平台设计/245-推理服务的safety-guardrails.md

第 245 题:推理服务的safety guardrails?内容过滤、速率限制?

题目

推理服务的safety guardrails?内容过滤、速率限制?


完整讲解

一、Safety guardrails 的含义

安全护栏:在推理 输入与输出 上做 内容过滤、滥用检测、速率限制,保证 合规、防滥用、可控风险。例如:禁止违法/违规内容限速防刷敏感信息脱敏

二、内容过滤

输入Prompt 过滤— 检测并拒绝 越狱、恶意指令、敏感词;可用 规则 + 分类模型(如敏感词表、小模型分类)。输出Response 过滤— 对生成结果做 敏感内容、PII、违规 检测;截断或替换 后再返回,或 拒绝生成 并返回安全提示。多模态:图/视频输入也需 内容审核(暴恐、违规图);可调用 审核 API 或模型 做前置或后置。

三、速率限制

限速:按 user_id、API key、IP 等维度限制 QPS 或并发,防止 单用户占满恶意刷量实现网关层推理网关令牌桶/漏桶滑动窗口 计数;超限返回 429 或排队。分级:不同用户/套餐 不同限速;与 计费与 quota 一致。Guardrails业务策略 结合:过滤规则可配置、可 A/B;限速与套餐与成本挂钩。

面试要点

  • Safety guardrails:内容过滤(输入/输出)、速率限制;合规、防滥用。
  • 内容过滤:prompt 与 response 的敏感/违规检测;规则+模型;多模态需审核。
  • 速率限制:按 user/key/IP 限 QPS 或并发;令牌桶等;超限 429;与套餐一致。

记忆要点

  1. Guardrails = 内容过滤 + 限速。
  2. 输入/输出过滤;多模态审核。
  3. 限速按维度;429;可配置、与套餐一致。

返回模块 | 返回总览

18-推理平台设计/246-模型fine-tuning-as-a-service的架构.md

第 246 题:模型fine-tuning as a service的架构?

题目

模型fine-tuning as a service的架构?


完整讲解

一、Fine-tuning as a service 定位

服务化微调:用户通过 API 或控制台 提交 基础模型、数据、超参,平台 在后台跑微调,完成后产出 新模型版本入库或直接部署。用户无需管 GPU 调度、环境与脚本,按需、按量 使用。

二、架构要点

提交API 接收「基础模型 ID、训练数据路径/上传、超参、任务名」;生成 微调 job,进入 训练队列(与普通训练共用调度或独立队列)。执行调度器 分配 GPU;运行时 拉取基础模型与数据、执行 LoRA/全量 等微调脚本;checkpoint 与日志 写回存储与可观测。产出:微调完成后 新模型 写入 模型仓库(带版本、元数据、父模型血缘);可选 自动部署 到推理或 仅入库 供用户选择部署。多租户资源隔离与 quota计费 按 GPU 时或按任务。

三、与训练平台的关系

复用 训练平台的 调度、存储、可观测差异任务形态(短任务、交互式提交、产出直接进模型仓库与推理)。数据:用户上传或指定路径;安全隐私(数据不跨租户、可加密)需保障。

面试要点

  • Fine-tuning as a service:用户提交模型+数据+超参,平台跑微调、产出新版本入库/部署。
  • 架构:提交 API → 微调 job → 调度执行 → checkpoint 与日志 → 模型仓库 + 可选部署。
  • 复用训练平台调度与存储;多租户与计费;数据安全与隐私。

记忆要点

  1. 服务化 = API 提交、平台执行、产出入库/部署。
  2. Job 队列、调度、存储、可观测;模型仓库 + 血缘。
  3. 多租户、计费、数据安全。

返回模块 | 返回总览

18-推理平台设计/247-推理服务的cost-optimization.md

第 247 题:推理服务的cost optimizationspot instancebatching

题目

推理服务的cost optimizationspot instancebatching


完整讲解

一、推理 cost 的构成

成本算力(GPU 实例)、存储(模型与缓存)、网络与带宽。优化目标:在 满足 SLA降低单位请求成本总成本

二、Spot instance

Spot(抢占式实例):价格低、可能被 随时回收推理无状态、可快速迁移;某实例被回收时 其他副本 接流量、新实例 再起。适用批处理、非实时、可容忍偶发中断 的推理;或 与 on-demand 混部,Spot 扛基线、on-demand 兜底尖峰。实现调度 支持 Spot 节点池;Pod 容忍 Spot 的 taint;优雅退出健康检查 配合,回收前尽量排空请求。

三、Batching

Batching多请求 合并为 一 batch 推理,提高 GPU 利用率、降低 单请求成本动态 batching:请求排队、凑满 batch 或超时后一起推理;连续 batching(流式)边生成边收新请求。权衡:batch 大则 吞吐高、成本低,但 排队与延迟 增;需按 SLA 调 batch 大小与超时。其它模型量化、小模型、缓存 也降单次推理成本;缩容与弹性 在低峰减实例。

面试要点

  • 成本:算力、存储、网络;优化 = Spot、batching、量化、缓存、弹性。
  • Spot:低价、可回收;无状态推理可接;与 on-demand 混部、优雅退出。
  • Batching:提高利用率、降单请求成本;与延迟权衡;动态/连续 batching。

记忆要点

  1. Cost = 算力+存储+网络;Spot + batching + 量化+缓存。
  2. Spot 无状态可接、混部兜底;batching 提利用率。
  3. 与 SLA 权衡;弹性缩容。

返回模块 | 返回总览

18-推理平台设计/248-模型on-device部署的infra支持.md

第 248 题:模型on-device部署的infra支持?Core MLTFLite

题目

模型on-device部署的infra支持?Core MLTFLite


完整讲解

一、On-device 部署场景

On-device:模型在 端侧(手机、IoT、边缘盒子)运行,低延迟、隐私、离线Infra 支持模型转换与下发版本与兼容监控与更新;与 云端推理 形成「云+端」协同。

二、Core ML、TFLite

Core ML(Apple):iOS/macOS 上推理框架;模型需 转换为 Core ML 格式(.mlmodel);支持 Neural Engine、GPU、CPU工具链:从 PyTorch/ONNX 等 导出 → 转 Core ML;平台可提供 转换流水线(如 ONNX → Core ML)、量化与优化版本与下发(通过 App 更新或 MDM)。TFLite(TensorFlow Lite):Android、嵌入式 常用;模型为 .tflite;支持 GPU delegate、NNAPI、Hexagon 等。转换:TF/Keras 或 TF 兼容 模型 → TFLite;量化、剪枝 在转换时可选。平台模型仓库多端格式(ONNX、TFLite、Core ML);CI 在训练/导出后 自动转 各端格式并做 兼容与性能测试OTA/MDM应用市场 下发。

三、统一与迭代

一次训练、多端部署统一 导出 ONNXIR,再 分别转 Core ML、TFLite、MNN 等;平台 管理「一模型多格式」的 版本与血缘迭代:端侧 上报 性能与崩溃;A/B 与灰度 控制新模型下发比例。

面试要点

  • On-device:端侧推理;infra 支持 = 转换、下发、版本、监控。
  • Core ML:iOS/macOS、.mlmodel、从 ONNX 等转;TFLite:Android/嵌入式、.tflite、delegate。
  • 平台:多端格式、转换流水线、版本与下发;一次训练多端部署。

记忆要点

  1. On-device = 端侧;Core ML = Apple;TFLite = Android/嵌入式。
  2. 转换流水线、多端格式、版本管理。
  3. 一次训练多端;OTA/MDM 下发。

返回模块 | 返回总览

18-推理平台设计/249-推理服务的latency-SLO保证.md

第 249 题:推理服务的latency SLO保证?p99 < 100ms如何实现?

题目

推理服务的latency SLO保证?p99 < 100ms如何实现?


完整讲解

一、Latency SLO 的含义

SLO服务等级目标,如「P99 延迟 < 100ms」。保证:通过 容量、限流、排队与调度 使 绝大多数请求 满足该目标;超 SLO 则告警、扩容或降载。

二、如何实现 P99 < 100ms

容量压测与建模 得到「单实例在目标负载下的 P99」;实例数负载 满足「总 P99 低于 100ms」(考虑排队与长尾)。排队请求队列 不宜过长;动态 batching最大等待时间 需小于 SLO 的一部分;或 限流 使排队可控。长尾P99冷启动、编译、GC、noisy neighbor 影响;预热预编译显存预留隔离(单实例单模型或 MIG)减长尾。监控实时 P99SLO 燃烧率;超阈值则 扩容或告警trace 定位 P99 请求特征(大 batch、长 seq 等)。

三、与容量与成本权衡

保证 P99 常需 过量供给保守 batching;与 成本 冲突。实践:按 SLA 分级(如核心接口 P99<100ms、其它 best-effort);弹性 在高峰扩容、低峰缩容;降级(如超载时返回缓存或简化模型)保核心。

面试要点

  • Latency SLO(如 P99<100ms):容量、排队、长尾控制;监控与告警。
  • 容量满足目标负载;排队与 batching 超时可控;预热、预编译、隔离减长尾。
  • 与成本权衡;分级 SLA、弹性、降级。

记忆要点

  1. SLO = P99 等目标;容量+排队+长尾控制。
  2. 预热、预编译、隔离;监控 P99、trace 定位。
  3. 分级、弹性、降级。

返回模块 | 返回总览

18-推理平台设计/250-推理请求的admission-control.md

第 250 题:推理请求的admission control?防止过载?

题目

推理请求的admission control?防止过载?


完整讲解

一、Admission control 的目的

准入控制:在 请求进入 推理前做 接受/拒绝 决策,防止过载:当 系统已接近或超过容量 时,拒绝新请求(或排队、降级)比 全盘接受导致雪崩 更可控。保证 已接受请求延迟与成功率

二、实现方式

基于队列请求队列最大长度;超过则 拒绝(返回 503/429)或 返回「排队中」 让客户端重试。基于负载当前 QPS、CPU/GPU 利用率、正在处理数 超过阈值则 拒绝;需 实时指标快速决策基于延迟当前 P99 或平均延迟 已超 SLO 则 暂停接纳,等负载下来再开。基于 token预留 一定「处理能力」或「并发槽位」;新请求 消耗 token,无 token 则拒绝;与 限流 结合(如每用户 token 桶)。

三、与限流、降级配合

限流:按 user、API key、租户 限 QPS,先于 admission 做;admission 是 全局 保护。降级:过载时 部分请求简化模型、缓存或默认回复,减少拒绝率但略降质量。反馈:拒绝时返回 Retry-Afterbackoff 建议,客户端可重试;队列 模式可返回 排队位置与预估时间

面试要点

  • Admission control:请求进入前接受/拒绝,防止过载、保护已接受请求的 SLA。
  • 实现:基于队列长度、负载、延迟、token/槽位;超阈值拒绝或排队。
  • 与限流(按用户)、降级配合;拒绝时 Retry-After 或排队信息。

记忆要点

  1. Admission = 准入;过载时拒绝或排队。
  2. 基于队列/负载/延迟/token;与限流、降级配合。
  3. 返回 503/429、Retry-After。

返回模块 | 返回总览

18-推理平台设计/251-模型ensemble和cascade的架构设计.md

第 251 题:模型ensemblecascade的架构设计?

题目

模型ensemblecascade的架构设计?


完整讲解

一、Ensemble

Ensemble多模型 对同一输入分别推理,结果融合(投票、平均、 stacking)后输出。架构路由 把请求 复制 到多个 模型服务聚合服务 收齐结果后做 融合 再返回。部署:多模型可 同机多副本分服务延迟最慢模型资源 为多份之和。适用提升准确率/鲁棒性A/B 多版本 也可视为轻量 ensemble(选一路)。

二、Cascade

Cascade多级 模型,先快后准第一级 快速模型(小、快)做 粗筛不确定或高价值 的再走 第二级 重模型。架构:请求先调 L1 服务;根据 置信度或规则 决定是否调 L2;最终返回 L1 或 L2 结果。优点平均延迟与成本 低(多数请求只经 L1);高价值请求 得到更好结果。实现路由/编排 按 L1 输出分支;L2 可 异步同步超时fallback(L2 超时则用 L1)需考虑。

三、对比与选型

Ensemble:多模型并行、结果融合;延迟与成本高准确率/鲁棒性 提升。Cascade:多级串行、先快后准;省成本与延迟复杂请求 走重模型。按 业务 选:要 稳定性 用 ensemble;要 成本与延迟 用 cascade。

面试要点

  • Ensemble:多模型并行、结果融合;提升准确率/鲁棒性;延迟与成本为多份之和。
  • Cascade:多级、先快后准;粗筛+重模型;省成本与平均延迟。
  • 选型:要稳定用 ensemble;要成本与延迟用 cascade。

记忆要点

  1. Ensemble = 多模型并行、融合;Cascade = 多级、先快后准。
  2. Ensemble 延迟/成本高;Cascade 省成本与延迟。
  3. 按业务选型。

返回模块 | 返回总览

18-推理平台设计/252-推理服务的debuggability.md

第 252 题:推理服务的debuggabilityrequest tracingmodel versioning

题目

推理服务的debuggabilityrequest tracingmodel versioning


完整讲解

一、Debuggability 需求

可调试性请求失败或延迟异常 时,能 快速定位 是模型、数据、实例还是网络问题;模型版本与配置 可追溯;单请求完整路径 可复现与分析。

二、Request tracing

Tracing:为每个请求分配 trace_id(或沿用上游),在 网关、推理服务、下游透传;各环节 打 span(开始、结束、标签)。排查:按 trace_id整条链路— 排队、调度、哪台实例、模型加载、推理各阶段耗时、是否超时或错误。实现OpenTelemetry 等标准;日志指标 带 trace_id,便于关联。与 SLO:P99 差时,取 P99 对应 trace 看瓶颈在排队、某层、还是网络。

三、Model versioning

版本管理:每次部署带 模型版本(如 digest、tag);请求 可带「期望版本」或 路由到指定版本排查错误或掉点 时确认 实际调用的版本回滚 到上一版本对比;血缘 记录版本对应的训练 job、数据与配置。平台模型仓库 存版本与元数据;推理 上报「请求 → 模型版本」;debug 界面 支持按版本查指标与 trace。

面试要点

  • Debuggability:请求失败/延迟异常可定位;request tracing + model versioning。
  • Tracing:trace_id 透传、span 打点;按 trace_id 查链路、定位瓶颈与错误。
  • Model versioning:请求与版本关联、回滚与血缘;平台存版本、推理上报版本。

记忆要点

  1. Debug = tracing + versioning。
  2. trace_id、span、整条链路可查。
  3. 版本与请求关联、回滚、血缘。

返回模块 | 返回总览

18-推理平台设计/253-实时推理和离线推理的统一架构.md

第 253 题:实时推理和离线推理的统一架构?

题目

实时推理和离线推理的统一架构?


完整讲解

一、实时与离线推理的差异

实时低延迟请求-响应 同步或流式;QPS 与 SLA 要求高;动态 batching、连续 batching离线批处理高吞吐、可 排队与调度延迟 要求松(分钟级可接受);大 batch、多 job 跑在集群上。统一架构同一套模型与运行时,通过 调度与资源配置 区分「实时服务」与「离线批处理」,减少 两套栈 的维护与不一致。

二、统一架构思路

共享模型仓库同一推理引擎(如 vLLM、Triton)、同一镜像与版本实时离线 都从同一仓库拉模型、同一引擎执行。调度分层实时常驻服务 + HPA,请求经 LB 进实例;离线Job 队列(如 K8s Job、Ray、队列消费),按需起任务、大 batch、跑完即释。资源实时预留或弹性 实例;离线空闲或 Spot,可与实时 混部(离线填谷)、或 独立池API统一 推理 API(如 OpenAI 兼容);实时 同步/流式 调用;离线 异步(提交 job、轮询或回调取结果)。

三、与成本、优先级

优先级实时 高优、离线 低优;离线 可抢占backfill 实时空闲时段的资源。成本:离线多用 Spot、弹性;统一架构下 资源池 共享,利用率 更高。

面试要点

  • 实时:低延迟、同步/流式、高 SLA;离线:批处理、高吞吐、延迟松。
  • 统一:同一模型与引擎、同一仓库与镜像;调度分层(常驻服务 vs Job 队列)。
  • 实时常驻+HPA;离线 Job/队列、按需、Spot;可混部、优先级与 backfill。

记忆要点

  1. 实时 vs 离线:延迟 vs 吞吐;统一 = 同模型同引擎。
  2. 调度:实时常驻、离线 Job;资源可混部。
  3. 优先级、Spot、backfill。

返回模块 | 返回总览

18-推理平台设计/254-推理服务的security.md

第 254 题:推理服务的security?模型加密、API认证?

题目

推理服务的security?模型加密、API认证?


完整讲解

一、推理服务安全需求

安全模型与数据 不被窃取与篡改;API 仅授权可访问;审计合规。涉及 模型加密、传输与存储安全、API 认证与鉴权

二、模型加密

静态模型文件存储与分发加密(如 AES);推理节点密钥(从 KMS 或安全模块获取)解密 后加载;密钥 不落盘、按需注入。运行时机密计算(如 TEE、SGX)可在 加密内存 中跑推理,模型与输入 对宿主机不可见;成本与兼容性需权衡。目的:防 模型泄露盗用;满足 合规(如模型含敏感信息)。

三、API 认证

认证API key、OAuth2、JWT 等;请求带 token网关或服务 校验后放行。鉴权RBAC— 谁可访问哪类模型、哪类接口(如只读、只推理);多租户 下按 tenant_id 隔离。传输TLS 全链路;内网 可 mTLS。审计访问日志(谁、何时、何接口、何模型);敏感操作 留痕;满足 合规与溯源

面试要点

  • 安全:模型加密、API 认证与鉴权、传输与审计。
  • 模型加密:静态加密+ KMS 解密;可选 TEE 机密计算。
  • API:API key/OAuth/JWT;RBAC;TLS;审计日志。

记忆要点

  1. 模型加密:存储/分发加密、KMS 解密;可选 TEE。
  2. API 认证:key/OAuth/JWT;RBAC、TLS。
  3. 审计与合规。

返回模块 | 返回总览

18-推理平台设计/255-推理平台的carbon-footprint优化.md

第 255 题:推理平台的carbon footprint优化?绿色AI?

题目

推理平台的carbon footprint优化?绿色AI?


完整讲解

一、Carbon footprint 与绿色 AI

碳足迹:推理与训练消耗 电力,间接产生 碳排放绿色 AI:通过 能效优化、资源利用率、清洁能源与调度 降低 单位算力或单位请求的能耗与碳,兼顾 成本与可持续

二、推理平台可做的优化

能效量化、蒸馏、小模型 降低单次推理 算力与显存,同 QPS 下 功耗更低批处理与利用率 提高 单卡吞吐,摊薄单请求能耗。调度与选址优先调度到 清洁能源比例高、PUE 低region 或机房低峰缩容迁到绿色电力多的区硬件新一代 GPU(如 H100)能效比更好;混部与弹性 减少 空转,提高整体利用率即降低「单位产出的碳」。监控能耗与碳 作为 指标(如每万 QPS 的 kWh、碳当量);看板与报表 驱动优化与汇报。

三、与成本、SLA 的协同

省电即省钱:多数优化(利用率、缩容、量化)同时 降成本SLA:在满足延迟与可用性前提下做 绿色调度(如优先绿色 region);碳预算 可与 配额 结合,引导业务在绿色时段或区域多用。

面试要点

  • Carbon footprint:电力与碳排放;绿色 AI = 能效、利用率、清洁能源与调度优化。
  • 推理优化:量化/小模型、批处理与利用率;调度到绿色 region、低峰缩容;新一代硬件。
  • 能耗与碳指标、看板;与成本、SLA 协同;碳预算与配额可选。

记忆要点

  1. 碳足迹 = 能耗与排放;绿色 AI = 能效与可持续。
  2. 量化、利用率、绿色 region、缩容、新硬件。
  3. 指标与看板;与成本、SLA 协同。

返回模块 | 返回总览

19-CPP与CUDA编程/README.md

19-CPP与CUDA编程(第 256–270 题)

题号 主题 文章
256 写一个线程安全的memory pool,支持allocate和`… 256-写一个线程安全的memory-pool,支持allocate和free.md
257 CUDA的__shared__ memory使用注意事项?`bank… 257-CUDA的__shared__-memory使用注意事项.md
258 实现一个ring buffer用于CPU-GPU异步数据传输 258-实现一个ring-buffer用于CPU-GPU异步数据传输.md
259 CUDA streamevent的同步机制?`cudaStre… 259-CUDA-stream和event的同步机制.md
260 thrust库的使用经验?transform_reduce 260-thrust库的使用经验.md
261 CUTLASSgemm调用示例?Epilogue定制? 261-CUTLASS的gemm调用示例.md
262 NCCLall-reduce实现?ring算法代码走读? 262-NCCL的all-reduce实现.md
263 zero-copy memory的使用场景?`cudaHostAll… 263-zero-copy-memory的使用场景.md
264 多GPU的peer-to-peer访问?`cudaDeviceEna… 264-多GPU的peer-to-peer访问.md
265 CUDA Graph的捕获条件?哪些操作不能捕获? 265-CUDA-Graph的捕获条件.md
266 template metaprogramming在CUDA优化中的应… 266-template-metaprogramming在CUDA优化中的应用.md
267 RAII模式管理CUDA资源?unique_ptr with c… 267-RAII模式管理CUDA资源.md
268 CUDA error处理的最佳实践?CUDA_CHECK宏? 268-CUDA-error处理的最佳实践.md
269 warp shuffle指令的使用?__shfl_sync 269-warp-shuffle指令的使用.md
270 cooperative groups的高级用法?`grid_grou… 270-cooperative-groups的高级用法.md

返回总览

19-CPP与CUDA编程/256-写一个线程安全的memory-pool,支持allocate和free.md

第 256 题:写一个线程安全的memory pool,支持allocatefree

题目

写一个线程安全的memory pool,支持allocatefree


完整讲解

一、目的与接口

内存池预分配大块内存、按块或按 size-class 分配/释放,减少 malloc/free 次数与碎片。接口通常为 allocate(size)free(ptr),多线程并发调用需保证线程安全。

二、实现要点

mutexspinlock 保护空闲链表(free list);按固定块大小或多种 size-class 管理;allocate 从链表取块,free 将块归还。高并发时可做 per-thread 子池 + 全局 fallback,减少锁竞争与假共享。

三、工程经验

大块预分配用 mallocmmap 一次;注意对齐与元数据开销;生产环境可选用 tcmalloc、jemalloc 等成熟实现。


面试要点

  • 内存池目的:减少 malloc/free 调用与碎片,接口 allocate/free 需线程安全。
  • 用 mutex/spinlock 保护 free list;按块或 size-class 管理。
  • 高并发可做 per-thread 子池 + 全局 fallback。
  • 预分配大块、控制元数据与对齐;可引用 tcmalloc/jemalloc。

记忆要点

  1. 内存池 = 预分配 + free list + 线程安全(锁或 per-thread 子池)。
  2. allocate 从链表取、free 归还;注意锁粒度与假共享。
  3. 工程上大块预分配、控制开销;复杂场景用现成分配器。

返回模块 | 返回总览

19-CPP与CUDA编程/257-CUDA的__shared__-memory使用注意事项.md

第 257 题:CUDA的__shared__ memory使用注意事项?bank conflict

题目

CUDA的__shared__ memory使用注意事项?bank conflict


完整讲解

一、__shared__ 使用注意

Shared memory 是 SM 内 block 内线程共享的片上存储,容量有限(几十 KB 级),速度快。需注意:静态分配 __shared__ T buf[N]动态 extern __shared__ T buf[] 配合 <<<..., size>>>;生命周期与 block 一致;同一 block 内线程可协作读写。

二、Bank conflict

Shared memory 按 4 字节(或 32 位宽)分成若干 bank;同一 warp 内多线程访问同一 bank 不同地址会串行化(bank conflict)。避免方式:保证同一 warp 访问不同 bank(如按 threadIdx.x stride 访问)、或访问同一地址(broadcast 不冲突);padding 可打散对齐以降低冲突。

三、工程要点

设计 shared 布局时先算访问模式,避免 32 路 bank 同 bank 不同地址;reduce、矩阵 tile 等常用 shared,注意边界与对齐。


面试要点

  • __shared__ 是 block 内共享、片上、容量有限;静/动态分配、生命周期与 block 一致。
  • Bank:按 4B 分 bank;同 warp 同 bank 不同地址 = bank conflict,会串行。
  • 避免:不同 bank 访问、或同地址 broadcast;可用 padding 打散。
  • 设计时算清访问模式,reduce/tile 常用 shared。

记忆要点

  1. Shared = block 内共享、片上、有限容量;注意静/动态分配。
  2. Bank conflict = 同 warp 同 bank 不同地址;避免或 padding。
  3. 工程上先算访问模式,reduce/tile 注意 stride 与对齐。

返回模块 | 返回总览

19-CPP与CUDA编程/258-实现一个ring-buffer用于CPU-GPU异步数据传输.md

第 258 题:实现一个ring buffer用于CPU-GPU异步数据传输

题目

实现一个ring buffer用于CPU-GPU异步数据传输


完整讲解

一、目的与结构

Ring buffer 固定大小、首尾相接,用于 CPU 与 GPU 之间双缓冲或多缓冲流水:CPU 写下一块数据时 GPU 读当前块,实现异步传输与计算重叠。典型:连续多段 host 内存(或 pinned)对应多段 device 内存,用下标或指针环回。

二、实现要点

维护 write_pos(CPU 写)、read_pos(GPU 读);空/满用 pos 差或 count 判断,避免判满与判空条件相同。用 cudaMemcpyAsync 配合 stream 按 slot 拷贝;CPU 侧用 pinned memory 提升 D2H/H2D 带宽。同步用 stream/event,保证「写完再拷、拷完再算」。

三、工程经验

Slot 数量一般 2~4 即可重叠;注意对齐与 stride;多 producer/consumer 时需原子或锁保护 pos。


面试要点

  • Ring buffer 用于 CPU-GPU 流水:多 slot 轮流写/读,实现传输与计算重叠。
  • write_pos/read_pos 环回;空满用 pos 差或 count 区分。
  • cudaMemcpyAsync + stream + pinned memory;用 event 同步「写→拷→算」。
  • Slot 数 2~4;多线程改 pos 需原子或锁。

记忆要点

  1. Ring = 固定大小、首尾相接;多 slot 实现 CPU 写与 GPU 读重叠。
  2. write_pos/read_pos、cudaMemcpyAsync + stream + pinned。
  3. 同步用 stream/event;slot 数 2~4,多线程保护 pos。

返回模块 | 返回总览

19-CPP与CUDA编程/259-CUDA-stream和event的同步机制.md

第 259 题:CUDA streamevent的同步机制?cudaStreamSynchronize

题目

CUDA streamevent的同步机制?cudaStreamSynchronize


完整讲解

一、Stream 与 Event 概念

CUDA stream 是设备上的操作队列,同一 stream 内 kernel、memcpy 顺序执行,不同 stream 可并发。Event 是时间点标记,可 cudaEventRecord(event, stream) 在 stream 某处插入,再 cudaStreamWaitEvent(stream2, event) 让另一 stream 等待该点。

二、cudaStreamSynchronize

cudaStreamSynchronize(stream) 阻塞当前 host 线程直到该 stream 上所有已提交操作完成。与 cudaDeviceSynchronize() 区别:后者等所有 stream,前者只等指定 stream。用于「host 需要该 stream 结果后再继续」的场景。

三、典型用法

用 event 做 stream 间依赖(如 stream B 等 stream A 的 kernel 完成);用 stream 做 kernel 与 memcpy 重叠;需要 host 取结果时对该 stream 做 cudaStreamSynchronize


面试要点

  • Stream:操作队列,同 stream 顺序、不同 stream 可并发;Event:时间点,可 record + wait。
  • cudaStreamSynchronize(stream):host 阻塞直到该 stream 完成;cudaDeviceSynchronize 等全部。
  • 用 event 做 stream 间依赖;用 stream 做 kernel 与 copy 重叠。

记忆要点

  1. Stream = 队列;Event = 时间点;record + wait 做依赖。
  2. cudaStreamSynchronize 只等指定 stream;DeviceSynchronize 等全部。
  3. 重叠用多 stream;host 要结果时再 sync。

返回模块 | 返回总览

19-CPP与CUDA编程/260-thrust库的使用经验.md

第 260 题:thrust库的使用经验?transform_reduce

题目

thrust库的使用经验?transform_reduce


完整讲解

一、Thrust 简介

Thrust 是 CUDA 自带的 C++ 模板库,提供类似 STL 的接口(vector、transform、reduce、sort 等),在 GPU 上执行。可减少手写 kernel 的工作,适合规则化的数据并行。

二、transform_reduce

thrust::transform_reduce 先对每个元素做一元/二元 transform(如平方、乘权),再对结果做 reduce(如 sum)。一次调用完成「映射+归约」,减少 kernel 启动与全局读写。用法:transform_reduce(itr_begin, itr_end, unary_op, init, binary_reduce_op)

三、使用经验

thrust::device_vector 管理显存;迭代器与 host/device 指针配合;复杂算子可自定义 functor。注意 thrust 会占用一定显存与编译时间,简单 kernel 手写有时更可控。


面试要点

  • Thrust = GPU 上的 STL 风格库;vector、transform、reduce、sort 等。
  • transform_reduce = 先 transform 再 reduce,一次完成映射+归约。
  • device_vector 管理显存;自定义 functor 做复杂逻辑;简单场景可手写 kernel。

记忆要点

  1. Thrust = GPU STL;transform_reduce = transform + reduce 一次完成。
  2. 用 device_vector、迭代器;复杂逻辑用 functor。
  3. 规则数据并行用 thrust 省事;极简 kernel 可手写。

返回模块 | 返回总览

19-CPP与CUDA编程/261-CUTLASS的gemm调用示例.md

第 261 题:CUTLASSgemm调用示例?Epilogue定制?

题目

CUTLASSgemm调用示例?Epilogue定制?


完整讲解

一、CUTLASS GEMM 概览

CUTLASS 是 NVIDIA 的 CUDA 模板库,提供高性能 GEMM(矩阵乘)等算子。通过模板配置 Tile 尺寸、ThreadBlockWarp 级结构,以及 Epilogue(C = f(accumulator),如 C = alphaAB + beta*C、ReLU 等)。

二、调用示例

典型流程:定义 GemmOperation 类型(指定 Element、Layout、Tile、Stages 等);用 gemm_op()operator() 传入 problem size、指针、ld、alpha/beta 等;可配合 CUDA stream。Epilogue 控制输出如何从累加器写回(线性组合、激活等)。

三、Epilogue 定制

Epilogue 是「累加器 → 输出」的步骤,可自定义:如 LinearCombination、带 bias/activation 的 fusion。通过指定 Epilogue 的 ElementCompute、ElementOutput、Functor 等模板参数,实现 D = activation(alphaAB + beta*C + bias) 等融合写法。


面试要点

  • CUTLASS 用模板配置 Tile、ThreadBlock、Epilogue,实现高性能 GEMM。
  • 调用:定义 GemmOperation,传入 size、指针、ld、alpha/beta、stream。
  • Epilogue 控制累加器→输出;可定制线性组合、bias、activation 等融合。
  • 常用于推理/训练中的 matmul 融合与定制。

记忆要点

  1. CUTLASS = 模板 GEMM;Tile + Epilogue 可配置。
  2. 调用:GemmOperation + problem size + 指针 + alpha/beta。
  3. Epilogue 定制 = 累加器→输出(线性、bias、activation 等)。

返回模块 | 返回总览

19-CPP与CUDA编程/262-NCCL的all-reduce实现.md

第 262 题:NCCLall-reduce实现?ring算法代码走读?

题目

NCCLall-reduce实现?ring算法代码走读?


完整讲解

一、NCCL All-Reduce 作用

NCCL 提供多 GPU/多机集合通信,all-reduce 即每 rank 有一份输入,结果每 rank 得到相同的规约值(如 sum)。用于分布式训练里梯度/参数同步。

二、Ring All-Reduce 思路

Ring 算法把 N 个节点连成环。Reduce-Scatter 阶段:数据分块,沿环多轮传递,每轮每节点做部分 reduce 并传给下一节点,最终每节点持有 1/N 的完整规约结果。All-Gather 阶段:再沿环把各节点持有的块广播出去,最后每节点得到完整结果。带宽利用好,适合大 tensor。

三、代码走读要点

NCCL 源码中 ring 实现在 ring.cu 等;关注 send/recv 方向chunk 划分in-place 与 buffer、以及 ncclSend/ncclRecv 与 kernel 的配合。不同拓扑(单机多卡、多机)会选 ring 或 tree 等算法。


面试要点

  • All-reduce:每 rank 输入,每 rank 得相同规约结果;NCCL 实现多种算法。
  • Ring:Reduce-Scatter(分块沿环 reduce)+ All-Gather(沿环广播);带宽友好。
  • 走读看 send/recv、chunk、buffer 与 kernel 配合;拓扑决定 ring/tree 等。
  • 用于分布式训练梯度/参数同步。

记忆要点

  1. All-reduce = 每 rank 同结果;Ring = Reduce-Scatter + All-Gather。
  2. 分块沿环传递,带宽利用率高;多机可选 ring/tree。
  3. 走读:ring 方向、chunk、buffer、ncclSend/Recv。

返回模块 | 返回总览

19-CPP与CUDA编程/263-zero-copy-memory的使用场景.md

第 263 题:zero-copy memory的使用场景?cudaHostAlloc

题目

zero-copy memory的使用场景?cudaHostAlloc


完整讲解

一、Zero-Copy 概念

Zero-copy memory(固定/pinned host 内存的一种用法)指 host 分配一块可被 GPU 直接访问的物理内存,GPU kernel 通过 PCIe 按需读取,无需显式 cudaMemcpy。适合「GPU 随机、稀疏访问 host 数据」或数据量不大、拷贝开销不划算的场景。

二、cudaHostAlloc

cudaHostAlloc(&ptr, size, flags) 分配 pinned host memory。flags 常用:cudaHostAllocDefault(默认)、cudaHostAllocMapped(同时映射到 device 地址空间,即 zero-copy)、cudaHostAllocPortable(多 GPU 可见)等。Mapped 时用 cudaHostGetDevicePointer(&d_ptr, ptr, 0) 取 device 侧指针,kernel 用 d_ptr 访问。

三、使用场景与注意

适合:小量、随机访问、或与计算重叠的流式访问。注意:通过 PCIe 访问延迟高、带宽有限,大块顺序访问不如先 Memcpy 再算;且 mapped 会占 host 物理页、可能影响 swap。


面试要点

  • Zero-copy:host 内存在 GPU 地址空间可见,kernel 直接读,无需显式 copy。
  • cudaHostAlloc(..., cudaHostAllocMapped) + cudaHostGetDevicePointer 得到 device 指针。
  • 适合小量、随机或流式访问;大块顺序访问仍建议 Memcpy 再算。
  • 注意 PCIe 延迟与带宽、以及 pinned 页占用。

记忆要点

  1. Zero-copy = host 映射到 device 空间,kernel 直接访问;cudaHostAllocMapped。
  2. cudaHostGetDevicePointer 取 device 指针;kernel 用该指针读。
  3. 适合随机/小量访问;大块顺序用 copy 更高效。

返回模块 | 返回总览

19-CPP与CUDA编程/264-多GPU的peer-to-peer访问.md

第 264 题:多GPU的peer-to-peer访问?cudaDeviceEnablePeerAccess

题目

多GPU的peer-to-peer访问?cudaDeviceEnablePeerAccess


完整讲解

一、P2P 概念

Peer-to-Peer(P2P) 指多 GPU 间直接访问对方显存,不经过 host。在支持 P2P 的拓扑下(如同一 PCIe 树、NVLink),可降低延迟、提高带宽,用于多卡 kernel 间直接读写。

二、cudaDeviceEnablePeerAccess

cudaDeviceEnablePeerAccess(peerDeviceId, flags) 使当前 device 能访问 peerDeviceId 的显存。需在两端都启用(A 能访问 B、B 能访问 A 需各调一次)。返回 cudaErrorPeerAccessAlreadyEnabled 表示已开。配合 cudaMemcpyPeer(dst, dstDev, src, srcDev, size) 做 D2D 拷贝。

三、条件与注意

拓扑需支持(同机多卡通常支持;跨机不行)。可先 cudaDeviceCanAccessPeer(&can, dev, peer) 查询。P2P 打开后,分配在 peer 上的指针可在本 device kernel 中通过统一地址或 Peer 接口使用(视驱动与 UVA 而定)。


面试要点

  • P2P = 多 GPU 直接访问对方显存,不经过 host;同机/同 PCIe 树常支持。
  • cudaDeviceEnablePeerAccess(peerId, 0) 使当前 device 能访问 peer;双向需各调一次。
  • cudaMemcpyPeer 做 D2D;先 cudaDeviceCanAccessPeer 查询是否支持。
  • 用于多卡间低延迟、高带宽数据交换。

记忆要点

  1. P2P = GPU 直接访问 GPU 显存;cudaDeviceEnablePeerAccess 开启。
  2. 双向访问需各自 Enable;cudaMemcpyPeer 做 D2D。
  3. 需拓扑支持;cudaDeviceCanAccessPeer 查询。

返回模块 | 返回总览

19-CPP与CUDA编程/265-CUDA-Graph的捕获条件.md

第 265 题:CUDA Graph的捕获条件?哪些操作不能捕获?

题目

CUDA Graph的捕获条件?哪些操作不能捕获?


完整讲解

一、CUDA Graph 捕获目的

CUDA Graph 把一段 kernel 与 memcpy 序列录成一张图,一次性提交、减少 host 侧启动开销,适合固定计算图、反复执行的推理或训练 step。

二、捕获条件

stream 上cudaStreamBeginCapture(stream) 开始、cudaStreamEndCapture(stream, &graph) 结束;期间在该 stream 上发的 kernel、memcpy 会被记录。要求:不能在捕获期间做依赖该 stream 结果的 host 同步(如 cudaStreamSynchronize)、不能做会阻塞或依赖未捕获操作的行为;子图、条件分支需用 stream 内可表达的方式。

三、不能捕获的操作

cudaStreamSynchronizecudaDeviceSynchronizecudaMemcpy(同步版)、cudaMalloc 等会阻塞或非异步的 API 不能在捕获期间对「被依赖的 stream」调用。cudaLaunchHostFunc 在部分版本/场景下有限制。用 cudaMemcpyAsynccudaMallocAsync(若可用)等异步接口即可纳入图。


面试要点

  • CUDA Graph 记录一段 kernel/copy 序列,一次提交反复执行,降低 launch 开销。
  • 捕获:cudaStreamBeginCapture / EndCapture;只能录异步、非阻塞的操作。
  • 不能捕获:StreamSynchronize、DeviceSynchronize、同步 cudaMemcpy、cudaMalloc 等阻塞调用。
  • 用 *Async 接口、避免在捕获期间 host 同步。

记忆要点

  1. Graph = 录一段操作序列;BeginCapture/EndCapture 在 stream 上。
  2. 只能录异步操作;同步/阻塞 API 不能出现在捕获路径上。
  3. 用 cudaMemcpyAsync、避免 Synchronize/cudaMalloc 等。

返回模块 | 返回总览

19-CPP与CUDA编程/266-template-metaprogramming在CUDA优化中的应用.md

第 266 题:template metaprogramming在CUDA优化中的应用?

题目

template metaprogramming在CUDA优化中的应用?


完整讲解

一、模板元编程在 CUDA 中的角色

CUDA kernel 常需在编译期确定 block 大小、tile 尺寸、循环上界、数据类型等,以生成最优指令与寄存器使用。C++ template metaprogramming(TMP) 用模板参数与特化在编译期计算类型与常量,避免运行时分支与重复代码。

二、典型应用

Tile 尺寸:用 template<int TileM, int TileN> 让编译器为不同 Tile 生成特化,便于调优。类型多态template<typename T> 写一套 kernel,对 float/half 等分别实例化。循环展开:用 #pragma unroll 配合模板常量做编译期展开。条件编译:用 if constexpr 或模板特化在编译期选择分支(如是否用 FP16 累加)。

三、工程经验

TMP 增加编译时间与二进制体积,但能消除运行时分支、利于寄存器分配与指令选择;CUTLASS、cuBLAS 等库大量使用模板配置 GEMM 与 epilogue。


面试要点

  • 模板元编程在编译期确定 tile、类型、循环等,利于 CUDA 生成最优代码。
  • 应用:Tile 尺寸、类型多态、循环展开、if constexpr 分支选择。
  • 增加编译成本,但减少运行时分支、利于寄存器与指令优化。
  • CUTLASS/cuBLAS 等大量用模板配置算子。

记忆要点

  1. TMP = 编译期确定参数;tile、类型、unroll 常用。
  2. 消除运行时分支、利于寄存器与指令;代价是编译时间。
  3. 工程上 CUTLASS 等用模板配置 GEMM/epilogue。

返回模块 | 返回总览

19-CPP与CUDA编程/267-RAII模式管理CUDA资源.md

第 267 题:RAII模式管理CUDA资源?unique_ptr with custom deleter?

题目

RAII模式管理CUDA资源?unique_ptr with custom deleter?


完整讲解

一、RAII 与 CUDA 资源

RAII(Resource Acquisition Is Initialization):构造时获取资源、析构时释放,避免泄漏与重复释放。CUDA 资源如 device 指针、stream、event、context 等都应「谁创建谁释放」,用 RAII 封装可防止异常路径泄漏。

二、unique_ptr with custom deleter

std::unique_ptr<T, Deleter> 在析构时调用 Deleter。对 device 指针:Deleter 里调用 cudaFree(ptr.get());对 stream:cudaStreamDestroy;对 event:cudaEventDestroy。定义 using CudaPtr = std::unique_ptr<float, decltype(&cudaFree)> 或写一个 functor 封装 cudaFree,即可 CudaPtr p(ptr, cudaFree),出作用域自动释放。

三、工程经验

可封装成 CudaDevicePtr<T>CudaStreamCudaEvent 等类,拷贝禁用、移动允许;与 STL 容器配合时注意 deleter 类型一致。避免 raw new/delete 与 cudaMalloc/cudaFree 混用导致的双重释放。


面试要点

  • RAII:构造获取、析构释放;CUDA 指针/stream/event 都适合 RAII。
  • unique_ptr + custom deleter:deleter 里 cudaFree/cudaStreamDestroy/cudaEventDestroy。
  • 封装成 CudaDevicePtr/CudaStream 等,禁用拷贝、允许移动。
  • 避免 raw 分配与手动 free 混用导致泄漏或双释。

记忆要点

  1. RAII = 构造拿资源、析构放资源;CUDA 资源用 RAII 防泄漏。
  2. unique_ptr,Deleter 里 cudaFree/StreamDestroy/EventDestroy。
  3. 封装成类、禁用拷贝;与 STL 配合注意 deleter 类型。

返回模块 | 返回总览

19-CPP与CUDA编程/268-CUDA-error处理的最佳实践.md

第 268 题:CUDA error处理的最佳实践?CUDA_CHECK宏?

题目

CUDA error处理的最佳实践?CUDA_CHECK宏?


完整讲解

一、CUDA 错误返回方式

多数 CUDA API 返回 cudaError_t;kernel 启动不阻塞,错误在后续同步或下一次 API 调用时才可见。因此需要在同步点或每次 API 调用后检查返回值,否则错误可能被忽略或延迟发现。

二、CUDA_CHECK 宏

常用写法:#define CUDA_CHECK(call) do { cudaError_t e = (call); if (e != cudaSuccess) { fprintf(stderr, "CUDA error %s at %s:%d\n", cudaGetErrorString(e), __FILE__, __LINE__); abort(); } } while(0)。用法:CUDA_CHECK(cudaMalloc(&p, n));CUDA_CHECK(cudaStreamSynchronize(s));。这样任意一次调用失败会立刻打印并终止,便于定位。

三、最佳实践

在 debug 构建中始终使用 CUDA_CHECK;kernel 后若有 sync,在 sync 处检查(因为 kernel 错误在 sync 时才报出)。可用 cudaGetLastError() 清除并获取上一次错误。Release 下可保留关键路径检查、或条件编译关闭以减开销。


面试要点

  • CUDA API 返回 cudaError_t;kernel 异步,错误在同步或后续 API 才暴露。
  • CUDA_CHECK 宏:调用 API、检查返回值、失败则打印 cudaGetErrorString 并 abort。
  • Debug 下全程 CHECK;kernel 后在 sync 处检查;可用 cudaGetLastError 清除错误。
  • Release 可只保留关键路径或条件编译。

记忆要点

  1. 错误在同步/后续 API 暴露;用宏统一检查返回值。
  2. CUDA_CHECK:call → 判 e != cudaSuccess → 打印 + abort。
  3. kernel 后在 sync 处 CHECK;cudaGetLastError 可清错误。

返回模块 | 返回总览

19-CPP与CUDA编程/269-warp-shuffle指令的使用.md

第 269 题:warp shuffle指令的使用?__shfl_sync

题目

warp shuffle指令的使用?__shfl_sync


完整讲解

一、Warp Shuffle 概念

Warp 是 32 个线程的 SIMD 组;warp shuffle 指同一 warp 内线程直接交换寄存器,不经过 shared memory 或 global memory,延迟低、带宽高。用于 warp 内 reduce、broadcast、scan 等。

二、__shfl_sync

__shfl_sync(mask, value, src_lane, width):在同一 warp 内,当前线程从 src_lane 号线程读其 value。mask 为参与线程的位掩码(通常 0xffffffff)。变体:__shfl_down_sync(从 lane + delta 读)、__shfl_up_sync__shfl_xor_sync(用于 butterfly reduce)等。sync 表示参与线程需先在该 warp 内同步(符合 CUDA 9+ 的 convergent 要求)。

三、使用注意

仅限 warp 内、同一 warp 的 32 线程;width 可小于 32 表示逻辑子 warp。用于 warp 内 sum、max、broadcast 时比 shared memory 更高效;跨 warp 仍用 shared。


面试要点

  • Warp shuffle:同一 warp 内通过寄存器直接交换数据,无需 shared/global。
  • __shfl_sync(mask, value, src_lane):从 src_lane 读 value;变体 down/up/xor 等。
  • mask 为参与线程掩码;sync 表示 convergent 使用。
  • 用于 warp 内 reduce、broadcast、scan;跨 warp 用 shared。

记忆要点

  1. Shuffle = warp 内寄存器交换;__shfl_sync(mask, value, src_lane)。
  2. 变体:shfl_down/up/xor;mask 与 sync 必写。
  3. 用于 warp 内 reduce/broadcast;比 shared 更省更快的 warp 内通信。

返回模块 | 返回总览

19-CPP与CUDA编程/270-cooperative-groups的高级用法.md

第 270 题:cooperative groups的高级用法?grid_group

题目

cooperative groups的高级用法?grid_group


完整讲解

一、Cooperative Groups 简介

Cooperative Groups(CUDA 9+)把「线程组」抽象成对象(thread_block、warp、grid 等),提供 sync()size()thread_rank() 等,并支持网格级同步(grid_group),替代传统 __syncthreads() 仅限 block 内。

二、grid_group 用法

grid_group grid = this_grid(); 需在 kernel 启动时cudaLaunchCooperativeKernel(或 cudaLaunchCooperativeKernelMultiDevice)才能获得有效的 grid_group。之后可 grid.sync()整个 grid 所有 block 在该点同步。用于跨 block 的全局 barrier、多阶段算法(如先全 grid 算完某阶段再进入下一阶段)等。

三、高级用法与注意

还可有 thread_block_tile(如 32 线程的 tile)、coalesced_threads() 等。grid_group 要求所有 block 都参与、且启动方式为 cooperative;否则未定义。适合多 block 协作的算法(如某些全局 reduce、迭代算法)。


面试要点

  • Cooperative Groups:线程组抽象(block、warp、grid);提供 sync、size、rank。
  • grid_group:整个 grid 同步;需 cudaLaunchCooperativeKernel 启动才有效。
  • grid.sync() 为全 grid barrier;用于跨 block 协作、多阶段算法。
  • 要求 cooperative launch、所有 block 参与。

记忆要点

  1. Cooperative Groups = 线程组抽象;grid_group = 全 grid。
  2. grid_group 需 cudaLaunchCooperativeKernel;grid.sync() 全 grid 同步。
  3. 用于跨 block 协作、多阶段算法;所有 block 必须参与。

返回模块 | 返回总览

20-Python高级/README.md

20-Python高级(第 271–280 题)

题号 主题 文章
271 Python的GIL对多线程的影响?`multiprocessing… 271-Python的GIL对多线程的影响.md
272 asyncio在IO密集型任务中的应用?aiohttp 272-asyncio在IO密集型任务中的应用.md
273 Python的memory profiler使用?`tracemal… 273-Python的memory-profiler使用.md
274 Cythonpybind11的区别?什么时候用? 274-Cython和pybind11的区别.md
275 Python的descriptor协议?property的实现? 275-Python的descriptor协议.md
276 context manager__enter__和`__exi… 276-context-manager的__enter__和__exit__.md
277 metaclass在框架设计中的应用?abc.ABCMeta 277-metaclass在框架设计中的应用.md
278 Python的import机制?sys.path、`PYTHON… 278-Python的import机制.md
279 pickle的局限性和替代方案?cloudpickle、`dil… 279-pickle的局限性和替代方案.md
280 Python代码的性能优化?cProfile、`line_profi… 280-Python代码的性能优化.md

返回总览

20-Python高级/271-Python的GIL对多线程的影响.md

第 271 题:Python的GIL对多线程的影响?multiprocessing vs threading

题目

Python的GIL对多线程的影响?multiprocessing vs threading


完整讲解

一、GIL 是什么

GIL(Global Interpreter Lock)是 CPython 中一把进程级互斥锁,同一时刻只允许一个线程执行 Python 字节码。目的是保护解释器内部状态(如引用计数)一致,但导致多线程无法并行执行 Python 代码,多核 CPU 上多线程只能交替执行。

二、对多线程的影响

CPU 密集型:多线程几乎无法提速,甚至因切换与锁竞争变慢;应改用 multiprocessing 多进程,每进程独立解释器、各自有 GIL。IO 密集型:线程在等待 IO 时会释放 GIL,多线程可重叠 IO 与计算,threading 仍有价值;也可用 asyncio 单线程并发 IO。

三、multiprocessing vs threading

threading:共享内存、轻量,受 GIL 限制,适合 IO 密集或需共享状态的场景。multiprocessing:多进程、无 GIL 限制、可真并行,适合 CPU 密集;进程间通信用 Queue、Pipe 等,数据需可序列化。选型:CPU 密集用 multiprocessing;IO 密集用 threading 或 asyncio。


面试要点

  • GIL:CPython 进程级锁,同一时刻仅一线程执行字节码;多线程无法并行执行 Python。
  • CPU 密集:多线程几乎不加速,用 multiprocessing;IO 密集:线程在 IO 时释放 GIL,threading 有用。
  • multiprocessing = 多进程、无 GIL、真并行;threading = 轻量、共享内存、受 GIL 限制。
  • 选型:CPU 密集用进程;IO 密集用线程或 asyncio。

记忆要点

  1. GIL 导致多线程不能并行执行 Python 字节码。
  2. CPU 密集用 multiprocessing;IO 密集用 threading 或 asyncio。
  3. 进程间不共享内存、需序列化;线程共享内存、受 GIL 限制。

返回模块 | 返回总览

20-Python高级/272-asyncio在IO密集型任务中的应用.md

第 272 题:asyncio在IO密集型任务中的应用?aiohttp

题目

asyncio在IO密集型任务中的应用?aiohttp


完整讲解

一、asyncio 与 IO 密集型

asyncio 是 Python 的异步 IO 框架,单线程内通过协程 + 事件循环并发执行多个「可挂起」任务。在等待 IO(网络、磁盘)时挂起当前协程、执行其他协程,从而在单线程下实现高并发 IO,无 GIL 并行执行问题(因为主要在等 IO)。

二、基本用法

async def 定义协程,await 挂起等待 IO 或其它协程;asyncio.run(main()) 运行入口。与 aiohttp 结合:async with aiohttp.ClientSession() as session: 内用 session.get(url) 等异步请求,多任务用 asyncio.gather() 并发执行,大量 HTTP 请求时比多线程更轻量、连接数可控。

三、aiohttp 与注意

aiohttp 提供异步 HTTP client/server;client 侧与 asyncio 配合做高并发爬虫、API 调用等。注意:标准库部分模块仍为同步,在 async 里调用会阻塞事件循环,需用 run_in_executor 或选异步库(如 aiofiles)。


面试要点

  • asyncio:单线程协程 + 事件循环,IO 等待时挂起、执行其他协程,适合 IO 密集。
  • async/await、asyncio.run、asyncio.gather 为常用写法。
  • aiohttp:异步 HTTP;与 asyncio 配合做高并发请求;注意同步调用会阻塞事件循环。
  • IO 密集用 asyncio 可省线程、高并发;CPU 密集仍需多进程。

记忆要点

  1. asyncio = 单线程协程 + 事件循环;await 挂起、不占线程。
  2. aiohttp = 异步 HTTP;与 asyncio 配合做高并发 client。
  3. 同步代码在 async 里会阻塞事件循环;用 run_in_executor 或异步库。

返回模块 | 返回总览

20-Python高级/273-Python的memory-profiler使用.md

第 273 题:Python的memory profiler使用?tracemalloc

题目

Python的memory profiler使用?tracemalloc


完整讲解

一、内存分析需求

Python 动态分配、引用计数与 GC,内存泄漏或大对象常需定位「谁在占用」。memory profiler 用于统计各函数/行分配量、追踪对象增长,便于发现泄漏与优化大结构。

二、tracemalloc 使用

tracemalloc(标准库,Python 3.4+)可追踪分配来源(文件名、行号)。tracemalloc.start() 开启;tracemalloc.get_traced_memory() 得当前 traced 内存;tracemalloc.get_tracemalloc_memory() 得 tracemalloc 自身开销;tracemalloc.get_object_traceback(obj) 可查某对象分配处。snapshot = tracemalloc.take_snapshot() 后对 snapshot.statistics('lineno') 排序可看分配最多的行。

三、其他工具与注意

memory_profiler 包:@profile 装饰器或 mprof run 做逐行内存占用;与 tracemalloc 互补(一个看行级、一个看调用栈/对象)。生产环境 tracemalloc 有开销,可按需开启或采样。


面试要点

  • 内存分析:定位泄漏、大对象;常用 tracemalloc(标准库)与 memory_profiler。
  • tracemalloc:start → take_snapshot → statistics('lineno') 看分配最多的行;get_object_traceback 查对象分配处。
  • memory_profiler:@profile 或 mprof 做逐行内存;可和 tracemalloc 配合。
  • tracemalloc 有运行时开销,生产可按需或采样开启。

记忆要点

  1. tracemalloc = 标准库、追踪分配来源(文件/行);snapshot + statistics。
  2. memory_profiler = 逐行内存;@profile / mprof。
  3. 分析泄漏看增长与引用;注意 tracemalloc 开销。

返回模块 | 返回总览

20-Python高级/274-Cython和pybind11的区别.md

第 274 题:Cythonpybind11的区别?什么时候用?

题目

Cythonpybind11的区别?什么时候用?


完整讲解

一、Cython 与 pybind11 定位

二者都用于 Python 调用 C/C++,提升性能或复用现有 C++ 库。Cython:写「类 Python」或带类型的 .pyx,编译成 C 再编成扩展模块;偏「用 Python 语法写扩展」。pybind11:在 C++ 侧用声明式 API 暴露类型与函数给 Python;偏「在 C++ 项目里加 Python 绑定」。

二、区别概览

Cython:可只改类型注解、逐步优化;与 NumPy 集成好(typed memoryview);适合重写热点或包装 C 库。pybind11:头文件库、C++11、绑定写法简洁;适合大型 C++ 项目暴露 API、与 STL/自定义类型映射;需写 C++。性能:二者都能达到 C/C++ 级;Cython 更易从纯 Python 渐进迁移。

三、何时用

已有 C++ 库、主要在 C++ 侧维护 → pybind11。从 Python 项目出发、热点循环或需要 NumPy 深度集成 → Cython。两者也可混用(如 Cython 调 pybind11 暴露的模块)。


面试要点

  • Cython:写 .pyx、编译成扩展;类 Python 语法、易从 Python 渐进优化;NumPy 友好。
  • pybind11:C++ 侧写绑定、声明式 API;适合已有 C++ 项目暴露给 Python。
  • 从 Python 出发、热点/NumPy 多用 Cython;从 C++ 出发、大库绑定用 pybind11。
  • 性能都可到 C/C++ 级;可按项目主导语言与维护成本选。

记忆要点

  1. Cython = Python 风格写扩展、.pyx;pybind11 = C++ 侧写绑定。
  2. 渐进优化、NumPy 多用 Cython;大 C++ 库暴露用 pybind11。
  3. 二者可混用;选型看主导语言与维护成本。

返回模块 | 返回总览

20-Python高级/275-Python的descriptor协议.md

第 275 题:Python的descriptor协议?property的实现?

题目

Python的descriptor协议?property的实现?


完整讲解

一、Descriptor 协议

Descriptor 是实现了 __get____set____delete__ 中至少一个的对象。当作为类属性被访问时,解释器会调用这些方法:a.x 触发 type(a).__dict__['x'].__get__(a, type(a))。用于实现 property、方法绑定、staticmethod、classmethod 等。

二、property 的实现

property(fget, fset, fdel, doc) 返回一个 descriptor:其 __get__ 调 fget(instance)、__set__ 调 fset(instance, value)。即「属性访问」被转成函数调用,从而可做计算、校验、懒加载等。等价于在类里放一个实现 __get__/__set__ 的 descriptor 对象。

三、常见用法

@property 装饰器定义只读或读写「属性」;只读可只写 __get__;只写需同时有 __set__(少见)。自定义 descriptor 可做类型检查、缓存、懒加载;注意区分数据 descriptor(有 __set__)与非数据 descriptor(仅 __get__),前者在实例字典之前参与查找。


面试要点

  • Descriptor:实现 get/set/delete 的对象;作为类属性时访问会调这些方法。
  • property 本质是 descriptor;get 调 getter、set 调 setter。
  • 用于计算属性、校验、懒加载;数据 descriptor(有 set)优先于实例字典。
  • 方法绑定、staticmethod、classmethod 也由 descriptor 实现。

记忆要点

  1. Descriptor = get/set/delete;作为类属性时被调用。
  2. property = descriptor,把属性访问转成 getter/setter 调用。
  3. 数据 descriptor 优先实例 dict;可做校验、缓存、懒加载。

返回模块 | 返回总览

20-Python高级/276-context-manager的__enter__和__exit__.md

第 276 题:context manager__enter____exit__

题目

context manager__enter____exit__


完整讲解

一、Context Manager 协议

Context manager 支持 with 语句,保证「进入时设、退出时清」。协议:实现 __enter__(self)__exit__(self, exc_type, exc_val, exc_tb)with obj: 时先调 __enter__,其返回值赋给 as 目标;离开 with 块时调 __exit__(含异常时三个参数非 None)。

二、enterexit 语义

__enter__:做资源申请或状态设置,返回给 as 的可为 self 或其它对象。__exit__:做清理(关文件、释锁、回滚等);若返回 True 表示「已处理异常」,解释器不再传播;返回 False 或 None 则异常继续向上抛。若 with 块内无异常,__exit__ 的三个异常参数均为 None。

三、实现方式

类实现上述两方法即可;或用 contextlib.contextmanager 写生成器:yield 前为 enter、后为 exit,用 try/finally 保证清理。常用于文件、锁、连接、临时状态等。


面试要点

  • Context manager 协议:enter(进入时调,返回值给 as)、exit(退出时调,异常信息传入)。
  • exit 返回 True 表示吞掉异常;False/None 则异常继续传播。
  • 可用类实现两方法,或用 contextlib.contextmanager + 生成器(yield 前后即 enter/exit)。
  • 用于文件、锁、连接等「进设退清」场景。

记忆要点

  1. enter = 进入时调;exit = 退出时调,可接收异常。
  2. exit 返回 True 吞异常;用 try/finally 保证清理。
  3. 类实现协议或 contextmanager + 生成器。

返回模块 | 返回总览

20-Python高级/277-metaclass在框架设计中的应用.md

第 277 题:metaclass在框架设计中的应用?abc.ABCMeta

题目

metaclass在框架设计中的应用?abc.ABCMeta


完整讲解

一、Metaclass 是什么

Metaclass 是「类的类」:类由 type 或其子类实例化得到,该子类即 metaclass。定义类时指定 metaclass=MyMeta,则类对象的创建由 MyMeta.__new__/__init__ 控制,可在类创建时注册、校验、注入属性或改继承关系,实现框架级行为。

二、在框架设计中的应用

插件/注册:metaclass 在类定义时把类注册到全局表。接口约束:要求子类实现某些方法,未实现则在类创建时报错。abc.ABCMeta:抽象基类用 ABCMeta 作为 metaclass,配合 @abstractmethod,子类未实现抽象方法则无法实例化。ORM/声明式 API:类属性(如列名)在 metaclass 里被收集成 schema。

三、abc.ABCMeta

from abc import ABC, abstractmethod;继承 ABC(其 metaclass 为 ABCMeta)并给方法加 @abstractmethod,则子类必须实现这些方法否则不能实例化。ABCMeta 还支持 register 做结构性子类型(duck typing 注册)。


面试要点

  • Metaclass = 类的类;控制类的创建(new/init),在「定义时」执行逻辑。
  • 应用:插件注册、接口校验、抽象基类、ORM 声明式收集属性。
  • abc.ABCMeta:抽象基类;@abstractmethod 强制子类实现;register 做结构性子类型。
  • 框架里少而精地用,避免过度魔法。

记忆要点

  1. Metaclass 控制类对象的创建;用于注册、校验、抽象基类。
  2. ABCMeta + @abstractmethod = 抽象方法、子类必须实现。
  3. 框架中用于声明式行为;不宜滥用。

返回模块 | 返回总览

20-Python高级/278-Python的import机制.md

第 278 题:Python的import机制?sys.pathPYTHONPATH

题目

Python的import机制?sys.pathPYTHONPATH


完整讲解

一、import 机制简述

import foofrom foo import bar 时,解释器在 sys.modules 查是否已加载;若无则按 查找路径 找 foo 对应模块(包或 .py),加载并执行、将结果放入 sys.modules,再绑定到当前命名空间。查找路径来自 sys.path:脚本所在目录、PYTHONPATH、标准库、site-packages 等。

二、sys.path 与 PYTHONPATH

sys.path 是字符串列表,为模块搜索路径的先后顺序。默认包含:当前脚本目录、环境变量 PYTHONPATH(若设)、安装的 prefix 下的 lib 等。修改 sys.path(如 append 项目根)可临时加入搜索路径;PYTHONPATH 在进程启动前设置,影响所有 import。包内相对 import 用 from . import xxx,依赖包结构。

三、工程注意

虚拟环境会改 sys.path 的 prefix;打包/部署需保证 PYTHONPATH 或 sys.path 含项目与依赖。避免在代码里随意改 sys.path,优先用包结构或安装为包。


面试要点

  • import 先查 sys.modules;未则按 sys.path 找模块文件,加载后放入 sys.modules。
  • sys.path:脚本目录、PYTHONPATH、标准库、site-packages 等;顺序即查找顺序。
  • PYTHONPATH 在启动前设,影响全局;可临时 append sys.path 但不推荐滥用。
  • 包内用相对 import(. 表示当前包);虚拟环境会改 path prefix。

记忆要点

  1. 查找顺序:sys.modules → sys.path 列表。
  2. sys.path 含当前目录、PYTHONPATH、标准库、site-packages。
  3. 改路径优先用包结构与安装;少改 sys.path。

返回模块 | 返回总览

20-Python高级/279-pickle的局限性和替代方案.md

第 279 题:pickle的局限性和替代方案?cloudpickledill

题目

pickle的局限性和替代方案?cloudpickledill


完整讲解

一、pickle 的局限性

pickle 是 Python 原生序列化,仅适合 Python 间传对象。局限:不安全,反序列化会执行任意代码,不可反序列化不可信数据;仅 Python,其它语言无法读;版本/类路径依赖,类定义变更或移动可能导致无法反序列化;不能序列化 函数、lambda、某些 C 扩展、含不可序列化引用的对象等。

二、cloudpickle、dill 等替代

cloudpickle:可序列化更多对象(如 lambda、嵌套函数、某些类),常用于分布式计算(如 Dask、Ray)在 worker 间传任务。dill:扩展更多类型(含更多函数、模块状态等),适合持久化复杂状态。二者 API 与 pickle 类似(dump/load、协议版本);仍仅限 Python 且需同环境,安全性与 pickle 类似,不可信数据勿用。

三、跨语言与安全场景

跨语言用 JSON、MessagePack、Protobuf 等;需安全反序列化则避免 pickle,用白名单结构或专用格式。


面试要点

  • pickle 局限:不安全(反序列化可执行代码)、仅 Python、版本/类路径敏感、不能序列化函数等。
  • cloudpickle:支持 lambda、嵌套函数等,常用于 Dask/Ray 等分布式传任务。
  • dill:支持更多类型与状态;仍仅 Python、不安全。
  • 跨语言用 JSON/Protobuf;不可信数据不用 pickle。

记忆要点

  1. pickle 不安全、仅 Python、不能序列化函数/lambda 等。
  2. cloudpickle/dill 扩展可序列化类型;分布式与持久化常用。
  3. 跨语言与安全场景用 JSON/Protobuf 等。

返回模块 | 返回总览

20-Python高级/280-Python代码的性能优化.md

第 280 题:Python代码的性能优化?cProfileline_profiler

题目

Python代码的性能优化?cProfileline_profiler


完整讲解

一、性能优化思路

定位热点再优化:用 profiler 找耗时函数与调用关系,避免盲目改。常见瓶颈:循环内重复计算、过多小对象分配、IO、算法复杂度。优化手段:算法与数据结构、减少分配、局部用 C 扩展(Cython/pybind11)、并发/异步等。

二、cProfile 使用

cProfile(标准库):cProfile.run('func()')python -m cProfile script.py,输出各函数调用次数与累计时间。按 cumulative 看「含子调用」总时间、按 tottime 看「不含子调用」自身时间;可 pstats.Stats 做排序、过滤。适合找「谁在耗时间」。

三、line_profiler 使用

line_profiler:逐统计耗时,需对目标函数加 @profile 装饰器,用 kernprof -l -v script.py 运行,得到每行命中次数与耗时。适合在已知热点函数内进一步定位到具体行。二者结合:cProfile 定函数、line_profiler 定行。


面试要点

  • 先 profiling 再优化;cProfile 看函数级、line_profiler 看行级。
  • cProfile:run() 或 -m cProfile;看 cumtime/tottime;pstats 排序过滤。
  • line_profiler:@profile + kernprof -l -v;得每行命中与耗时。
  • 结合使用:cProfile 找热点函数,line_profiler 找热点行。

记忆要点

  1. cProfile = 函数级统计;cumtime/tottime;找热点函数。
  2. line_profiler = 行级;@profile + kernprof;找热点行。
  3. 先测再优;算法与数据结构优先,再考虑 C 扩展与并发。

返回模块 | 返回总览

21-算法与数据结构/README.md

21-算法与数据结构(第 281–290 题)

题号 主题 文章
281 实现一个LRU cache,支持并发访问 281-实现一个LRU-cache,支持并发访问.md
282 大文件的external sort实现?k-way merge 282-大文件的external-sort实现.md
283 分布式consistent hashing的实现?`virtual … 283-分布式consistent-hashing的实现.md
284 bloom filter在缓存中的应用?假阳性率计算? 284-bloom-filter在缓存中的应用.md
285 skip list的实现?level随机化策略? 285-skip-list的实现.md
286 B+ tree在数据库中的应用?为什么适合磁盘? 286-B+-tree在数据库中的应用.md
287 实现一个rate limitertoken bucket vs… 287-实现一个rate-limiter.md
288 字符串匹配的KMP算法?prefix function 288-字符串匹配的KMP算法.md
289 图算法的shortest pathDijkstra、`Bell… 289-图算法的shortest-path.md
290 并查集(Union-Find)的实现?`path compression… 290-并查集(Union-Find)的实现.md

返回总览

21-算法与数据结构/281-实现一个LRU-cache,支持并发访问.md

第 281 题:实现一个LRU cache,支持并发访问

题目

实现一个LRU cache,支持并发访问


完整讲解

一、LRU 与并发需求

LRU cache:容量上限,满时淘汰最久未使用的项;get/put 都算「使用」。并发:多线程同时 get/put,需保证正确性与尽量少阻塞。典型接口:get(key)、put(key, value)、可选 get 时刷新「最近使用」顺序。

二、数据结构与策略

经典实现:哈希表 + 双向链表。哈希表 key → 链表节点(含 key、value);链表按「最近使用」顺序,头为 MRU、尾为 LRU。get:查哈希表、有则把节点移到头并返回值。put:有则更新并移到头;无则新建节点插头,若超容量则删尾节点并从哈希表删除。并发:用一把读写锁(或 mutex)保护整个结构;或分段锁 + 每段一个 LRU;高并发可考虑 per-bucket 锁或 lock-free 结构(实现复杂)。

三、实现要点

双向链表便于 O(1) 删除任意节点并移到头;哈希表 O(1) 查找。注意「先删后加」避免重复 key 时链表成环。并发下 put 可能触发 evict,需在锁内完成「删尾 + 删表项」。


面试要点

  • LRU:容量满时淘汰最久未用;哈希表 + 双向链表实现 O(1) get/put。
  • 链表维护访问顺序(头=MRU、尾=LRU);get 时移到头,put 满时删尾。
  • 并发:整体 mutex 或读写锁;高并发可分段锁或 per-bucket 锁。
  • 注意重复 key 时先删后加、evict 在锁内完成。

记忆要点

  1. 结构:哈希表 + 双向链表;头 MRU、尾 LRU。
  2. get 查表并移到头;put 更新/插入到头,满则删尾。
  3. 并发用锁保护;可选分段或 per-bucket 降低竞争。

返回模块 | 返回总览

21-算法与数据结构/282-大文件的external-sort实现.md

第 282 题:大文件的external sort实现?k-way merge

题目

大文件的external sort实现?k-way merge


完整讲解

一、外部排序目的

数据量超过内存,无法一次性排序,需分块读入、排序、再合并。核心:利用磁盘顺序 IO,多路归并降低轮数。

二、流程与 k-way merge

阶段一:按内存能容纳的大小(如 M 条记录)读入、内排(快排等)、写出为有序段(run),得到多个有序文件。阶段二k-way merge:同时打开 k 个有序段,用最小堆维护当前 k 个候选最小元;每次取堆顶输出,并从对应段补入下一条,直到所有段读完。k 越大,归并轮数越少,但需要 k 路缓冲与堆大小。

三、实现要点

内排阶段可并行(多块同时排序)。k-way 时堆中元素需带「来自哪一段」信息;段读完则从堆中移除该路。磁盘 IO 顺序读顺序写,性能好。可扩展为多轮 k-way(若段数远大于 k)。


面试要点

  • 外部排序:分块读入、内排、写出有序段;再 k 路归并。
  • k-way merge:用最小堆维护 k 个当前最小值;取堆顶输出并从对应段补入。
  • 内排可并行;k 大可减少轮数但占缓冲;顺序 IO 友好。
  • 堆中需记录元素来自哪一段,段读完则撤掉该路。

记忆要点

  1. 两阶段:内排成多段 → k-way 归并。
  2. k-way:最小堆 + 每路一个当前值;取堆顶、补该路下一条。
  3. k 大则轮数少;顺序 IO;可多轮 k-way。

返回模块 | 返回总览

21-算法与数据结构/283-分布式consistent-hashing的实现.md

第 283 题:分布式consistent hashing的实现?virtual node

题目

分布式consistent hashing的实现?virtual node


完整讲解

一、一致性哈希目的

分布式缓存/存储中,节点增删时希望只影响少量 key 的映射,避免全量 rehash。一致性哈希:将 hash 空间视为环,节点与 key 都映射到环上;key 归属「顺时针方向第一个节点」。增删节点只影响相邻一段 key。

二、Virtual node(虚拟节点)

若节点数少,在环上分布可能不均,导致负载倾斜虚拟节点:每个物理节点对应多个虚拟节点(如 100~200 个),每个虚拟节点在环上占一点;key 先映射到虚拟节点再落到物理节点。虚拟节点数多则分布更均匀,负载更平衡;实现时虚拟节点名可用 node#v1node#v2 等 hash 到环上。

三、实现要点

环用有序结构(如 TreeMap)存「hash 值 → 节点」;查找 key 时算 key 的 hash,在环上找第一个 >= 该 hash 的节点(没有则取环首)。虚拟节点插入/删除时维护同一物理节点的多个映射即可。


面试要点

  • 一致性哈希:hash 环、key 归属顺时针第一节点;增删节点只影响相邻 key。
  • 虚拟节点:一物理节点对应多虚拟点,打散到环上,减轻负载倾斜。
  • 环用有序结构存 hash→节点;查找 key 找 >= hash(key) 的第一个节点。
  • 用于分布式缓存、存储的 sharding 与扩缩容。

记忆要点

  1. 环上 key 归属顺时针第一节点;增删节点影响局部。
  2. 虚拟节点 = 一物理多虚拟、均匀分布;减少倾斜。
  3. 实现:有序结构 + 查找 >= hash(key) 的节点。

返回模块 | 返回总览

21-算法与数据结构/284-bloom-filter在缓存中的应用.md

第 284 题:bloom filter在缓存中的应用?假阳性率计算?

题目

bloom filter在缓存中的应用?假阳性率计算?


完整讲解

一、Bloom filter 与缓存应用

Bloom filter:位数组 + k 个哈希函数;插入时把 k 个位置置 1,查询时 k 个位置全为 1 则「可能存在」(有假阳性),任一为 0 则「一定不存在」。在缓存中用于前置过滤:先查 Bloom filter,若为「不存在」则不必访问缓存或 DB,减少穿透;若为「可能存在」再查缓存/DB。

二、假阳性率

设位数组长 m、元素数 n、哈希函数数 k。近似假阳性率 p ≈ (1 - e^(-kn/m))^k。在 n 给定下,取 k = (m/n) ln 2 时 p 最小,约 0.6185^(m/n)。故 m 越大、n 越少,假阳性率越低;工程上常取 m/n 为 10~20、k 据此计算。

三、注意

不支持删除(除非用 counting Bloom filter);假阳性可接受时能大幅减少无效查询。常用于缓存/DB 前、去重、爬虫已访问集合等。


面试要点

  • Bloom filter:位数组 + k 个 hash;无假阴性、有假阳性;用于「一定不存在」的快速判断。
  • 缓存中做前置过滤:Bloom 判不存在则不打缓存/DB;判存在再查。
  • 假阳性率 p ≈ (1 - e^(-kn/m))^k;k ≈ (m/n)ln2 时 p 最小;m/n 大则 p 小。
  • 不支持删除(或需 counting BF);适合穿透防护、去重等。

记忆要点

  1. 位数组 + k 个 hash;全 1 则可能存在、有 0 则一定不存在。
  2. 假阳性率与 m、n、k 相关;k≈(m/n)ln2 最优。
  3. 缓存中做前置过滤;不支持删除。

返回模块 | 返回总览

21-算法与数据结构/285-skip-list的实现.md

第 285 题:skip list的实现?level随机化策略?

题目

skip list的实现?level随机化策略?


完整讲解

一、Skip list 结构

跳表:多层有序链表,底层为完整有序链表,上层为「索引」、每层为下层的稀疏子集。从顶层头开始,向右走直到下一节点大于目标则下一层,直到底层找到或确定不存在。查找、插入、删除期望 O(log n),实现简单,无需平衡(如红黑树)的复杂旋转。

二、Level 随机化

每个节点有一个 level(高度);插入时用随机决定 level:常见策略为「以概率 p(如 1/2 或 1/4)加一层」,即 level 0 必选,level i+1 以 p 概率选。这样高层节点数约为下层的 1/p,形成类似「二分」的索引,期望层数 O(log n)。随机化避免刻意构造的退化,期望性能稳定。

三、实现要点

每节点含 forward 数组(各层后继);头节点层高为最大层。查找:从最高层头开始,本层向右走到「下一个 > key」则下一层。插入:随机出 level,自顶向下找插入位置,在各层链入新节点。删除:找节点并在各层摘链。


面试要点

  • 跳表:多层有序链表,上层为下层索引;查找从顶向右、大则下一层。
  • Level 随机化:插入时以概率 p 决定层高,形成 O(log n) 期望层数;避免退化。
  • 每节点有各层 forward;头节点层高足够;插入/删除需维护各层指针。
  • 期望 O(log n);实现简单,Redis 等用跳表做有序结构。

记忆要点

  1. 多层链表,上层稀疏;查找从顶向右、大则下一层。
  2. Level 随机:以 p 加层,期望 O(log n) 层。
  3. 实现:forward 数组、头节点、插入删除维护各层链。

返回模块 | 返回总览

21-算法与数据结构/286-B+-tree在数据库中的应用.md

第 286 题:B+ tree在数据库中的应用?为什么适合磁盘?

题目

B+ tree在数据库中的应用?为什么适合磁盘?


完整讲解

一、B+ tree 在数据库中的应用

B+ tree 是数据库索引的主流结构:多路平衡所有 key 在叶子层有序且形成有序链表、非叶节点只存 key 与子指针(不存数据),叶子层存 key 与记录指针或数据。支持范围查询、顺序扫描、高扇出(单节点可存大量 key),适合磁盘块为单位的读写。

二、为什么适合磁盘

磁盘按块读写(如 4KB),随机 IO 贵。B+ tree 节点大小设计成块大小,一次 IO 读入一节点;高扇出(阶大)使树矮,查找次数 = 树高,通常 3~4 层即可覆盖海量数据,即 3~4 次磁盘访问。叶子链表使范围查询与全表顺序扫描只需沿叶子链,顺序 IO 友好。平衡保证任意 key 的查找路径等长,性能稳定。

三、与 B tree 区别

B+ 非叶节点不存数据、只做索引;叶子层含全部 key 且链表串联。B tree 的 key 与数据可在非叶节点出现。B+ 范围查询与顺序扫描更优,数据库多用 B+。


面试要点

  • B+ tree:多路平衡、key 全在叶子且叶子成有序链、非叶仅索引;数据库索引常用。
  • 适合磁盘:节点=块大小、高扇出树矮、查找=树高次 IO;叶子链支持范围与顺序扫描。
  • 高扇出减少树高;平衡保证路径等长;顺序 IO 友好。
  • 与 B tree:B+ 数据只在叶、叶子链;范围与顺序更优。

记忆要点

  1. B+ = 多路平衡、叶存全部 key 且成链、非叶仅索引。
  2. 节点=块、高扇出、树矮 → 少次 IO;叶子链 → 范围/顺序友好。
  3. 数据库索引首选;3~4 层覆盖大量数据。

返回模块 | 返回总览

21-算法与数据结构/287-实现一个rate-limiter.md

第 287 题:实现一个rate limitertoken bucket vs leaky bucket

题目

实现一个rate limitertoken bucket vs leaky bucket


完整讲解

一、Rate limiter 目的

限制请求速率,防止过载、保证公平或满足上游配额。常见策略:固定窗口滑动窗口token bucketleaky bucket。实现时需考虑并发、分布式下多实例的协同(如用 Redis 做共享计数)。

二、Token bucket vs Leaky bucket

Token bucket:桶里放「令牌」,以固定速率补充;请求消耗若干令牌,无令牌则拒绝或等待。允许突发(桶满时一段时间可高吞吐),适合「平均速率限制、允许短时突发」的场景。Leaky bucket:请求进桶,以固定速率「漏出」被处理;超出桶容量则拒绝或排队。平滑输出、不允许多余突发,适合「输出速率严格恒定」的场景。二者可互相近似(如 leaky 的「漏率」对应 token 的「补充率」),侧重点不同。

三、实现要点

Token bucket:记录 last_time、tokens;每次请求时按时间差补令牌、扣减;需加锁或原子操作。Leaky bucket:记录 last_time、水位;按漏率更新水位再判断是否接受。分布式时用 Redis 的计数器 + 时间窗口或 Lua 脚本保证原子性。


面试要点

  • Rate limiter 限制请求速率;策略有固定/滑动窗口、token bucket、leaky bucket。
  • Token bucket:令牌按速率补充、请求消耗;允许突发;适合平均限速。
  • Leaky bucket:请求入桶、按固定速率漏出;输出平滑、限制突发。
  • 实现:记录时间与容量/令牌;并发用锁或原子;分布式用 Redis 等。

记忆要点

  1. Token bucket = 令牌补充 + 消耗;允突发。Leaky bucket = 入桶 + 固定漏率;平滑输出。
  2. 实现:last_time + tokens/水位;按时间更新再判断。
  3. 分布式用共享存储(如 Redis)做计数与原子性。

返回模块 | 返回总览

21-算法与数据结构/288-字符串匹配的KMP算法.md

第 288 题:字符串匹配的KMP算法?prefix function

题目

字符串匹配的KMP算法?prefix function


完整讲解

一、KMP 目的

在文本 T 中找模式 P 的首次出现,线性时间 O(|T|+|P|)。朴素匹配在失配时只移 1 位;KMP 利用「已匹配部分」的信息,一次滑动多位,且不回溯 T 的指针。

二、Prefix function(next 数组)

前缀函数 π[i]:P[0..i] 的真后缀与 P 的真前缀的最长匹配长度。即 π[i] = max{k : P[0..k-1] = P[i-k+1..i], k < i+1}。求法:用递推,若 P[i]=P[π[i-1]] 则 π[i]=π[i-1]+1,否则用 π[π[i-1]-1] 递归尝试。next 数组 常指「失配时 P 应移动到的下标」:next[j] = π[j-1](或按实现略有偏移),表示在 j 处失配时,用 next[j] 作为 P 的新对齐位置(T 指针不回溯)。

三、匹配过程

T 与 P 从左对齐,逐位比较;失配时 T 指针不动,P 按 next 右移(即 P 的 next[j] 与当前 T 位置对齐),继续比较。构造 next 与匹配均为 O(n)。


面试要点

  • KMP:线性时间字符串匹配;失配时 P 按 next 右移、T 不回溯。
  • 前缀函数 π[i]:P[0..i] 的真后缀与真前缀的最长匹配;递推可求。
  • next[j]:j 处失配时 P 应对齐的下标;用 π 得到。
  • 构造 next O(|P|)、匹配 O(|T|)。

记忆要点

  1. 前缀函数 = 真后缀与真前缀最长匹配;递推求 next。
  2. 失配时 T 不动、P 按 next 右移。
  3. 时间 O(|T|+|P|)。

返回模块 | 返回总览

21-算法与数据结构/289-图算法的shortest-path.md

第 289 题:图算法的shortest pathDijkstraBellman-Ford

题目

图算法的shortest pathDijkstraBellman-Ford


完整讲解

一、最短路径问题

在带权有向/无向图中求单源或多源最短路径。单源:从一个点 s 到其余各点;常用 Dijkstra(非负权)、Bellman-Ford(可有负权、检负环)。多源:Floyd-Warshall 等。

二、Dijkstra

贪心:维护「已确定最短距离」的集合,每次取当前距离最小的未确定点 u,松弛其出边,将 u 标为已确定。要求边权非负。用优先队列(小根堆)存 (dist, v),复杂度 O((V+E) log V)。每个点最多入队出队一次,出队时即得最短路。

三、Bellman-Ford

松弛:对每条边 (u,v,w) 做 relax:若 dist[u]+w < dist[v] 则更新。重复 V-1 轮(或直到无更新),即可得到单源最短路;若第 V 轮仍能更新则存在负权环。复杂度 O(VE)。适合有负权、需判负环的场景;可做分布式(每轮本地松弛)。


面试要点

  • 单源最短路:Dijkstra(非负权、贪心+优先队列)、Bellman-Ford(可负权、V-1 轮松弛)。
  • Dijkstra:每次取 dist 最小未确定点松弛出边;O((V+E)log V)。
  • Bellman-Ford:重复松弛所有边 V-1 轮;能检负环(第 V 轮仍更新)。
  • 负权用 Bellman-Ford;非负权用 Dijkstra 更高效。

记忆要点

  1. Dijkstra = 非负权、贪心取最小 dist、松弛;Bellman-Ford = 可负权、多轮松弛。
  2. Dijkstra 用堆 O((V+E)log V);Bellman-Ford O(VE)、可判负环。
  3. 负环:Bellman-Ford 第 V 轮仍能更新则存在。

返回模块 | 返回总览

21-算法与数据结构/290-并查集(Union-Find)的实现.md

第 290 题:并查集(Union-Find)的实现?path compression

题目

并查集(Union-Find)的实现?path compression


完整讲解

一、并查集用途

维护 disjoint sets(无交集合),支持 Union(合并两集合)与 Find(查某元素所属集合代表元),用于判连通、等价类、最小生成树(Kruskal)等。目标:Union 与 Find 尽量快,均摊近 O(1)。

二、基本实现

父指针数组 parent[]:parent[i] 为 i 的父节点,根节点 parent[i]=i 或 -1。Find(x):沿 parent 一路向上直到根,返回根。Union(x,y):Find 得到 x、y 的根 rx、ry,将 rx 的 parent 设为 ry(或按秩挂)。朴素实现 Find/Union 最坏 O(n);路径压缩按秩合并可均摊到近 O(1)。

三、Path compression(路径压缩)

Find 时,把从 x 到根路径上所有节点的 parent 直接改为根。这样下次 Find 这些节点为 O(1)。实现:递归 Find 中在返回前写 parent[x]=Find(parent[x]);或迭代两次,第一次找根、第二次把路径全部挂到根。与按秩合并(小树挂到大树根下)一起,均摊复杂度 O(α(n)),α 为反阿克曼函数,实际可视为常数。


面试要点

  • 并查集:维护不相交集合;Union 合并、Find 查代表元。
  • 实现:parent 数组;Find 沿 parent 找根;Union 把两集合的根挂一起。
  • 路径压缩:Find 时把路径上节点直接连到根,下次 Find 更快。
  • 按秩合并:小树挂大树下;与路径压缩一起均摊近 O(1)。

记忆要点

  1. parent 数组;Find 找根、Union 并根。
  2. 路径压缩 = Find 时把路径挂到根。
  3. 按秩合并 + 路径压缩 → 均摊 O(α(n))。

返回模块 | 返回总览

22-网络/README.md

22-网络(第 291–300 题)

题号 主题 文章
291 TCP和RDMA的对比?为什么AI训练需要RDMA? 291-TCP和RDMA的对比.md
292 InfiniBand的Verbs编程?ibv_post_send 292-InfiniBand的Verbs编程.md
293 RoCE v2ECNPFC拥塞控制? 293-RoCE-v2的ECN和PFC拥塞控制.md
294 多机训练的网络拓扑?fat-treedragonfly 294-多机训练的网络拓扑.md
295 NCCLbootstraptransport层? 295-NCCL的bootstrap和transport层.md
296 网络jitter对训练的影响?如何测量? 296-网络jitter对训练的影响.md
297 DPDK在AI网络中的应用? 297-DPDK在AI网络中的应用.md
298 RDMAmemory registration开销? 298-RDMA的memory-registration开销.md
299 网络虚拟化?SR-IOV vs virtio 299-网络虚拟化.md
300 跨可用区(AZ)训练的网络挑战? 300-跨可用区(AZ)训练的网络挑战.md

返回总览

22-网络/291-TCP和RDMA的对比.md

第 291 题:TCP和RDMA的对比?为什么AI训练需要RDMA?

题目

TCP和RDMA的对比?为什么AI训练需要RDMA?


完整讲解

一、TCP 与 RDMA 对比

TCP:内核协议栈、需多次拷贝(用户态↔内核↔网卡)、CPU 参与每包处理,延迟与 CPU 占用较高,但通用、易部署。RDMA(Remote Direct Memory Access):零拷贝内核旁路,网卡直接读写本端/对端用户态内存,CPU 仅投递/回收描述符,低延迟、高带宽、低 CPU,需专用网卡(InfiniBand 或 RoCE)与驱动。

二、AI 训练为何需要 RDMA

分布式训练中 all-reduce 等集合通信带宽敏感、延迟敏感,且数据量大、持续时间长。TCP 的拷贝与协议栈开销会占大量 CPU、成为瓶颈;RDMA 把数据从 GPU/内存直接经网卡到对端内存,减少 CPU 与拷贝,提高通信效率,缩短每 step 时间。多机多卡训练里,通信常是瓶颈,RDMA 能显著提升扩展性与吞吐。

三、选型注意

RDMA 需硬件与网络支持(IB 或 RoCE、PFC/ECN 等);部署与排障复杂。TCP 无特殊硬件、易运维。小规模或无 RDMA 环境可用 TCP + 优化(如 GPU Direct RDMA 的替代方案);大规模训练集群普遍采用 RDMA。


面试要点

  • TCP:内核协议栈、多拷贝、CPU 参与;通用易部署。RDMA:零拷贝、内核旁路、低延迟低 CPU。
  • AI 训练:all-reduce 等通信带宽与延迟敏感;RDMA 减少 CPU 与拷贝,提升通信效率。
  • 多机多卡训练通信常为瓶颈;RDMA 显著提升扩展性与 step 吞吐。
  • RDMA 需专用网卡与网络;无 RDMA 时可用 TCP 或其它优化。

记忆要点

  1. TCP = 内核、多拷贝;RDMA = 零拷贝、内核旁路、低 CPU。
  2. 训练通信带宽/延迟敏感;RDMA 提升通信效率与扩展性。
  3. 大规模集群多用 RDMA;小规模或无硬件可用 TCP。

返回模块 | 返回总览

22-网络/292-InfiniBand的Verbs编程.md

第 292 题:InfiniBand的Verbs编程?ibv_post_send

题目

InfiniBand的Verbs编程?ibv_post_send


完整讲解

一、InfiniBand Verbs 简介

Verbs 是 InfiniBand(以及 RoCE 等 RDMA)的编程接口,提供队列对(QP)、完成队列(CQ)、内存注册(MR)等抽象。用户态应用通过 Verbs API 提交发送/接收请求(WR),网卡异步执行,通过 CQ 或轮询获知完成。实现零拷贝、内核旁路的 RDMA 通信。

二、ibv_post_send

ibv_post_send发送请求(Send WR)挂到发送队列(SQ)上。每个 WR 描述「要发送的数据在哪、多长、什么操作」(如 Send、RDMA Write、RDMA Read 等)。网卡消费 SQ,将数据从本地 MR 发到对端;完成后在 CQ 产生 CQE。典型流程:注册内存(ibv_reg_mr)→ 建 QP、CQ → ibv_post_send 投递 WR → 轮询或等待 ibv_poll_cq 得到完成。

三、配套 API

ibv_post_recv:投递接收 WR,用于接收消息或 RDMA Read 的 target。ibv_reg_mr:注册内存供 RDMA 访问。ibv_create_qp、ibv_create_cq:建 QP/CQ。连接建立后(CM 或 socket 交换 QP 信息)即可 post_send/post_recv 做双向通信。


面试要点

  • Verbs = IB/RDMA 编程接口;QP、CQ、MR;零拷贝、内核旁路。
  • ibv_post_send:把发送 WR 投到 SQ;描述数据位置、长度、操作类型(Send/Write/Read)。
  • 流程:reg_mr → create_qp/cq → 建连 → post_send/post_recv → poll_cq。
  • 配套:ibv_post_recv、ibv_reg_mr、ibv_create_qp、ibv_poll_cq。

记忆要点

  1. Verbs = QP/CQ/MR;post_send 投发送 WR。
  2. WR 描述 buffer、长度、操作;完成后 CQ 产生 CQE。
  3. 流程:注册内存、建 QP/CQ、建连、post、poll。

返回模块 | 返回总览

22-网络/293-RoCE-v2的ECN和PFC拥塞控制.md

第 293 题:RoCE v2ECNPFC拥塞控制?

题目

RoCE v2ECNPFC拥塞控制?


完整讲解

一、RoCE v2 与拥塞

RoCE(RDMA over Converged Ethernet)在以太网上跑 RDMA。RoCE v2 基于 UDP,可在标准 L3 网络部署。高速 RDMA 流量易造成拥塞与丢包,而 RDMA 对丢包敏感(重传与恢复代价大),因此需要拥塞控制无损或低损能力。

二、ECN(显式拥塞通知)

ECN:交换机在队列超过阈值时对包打 ECN 标记(不改丢包),接收端通过 ACK 或 CNP 把「拥塞」反馈给发送端;发送端降速(如减窗口、降发送率),从而缓解拥塞。RoCE 场景下可与 DCQCN 等算法结合:接收端生成 CNP(Congestion Notification Packet)回给发送端,发送端根据 CNP 率调节发送速率。

三、PFC(Priority Flow Control)

PFC:基于优先级链路层流控。当某优先级队列超过阈值,接收端向发送端发 Pause,发送端暂停该优先级发送,实现无损(不丢包)。代价是可能头阻塞、传播暂停。RoCE 常配合 PFC 做无损或低损,再配合 ECN/DCQCN 做端到端拥塞控制,平衡无丢包与公平性。


面试要点

  • RoCE v2 = RDMA over UDP;需拥塞控制与无损/低损机制。
  • ECN:交换机打标记、端到端反馈;发送端降速;可与 DCQCN 等结合。
  • PFC:优先级流控、Pause 帧;实现无损、可能头阻塞。
  • 工程上常 ECN + PFC 配合:PFC 保无损、ECN 做拥塞控制与公平性。

记忆要点

  1. ECN = 拥塞标记 + 反馈 + 发送端降速;RoCE 常用 DCQCN。
  2. PFC = 优先级 Pause、无损;可能头阻塞。
  3. 二者配合:PFC 减丢包、ECN 控拥塞。

返回模块 | 返回总览

22-网络/294-多机训练的网络拓扑.md

第 294 题:多机训练的网络拓扑?fat-treedragonfly

题目

多机训练的网络拓扑?fat-treedragonfly


完整讲解

一、多机训练与拓扑

多机多卡训练时,通信拓扑决定 all-reduce 等集合通信的跳数、带宽、拥塞。理想情况:每对节点间带宽大、延迟低、无单点瓶颈。常见拓扑有 fat-treedragonflymesh 等。

二、Fat-tree

Fat-tree(胖树):自上而下带宽递增(越靠近核心越宽),叶子为计算节点、上层为交换机。同 pod 内通信走下层、跨 pod 走上层;无 oversubscription( bisection 带宽充足)时通信性能好。常用于数据中心、HPC;成本与布线复杂度较高。

三、Dragonfly

Dragonfly分组(group)内全连或高连接,组间通过少量链路连接,形成「组内密、组间疏」的层次。全局负载均衡:通信尽量走组内或少跳,长距离流量分散到多条路径,减少热点。适合超大规模、对 bisection 与平均跳数有要求的场景。与 fat-tree 相比,在相同端口数下可 scale 更多节点,但路由与负载均衡更复杂。


面试要点

  • 多机训练通信受拓扑影响;fat-tree、dragonfly 为常见数据中心/HPC 拓扑。
  • Fat-tree:自上而下带宽递增、无 oversubscription 时性能好;成本与布线高。
  • Dragonfly:组内密、组间疏;全局负载均衡、少跳;scale 大、路由复杂。
  • 选型看规模、带宽需求、成本与运维。

记忆要点

  1. Fat-tree = 胖树、带宽递增、无 oversubscription 时通信好。
  2. Dragonfly = 组内全连/高连、组间稀疏;负载均衡、少跳。
  3. 拓扑决定 all-reduce 等通信的跳数与带宽。

返回模块 | 返回总览

22-网络/295-NCCL的bootstrap和transport层.md

第 295 题:NCCLbootstraptransport层?

题目

NCCLbootstraptransport层?


完整讲解

一、NCCL 分层

NCCL 提供多 GPU/多机集合通信(all-reduce、all-gather、reduce-scatter 等),内部大致分 bootstraptransport 等层。Bootstrap:负责发现与组网——哪些 rank、如何找到彼此(如通过环境变量、socket、共享存储等),建立控制面。Transport:负责实际数据传输——选择网络路径(如 Net/Socket、IB、RoCE)、选择算法(ring、tree 等)、执行 send/recv 与同步。

二、Bootstrap 层

启动时各 rank 需知道「总 rank 数、本 rank id、其它 rank 的地址」等。NCCL 支持多种 bootstrap:如 env(NCCL_SOCKET_IFNAME、master 地址等环境变量)、file(共享文件里写地址)、tcp(指定 master 与 port)等。Bootstrap 完成后,各 rank 拥有一致的 group 与拓扑信息,供 transport 建连与选算法。

三、Transport 层

根据检测到的网络(IB、RoCE、TCP 等)创建 channel、QP 或 socket;根据 topology(单机多卡、多机)选择 ring、tree、collnet 等算法;执行实际的 reduce、all-gather 等步骤。调优常涉及 NCCL_DEBUG、NCCL_IB_DISABLE、NCCL_ALGO 等环境变量。


面试要点

  • Bootstrap = 发现与组网:rank 发现、地址交换、建控制面;支持 env/file/tcp 等。
  • Transport = 实际传输:选网(IB/RoCE/TCP)、选算法(ring/tree)、执行通信。
  • Bootstrap 决定「谁和谁通信」;Transport 决定「怎么传、走哪条路」。
  • 调优:NCCL_DEBUG、NCCL_ALGO、NCCL_IB 等环境变量。

记忆要点

  1. Bootstrap = 组网与发现;Transport = 传输与算法选择。
  2. Bootstrap 有 env/file/tcp 等;Transport 有 ring/tree、IB/Socket。
  3. 排障与调优看 bootstrap 是否成功、transport 选用的网络与算法。

返回模块 | 返回总览

22-网络/296-网络jitter对训练的影响.md

第 296 题:网络jitter对训练的影响?如何测量?

题目

网络jitter对训练的影响?如何测量?


完整讲解

一、Jitter 对训练的影响

Jitter(抖动)指延迟或到达时间的不稳定:同一类操作(如 all-reduce)在不同 step 或不同 rank 上耗时差异大。训练中集合通信需所有 rank 到齐才继续,最慢的 rank 决定 step 时间。若某 rank 因网络 jitter 偶发变慢,会拖慢整机;若频繁发生,有效吞吐下降、扩展性变差,且难以复现与排查。

二、如何测量

延迟分布:多次测量同一操作(如 ncclAllReduce)的耗时,看 P50/P90/P99;P99 远大于 P50 即存在明显 jitter。工具:NCCL 的 NCCL_DEBUG=INFOtimeline 可看各 rank 的通信时间;nsys/nvprof 看 kernel 与通信重叠;ping、iperf 看基础网络 RTT 与带宽稳定性。多机:对比单机与多机、同 AZ 与跨 AZ 的延迟分布,定位是否由网络路径或共享资源争抢导致。

三、缓解思路

网络侧:专用链路、QoS、避免与其它业务混跑。拓扑与 placement:尽量同机架、同交换机。应用侧:重叠计算与通信、适当增大 batch 或减少通信频率,降低对单次延迟的敏感度。


面试要点

  • Jitter = 延迟/到达时间不稳定;最慢 rank 决定 step 时间,拖慢整机与扩展性。
  • 测量:同一操作多次测 P50/P90/P99;NCCL_DEBUG、timeline、nsys 看各 rank 耗时。
  • 对比单机/多机、同 AZ/跨 AZ 的分布,定位网络或争抢。
  • 缓解:专用网络、QoS、placement、重叠计算与通信。

记忆要点

  1. Jitter 导致最慢 rank 拖慢 step;P99 远大于 P50 即存在抖动。
  2. 测量:延迟分布、NCCL timeline、nsys;对比不同拓扑与 AZ。
  3. 缓解:网络隔离、placement、计算通信重叠。

返回模块 | 返回总览

22-网络/297-DPDK在AI网络中的应用.md

第 297 题:DPDK在AI网络中的应用?

题目

DPDK在AI网络中的应用?


完整讲解

一、DPDK 简介

DPDK(Data Plane Development Kit)是用户态高性能网络数据面框架:轮询(poll-mode)网卡、零拷贝大页绑核,把包处理从内核移到用户态,降低延迟、提高小包吞吐,常用于网关、负载均衡、NFV 等。

二、在 AI 网络中的应用

AI 训练/推理集群中,控制面(调度、元数据、监控)与数据面(RDMA/GPU 通信)通常分离。DPDK 可用于:控制面网关——高并发 API、健康检查、服务发现等,用 DPDK 做用户态 TCP/UDP 加速;自定义协议或代理——在非 RDMA 路径上做低延迟转发或聚合;监控与抓包——用户态抓包、带外监控流量,少占内核。数据面本身多以 RDMA(NCCL/IB)为主,DPDK 更多补足非 RDMA 的高性能网络路径或控制面流量。

三、适用场景

需要高 PPS、低延迟的 TCP/UDP 处理、且可接受用户态开发与绑核时,可考虑 DPDK;与 RDMA 并存时,DPDK 负责控制或辅助路径,RDMA 负责训练数据。


面试要点

  • DPDK = 用户态、轮询、零拷贝、大页;高性能数据面,常用于网关/NFV。
  • AI 中:控制面网关、自定义协议/代理、监控抓包等可用 DPDK;数据面主用 RDMA。
  • 适用高 PPS、低延迟的 TCP/UDP 处理;与 RDMA 分工(控制 vs 数据)。
  • 需用户态开发与绑核;与内核协议栈并存时注意分工。

记忆要点

  1. DPDK = 用户态数据面、轮询、零拷贝;AI 里多用于控制面或辅助路径。
  2. 数据面以 RDMA 为主;DPDK 补足非 RDMA 高性能需求。
  3. 适用高 PPS/低延迟;与 RDMA 分工明确。

返回模块 | 返回总览

22-网络/298-RDMA的memory-registration开销.md

第 298 题:RDMAmemory registration开销?

题目

RDMAmemory registration开销?


完整讲解

一、Memory registration 是什么

RDMA 要求参与传输的内存必须先注册(Memory Registration):把用户态 buffer 的物理页固定并告知网卡,网卡才能直接 DMA 读写。MR 创建时内核/驱动会 pin 页、建立虚拟地址到物理地址的映射供 HCA 使用,并可能注册到设备 TPT(Translation and Protection Table)等,有 CPU、TLB、内核元数据开销。

二、开销来源

Pin 页:物理页不可 swap、占用常驻内存。建立映射:大量 MR 时 TLB 与设备侧 TPT 压力大。注册/注销本身cudaMalloc 等分配的内存若要做 RDMA,需再注册为 MR;注册与注销是同步、相对重的操作,频繁 reg/dereg 会明显拉高延迟与 CPU。大块、长生命周期的 buffer 注册一次、复用可摊薄开销;小块、短生命周期则可能成为瓶颈。

三、工程应对

池化 MR:预注册大块、应用内按需切分或复用,避免每次分配都 reg。On-demand pin:部分驱动/库支持按需 pin 或 lazy registration。GPU:GPUDirect RDMA 时 GPU 内存也需注册,同样注意注册范围与生命周期;减少注册次数、扩大单次注册块有利于性能。


面试要点

  • Memory registration = 把 buffer 固定并告知网卡,供 RDMA DMA;有 pin、映射、元数据开销。
  • 开销:pin 占内存、大量 MR 时 TLB/TPT 压力、reg/dereg 为同步重操作。
  • 频繁小块 reg/dereg 易成瓶颈;大块长生命周期、复用可摊薄。
  • 工程:MR 池化、按需 pin、减少注册次数与范围。

记忆要点

  1. MR = pin 页 + 建立设备可访问映射;reg/dereg 有开销。
  2. 频繁小块注册是瓶颈;大块复用、池化可摊薄。
  3. GPU 内存做 RDMA 也需注册;注意范围与生命周期。

返回模块 | 返回总览

22-网络/299-网络虚拟化.md

第 299 题:网络虚拟化?SR-IOV vs virtio

题目

网络虚拟化?SR-IOV vs virtio


完整讲解

一、网络虚拟化需求

云与容器场景下,多租户、多实例共享物理机,需要隔离灵活组网:每 VM/容器有独立 IP、MAC、策略,且不暴露底层物理细节。网络虚拟化即在物理网上抽象出多套逻辑网络。

二、SR-IOV

SR-IOV(Single Root I/O Virtualization):物理网卡呈现多个虚拟功能(VF),每个 VF 可直通给一台 VM,绕过宿主机协议栈,接近物理网卡性能、延迟低。适合性能敏感、需低延迟的 VM;缺点是需要硬件与驱动支持、VF 数量有限、迁移与策略需额外方案。

三、Virtio

Virtio半虚拟化方案,前端(guest 内 virtio-net 驱动)与后端(宿主机 vhost-net 或用户态 vhost-user)通过共享队列通信,数据仍经宿主机内核或用户态处理。易迁移、易扩展、不依赖特定硬件;性能与延迟不如 SR-IOV 直通,但足够多数云工作负载。vhost-net 在内核、vhost-user 在用户态(如 DPDK),可进一步加速。

对比:SR-IOV = 直通、高性能、硬件依赖;Virtio = 半虚拟、易迁移与扩展、性能次之。选型看是否强需求「接近物理性能」与硬件能力。


面试要点

  • 网络虚拟化:多租户隔离与逻辑组网;SR-IOV 与 Virtio 为两种常见方案。
  • SR-IOV:VF 直通 VM、绕过宿主机、高性能;需硬件支持、VF 数有限。
  • Virtio:半虚拟、前后端队列;易迁移、易扩展;vhost-net/vhost-user 可加速。
  • 高性能直通用 SR-IOV;通用与易用选 Virtio。

记忆要点

  1. SR-IOV = VF 直通、高性能;Virtio = 半虚拟、队列、易迁移。
  2. SR-IOV 需硬件;Virtio 有 vhost-net/user 等后端。
  3. 选型看性能需求与硬件/迁移需求。

返回模块 | 返回总览

22-网络/300-跨可用区(AZ)训练的网络挑战.md

第 300 题:跨可用区(AZ)训练的网络挑战?

题目

跨可用区(AZ)训练的网络挑战?


完整讲解

一、跨 AZ 的含义

可用区(AZ) 是同一地域内物理隔离的数据中心(不同电、不同楼),提供高可用。跨 AZ 训练即训练任务跨多个 AZ 部署(如部分 rank 在 AZ1、部分在 AZ2),以利用资源或做容灾,但网络路径跨机房,带来延迟与带宽挑战。

二、网络挑战

延迟:跨 AZ 通常经过骨干或专线,RTT 比同 AZ 内高一个数量级(如同 AZ 亚毫秒、跨 AZ 数毫秒)。带宽与成本:跨 AZ 带宽贵、有时有上限,all-reduce 等通信带宽需求大,易成瓶颈。抖动:跨 AZ 路径更长、经过设备更多,jitter 更明显,集合通信的 P99 延迟上升,拖慢整机。一致性:若存储或元数据跨 AZ,还需考虑一致性与故障域。

三、应对思路

尽量同 AZ:训练 job 调度时优先同 AZ 放置,减少跨 AZ 通信。跨 AZ 时:降低通信频率(如梯度累积)、压缩、或接受更长 step 时间;关键路径避免跨 AZ。存储与调度:跨 AZ 的 checkpoint/数据拉取可异步或放非关键路径。


面试要点

  • 跨 AZ = 跨物理数据中心;延迟、带宽、jitter 均劣于同 AZ。
  • 挑战:RTT 高、带宽贵/有限、jitter 大,集合通信易成瓶颈。
  • 尽量同 AZ 调度;跨 AZ 时降通信频率、压缩或接受性能损失。
  • 存储与元数据跨 AZ 需考虑一致性与故障域。

记忆要点

  1. 跨 AZ 延迟与带宽劣于同 AZ;jitter 更明显。
  2. 训练尽量同 AZ;跨 AZ 时通信易成瓶颈。
  3. 应对:调度同 AZ 优先;跨 AZ 时降频、压缩或接受代价。

返回模块 | 返回总览

23-存储与虚拟化/301-容器运行时.md

第 301 题:容器运行时?containerdcri-o

题目

容器运行时?containerdcri-o


完整讲解

一、容器运行时角色

容器运行时负责根据镜像与配置创建、启停、删除容器进程与隔离环境(命名空间、cgroup、rootfs 等)。Kubernetes 通过 CRI(Container Runtime Interface)与运行时对接,不直接绑死某一实现。

二、containerd

containerd:由 Docker 捐出、CNCF 毕业项目,工业级容器运行时。负责镜像拉取与存储、容器生命周期、网络 namespace 等;不包含构建与高层 API,常与 runc 配合做实际「跑容器」的 OCI 实现。K8s 通过 CRI 插件(containerd 内嵌 cri)对接,kubelet 可直连 containerd,无需 Docker daemon,路径更短、资源占用更小,当前主流选择。

三、CRI-O

CRI-O轻量、专注 K8s CRI,只做「跑 Pod/容器」所需的最小集合:镜像拉取、存储、OCI 运行时(runc 等)。无 Docker 兼容层、无构建,与 K8s 绑定紧,Red Hat/OpenShift 系常用。与 containerd 相比:都符合 CRI/OCI,containerd 生态与第三方集成更广,CRI-O 更偏「仅 K8s」的极简运行时。


面试要点

  • 容器运行时负责容器生命周期与隔离;K8s 通过 CRI 对接。
  • containerd:工业级、与 runc 配合、内嵌 CRI;kubelet 可直连,主流选择。
  • CRI-O:轻量、专注 CRI、无 Docker 层;OpenShift 系常用。
  • 二者都符合 CRI/OCI;containerd 生态更广,CRI-O 更极简。

记忆要点

  1. 运行时 = 镜像+容器生命周期+隔离;K8s 用 CRI 对接。
  2. containerd = 主流、CRI 内嵌、与 runc 配合;CRI-O = 轻量、仅 K8s。
  3. 选型看生态与发行版(如 OpenShift 用 CRI-O)。

返回模块 | 返回总览

23-存储与虚拟化/302-Kubernetes的CNI插件.md

第 302 题:Kubernetes的CNI插件?CalicoCilium

题目

Kubernetes的CNI插件?CalicoCilium


完整讲解

一、CNI 作用

CNI(Container Network Interface)是 Kubernetes 的网络插件接口:kubelet 在创建/删除 Pod 时调用配置好的 CNI 插件,为 Pod 配置网络命名空间(网卡、IP、路由、与集群/外网互通等)。插件以二进制或脚本形式存在,通过 stdin 接收配置、通过 stdout 返回结果。

二、Calico

Calico:基于 BGPoverlay(VxLAN 等)的三层网络方案,每 Pod 有独立 IP、可做网络策略(NetworkPolicy)、支持 eBPF 数据面。适合大规模、需策略与可观测的集群;可纯 BGP 与底层网络集成、无 overlay 封装,性能好。常用于生产、混合云与多集群。

三、Cilium

Cilium:基于 eBPF 的 CNI,内核态实现转发、负载均衡、策略、可观测(替代 iptables 与部分 kube-proxy)。支持 Hubble 观测、多集群服务网格 等高级能力。适合高性能、可观测与安全需求;对内核版本有要求。与 Calico 相比:都支持 NetworkPolicy 与高性能;Cilium 更偏 eBPF 与可观测、Calico 更成熟于 BGP 与策略。


面试要点

  • CNI = K8s 网络插件接口;Pod 创建/删除时配置网络命名空间。
  • Calico:BGP 或 overlay、NetworkPolicy、可 eBPF;适合大规模与策略。
  • Cilium:eBPF 驱动、可观测(Hubble)、服务网格;高性能与可观测。
  • 选型看规模、策略需求、是否要 eBPF 与可观测。

记忆要点

  1. CNI = 插件接口;为 Pod 配网卡、IP、路由。
  2. Calico = BGP/overlay、策略;Cilium = eBPF、可观测。
  3. 二者都支持高性能与策略;Cilium 偏 eBPF 与可观测。

返回模块 | 返回总览

23-存储与虚拟化/303-GPU虚拟化技术.md

第 303 题:GPU虚拟化技术?vGPUMIGSR-IOV

题目

GPU虚拟化技术?vGPUMIGSR-IOV


完整讲解

一、GPU 虚拟化需求

云与多租户场景下,需把物理 GPU 拆分或隔离给多 VM/容器,实现分时或分片使用。常见技术:vGPU(厂商方案)、MIG(多实例 GPU)、SR-IOV(直通)等。

二、vGPU

vGPU(如 NVIDIA vGPU):在虚拟化层(Hypervisor)将一块物理 GPU 分成多块虚拟 GPU,每块直通给一台 VM;时间片调度或硬件分区由驱动与 License 管理。共享与隔离兼顾,但需厂商 License、与特定虚拟化栈(如 vSphere)配合。适合企业虚拟桌面与云主机。

三、MIG 与 SR-IOV

MIG(Multi-Instance GPU):A100/A30 等在硬件上把单卡拆成多个实例(如 7 个 1g.5gb),每实例有独立显存与算力,强隔离、无时间片切换开销。适合容器级细粒度共享、多小 job 同卡。SR-IOV:物理 GPU 暴露多个 VF,每 VF 直通给 VM,接近物理性能;需驱动与平台支持,VF 数有限。对比:vGPU 偏虚拟化与 License;MIG 偏容器与硬隔离;SR-IOV 偏 VM 直通性能。


面试要点

  • GPU 虚拟化:vGPU、MIG、SR-IOV 等,实现分时或分片。
  • vGPU:Hypervisor 层拆分、直通 VM;需厂商 License、与虚拟化栈配合。
  • MIG:A100 等硬件多实例、强隔离;适合容器多小 job。SR-IOV:VF 直通 VM、高性能。
  • 选型看场景(VM/容器)、隔离与性能需求、硬件与 License。

记忆要点

  1. vGPU = 虚拟化层拆分、需 License;MIG = 硬件多实例、容器级;SR-IOV = VF 直通。
  2. MIG 强隔离、无时间片;SR-IOV 接近物理性能。
  3. 按 VM/容器、隔离与性能选型。

返回模块 | 返回总览

23-存储与虚拟化/304-存储的CSI驱动开发.md

第 304 题:存储的CSI驱动开发?

题目

存储的CSI驱动开发?


完整讲解

一、CSI 是什么

CSI(Container Storage Interface)是 Kubernetes 的存储插件标准:抽象「卷的创建、挂载、扩容、快照等」,由独立组件(CSI 驱动)实现,与 K8s 解耦。K8s 通过 VolumePVC/PVStorageClass 发请求,kubeletexternal-provisioner/attacher 等侧车调用 CSI 驱动的 gRPC 接口,由驱动与后端存储(云盘、Ceph、NFS 等)交互。

二、CSI 驱动开发要点

接口:实现 CSI 规定的 Identity、Controller、Node 三类 gRPC 服务。Identity:GetPluginInfo、GetPluginCapabilities 等。Controller:CreateVolume/DeleteVolume、ControllerPublishVolume(挂到节点)等,常由单独进程(与 K8s 控制面同机或集中部署)提供。Node:NodeStageVolume/NodePublishVolume(在节点上挂到 Pod 路径)等,由每节点的 DaemonSet 或 kubelet 调用的进程提供。流程:用户建 PVC → provisioner 调 CreateVolume → 调度到某节点 → attacher 调 ControllerPublish → kubelet 调 NodeStage/NodePublish,最终 Pod 内可见卷。

三、实现注意

驱动需幂等(重复调用不报错);考虑拓扑(如云盘只能挂同 AZ 节点);扩容、快照、克隆按能力实现对应 RPC。常用框架有 csi-test、各云厂商与 Ceph 的参考实现。


面试要点

  • CSI = K8s 存储插件标准;卷的创建、挂载、扩容等由驱动实现。
  • 三类服务:Identity、Controller(CreateVolume、Publish)、Node(Stage、Publish)。
  • Controller 常集中部署;Node 每节点部署;都通过 gRPC 暴露。
  • 实现需幂等、考虑拓扑与能力(扩容、快照等)。

记忆要点

  1. CSI = Identity + Controller + Node 三类 gRPC;与 PVC/PV、StorageClass 配合。
  2. Controller 做 Create/Delete/Publish;Node 做 Stage/Publish 到 Pod 路径。
  3. 开发注意幂等、拓扑、能力声明。

返回模块 | 返回总览

23-存储与虚拟化/305-etcd在K8s中的作用.md

第 305 题:etcd在K8s中的作用?性能调优?

题目

etcd在K8s中的作用?性能调优?


完整讲解

一、etcd 在 K8s 中的作用

etcd 是 Kubernetes 的后端存储:存集群状态(Pod、Node、Service、ConfigMap 等所有 API 对象)、元数据与 lease。API Server 是唯一写 etcd 的组件;Controller、Scheduler、kubelet 等通过 API Server 读/写。etcd 提供 watch,使各组件能增量感知变更,实现协调与声明式逻辑。高可用部署通常 3 或 5 节点,用 Raft 共识保证一致性与容错。

二、性能瓶颈与调优

写入:大量 Pod 创建/删除、频繁更新(如 status、annotation)会推高 QPS 与 compaction 压力。大 key/value:单对象过大(如 ConfigMap 几 MB)会拉长单次请求与 compaction。历史版本:etcd 保留多版本,compaction 不及时会占磁盘与内存。调优--auto-compaction--compact-interval 控制压缩周期;--quota-backend-bytes 限制 DB 大小防爆盘;SSD、足够内存分离 watch 与读写(可读副本);控制单对象大小与更新频率(如 status 与主对象分离、限流)。

三、运维要点

监控 etcd 延迟、QPS、db size、compaction;避免单对象过大与全量 list;升级与备份按官方建议做;生产至少 3 节点、定期备份与恢复演练。


面试要点

  • etcd = K8s 集群状态存储;API Server 唯写;watch 供各组件增量感知。
  • 性能:写 QPS、大对象、历史版本与 compaction;调优:auto-compaction、quota、SSD/内存。
  • 控制单对象大小与更新频率;监控延迟、db size、compaction。
  • 高可用 3/5 节点;备份与恢复演练。

记忆要点

  1. etcd 存全集群 API 对象;API Server 写、各组件通过 watch 感知。
  2. 调优:compaction、quota、SSD;控制大对象与频繁更新。
  3. 监控延迟与 db size;生产多节点、定期备份。

返回模块 | 返回总览