学习环境:在 Mac 上学
结论:除了必须用 NVIDIA GPU 的部分,十五本手册的代码在 Mac 上都能跑——正文的例子都按 CPU 版 PyTorch 验证过,分布式的例子用多进程 + gloo 在一台机器上模拟多卡。CUDA kernel 在 Mac 上用 CPU 模拟器检查正确性;测速度、用 Nsight、跑真实的推理引擎,需要一块 NVIDIA GPU(租云 GPU 或用 WSL2 的 PC),这些内容集中在少数几周,可以攒到一起做。
一键准备环境
git clone https://github.com/AnranS/ai-infra-handbooks.git
cd ai-infra-handbooks
bash env/setup-macos.sh # Xcode 命令行工具、brew 的 cmake / llvm、uv、Python 环境、三个小模型(约 4 GB)
.venv/bin/python tools/mac_check.py # 自检:每本书跑几个有代表性的例子,约 10 分钟
脚本会建一个共用的虚拟环境 .venv(Python 3.12 + CPU / MPS 版 PyTorch 等),再单独建一个 Python 3.14 的环境给 Python 手册;模型放在仓库根目录的 models/,各手册通过软链接共用。之后在 source .venv/bin/activate 的环境里跑各章的代码即可。
自检脚本
tools/mac_check.py 如果有失败项,把终端里的汇总(完整日志在 build/mac_check/)发出来,就能针对性地修。每本书在 Mac 上的情况
| 手册 | Mac 上 | 说明 |
|---|---|---|
| Python 进阶 | 可以 | 纯 Python,例子按 Python 3.14 验证(环境脚本已装好)。 |
| C++ 进阶 | 可以,有差异 | 编译器是 clang(建议 brew install llvm cmake,较新的 libc++ 才有 std::jthread)。ASan、UBSan、TSan 都能用,LeakSanitizer 不支持:一个故意泄漏的例子要改用 leaks --atExit -- ./a.out 检查;TSan 的锁顺序检测在 Apple 平台上不可靠,那个故意演示死锁的例子可能不报(检查脚本只记为差异)。pybind11 / PyTorch 扩展一章的构建脚本认 CXX 环境变量(检查脚本会传同一个编译器);苹果命令行工具里的 ld 偶尔比 SDK 旧,用苹果 clang 链接共享库会报 tapi error: malformed file,这时用 Homebrew 的 LLVM 或更新命令行工具。libc++ 与 Linux 上的 libstdc++ 实现细节不同,sizeof(std::string)、容量、哈希表桶数这类输出会和页面不一样;perf 换成 Instruments。 |
| 大模型原理 | 可以 | CPU 版 PyTorch + Qwen3-0.6B。页面按 CPU 验证,个别浮点输出在最后一位可能略有不同。 |
| 数学基础 | 可以 | 和大模型原理同一套环境(CPU 版 PyTorch + Qwen3-0.6B),例子在仓库的 llm/ 目录下运行。 |
| CUDA 进阶 | 部分 | CPU 模拟器、练习题判题和 C++ 手册的检查都优先用 Homebrew 的 LLVM(brew install llvm,自动选);torch.compile 只能用苹果 clang(PyTorch 的头文件和 Homebrew clang 不兼容),所以 xcode-select 要指向和 SDK 同一代的工具链——指向旧 Xcode 时链接会报 tapi error: unknown architecture,用 sudo xcode-select -s /Library/Developer/CommandLineTools 切过去。kernel 不能在 Mac 上真跑:用 CPU 模拟器检查正确性——python cuda/tools/emu_run.py reduction.cu(书里的例子)或 python cuda/tools/emu_run.py 你的文件.cu。“框架与编译器”6 章(PyTorch 内部机制、torch.compile)可以在 Mac 上跑。Triton 在 macOS 上没有安装包,用练习题里的 Triton 模拟器。测带宽和算力、Nsight、多卡通信需要 NVIDIA GPU。 |
| 分布式训练 | 可以 | torchrun + gloo 在一台机器上起多个进程。遇到 gloo 连接报错,设置 export GLOO_SOCKET_IFNAME=lo0(检查脚本会自动设置)。 |
| 推理系统 | 可以 | 从零写的引擎、分布式、通信与存储、前沿专题、生产与生态的例子都能跑;线性注意力和多模态两章用 Qwen3.5-0.8B(环境脚本已下载)。vLLM、SGLang 本身不能在 Mac 上部署,源码导读只需要读代码。 |
| 手写 mini-sglang | 可以 | 63 个测试在 CPU 上跑(GPU 库用同接口的假实现);依赖 Triton 的 1 个测试在 Mac 上自动跳过。上 GPU 跑性能是大作业三的内容。 |
| 练习题 | 可以 | 浏览器里直接判题;本地的 python practice/judge.py 支持 macOS:C++ 题用 clang + sanitizer,CUDA 题用 CPU 模拟器(只查正确性,不给性能档位)。 |
| 大作业 | 一、二、四可以 | 大作业一(从零训练小语言模型)、二(DDP、ZeRO-1、重计算)和四(给 mini-sglang 接入 Qwen3.5)只要 CPU;大作业三(推理引擎的 GPU 性能门槛)需要 NVIDIA GPU。 |
需要 GPU 的时候
冲刺计划以 Mac 为主:看书、写代码、跑正确性检查都在 Mac 上完成,真正需要 NVIDIA GPU 的只有测性能和跑真实推理引擎的时候。下面是租卡清单:哪几周要用、做什么、要什么卡、大约多少小时(小时数按"准备好代码再开机"估算,不含调试环境的时间)。
| 周次 | 做什么 | 需要的卡 | 约多少小时 | 在 Mac 上先做好的部分 |
|---|---|---|---|---|
| 第 2~3 周 | CUDA 手册的性能实验:带宽、SGEMM、Tensor Core、Nsight 分析;练习题的性能档位(judge.py bench) | 任意较新的 NVIDIA 卡(4090、L4、A10 都行) | 8~12 | 用 CPU 模拟器检查每个 kernel 的正确性、合并访存和 bank conflict |
| 第 7 周 | 手写 mini-sglang 上 GPU:CUDA Graph、FlashInfer / FlashAttention 后端、和 SGLang 对比吞吐(作品 A、大作业三) | A100 / H100,或者 4090(模型选 Qwen3-0.6B) | 10~15 | 63 个测试在 CPU 上全部通过;准备好压测脚本和请求集 |
| 第 10 周 | 跑 FlashMLA、DeepGEMM 的官方 benchmark,读它们的主循环 | H100 / H800(Hopper 专用的指令) | 6~10 | 读完 MLA、FP8 分块 GEMM 两章,想清楚要测什么 |
| 第 13 周 | GPU 算子作品:TMA、WGMMA、和 cuBLAS / FA2 对比性能 | H100(Hopper 特性) | 10~15 | 在模拟器上把算法和分块方案验证好 |
| 可选 | 从零训练教程的 GPU 版脚本(bf16、torch.compile、DDP) | 1~8 张任意 NVIDIA 卡 | 2~5 | CPU 上把三章的代码跑通 |
合计约 40~60 小时。省钱的办法:代码在 Mac 上写好、测好再开机,一次开机把要测的东西批量跑完;把装好环境的机器存成镜像,下次直接用;能用抢占式实例的地方就用。价格各平台差别很大、变化也快,按上表的卡型和小时数自己比较即可。几种获取 GPU 的方式:
- 按小时租云 GPU:选一台带 H100 / A100 / 4090 的机器,按需开关;上面的几块内容加起来大约 30~50 小时。仓库里的
practice/env/setup-wsl2.sh同样适用于 Linux 云主机; - 一台带 NVIDIA 显卡的 Windows PC + WSL2:用
practice/env/setup-wsl2.sh一键配置; - 免费或按题付费的入口:Google Colab 的免费 T4 足够学完 CUDA 的基础和经典算子;LeetGPU 可以在浏览器里写 CUDA、在真实 GPU 上运行。
Mac 上的 MPS(Apple GPU)可以加速 PyTorch 的计算,但它不是 CUDA:CUDA 手册的 kernel、FlashAttention、NCCL、Nsight 这些都用不了,推理引擎的性能数字也没有可比性。
常见问题
- 分布式的例子卡住或报 gloo 的连接错误:
export GLOO_SOCKET_IFNAME=lo0后重试; torch.compile报编译器错误:确认装了 Xcode 命令行工具(xcode-select --install);- 输出和页面差一点:页面上的输出是在 Linux + CPU 上跑出来的,Mac(ARM)上的浮点运算顺序不同,个别数字在最后一位可能不一样;C++ 的差异见上表;
- 模型下载慢:脚本先用 ModelScope,失败时换 Hugging Face;也可以手动下载到
models/下同名目录。