首页
/ DGX Spark 容器工作流实战:NGC PyTorch 与 Unsloth 镜像的 docker run 规范、标签解析与可复现运行

DGX Spark 容器工作流实战:NGC PyTorch 与 Unsloth 镜像的 docker run 规范、标签解析与可复现运行

2026-09-09 20:12:14作者:董斯意

本指南是 DGX Spark 环境技能包中"容器工作流"(container-workflow)参考文档的完整展开。它面向在 NVIDIA DGX Spark(GB10 / aarch64 / SM121 / CUDA 13)上进行 PyTorch 训练与 Unsloth 微调的工程师,给出两条官方认可镜像的具体 docker run 调用、移动标签的摘要(digest)固定流程、拉取与本地重建的取舍,以及裸 pip 兜底方案。读完本文,你将能按可复现的标准在 Spark 上启动训练容器、把结果落盘到宿主机、并对"容器优先"(Container-First)规则背后的 ABI 匹配逻辑形成体系化认知。

背景:为什么 Spark 上"容器优先"是硬规则

DGX Spark 搭载 GB10 Grace Blackwell 芯片:aarch64 CPU、SM121 GPU、128GB 统一内存(UMA)、CUDA 13。相比常见的 x86 + CUDA 12 服务器,这是一个更窄、更年轻的平台——aarch64 + CUDA 13 的 wheel 生态仍在逐步补齐(依据 spark-environment-setup/SKILL.md 的定位描述)。

容器优先的核心理由是固定版本(pinning),而非便利。Triton、xformers、transformers 的版本与 GB10 的 SM121 目标和 CUDA 13 之间存在窄交互;容器把三者锁定在一个已在当前硬件上验证过的组合里,而裸 pip 把解析责任留给你自己,代价是"一次一个导入错误"。仓库技能包甚至为这个决策预置了快速判定:

  • 标准训练/推理工作 → NGC PyTorch 容器;
  • Unsloth 为中心的微调 → Unsloth 容器(自带已验证的 Triton/xformers/transformers 组合);
  • 两者都不合适(自定义系统包、本地 IDE 解释器)→ 按精确顺序执行裸 pip。

判定细节可参见 SKILL.md 的 Container-First Rule,而本文聚焦其中可落地的两条容器路径。

NGC PyTorch 容器:标准训练的通用底座

NGC 镜像用于通用训练/推理底座。参考文档给出了如下具体调用:

docker run --runtime=nvidia --gpus all -it --rm \
  --ipc=host --ulimit memlock=-1 --ulimit stack=67108864 \
  -v "$(pwd)/finetuning:/workspace/finetuning" \
  nvcr.io/nvidia/pytorch:25.09-py3

每个参数的用途必须理解到位,否则容器内环境会以隐蔽方式失败:

  • --runtime=nvidia --gpus all:将 GB10 GPU 暴露给容器。缺少该参数时,容器内的 PyTorch 会报告"无 CUDA 设备",尽管宿主机侧一切正常。这与 gotcha-checks.md 的 GPU 检测五假设 中的第一项(运行时/标志)直接对应——在容器内执行 nvidia-smi 失败即指向这一项。
  • --ipc=host--ulimit 组合--ipc=host 避免共享内存饥饿;--ulimit memlock=-1 解除内存锁上限;--ulimit stack=67108864(64MB)放宽栈空间。三者共同保护 PyTorch DataLoader 多进程 worker 的共享内存与栈需求。
  • -v "$(pwd)/finetuning:/workspace/finetuning":把仓库的 finetuning/ 运行目录挂载进容器。检查点与日志因此落在宿主机文件系统,而非临时容器层——--rm 标志在退出时删除容器(以及一切未挂载出去的内容)。若省略挂载,训练产物会随容器销毁而丢失。

标签(Tag)指引:25.09 与更新 blessed tag 的取舍

