L0.6 实操环境与安装基线
三维坐标
layer: L0(基础)|level: Engineer|pillar: 硬件架构本文是 L0 新手村的收官篇,也是全站的「实操准入闸门」。目标不是讲透某个组件,而是把后续所有动手实验所需的环境、硬件、依赖一次性铺平——让你在进入 L1 微架构实战前,手里已经有一套可复现、可隔离、可观测的开发基线。
学习目标
- 前置知识:读过 L0.1–L0.5;会用命令行、装过 pip 包、对 Docker 有耳闻即可。无需 K8s/运维经验。
- 学完产出:① 看懂「驱动 → 容器运行时 → CUDA Toolkit → Python 环境」这条工具栈是如何分层咬合的,以及任一环错配会卡在哪;② 用「CPU 工作台 + 临时租卡」的思路,在本地硬核与云端低成本两套方案间做成本最优编排;③ 掌握「按层装包」铁律,知道做哪一层只装哪一层;④ 亲手写一个最小 Dockerfile,在容器里跑通第一个
hello_infra.py,拿到「实操准入就绪」的凭证。 - 阅读姿势:记住一句话——「能在容器里跑的,绝不污染宿主机;做哪一层实验,就只装哪一层的依赖。」 这是全站所有动手实验的环境契约。
背景与现状
做 AI Infra 最大的隐形成本,不是算法难度,而是 「环境地狱」:CUDA 版本与驱动错配、Python 包依赖打架、「在我机器上能跑」的不可复现性。一个成熟的 infra 工程师,第一项硬功夫就是把环境本身工程化——用容器锁定运行时、用版本管理器隔离 Python、用基础镜像统一 CUDA ABI。
从业界实践看,环境管理的演进同样是三句话:
- 裸机时代:直接
pip install到系统 Python,结果是「装一个新项目,废掉一个旧项目」。 - 虚拟环境时代:
venv/conda隔离 Python 依赖,但系统级的 CUDA / cuDNN / 驱动仍然全局共享,跨机器复现困难。 - 容器化时代(当下):以 Docker + nvidia-container-toolkit 为标准,把「Python 包 + CUDA 运行时 + 系统库」整体打包成镜像,配合 kind(推荐;亦可用 minikube)在本地模拟 K8s 调度——这是云原生 AI 的事实基线。
业界信号:几乎所有主流框架(PyTorch、vLLM、Megatron-LM)都首推官方 Docker 镜像作为安装方式,正是因为「镜像即环境契约」。
nvidia/cuda与pytorch/pytorch系列镜像的海量拉取量,说明「容器化准入」已是大模型工程的默认起点。截至 2026 年,主流栈已是 CUDA 12.8(生产)~ 13.3(最新)+ PyTorch 2.9~2.13(2026-07 最新稳定 2.13)+ Python 3.11/3.12,但「锁版本、整体打包」的容器哲学始终不变。
本站的实操约定:能在容器里跑的,绝不污染宿主机;做哪一层实验,就只装哪一层的依赖。本文给出这套约定的完整落地基线。
配套代码仓库:github.com/blueyi/ai-infra-labs — 含
hello_infra.py、Dockerfile 与scripts/run_all_labs.py一键验证脚本。单卡 6GB 环境已验证通过。
原理与架构
理解实操基线,关键是看清两件事:工具栈是如何分层咬合的,以及两套硬件方案各自的取舍边界。
2.1 工具栈分层关系图
自底向上读这张图:宿主机的 NVIDIA Driver 是一切 GPU 能力的内核态根基(它决定了你能用的 CUDA 最高版本)→ Docker Engine 提供隔离的运行时 → nvidia-container-toolkit 是把宿主 GPU「桥接」进容器的关键胶水(没有它,--gpus all 直接失败)→ 容器内的 CUDA Toolkit 提供 nvcc、cuBLAS 等编译与算子库 → 最上层是 Python 3.11 + uv/conda 隔离的包环境。旁路的 Ollama 用来快速验证「这台机器的显存到底能跑多大模型」,kind 则让你在单机上练习 K8s 调度而不必租真集群(详见 L1.7 K8s 核心对象)。
2.2 两套硬件方案对比
| 维度 | 本地硬核玩家 | 云端低成本玩家 |
|---|---|---|
| 典型配置 | RTX 3090 / 4090(24G)或 A100 / 昇腾 910B;内存 ≥ 32G | 无 GPU 云主机(编译 LLVM/MLIR、跑 CPU 实验)+ 按需租 GPU |
| GPU 来源 | 自有显卡,常驻可用 | Colab / RunPod / Lambda 按小时租用 |
| 最适合做的层 | L1 微架构 profile、L3 多卡并行、L4 Serving 压测 | L0/L2 概念与编译实验、轻量算子验证、写代码 |
| 首付成本 | 高(整机数万元) | 极低(按分钟计费,几元起) |
| 复现性 | 强(环境长期固定) | 中(每次开实例需重建环境,靠镜像/脚本固化) |
| 核心痛点 | 散热、功耗、驱动维护 | 数据上传带宽、实例随时被回收、冷启动慢 |
| 建议策略 | 重活(训练/压测)本地跑 | 编译/写码在便宜 CPU 机,跑 GPU 算子时临时租卡 |
需要强调的是:两套方案不是二选一,而是 「CPU 机当工作台,GPU 卡当试验场」 的组合。绝大多数 L0–L2 的学习实验根本不需要 GPU(编译 MLIR、读源码、跑 CPU 版 PyTorch 验证逻辑),只在真正测算子性能时才租卡——这能把学习成本压到最低。
2.3 按层安装原则
全站遵循一条铁律:做哪一层,只装哪一层的包。
- L0/L1:
torch(CPU 或 CUDA 版)+nvidia-ml-py(查显存)即可。 - L2 编译:额外装
triton/ LLVM / MLIR 工具链。 - L3 训练:再加
deepspeed/megatron-core。 - L4 推理:再加
vllm/tensorrt-llm。
这样每一层环境最小、冲突最少。当需要一键全量复现整站环境时,再用一份顶层 requirements.txt 锁版本(见下文动手实践一节)。
2.4 Docker 镜像分层与运行时隔离
理解 Dockerfile 不是「一串命令」,而是**分层文件系统(Union FS)**的叠加——每一行 RUN / COPY 产生一个新 layer,层与层之间可缓存复用。
| 实践 | 原因 |
|---|---|
| 把不常变的放上面、常变的放下面 | COPY requirements.txt + pip install 在 COPY . 之前,改代码不 invalidate 依赖层 |
| 多阶段构建(multi-stage) | build 阶段用 devel 镜像编译,runtime 阶段只 COPY 二进制,镜像从 8GB 降到 2GB |
用 .dockerignore | 排除 .git、__pycache__、大数据,避免 layer 膨胀 与缓存失效 |
固定 digest 而非 :latest | python:3.11-slim@sha256:... 保证 CI 与本地一致 |
| 运行时隔离 | 容器进程看不到宿主机其他进程;GPU 通过 nvidia-container-toolkit 选择性挂载设备 |
# 多阶段示例:编译与运行分离
FROM nvidia/cuda:12.6.0-devel-ubuntu22.04 AS builder
RUN pip install torch --index-url https://download.pytorch.org/whl/cu126
COPY build_ext.sh .
RUN ./build_ext.sh
FROM nvidia/cuda:12.6.0-runtime-ubuntu22.04
COPY /opt/wheels /opt/wheels
RUN pip install /opt/wheels/*.whl
COPY app/ /app/
WORKDIR /app
查看镜像层:docker history hello-infra:gpu --no-trunc | head。层数过多会拖慢 push/pull——合并相邻 RUN apt 命令是常见优化。
动手实践:用 Docker 起最小可复现环境
实验目标:用一个最小 Dockerfile 从零构建一个隔离环境,在容器内跑通本站第一个 hello_infra.py——打印 PyTorch 版本、检测设备、跑一次 256×256 矩阵乘并计时。产出物:一段容器内的执行输出,证明你的「实操准入」已就绪。
双 venv 提示(ai-infra-labs 实测):32 个核心 lab 用默认
.venv即可。AWQ / vLLM / 完整datasets链路建议另建.venv-sys(uv venv --python /usr/bin/python3),因为 pyenv 编译的 Python 若缺_lzma会导致mlflow/datasets无法 import。
3.1 Hello-Infra 脚本
# hello_infra.py —— 本站第一个 Infra 健康检查脚本
import time
import torch
print("=" * 48)
print(f"[Hello-Infra] torch version : {torch.__version__}")
cuda_ok = torch.cuda.is_available()
print(f"[Hello-Infra] CUDA available: {cuda_ok}")
dev = "cuda" if cuda_ok else "cpu"
if cuda_ok:
print(f"[Hello-Infra] GPU name : {torch.cuda.get_device_name(0)}")
print(f"[Hello-Infra] using device : {dev}")
# 一次小矩阵乘 + 计时(验证算子能落到设备上执行)
a = torch.randn(256, 256, device=dev)
b = torch.randn(256, 256, device=dev)
# 预热(首次会触发 kernel JIT / cuBLAS handle 初始化)
for _ in range(3):
_ = a @ b
if cuda_ok:
torch.cuda.synchronize()
t0 = time.perf_counter()
c = a @ b
if cuda_ok:
torch.cuda.synchronize() # 异步 kernel 必须同步后再停表
dt = (time.perf_counter() - t0) * 1e3
print(f"[Hello-Infra] 256x256 matmul: {dt:.3f} ms -> result sum={c.sum().item():.2f}")
print("=" * 48)
print(">>> 环境基线就绪,欢迎进入 AI Infra 实战。")
3.2 最小 Dockerfile —— CPU / Mac 路径(默认)
# Dockerfile.cpu —— 纯 CPU 最小镜像,适合 Mac / 无 GPU 云主机
FROM python:3.11-slim
WORKDIR /app
# 只装 CPU 版 torch,镜像最小化(不拉 CUDA 运行时)
RUN pip install --no-cache-dir \
torch --index-url https://download.pytorch.org/whl/cpu
COPY hello_infra.py /app/hello_infra.py
CMD ["python", "hello_infra.py"]
构建并运行:
# 构建镜像
docker build -f Dockerfile.cpu -t hello-infra:cpu .
# 运行(无需 GPU)
docker run --rm hello-infra:cpu
# 预期输出:CUDA available: False,using device: cpu,并打印 matmul 耗时
3.3 GPU 路径 —— NVIDIA CUDA 基础镜像
有 NVIDIA 显卡时,换用官方 CUDA 基础镜像,并在 docker run 时加 --gpus all 暴露设备:
# Dockerfile.gpu —— 基于 CUDA 运行时镜像
FROM nvidia/cuda:12.1.1-runtime-ubuntu22.04
WORKDIR /app
# 装 Python 3.11 与 pip
RUN apt-get update && apt-get install -y --no-install-recommends \
python3.11 python3-pip && \
rm -rf /var/lib/apt/lists/*
# 装匹配 CUDA 12.1 的 torch wheel(cu121)
RUN pip3 install --no-cache-dir \
torch --index-url https://download.pytorch.org/whl/cu121
COPY hello_infra.py /app/hello_infra.py
CMD ["python3", "hello_infra.py"]
# 前置:宿主机必须已装 NVIDIA Driver + nvidia-container-toolkit
docker build -f Dockerfile.gpu -t hello-infra:gpu .
# 关键:--gpus all 才能把宿主 GPU 暴露进容器
docker run --rm --gpus all hello-infra:gpu
# 预期输出:CUDA available: True,并打印 GPU 型号与更快的 matmul 耗时