news 2026/9/16 15:36:18

SkyPilot 快速上手:用 PyTorch DDP 在云端启动 minGPT 分布式训练

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SkyPilot 快速上手:用 PyTorch DDP 在云端启动 minGPT 分布式训练

SkyPilot 快速上手:用 PyTorch DDP 在云端启动 minGPT 分布式训练

【免费下载链接】skypilotThe AI Compute Platform for frontier teams. SkyPilot turns fragmented AI compute into one AI supercomputer, so frontier AI teams build custom intelligence faster.项目地址: https://gitcode.com/GitHub_Trending/sk/skypilot

本文以 SkyPilot 官方的 Quickstart 教程(docs/source/getting-started/tutorial.rst)为主线,带你从零跑通一个完整的分布式训练任务:使用 PyTorch 的 Distributed Data Parallel(DDP)训练一个受 Karpathy minGPT 启发的 GPT 类语言模型。你将掌握通过CLI(sky launchPython SDK(sky.Task两种方式定义任务、提交训练、查看日志、优雅地取消/分离作业,以及用num_nodes与 SkyPilot 内置环境变量一键把单机训练扩展到多节点。文末还会结合仓库源码剖析这些内置环境变量(SKYPILOT_NUM_NODESSKYPILOT_NODE_IPSSKYPILOT_NUM_GPUS_PER_NODESKYPILOT_NODE_RANK)的生成原理,帮助你理解 SkyPilot 分布式执行(gang scheduling)背后的机制。

任务背景:minGPT + DDP

示例任务训练的是一个 GPT 风格模型(灵感来自 Karpathy 的 minGPT),训练框架采用 PyTorch 官方的distributed/minGPT-ddp示例,训练方式为 DDP(Distributed Data Parallel)。DDP 的核心思想是:每个进程持有模型的一个副本,各自在本地 GPU 上处理不同 batch 的数据,通过梯度同步(AllReduce)保持模型参数一致。

在 SkyPilot 中,你不需要手动去各云厂商控制台创建虚拟机、配置 SSH、安装环境,只需要用一段 YAML(或几行 Python)描述"要什么资源"、"怎么装环境"、"跑什么命令",剩下的调度与交付由 SkyPilot 完成。

本教程对应的可运行示例也收录在仓库的 examples/distributed-pytorch/train.yaml 与 examples/distributed-pytorch/sdk_scripts/train.py 中,可直接对照阅读。

方式一:使用 CLI + SkyPilot YAML

SkyPilot 提供了一个直观的 YAML 接口,用于描述集群、作业或服务的全部要素:资源需求、setup 命令、run 命令、文件挂载、存储挂载等。YAML 规范中的所有字段都是可选的,未指定时使用默认值,你只需要写与任务相关的字段(完整字段说明见 docs/source/reference/yaml-spec.rst)。

编写 train.yaml

# train.yaml name: minGPT-ddp resources: cpus: 4+ accelerators: L4:4 # Or A100:8, H100:8 # Optional: upload a working directory to remote ~/sky_workdir. # Commands in "setup" and "run" will be executed under it. # # workdir: . # Optional: upload local files. # Format: # /remote/path: /local/path # # file_mounts: # ~/.vimrc: ~/.vimrc # ~/.netrc: ~/.netrc setup: | git clone --depth 1 https://github.com/pytorch/examples || true cd examples git filter-branch --prune-empty --subdirectory-filter distributed/minGPT-ddp uv pip install --system -r requirements.txt run: | cd examples/mingpt export LOGLEVEL=INFO echo "Starting minGPT-ddp training" torchrun \ --nproc_per_node=$SKYPILOT_NUM_GPUS_PER_NODE \ main.py

逐段解读这个文件:

  • name:任务名,用于展示与区分任务。
  • resources:硬件需求。cpus: 4+表示至少 4 个 vCPU;accelerators: L4:4表示每节点 4 张 NVIDIA L4 GPU(也可换成A100:8H100:8等,格式为型号:数量)。SkyPilot 会自动在可用云中寻找满足该需求的最便宜实例完成交付。
  • workdir(可选,默认注释):把本地目录整体上传到远端~/sky_workdirsetuprun中的命令都会在该目录下执行。
  • file_mounts(可选,默认注释):将本地文件挂载到远端,格式为远端路径: 本地路径,例如把~/.vimrc~/.netrc带过去。
  • setup:一次性初始化命令,在每个节点上执行。这里克隆 PyTorch 官方示例仓库,并用git filter-branch抽取其中的distributed/minGPT-ddp子目录,然后安装依赖。|| true保证仓库已存在时克隆失败也不会中断流程。
  • run:作业运行时执行的命令。通过torchrun启动 DDP 训练,其中--nproc_per_node=$SKYPILOT_NUM_GPUS_PER_NODE让每个节点上的进程数自动等于该节点被分配的 GPU 数——这正是 SkyPilot 自动注入的分布式训练环境变量,详见下文"环境变量"一节。

提示workdirfile_mounts在示例中是注释掉的。要学习如何用它们挂载本地目录/文件或对象存储桶(S3、GCS、R2),可参考 docs/source/examples/syncing-code-artifacts.rst。

提示SKYPILOT_NUM_GPUS_PER_NODE环境变量由 SkyPilot 自动设置为每个节点的 GPU 数量,完整环境变量列表见 docs/source/running-jobs/environment-variables.rst。

启动训练

$ sky launch -c mingpt train.yaml
  • -c mingpt:为集群命名,之后对同一集群的复用(如sky exec)都靠这个名字。
  • SkyPilot 会完成:交付资源 → 执行 setup → 执行 run的完整流程,并且优先选择满足资源需求的最便宜集群(这是 SkyPilot 的云优选器 core 能力)。

方式二:使用 Python SDK

如果你更习惯在 Python 中以编程方式驱动训练,SkyPilot 提供了一等公民的 Python SDK(接口参考见 docs/source/reference/pythonapi.rst)。

编写 train.py

# train.py import sky minGPT_ddp_task = sky.Task( name='minGPT-ddp', resources=sky.Resources( cpus='4+', accelerators='L4:4', ), # Optional: upload a working directory to remote ~/sky_workdir. # Commands in "setup" and "run" will be executed under it. # # workdir='.', # # Optional: upload local files. # Format: # /remote/path: /local/path # # file_mounts={ # '~/.vimrc': '~/.vimrc', # '~/.netrc': '~/.netrc', # }, setup=[ 'git clone --depth 1 https://github.com/pytorch/examples || true', 'cd examples', 'git filter-branch --prune-empty --subdirectory-filter distributed/minGPT-ddp', 'uv pip install --system -r requirements.txt', ], run=[ 'cd examples/mingpt', 'export LOGLEVEL=INFO', 'torchrun --nproc_per_node=$SKYPILOT_NUM_GPUS_PER_NODE main.py', ] ) cluster_name = 'mingpt' launch_request = sky.launch(task=minGPT_ddp_task, cluster_name=cluster_name) job_id, _ = sky.stream_and_get(launch_request) sky.tail_logs(cluster_name, job_id, follow=True)

与 YAML 写法一一对应:

  • sky.Task(...):等价于 YAML 中的顶层任务描述。
  • sky.Resources(cpus='4+', accelerators='L4:4'):等价于resources字段。
  • setup=[...]/run=[...]:与 YAML 的setup/run对应,传字符串列表即可。
  • sky.launch(task=..., cluster_name=...):发起启动请求,等价于sky launch -c mingpt train.yaml
  • sky.stream_and_get(launch_request):等待任务提交完成并返回(job_id, handle)
  • sky.tail_logs(cluster_name, job_id, follow=True):实时跟踪远端训练日志。

运行

$ python train.py

仓库中的 examples/distributed-pytorch/sdk_scripts/train.py 在训练结束后还演示了如何用scp下载gpt_snapshot.pt检查点,并通过sky.down(cluster_name)释放集群,非常适合作为"训练 → 取产物 → 销毁"完整闭环的参考。

作业生命周期:分离、取消与取回产物

任务提交后,SkyPilot 会交付满足资源需求的最便宜集群、执行 setup、再执行 run。有几个与作业生命周期相关的实用点:

  • 安全地分离:训练开始后,你可以放心地按下Ctrl-C断开日志输出,任务仍会在远端集群上继续运行。
  • 停止作业:如需停止,使用sky cancel <cluster_name> <job_id>(CLI 完整参考见 docs/source/reference/cli.rst)。
  • 取回产物:训练结束后,用熟悉的工具(如scprsync,或文件挂载)把日志、检查点等产物取回本地,参考 docs/source/examples/syncing-code-artifacts.rst。

你可以放心地把上面的 YAML 或 Python 代码复制过去,针对自己的项目做定制。

扩展到多节点:加一个 num_nodes 即可

把单机训练扩展到多机集群,只需要在任务中加一行num_nodes,并把run命令升级为 torchrun 的多节点形态。

在 YAML 中扩展

resources: cpus: 4+ accelerators: L4:4 # Use 2 nodes with 4 GPUs each (8 GPUs total) num_nodes: 2

对应的run更新为 torchrun 的多节点参数:

run: | cd examples source .venv/bin/activate cd mingpt export LOGLEVEL=INFO MASTER_ADDR=$(echo "$SKYPILOT_NODE_IPS" | head -n1) echo "Starting distributed training, head node: $MASTER_ADDR" torchrun \ --nnodes=$SKYPILOT_NUM_NODES \ --nproc_per_node=$SKYPILOT_NUM_GPUS_PER_NODE \ --master_addr=$MASTER_ADDR \ --master_port=8008 \ --node_rank=${SKYPILOT_NODE_RANK} \ main.py

要点说明:

  • num_nodes: 2表示任务运行在 2 个节点上,每个节点 4 张 L4(共 8 张 GPU)。
  • MASTER_ADDR=$(echo "$SKYPILOT_NODE_IPS" | head -n1):从 SkyPilot 注入的节点 IP 列表中取出第一行作为 torchrun 的 master 地址。
  • --master_port=8008:master 节点上用于分布式通信的端口。
  • 使用uv venv/source .venv/bin/activate管理虚拟环境时,记得在 run 命令中先激活(完整多节点版见 examples/distributed-pytorch/train.yaml)。

SkyPilot 自动注入的分布式环境变量

以下环境变量由 SkyPilot 自动为分布式训练设置,你无需手动配置:

  • SKYPILOT_NUM_NODES:集群/任务的总节点数。
  • SKYPILOT_NUM_GPUS_PER_NODE:每个节点上的 GPU 数量。
  • SKYPILOT_NODE_RANK:当前节点的 rank(从 0 开始)。
  • SKYPILOT_NODE_IPS:所有节点的 IP 地址列表,每行一个。

完整环境变量参考见 docs/source/running-jobs/environment-variables.rst。

用 CLI 直接指定资源来扩展

除了修改 YAML,sky launch也支持在命令行直接覆盖资源需求完成扩容。例如仓库 examples/distributed-pytorch/README.md 中的做法——在同一个 YAML 上直接指定 4 个节点、每节点 4 张 L4,同时把 CPU 提到 8 核以上以避免 CPU 成为瓶颈:

sky launch -c train train.yaml --num-nodes 4 --gpus L4:4 --cpus 8+

环境变量的底层原理:从源码看 SKYPILOT_* 是如何注入的

理解这些内置环境变量的来源,能帮你更自信地编写分布式启动脚本。相关实现集中在 sky/skylet/constants.py 与 sky/backends/task_codegen.py。

变量名的定义

在 sky/skylet/constants.py 中可以看到这些变量的统一定义,它们统一以SKYPILOT_前缀(SKYPILOT_ENV_VAR_PREFIX = 'SKYPILOT_')开头:

SKYPILOT_NUM_NODES = f'{SKYPILOT_ENV_VAR_PREFIX}NUM_NODES' SKYPILOT_NODE_IPS = f'{SKYPILOT_ENV_VAR_PREFIX}NODE_IPS' SKYPILOT_SETUP_NUM_GPUS_PER_NODE = ( f'{SKYPILOT_ENV_VAR_PREFIX}SETUP_NUM_GPUS_PER_NODE') SKYPILOT_NUM_GPUS_PER_NODE = f'{SKYPILOT_ENV_VAR_PREFIX}NUM_GPUS_PER_NODE' SKYPILOT_NODE_RANK = f'{SKYPILOT_ENV_VAR_PREFIX}NODE_RANK'

注意还有一个SKYPILOT_SETUP_NUM_GPUS_PER_NODE——它在 setup 阶段注入,供 setup 命令获知每节点 GPU 数。

注入流程:Ray placement group + 运行时求值

在 sky/backends/task_codegen.py 的_add_ray_task中可以看到完整的注入逻辑:

  1. 收集节点 IP 与总节点数(task_codegen.py#L630-L631):通过 Ray 的 placement group 做 gang scheduling(STRICT_SPREAD,见 task_codegen.py#L464-L466),先在各节点上探测ray.util.get_node_ip_address(),得到节点 IP 排序列表后,写入:

    • SKYPILOT_NODE_IPS = job_ip_list_str'\n'.join(job_ip_rank_list),每行一个 IP)
    • SKYPILOT_NUM_NODES = len(job_ip_rank_list)
  2. 按节点注入 GPU 数与 rank(task_codegen.py#L654-L670):每个节点的 Ray task 在运行时,依据gang_scheduling_id得到该节点 IP,再由 IP 映射到全局 rank,从而设置:

    • SKYPILOT_NUM_GPUS_PER_NODE = int(math.ceil(num_gpus))(向上取整,因此即使accelerators写了 GPU 小数份额也能得到正确的整数)
    • SKYPILOT_NODE_RANK = rank(0、1、2……)
  3. 随任务脚本一起下发:最终这些变量被塞进sky_env_vars_dict,通过run_bash_command_with_log_and_return_pid.remote(..., env_vars=sky_env_vars_dict, ...)注入到每个节点执行 run 命令的进程中。

这正是 docs/source/running-jobs/distributed-jobs.rst 所描述语义的代码级印证:

  • SKYPILOT_NODE_RANK:执行当前作业的节点 rank(0 到num_nodes-1);
  • SKYPILOT_NODE_IPS:为作业保留的节点 IP 字符串,每行一个;
  • SKYPILOT_NUM_NODES:为作业保留的节点数,等于echo "$SKYPILOT_NODE_IPS" | wc -l
  • SKYPILOT_NUM_GPUS_PER_NODE:每节点为作业保留的 GPU 数,等于accelerators: <name>:<count>中的 count(小数向上取整)。

此外,setup阶段执行时也会注入SKYPILOT_NUM_NODES(见 task_codegen.py#L479),所以在 setup 脚本中同样可以读取到集群规模信息。

为什么分布式训练能"自动"工作

由于这些变量是在集群已经交付、节点 IP 与 rank 确定之后由 SkyPilot 在运行时计算并注入的,你的run脚本只需要像普通 shell 一样读取它们,就能获得正确的节点拓扑信息——无需手工维护 hostfile、无需预先知道 master 地址,也无需关心云厂商的 IP 分配方式。这也就是为什么上面的多节点 torchrun 命令可以原样拷贝到任意云(AWS、GCP、Azure、Kubernetes 等)上运行。

更多进阶参考

  • 想要更深入理解多节点作业,可阅读 docs/source/running-jobs/distributed-jobs.rst,其中还包含大节点数(如 100 节点)场景下[Errno 24] Too many open files的解决建议(ulimit -n 65535)。
  • torchrun 的另一个常用后端是rdzv(rendezvous):它自动处理各节点的 rank,示例见 examples/distributed-pytorch/train-rdzv.yaml(使用--rdzv_backend=c10d --rdzv_endpoint=$MASTER_ADDR:29500 --rdzv_id $SKYPILOT_TASK_ID),对应 SDK 版本见 examples/distributed-pytorch/sdk_scripts/train_rdzv.py。
  • SkyPilot 的环境变量远不止这 4 个,完整的SKYPILOT_*变量清单(含SKYPILOT_TASK_IDSKYPILOT_CLUSTER_INFO等)见 docs/source/running-jobs/environment-variables.rst。
  • 关于 YAML 的完整字段(volumesenvssecretsjob_recoveryany_of/ordered多集群选择等),见 docs/source/reference/yaml-spec.rst。

至此,你已经掌握了用 SkyPilot 以 CLI 与 Python SDK 两种方式提交 PyTorch DDP 分布式训练、动态扩展多节点、读取内置分布式环境变量,并理解其底层注入原理的完整链路。接下来,直接复制本文的 YAML/Python 示例,把任务名、资源与 setup 命令替换成你自己的模型与依赖,即可在云端跑起属于自己的大规模训练。

【免费下载链接】skypilotThe AI Compute Platform for frontier teams. SkyPilot turns fragmented AI compute into one AI supercomputer, so frontier AI teams build custom intelligence faster.项目地址: https://gitcode.com/GitHub_Trending/sk/skypilot

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 15:35:18

tmux终端复用器实战:从防断线到高效工作流

用过终端的人&#xff0c;应该都有过这种经历&#xff1a;远程连了台服务器&#xff0c;部署跑了一半&#xff0c;网络一抖&#xff0c;SSH一断&#xff0c;整个任务跟着终端一起没了。那个瞬间&#xff0c;悔恨、无奈、想砸电脑的情绪交织在一起&#xff0c;最后只能老老实实重…

作者头像 李华
网站建设 2026/9/16 15:33:01

Python命令行参数类型管理实战指南

1. 为什么需要参数类型管理在Python命令行工具开发中&#xff0c;参数解析是每个开发者都要面对的基础问题。记得我第一次写命令行工具时&#xff0c;处理用户输入的各种参数格式简直让人抓狂 - 数字被当成字符串、文件路径需要手动验证、布尔值判断写了一大堆if...else。直到深…

作者头像 李华
网站建设 2026/9/16 15:32:16

InternVL MMMU评测教程:多模态多任务理解的权威基准

InternVL MMMU评测教程&#xff1a;多模态多任务理解的权威基准 【免费下载链接】InternVL [CVPR 2024 Oral] InternVL Family: A Pioneering Open-Source Alternative to GPT-4o. 接近GPT-4o表现的开源多模态对话模型 项目地址: https://gitcode.com/GitHub_Trending/in/Int…

作者头像 李华
网站建设 2026/9/16 15:31:20

校园视频监控SSM毕设源码解析:从环境部署到二次开发实战

简介&#xff1a;面向Java毕业设计/课程设计学生的校园视频监控系统完整项目&#xff0c;基于SSM&#xff08;Spring、SpringMVC、MyBatis&#xff09;与MySQL实现&#xff0c;覆盖个人中心、用户权限、视频管理员、摄像头管理、实时监控、留言板与系统管理等核心业务模块&…

作者头像 李华
网站建设 2026/9/16 15:29:54

Spark ALS音乐推荐实战:解决冷启动与稀疏性问题

简介&#xff1a;本资源是一套完整的Spark大数据音乐推荐系统实践项目&#xff0c;面向计算机、人工智能、电子信息等专业学生及初学者&#xff0c;聚焦协同过滤核心算法在真实场景中的工程落地。项目基于ALS矩阵分解实现个性化推荐&#xff0c;包含详细技术文档、可运行源码、…

作者头像 李华