25.09-py3在该硬件上实际验证过可工作的标签(内置 torch 2.9.0a0+50eac811a6.nv25.09、CUDA 13.0,满足 ABI 规则预期;对于微调工作流中实际用到的包,未观察到功能差异)。参考文档明确了一条务实原则:当 SKILL.md 提到更新的 blessed tag(如 25.11-py3)时,应将其视为"本地可用则拉取"的指引,而非硬性要求——如果引用的新 tag 未在本地缓存且拉取不现实,就回退到最新可用的 25.x tag,并在运行记录(run notes)中注明这个缺口,不要阻塞在 tag 上

同时要注意 NGC 构建的一个特性:其 PyTorch 是在容器内部针对 CUDA 13 编译的,没有 +cu130 wheel 标签——因此 pip show torch 不会出现 cu130 字样,这个"缺失"本身不是失败(详见 stack-matrix.md 与 ABI 规则)。

Unsloth 容器:移动标签必须先固定摘要再运行

对于以 Unsloth 为中心的微调运行,应优先使用专门镜像而非通用 NGC 镜像——它自带了为该硬件验证过的固定 Triton/xformers/transformers 组合。

与 NGC 的带日期 tag(25.09-py3)不同,unsloth/unsloth:dgxspark-latest 是一个移动 tag(moving tag)。直接把它当作正式运行的调用是不可靠的——必须先解析并固定它的 digest,然后按 digest 运行。参考文档给出的完整三步流程:

# 1. Discovery step: pull the moving tag and confirm it starts.
docker pull unsloth/unsloth:dgxspark-latest

# 2. Resolve the tag to its current digest.
docker inspect --format='{{index .RepoDigests 0}}' unsloth/unsloth:dgxspark-latest
# -> unsloth/unsloth@sha256:<resolved digest>

# 3. Run by digest — this is the reproducible invocation.
docker run --runtime=nvidia --gpus all -it --rm \
  --ipc=host --ulimit memlock=-1 --ulimit stack=67108864 \
  -v "$(pwd)/finetuning:/workspace/finetuning" \
  unsloth/unsloth@sha256:<resolved digest>
  • 第 1 步的 docker pull发现步骤:拉取移动 tag 并确认它能启动;
  • 第 2 步用 docker inspect 把 tag 解析为当前 digest(RepoDigests 中的 sha256:...);
  • 第 3 步按 digest 运行,这才是可复现的正式调用。

在 CI 或任何"可复现性重要"的流水线中,应把固定的 @sha256:... digest 替换掉 tag——如果运行记录只写了 dgxspark-latest,一旦 tag 移动,这个运行将无法复现。每次接手新的 blessed release 时都要重新解析并重新固定 digest(参见下文"拉取 vs 重建")。其余参数(--runtime=nvidia --gpus all--ipc=host、ulimit、finetuning/ 挂载)的理由与 NGC 调用完全一致。

这条"移动 tag 必须先固定"的约束同样被上游正式使用:在 stack-matrix.md 的组件矩阵 中,Unsloth 行明确标注 unsloth/unsloth:dgxspark-latest 是移动 tag,并要求可复现/CI 场景下固定 digest。

拉取 vs 重建:什么时候该做什么

参考文档给出了两条边界清晰的原则:

应当拉取新 tag 的场景:有新 blessed release 发布,或你在追查一个"新 tag 的变更日志声称已修复"的 bug。

应当在本地重建的场景:某个具体项目需要一个额外的系统包或 Python 依赖层(以两条基础镜像之一为 FROM 起点),且该依赖与固定的训练栈不冲突。

明确禁止的场景:不要为了"升级"基础镜像已经固定的某个组件而重建——那会重新引入容器存在本来就是为了规避的版本矩阵问题。这与技能包的 G9 教训一致:裸 pip 环境里 Triton、xformers、transformers 各自漂移,没有任何东西把它们钉在 GB10 的 SM121 目标上(见 spark-training-gotchas/SKILL.md G9)。

裸 pip 逃生通道:uv 隔离与 --override 强制固定

