
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 ParallelDDP训练一个受 Karpathy minGPT 启发的 GPT 类语言模型。你将掌握通过CLIsky launch与Python SDKsky.Task两种方式定义任务、提交训练、查看日志、优雅地取消/分离作业以及用num_nodes与 SkyPilot 内置环境变量一键把单机训练扩展到多节点。文末还会结合仓库源码剖析这些内置环境变量SKYPILOT_NUM_NODES、SKYPILOT_NODE_IPS、SKYPILOT_NUM_GPUS_PER_NODE、SKYPILOT_NODE_RANK的生成原理帮助你理解 SkyPilot 分布式执行gang scheduling背后的机制。任务背景minGPT DDP示例任务训练的是一个 GPT 风格模型灵感来自 Karpathy 的 minGPT训练框架采用 PyTorch 官方的distributed/minGPT-ddp示例训练方式为 DDPDistributed 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 YAMLSkyPilot 提供了一个直观的 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 LOGLEVELINFO echo Starting minGPT-ddp training torchrun \ --nproc_per_node$SKYPILOT_NUM_GPUS_PER_NODE \ main.py逐段解读这个文件name任务名用于展示与区分任务。resources硬件需求。cpus: 4表示至少 4 个 vCPUaccelerators: L4:4表示每节点 4 张 NVIDIA L4 GPU也可换成A100:8、H100:8等格式为型号:数量。SkyPilot 会自动在可用云中寻找满足该需求的最便宜实例完成交付。workdir可选默认注释把本地目录整体上传到远端~/sky_workdirsetup与run中的命令都会在该目录下执行。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 自动注入的分布式训练环境变量详见下文环境变量一节。提示workdir和file_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( nameminGPT-ddp, resourcessky.Resources( cpus4, acceleratorsL4: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 LOGLEVELINFO, torchrun --nproc_per_node$SKYPILOT_NUM_GPUS_PER_NODE main.py, ] ) cluster_name mingpt launch_request sky.launch(taskminGPT_ddp_task, cluster_namecluster_name) job_id, _ sky.stream_and_get(launch_request) sky.tail_logs(cluster_name, job_id, followTrue)与 YAML 写法一一对应sky.Task(...)等价于 YAML 中的顶层任务描述。sky.Resources(cpus4, acceleratorsL4: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, followTrue)实时跟踪远端训练日志。运行$ 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_idCLI 完整参考见 docs/source/reference/cli.rst。取回产物训练结束后用熟悉的工具如scp、rsync或文件挂载把日志、检查点等产物取回本地参考 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 LOGLEVELINFO 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_port8008 \ --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_port8008master 节点上用于分布式通信的端口。使用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 直接指定资源来扩展除了修改 YAMLsky 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中可以看到完整的注入逻辑收集节点 IP 与总节点数task_codegen.py#L630-L631通过 Ray 的 placement group 做 gang schedulingSTRICT_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)每行一个 IPSKYPILOT_NUM_NODES len(job_ip_rank_list)按节点注入 GPU 数与 ranktask_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 rank0、1、2……随任务脚本一起下发最终这些变量被塞进sky_env_vars_dict通过run_bash_command_with_log_and_return_pid.remote(..., env_varssky_env_vars_dict, ...)注入到每个节点执行 run 命令的进程中。这正是 docs/source/running-jobs/distributed-jobs.rst 所描述语义的代码级印证SKYPILOT_NODE_RANK执行当前作业的节点 rank0 到num_nodes-1SKYPILOT_NODE_IPS为作业保留的节点 IP 字符串每行一个SKYPILOT_NUM_NODES为作业保留的节点数等于echo $SKYPILOT_NODE_IPS | wc -lSKYPILOT_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 的另一个常用后端是rdzvrendezvous它自动处理各节点的 rank示例见 examples/distributed-pytorch/train-rdzv.yaml使用--rdzv_backendc10d --rdzv_endpoint$MASTER_ADDR:29500 --rdzv_id $SKYPILOT_TASK_ID对应 SDK 版本见 examples/distributed-pytorch/sdk_scripts/train_rdzv.py。SkyPilot 的环境变量远不止这 4 个完整的SKYPILOT_*变量清单含SKYPILOT_TASK_ID、SKYPILOT_CLUSTER_INFO等见 docs/source/running-jobs/environment-variables.rst。关于 YAML 的完整字段volumes、envs、secrets、job_recovery、any_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),仅供参考