Sequence 04 - JD 技术深挖学习
本文件只讲 JD 会深挖的技术。每个技术都按“是什么、为什么、怎么查、和 CV 怎么接”来学。
1. 总技术栈图
flowchart TB
Workload[AI Workloads] --> Serving[Inference / Model Serving]
Workload --> Training[Training / Parallelism]
Serving --> Prefill[Prefill]
Serving --> Decode[Decode]
Serving --> KV[KV Cache]
Serving --> Runtime[Runtime Systems]
Runtime --> Dynamo[Dynamo]
Runtime --> NIXL[NIXL]
Training --> NCCL[NCCL]
Training --> Parallel[DP / TP / PP / FSDP]
Runtime --> Comm[Communication Libraries]
Comm --> UCX[UCX]
Comm --> MPI[MPI]
Comm --> GPUNetIO[GPUNetIO]
UCX --> RDMA[RDMA / RoCE]
RDMA --> GDR[GPUDirect RDMA]
Serving --> CUDA[CUDA / GPU Programming]
CUDA --> Nsight[Nsight Systems / Compute]
2. AI inference / model serving
是什么:
把模型变成在线服务。它不是一次 Python 函数调用,而是一个由队列、调度、prefill、decode、KV cache、streaming、metrics 组成的 runtime system。
关键机制:
| 机制 | 解释 | 常见瓶颈 |
|---|---|---|
| Queueing | 请求进入系统后的等待 | P99/TTFT 变差 |
| Scheduling | 决定哪些请求一起执行 | fairness、batching、tail latency |
| Prefill | 处理输入 prompt,生成 KV cache | 长 prompt、TTFT |
| Decode | 逐 token 生成 | TPOT、KV cache read、collectives |
| KV cache | attention 历史状态 | 显存压力、state movement |
| Continuous batching | 动态合批 | throughput 提升,P99 风险 |
面试深挖图:
flowchart TB
Req[Request] --> Q[Queue]
Q --> S[Scheduler]
S --> P[Prefill]
P --> K[KV Cache]
K --> D[Decode Loop]
D --> Out[Streaming Output]
Q --> TTFT[TTFT]
P --> TTFT
D --> TPOT[TPOT]
Q --> P99[P99]
S --> P99
3. NIXL
是什么:
NIXL 是 inference data/state movement 方向的库,重点不是 collective,而是把 inference runtime 里的状态和数据高效搬动,例如 KV cache 或 prefill/decode disaggregation 里的 state transfer。
和 NCCL 区别:
| 维度 | NIXL | NCCL |
|---|---|---|
| 主要场景 | inference state/data movement | distributed collective tensor communication |
| 典型对象 | KV cache、request state、buffer | gradients、activation shards、tensor partitions |
| 操作类型 | point-to-point / transfer abstraction | all-reduce/all-gather/reduce-scatter |
| 指标 | transfer latency、overlap、TTFT/TPOT 影响 | algbw、busbw、collective time |
flowchart TB
PrefillWorker[Prefill Worker] --> KVBlock[KV Blocks]
KVBlock --> NIXL[NIXL Transfer]
NIXL --> DecodeWorker[Decode Worker]
DecodeWorker --> Decode[Decode Tokens]
NIXL --> Metric1[Transfer latency]
NIXL --> Metric2[Overlap with compute]
NIXL --> Metric3[TTFT impact]
4. UCX / RDMA / GPUDirect
UCX 是什么:
UCX 是通信 transport abstraction。它不是某一种网络,而是可以在底层选择 TCP、shared memory、RDMA、CUDA-aware path 等。
RDMA 是什么:
RDMA 允许 RNIC 直接访问远端 registered memory,减少 CPU/kernel involvement。
GPUDirect RDMA 是什么:
在硬件和驱动支持下,RNIC 可以直接访问 GPU memory,减少 CPU staging。
flowchart TB
subgraph TCP[CPU-staged TCP path]
G1[GPU Memory] --> H1[Host Staging]
H1 --> CPU[CPU / Kernel Network Stack]
CPU --> NIC[NIC]
NIC --> NET[Network]
end
subgraph RDMA[GPUDirect RDMA path]
G2[GPU Memory] --> RNIC[RNIC]
RNIC --> RNET[RDMA Network]
RNET --> Remote[Remote GPU/Host Memory]
end
慢了怎么查:
| 层 | 检查什么 |
|---|---|
| transport | 是否走 RDMA,还是 TCP fallback |
| memory | CPU pageable、pinned、GPU memory |
| registration | MR 是否重复注册,registration cache 是否命中 |
| topology | GPU 和 NIC 是否同 PCIe/NUMA 近端 |
| message size | 小消息 latency,大消息 bandwidth |
| progress | polling、completion、progress thread |
| fabric | RoCE PFC/ECN/QoS、IB counters、congestion |
5. GPUNetIO
是什么:
GPUNetIO 是 NVIDIA DOCA 里的 GPU-centric networking 能力,让 GPU 更直接参与网络 packet/data path。
它和 GPUDirect RDMA:
| 技术 | 重点 |
|---|---|
| GPUDirect RDMA | NIC 直接访问 GPU memory 的 data path 能力。 |
| GPUNetIO | GPU 参与网络数据处理/packet path 的编程模型和 runtime。 |
什么时候值得用:
flowchart TB
Data[Network Data] --> CPUPath[CPU handles packet/data path]
CPUPath --> Copy[Copy/Sync to GPU]
Copy --> GPU[GPU consumes data]
Data --> GPUNetIO[GPUNetIO GPU-centric path]
GPUNetIO --> GPU2[GPU consumes/processes data]
CPUPath --> Bottleneck[CPU overhead / copy / latency bottleneck]
Bottleneck --> Need[Consider GPUNetIO]
不要乱说:
不是所有网络场景都该用 GPUNetIO。
如果 CPU path 不在 critical path,上 GPUNetIO 可能只增加复杂度。
6. CUDA / Nsight / performance
必须掌握:
| 概念 | 面试解释 |
|---|---|
| warp | NVIDIA GPU 通常 32 threads 的执行组。 |
| coalescing | 相邻线程访问连续地址,减少 memory transaction。 |
| shared memory | block 内低延迟 on-chip memory,用于 tiling/data reuse。 |
| pinned memory | page-locked host memory,适合 DMA/async copy。 |
| occupancy | SM 上活跃 warp/block 程度,但不是越高越好。 |
| memory-bound | 受 memory bandwidth/latency 限制。 |
| compute-bound | 受 arithmetic pipeline/tensor core 限制。 |
| Nsight Systems | 看整体 timeline。 |
| Nsight Compute | 看单 kernel 细节。 |
flowchart TB
Slow[Program Slow] --> Systems[Nsight Systems]
Systems --> Timeline[CPU/GPU timeline]
Timeline --> Kernel{Kernel dominates?}
Kernel -->|Yes| Compute[Nsight Compute]
Kernel -->|No| API[Check CPU/API/copy/sync/queueing]
Compute --> Metrics[occupancy/memory/stalls/instructions]
Metrics --> Fix[coalescing/tiling/copy overlap/kernel redesign]
6.1 nsys / ncu 的正确使用顺序
不要一上来就用 ncu 看 kernel。面试里要讲出顺序:
先用 nsys 找“时间花在哪里”。
再用 ncu 解释“某个 kernel 为什么慢”。
最后回到 end-to-end metrics,确认优化真的改善 TTFT / TPOT / P99 / throughput。
flowchart TB
AppSlow[Application Slow] --> NSYS[nsys: End-to-end Timeline]
NSYS --> CPU{CPU / Queue / Launch / Sync dominates?}
CPU -->|Yes| CPUFix[Fix CPU feeding / batching / sync / memcpy]
CPU -->|No| KernelPick[Find Dominant Kernel]
KernelPick --> NCU[ncu: Kernel Deep Dive]
NCU --> Bound{Limiter?}
Bound -->|Memory| MemFix[Coalescing / Tiling / Layout / Reduce Traffic]
Bound -->|Compute| ComputeFix[Tensor Core / Fusion / Arithmetic Efficiency]
Bound -->|Occupancy| OccFix[Registers / Shared Memory / Block Size]
Bound -->|Stall| StallFix[Dependency / Barrier / Divergence / Memory Latency]
CPUFix --> E2E[Re-run End-to-end Benchmark]
MemFix --> E2E
ComputeFix --> E2E
OccFix --> E2E
StallFix --> E2E
E2E --> Decision{TTFT / TPOT / P99 improved?}
Decision -->|Yes| Keep[Keep Change]
Decision -->|No| Rollback[Rollback or New Hypothesis]
6.2 Nsight Systems / nsys 看什么
nsys 是 system profiler,重点不是单个 kernel 的内部指标,而是全局 timeline:
| 观察点 | 说明 | 常见问题 |
|---|---|---|
| CPU thread timeline | CPU 是否在准备数据、tokenization、scheduler、RPC、logging。 | CPU feeding 慢,GPU idle。 |
| CUDA API row | cudaMemcpy, cudaLaunchKernel, cudaStreamSynchronize 等调用。 |
同步 API、launch overhead、频繁小 kernel。 |
| GPU kernel timeline | GPU 上 kernel 是否连续执行。 | kernel 之间有 gap,说明 feeding/sync/copy 问题。 |
| memcpy timeline | H2D/D2H/D2D copy 的时间和是否 overlap。 | copy 阻塞 compute,或者 pageable memory 低效。 |
| CUDA streams | 多 stream 是否真的并行。 | 默认 stream 隐式同步,stream dependency 错。 |
| NVTX range | 业务阶段标记:queue、prefill、decode、transfer。 | 没有 NVTX 会导致 timeline 难解释。 |
典型命令:
nsys profile \
--trace=cuda,nvtx,osrt \
--cuda-memory-usage=true \
--force-overwrite=true \
-o reports/llm_serving_timeline \
./your_app --args
怎么看结果:
如果 GPU timeline 上有大段空白,先别优化 kernel,先查 CPU feeding、queueing、copy、sync。
如果 H2D/D2H copy 和 kernel 完全串行,查 pinned memory、stream、async copy、dependency。
如果每个 request 都有很多很短 kernel,查 kernel launch overhead、fusion、batching。
如果 decode step 之间 gap 很大,查 scheduler、sampling、streaming backpressure、communication wait。
6.3 Nsight Compute / ncu 看什么
ncu 是 kernel profiler,适合回答“这个 CUDA kernel 为什么慢”。它会显著改变运行时间,所以不要用它直接判断线上 P99;它用于解释 kernel-level limiter。
典型命令:
ncu \
--set full \
--target-processes all \
--kernel-name regex:your_kernel_name \
--launch-skip 10 \
--launch-count 1 \
--force-overwrite \
-o reports/your_kernel_ncu \
./your_app --args
核心指标怎么读:
| 维度 | 你要看什么 | 如果异常,怎么解释 |
|---|---|---|
| SM / Compute Throughput | SM 是否接近峰值。 | 高则可能 compute-bound,低则可能等 memory、sync、launch。 |
| Memory Throughput | DRAM/L2 throughput 是否接近上限。 | 高且 SM 不高,多半 memory-bound。 |
| Occupancy | active warps 是否受 registers/shared memory/block size 限制。 | occupancy 低不一定坏,但可能隐藏 latency 能力不足。 |
| Warp Stall | stall 原因:memory dependency、barrier、not selected、execution dependency。 | 用来判断是 memory、同步、依赖还是调度问题。 |
| Memory Transactions | global load/store 是否 coalesced。 | transaction 多说明 stride/scatter/layout 问题。 |
| Shared Memory | bank conflict、shared load/store。 | bank conflict 会让 shared memory 优势打折。 |
| Instruction Mix | FP/INT/Tensor Core/LDST 比例。 | 判断算力单元是否用对。 |
优化判断:
Memory-bound:
优先减少 global memory traffic,改 layout,coalescing,tiling,用 shared memory/cache,提高 reuse。
Compute-bound:
优先看 tensor core、kernel fusion、instruction efficiency、数据类型、算法复杂度。
Occupancy-limited:
看 registers、shared memory、block size。不要盲目追求 100% occupancy,要看是否真的改善 latency hiding。
Launch/sync-bound:
ncu 可能看不到系统瓶颈,要回到 nsys,看 kernel gap、CPU launch、stream sync、batching。
6.4 面试里怎么把 nsys / ncu 和 LLM serving 连接起来
如果 TTFT 高:
先 nsys 看 queueing、tokenization、prefill、KV allocation、H2D copy、prefill kernel timeline。
如果 prefill kernel 真的是主因,再 ncu 看 prefill kernel 是否 memory-bound/compute-bound。
如果 TPOT 高:
先 nsys 看 decode step timeline,确认每个 token 慢是 kernel 慢、communication 慢、sampling 慢,还是 step 之间有 gap。
如果 decode kernel 占主导,再 ncu 看 KV cache access、memory bandwidth、occupancy、warp stall。
如果 P99 高:
先按 request shape 拆:prompt length、output length、tenant、worker、GPU、node。
再用 nsys 对比 fast request 和 slow request 的 timeline。
只有在 slow request 的某个 kernel 明显慢时,才用 ncu 深挖 kernel。
如果 NCCL/communication 慢:
先 nsys 看 compute/communication 是否 overlap,GPU 是否等待 collective。
再结合 NCCL logs、topology、nccl-tests。ncu 通常不是第一工具。
面试英文版:
I would start with Nsight Systems, not Nsight Compute. Nsight Systems tells me where time is spent across the whole application: CPU work, CUDA API calls, memory copies, kernels, streams, synchronization, NVTX ranges, and GPU idle gaps. If the GPU is idle or kernels have gaps between them, kernel optimization is not the first target.
After I identify a dominant kernel, I use Nsight Compute to understand why that kernel is slow. I would look at memory throughput, compute throughput, occupancy, warp stalls, memory transactions, shared memory behavior, and instruction mix. Then I map the result to an optimization: coalescing and layout for memory-bound kernels, tensor core or fusion for compute-bound kernels, register/shared-memory/block-size changes for occupancy issues, and stream or batching changes for launch/synchronization issues.
For LLM serving, I would connect this to TTFT, TPOT, and P99. High TTFT usually starts with queueing, tokenization, prefill, KV allocation, or transfer. Bad TPOT points to decode kernels, KV cache access, batching, or communication. Bad P99 requires comparing fast and slow request timelines before optimizing any single kernel.
7. System architecture / prototype
Architect 面试不会只问定义,会问你怎么判断一个优化是否值得做。
标准方法:
flowchart TB
Problem[Problem] --> Hypothesis[Hypothesis]
Hypothesis --> Baseline[Baseline Metrics]
Baseline --> Micro[Microbenchmark]
Micro --> Prototype[Small Prototype]
Prototype --> E2E[End-to-end Validation]
E2E --> Decision[Roadmap Decision]
Decision --> Rollout[Rollout / Fallback / Observability]
回答模板:
I would start with a hypothesis and baseline metrics. Then I would isolate the communication or runtime pattern with a microbenchmark, build the smallest prototype, and finally validate it against end-to-end metrics such as TTFT, TPOT, P99 latency, throughput, memory usage, and operational complexity.