当容器确实不合适(参见 SKILL.md 的 Container-First Rule)时,参考文档要求:uv 隔离环境,而非系统 Python,并在其中按 NVIDIA playbook 的安装顺序执行。

其中的关键陷阱与对策:

  • 如果 uv 坚持选择一个与 playbook 固定版本冲突的依赖版本(在 aarch64/CUDA 13 wheel 生态尚年轻的当下很常见),使用 uv pip install --override 强制固定版本通过,而不是让解析器静默替换成不兼容的构建;
  • 环境建立后,必须先用 SKILL.md 的 Verification Commands 验证,再信任该环境。

完整的固定版本序列(来自 SKILL.md,对应 stack-matrix 的 dated 已知可用矩阵):

pip install "transformers==5.13.1" "peft==0.19.1" "hf_transfer==0.1.9" "datasets==4.3.0" "trl==1.8.0"
pip install --no-deps "unsloth==2026.7.2" "unsloth_zoo==2026.7.2" "bitsandbytes==0.49.2"
pip install -U "torchao==0.17.0"
  • 第二条命令的 --no-deps 不是可选项:在 aarch64 上让 pip 重新解析 Unsloth 的依赖树,是拉入不兼容 torch 或 triton 构建的常见途径;
  • 第三条 torchao==0.17.0 也不是可选项:NGC 基础镜像内置的 torchao 对当前 peft 的 LoRA-attach 路径来说太旧(ImportError: ... torchao ... only versions above 0.16.0 are supported),这是硬阻塞,不是警告
  • 所有 == 固定都是承重的(load-bearing),取自 stack-matrix.md 的 dated 已知可用版本矩阵——未固定的安装会解析到当前 PyPI 版本,远远超出该 Unsloth 版本声明支持的区间。

一个值得注意的生态变化(记录在 stack-matrix.md):HF_HUB_ENABLE_HF_TRANSFERhuggingface_hub 1.23+ 已废弃,设置它只会产生 FutureWarning,下载实际走 Xet。在 1.23+ 上应改为设置 HF_XET_HIGH_PERFORMANCE=1;旧文档中提及 hf_transfer 的指令应理解为"让下载变快"的意图,而非字面意义的当前 API 要求。

启动前验证:容器内环境是否真正就绪

无论走哪条容器路径,参考文档与技能包都要求在跑昂贵负载之前先验证 GPU 可见性。容器启动后立即执行:

import torch
print(torch.cuda.is_available(), torch.version.cuda)

预期输出为一行 <bool> <cuda-version>

True 13.0

如果输出 False不要直接跳到重装 wheel——ABI 不匹配只是多种原因之一。技能包给出的排查假设表(详见 stack-matrix.md 的逐假设细节):

假设 快速检查
运行时/标志 容器内 nvidia-smi 同样失败
设备可见性 echo $CUDA_VISIBLE_DEVICES(注意:显式设为空串会隐藏所有设备)
权限 ls -l /dev/nvidia*
CUDA 初始化状态 进程卡死;用全新 shell/容器重试
ABI 不匹配(常见元凶) torch.version.cuda 不以 13 开头

先查 nvidia-smi:如果它不显示 GPU,问题属于前三类而非 ABI。只有确认是 ABI 问题后才重装 wheel——在排除 1–4 之前重装只会浪费一次循环而不改变结果。ABI 规则的详细内容(CUDA 12/13 wheel 对 libcudart.so.12/.so.13 的链接错配、典型症状、修复路径)可参见 spark-environment-setup/SKILL.md 的 ABI Rule 一节

另一个高频坑:训练开始后如果 Triton 内核编译失败,设置 TRITON_PTXAS_PATH=/usr/local/cuda/bin/ptxas 重试(组件矩阵中 Triton 一行的要求)。

组件矩阵与已知可用版本:支撑上述决策的事实表

