Appearance
Part 6: 练习
1. GPU 后端 + 总结
练习 1:Metal 管线追踪
题目:描述一个 Metal kernel 从源码到执行的完整路径。
参考答案(先自己尝试,再展开查看)
1. .metal 源码 → 编译为 MTLLibrary(GPU 字节码)
id<MTLLibrary> lib = [device newLibraryWithSource:...];
2. 从 library 提取 kernel 函数
id<MTLFunction> fn = [lib newFunctionWithName:@"kernel_name"];
3. 创建计算管线(编译为 GPU 可执行的微码)
id<MTLComputePipelineState> pipe = [device newComputePipelineStateWithFunction:fn ...];
4. 创建命令缓冲区
id<MTLCommandBuffer> cmd = [queue commandBuffer];
5. 编码计算命令(设置 buffer、分发线程组)
[encoder setComputePipelineState:pipe];
[encoder setBuffer:buf offset:0 atIndex:0];
[encoder dispatchThreadgroups:grid threadsPerThreadgroup:group];
6. 提交执行
[cmd commit];
[cmd waitUntilCompleted];练习 2:CPU vs GPU 对比
题目:对于矩阵乘法 [4096, 2048] × [2048, 4096](约 160 亿 FLOP),比较 CPU 和 GPU 的处理方式。
参考答案(先自己尝试,再展开查看)
输出矩阵大小: 4096 × 4096 = 16,777,216 个元素
每个元素: 2048 次乘加 = 4096 FLOP
总 FLOP: 16.8M × 4096 ≈ 68.7B
CPU (8 核):
每个 core 处理 ~2.1M 元素
串行计算每个元素
时间: ~68.7B FLOP / (8 × ~100 GFLOP/s) ≈ 0.09s
GPU (M3 Max, ~4000 核):
每个 core 处理 ~4,200 元素
所有 core 并行执行
时间: ~68.7B FLOP / (~13 TFLOP/s) ≈ 0.005s
加速比: ~18× (理论值,实际受内存带宽限制)练习 3:知识串联
题目:用一个请求的完整生命周期串联所有主题学到的知识。
"用户发送 POST /v1/chat/completions 请求,得到流式回复。"
参考答案(先自己尝试,再展开查看)
HTTP: 服务器接收请求(socket → recv → 解析 HTTP)
HTTP: JSON 解析请求体(手写递归下降解析器)
HTTP: 解析 messages、tools、temperature 等字段
分词: Chat 模板渲染(特殊 token 组装)
分词: BPE 分词(text → token IDs)
服务: 检查磁盘 KV cache(SHA1 匹配前缀)
加载: 模型权重通过 mmap 加载(零拷贝)
加载: Metal GPU 框架初始化
推理: Prefill 阶段(所有 prompt token 通过 43 层)
架构: 每层访问 weights_bind 绑定的权重指针
加载: 权重从 GGUF 张量数据中读取
架构: 量化权重解码(IQ2_XXS/Q2_K → float)
架构: Self-Attention 计算(Q·K^T → softmax → V 加权)
架构: KV Cache 写入(raw sliding window + MLA 压缩)
架构: MoE 前向传播(路由 → 6 专家 → SwiGLU)
推理: RoPE 旋转位置编码
推理: Decode 循环(自回归,逐 token 生成)
采样: 采样(temperature + top-p → 选择 token)
分词: Token 解码(ID → 文本)
HTTP: SSE 流式发送给客户端
服务: KV cache 保存到磁盘今日学习检查清单
- 能描述 Metal kernel 从源码到执行的路径
- 理解 GPU 并行计算的优势
- 理解零拷贝 MTLBuffer 的工作原理
- 能解释 Flash Attention 的核心思想
- 能用完整请求生命周期串联 15 天的知识
- 能总结 ds4.c 的 6 大设计哲学
延伸挑战
挑战 1(中级):Metal vs CPU 性能对比
分别用 ./ds4(Metal 加速)和 make cpu && ./ds4(纯 CPU)运行相同的 prompt。对比 prefill 速度和 decode 速度。GPU 加速比是多少?在哪些阶段加速最明显?
挑战 2(高级):端到端请求追踪(capstone 预习)
用 lldb attach 到 ds4-server,在 client_main、ds4_tokenize_rendered_chat、prefill_layer_major_cpu、sample_full_vocab、sse_chunk 五个函数设断点。发送一个 HTTP 请求,记录每个断点的调用栈和参数。写一份完整的"一个 HTTP 请求的一生"调试报告。