SkypilotExecutor#
Launch tasks across clouds (AWS, GCP, Azure, Kubernetes, and more) via SkyPilot.
Prerequisites#
Install the SkyPilot extras:
pip install "nemo_run[skypilot]"
Configure at least one cloud with
sky check. Follow the SkyPilot cloud setup guide for your provider.
Executor configuration#
from nemo_run.core.execution.skypilot import SkypilotExecutor
executor = SkypilotExecutor(
cloud="kubernetes", # or "aws", "gcp", "azure", …
gpus="A100", # GPU type string recognised by SkyPilot
gpus_per_node=8,
num_nodes=1,
container_image="nvcr.io/nvidia/pytorch:24.05-py3",
env_vars={"PYTHONUNBUFFERED": "1"},
# Optional: reuse an existing cluster instead of provisioning a new one
cluster_name="my-sky-cluster",
setup="""
conda deactivate
nvidia-smi
""",
)
Key parameters:
Parameter |
Description |
|---|---|
|
Cloud provider or |
|
GPU type string (e.g. |
|
GPUs per node |
|
Number of nodes |
|
Docker image for the job |
|
Optional: name of an existing cluster to reuse |
|
Shell commands to run once on the cluster before the job |
|
Tear the cluster down once jobs finish. Defaults to |
|
Stop (or tear down, with |
E2E workflow#
import nemo_run as run
from nemo_run.core.execution.skypilot import SkypilotExecutor
task = run.Script("python train.py --lr=3e-4 --max-steps=500")
executor = SkypilotExecutor(
cloud="kubernetes",
gpus="RTX5880-ADA-GENERATION",
gpus_per_node=8,
num_nodes=1,
container_image="nvcr.io/nvidia/pytorch:24.05-py3",
)
with run.Experiment("my-experiment") as exp:
exp.add(task, executor=executor, name="training")
exp.run(detach=True)
# Later — reconnect and check status
experiment = run.Experiment.from_id("my-experiment_<id>")
experiment.status()
experiment.logs("training")
Advanced options#
SkypilotJobsExecutor (managed jobs)#
SkypilotJobsExecutor submits SkyPilot Managed Jobs, which survive controller failures and support spot instances with auto-recovery:
from nemo_run.core.execution.skypilot import SkypilotJobsExecutor
executor = SkypilotJobsExecutor(
cloud="aws",
gpus="A100",
gpus_per_node=8,
num_nodes=4,
container_image="nvcr.io/nvidia/pytorch:24.05-py3",
use_spot=True,
)
Cluster lifecycle and teardown#
By default a SkypilotExecutor cluster outlives the job. autodown and idle_minutes_to_autostop are
both off, and cleanup() only downloads logs, so on Kubernetes the pod stays Running and keeps its GPUs
allocated until the cluster is brought down. That is SkyPilot’s behaviour for an unmanaged cluster, not a
NeMo Run defect, but the knobs are worth knowing:
executor = SkypilotExecutor(
...,
autodown=True, # tear down once all jobs finish
idle_minutes_to_autostop=10, # or wait for 10 idle minutes first
)
These map onto sky.launch(down=..., idle_minutes_to_autostop=...). autodown=True on its own tears the
cluster down after all jobs reach a terminal state, and combining it with idle_minutes_to_autostop delays
that until the cluster has been idle for the given time. A cluster that fails during provisioning, data
sync or setup is deliberately left up by SkyPilot for debugging, so those need sky down <cluster> by hand.
To keep the cluster but stop paying for idle GPUs, set idle_minutes_to_autostop with autodown=False,
which stops rather than deletes it.
Package code from git#
executor = SkypilotExecutor(
...,
packager=run.GitArchivePackager(subpath="src"),
)