stack-matrix.md 是本文所有容器/裸 pip 决策背后的逐组件事实表,与 SKILL.md 的 Component Quick Table 一一对应:

组件 状态 说明
PyTorch(cu130, aarch64) 官方 wheel 位于 download.pytorch.org/whl/cu130,匹配系统 CUDA 13 ABI
bitsandbytes 0.48+ 开箱即用
Triton ✅(需环境变量) 需设置 TRITON_PTXAS_PATH=/usr/local/cuda/bin/ptxas,否则内核编译找不到 ptxas
flash-attn ❌ 跳过 无 sm_121 内核可发布或可构建;此硬件上 PyTorch 的 SDPA 后端更快
xformers 仅源码构建 无预编译 aarch64/SM121 wheel;构建需设 TORCH_CUDA_ARCH_LIST=12.1
vLLM 仅 nightly wheel 使用 wheels.vllm.ai/nightly/cu130;SM121 修复约在 2026-06 进入 nightly 通道
TransformerEngine / NVFP4 训练 仅容器 裸 pip 不现实;NVFP4BlockScaling 面向 SM100,SM121 支持视为有保留
Unsloth ✅(容器优先) 官方镜像 unsloth/unsloth:dgxspark-latest(移动 tag,需固定 digest)或 NVIDIA playbook pip 序列
Axolotl / TRL / PEFT 标准安装,无需特殊处理
LLaMA-Factory / NeMo 脆弱/进行中 在本平台不可靠,先查上游 issue

一个值得单独强调的硬件细节是 sm_121 vs sm_121a:GB10 的 GPU 识别为 sm_121,但部分较新内核特性(尤其 NVFP4 的原生 cvt.e2m1x2 转换指令)需要为超集目标 sm_121a 编译的代码。若 NVFP4 推理比 FP8 慢约 32%,通常就是这个原因——检查所用 wheel/容器的构建标志,再下结论说硬件是瓶颈(对应训练 gotchas 的 G7)。

与技能包其他部分的衔接

容器工作流是整个 DGX Spark 环境设置技能的落地执行层,与同包其他文件形成闭环:

  • 决策入口spark-environment-setup/SKILL.md 定义 Container-First Rule、ABI Rule 与 Verification Commands,本文是其 references/container-workflow.md 的展开;
  • 事实底座references/stack-matrix.md 提供逐组件状态与 dated 已知可用版本矩阵;
  • 启动前预检spark-training-gotchas/SKILL.md 定义 G1–G10 失败模式,其中 G1(ABI 不匹配)、G9(容器优先 vs 裸 pip)直接由本工作流解决;其 assets/preflight.sh 可自动执行 G1/G3/G4/G7/G9 检查;
  • Agent 化执行dgx-spark-ops-engineer.md 描述"环境医生"型 Agent 的容器工作流引导职责——在推荐宿主机级改动之前,先引导修复走向 NGC 或 Unsloth 容器镜像;spark-preflight.md 则把预检编排成可调用的命令并产出 env-report.json
  • 运行期运维spark-memory-thermal-ops/SKILL.md 承接"环境已验证之后"的阶段——UMA 内存头寸、OOM Ladder、热监控。

结语

容器工作流在 DGX Spark 环境设置中承担"可执行层"的角色:NGC 镜像用带日期 tag 直接运行即可,Unsloth 镜像必须先固定 digest 再运行,本地重建只用于叠加不冲突的依赖而绝非"升级"已固定组件,裸 pip 则是必须遵循固定顺序与 --override 纪律的兜底通道。所有路径共享同一条验证底线:在启动任何昂贵负载之前,确认 torch.cuda.is_available()Truetorch.version.cuda13 开头。参考文档右上角的 "Last verified: 2026-07-14" 提醒所有 tag 与版本信息都是带日期快照——新 blessed tag 发布时应重新验证并更新决策,这正是把"固定版本"当作流程而非一次性动作的正确姿势。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
docsdocs
暂无描述
Markdown
899
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
525
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
395