Local mode#
Important
This user guide shows how to use local mode with Ray Train V2 only. To migrate from Ray Train V1 to V2, see the Train V2 migration guide.
What’s local mode?#
Local mode in Ray Train runs your training function directly in the current process instead of launching Ray Train worker actors and distributing your training code across them. This gives you a simplified debugging environment where you can iterate quickly on your training logic.
Local mode supports two execution modes:
Single-process mode: Runs your training function in a single process. Use it for rapid iteration and debugging.
Multi-process mode with
torchrun: Launches multiple processes for multi-GPU training. Use it to debug distributed training logic with familiar tools.
Enable local mode#
To enable local mode, set num_workers=0 in your ScalingConfig:
from ray.train import ScalingConfig
from ray.train.torch import TorchTrainer
def train_func(config):
# Your training logic
pass
trainer = TorchTrainer(
train_loop_per_worker=train_func,
scaling_config=ScalingConfig(num_workers=0),
)
result = trainer.fit()
Local mode provides the same ray.train APIs you use in distributed training, so your training code runs without other changes. You can verify your training logic locally before you scale to distributed training.
When to use local mode#
Use single-process local mode for the following tasks:
Develop and iterate quickly: Test changes to your training function locally.
Write unit tests: Verify that your training logic works correctly in a simplified environment.
Debug training logic: Step through your training code with standard Python debugging tools to find issues.
Use multi-process local mode with torchrun for the following tasks:
Test multi-GPU logic: Verify that your distributed training code works correctly across multiple GPUs with familiar
torchruncommands.Migrate existing code: Bring existing
torchrun-based training scripts into Ray Train and keep your development workflow.Debug distributed behavior: Isolate issues in your distributed training logic with
torchrunprocess management.
Note
In local mode, Ray Train doesn’t launch worker actors. Your training code can still launch Ray actors or use other Ray features, such as Ray Data in single-process mode.
Single-process local mode#
The following example shows how to use single-process local mode with PyTorch:
import torch
from torch import nn
import ray
from ray.train import ScalingConfig
from ray.train.torch import TorchTrainer
def train_func(config):
model = nn.Linear(10, 1)
optimizer = torch.optim.SGD(model.parameters(), lr=config["lr"])
for epoch in range(config["epochs"]):
# Training loop
loss = model(torch.randn(32, 10)).sum()
loss.backward()
optimizer.step()
# Report metrics
ray.train.report({"loss": loss.item()})
trainer = TorchTrainer(
train_loop_per_worker=train_func,
train_loop_config={"lr": 0.01, "epochs": 3},
scaling_config=ScalingConfig(num_workers=0),
)
result = trainer.fit()
print(f"Final loss: {result.metrics['loss']}")
Note
Local mode works with all Ray Train framework integrations, including PyTorch Lightning, Hugging Face Transformers, LightGBM, XGBoost, and TensorFlow.
Test with local mode#
The following example shows how to write a unit test with local mode:
import pytest
import ray
from ray.train import ScalingConfig
from ray.train.torch import TorchTrainer
def test_training_runs():
def train_func(config):
# Report minimal training result
ray.train.report({"loss": 0.5})
trainer = TorchTrainer(
train_loop_per_worker=train_func,
scaling_config=ScalingConfig(num_workers=0),
)
result = trainer.fit()
assert result.error is None
assert result.metrics["loss"] == 0.5
Use local mode with Ray Data#
Single-process local mode works with Ray Data for data loading and preprocessing. Ray Data processes your data and returns it to your training function in the local process.
The following example shows how to use Ray Data with single-process local mode:
import ray
from ray.train import ScalingConfig
from ray.train.torch import TorchTrainer
def train_func(config):
# Get the dataset shard
train_dataset = ray.train.get_dataset_shard("train")
# Iterate over batches
for batch in train_dataset.iter_batches(batch_size=32):
# Training logic
pass
# Create a Ray Dataset
dataset = ray.data.read_csv("s3://bucket/data.csv")
trainer = TorchTrainer(
train_loop_per_worker=train_func,
scaling_config=ScalingConfig(num_workers=0),
datasets={"train": dataset},
)
result = trainer.fit()
Warning
Ray Data isn’t supported when you use torchrun for multi-process training in local mode. For multi-process training, use standard PyTorch data loading, such as DataLoader with DistributedSampler.
Multi-process local mode with torchrun#
Local mode supports multi-GPU training through torchrun, so you can develop and debug with torchrun process management.
Single-node multi-GPU training#
The following example shows how to use torchrun with local mode for multi-GPU training on a single node. Use this approach to migrate existing PyTorch training code or to debug distributed training logic with the familiar torchrun process management. The example loads data with the standard PyTorch DataLoader, so you can adapt your existing PyTorch training code to it.
First, create your training script, train_script.py:
import os
import tempfile
import torch
import torch.distributed as dist
from torch import nn
from torch.utils.data import DataLoader
from torchvision.datasets import FashionMNIST
from torchvision.transforms import ToTensor, Normalize, Compose
from filelock import FileLock
import ray
from ray.train import Checkpoint, ScalingConfig, get_context
from ray.train.torch import TorchTrainer
def train_func(config):
# Load dataset with file locking to avoid multiple downloads
transform = Compose([ToTensor(), Normalize((0.5,), (0.5,))])
data_dir = "./data"
# Only local rank 0 downloads the dataset
local_rank = get_context().get_local_rank()
if local_rank == 0:
with FileLock(os.path.join(data_dir, "fashionmnist.lock")):
train_dataset = FashionMNIST(
root=data_dir, train=True, download=True, transform=transform
)
# Wait for rank 0 to finish downloading
dist.barrier()
# Now all ranks can safely load the dataset
train_dataset = FashionMNIST(
root=data_dir, train=True, download=False, transform=transform
)
train_loader = DataLoader(
train_dataset, batch_size=config["batch_size"], shuffle=True
)
# Prepare dataloader for distributed training
train_loader = ray.train.torch.prepare_data_loader(train_loader)
# Prepare model for distributed training
model = nn.Sequential(
nn.Flatten(),
nn.Linear(28 * 28, 128),
nn.ReLU(),
nn.Linear(128, 10)
)
model = ray.train.torch.prepare_model(model)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=config["lr"])
# Training loop
for epoch in range(config["epochs"]):
# Set epoch for distributed sampler
if ray.train.get_context().get_world_size() > 1:
train_loader.sampler.set_epoch(epoch)
epoch_loss = 0.0
for batch_idx, (images, labels) in enumerate(train_loader):
outputs = model(images)
loss = criterion(outputs, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
epoch_loss += loss.item()
avg_loss = epoch_loss / len(train_loader)
# Report metrics and checkpoint
with tempfile.TemporaryDirectory() as temp_dir:
torch.save(model.state_dict(), os.path.join(temp_dir, "model.pt"))
ray.train.report(
{"loss": avg_loss, "epoch": epoch},
checkpoint=Checkpoint.from_directory(temp_dir)
)
# Configure trainer for local mode
trainer = TorchTrainer(
train_loop_per_worker=train_func,
train_loop_config={"lr": 0.001, "epochs": 10, "batch_size": 32},
scaling_config=ScalingConfig(num_workers=0, use_gpu=True),
)
result = trainer.fit()
Then, launch training with torchrun:
# Train on 4 GPUs on a single node
torchrun --nproc-per-node=4 train_script.py
Ray Train automatically detects the torchrun environment variables and configures distributed training accordingly. To access distributed training information, use ray.train.get_context():
from ray.train import get_context
context = get_context()
print(f"World size: {context.get_world_size()}")
print(f"World rank: {context.get_world_rank()}")
print(f"Local rank: {context.get_local_rank()}")
Warning
Ray Data isn’t supported when you use torchrun for multi-process training in local mode. For multi-process training, use standard PyTorch data loading, such as DataLoader with DistributedSampler.
Multi-node multi-GPU training#
You can also use torchrun to launch multi-node training with local mode. The following example shows how to launch training across two nodes with four GPUs each.
On the master node at 192.168.1.1, run the following command:
RAY_TRAIN_V2_ENABLED=1 torchrun \
--nnodes=2 \
--nproc-per-node=4 \
--node_rank=0 \
--rdzv_backend=c10d \
--rdzv_endpoint=192.168.1.1:29500 \
--rdzv_id=job_id \
train_script.py
On the worker node, run the following command:
RAY_TRAIN_V2_ENABLED=1 torchrun \
--nnodes=2 \
--nproc-per-node=4 \
--node_rank=1 \
--rdzv_backend=c10d \
--rdzv_endpoint=192.168.1.1:29500 \
--rdzv_id=job_id \
train_script.py
Transition from local mode to distributed training#
When you’re ready to scale from local mode to distributed training, change num_workers to a value greater than 0:
trainer = TorchTrainer(
train_loop_per_worker=train_func,
train_loop_config=config,
- scaling_config=ScalingConfig(num_workers=0),
+ scaling_config=ScalingConfig(num_workers=4, use_gpu=True),
)
Your training function stays the same, and Ray Train handles distributed coordination automatically.
Limitations and API differences#
Local mode provides simplified implementations of Ray Train APIs for rapid debugging without distributed orchestration. As a result, some features behave differently or aren’t available.
Features not available in local mode#
The following Ray Train features aren’t available in local mode:
Worker-level fault tolerance: Ray Train’s automatic fault tolerance features, such as restarting workers on failure, aren’t available. If you configure
FailureConfig, its settings don’t apply in local mode.Callbacks: Local mode doesn’t invoke callbacks that you specify in
RunConfig.Ray Data with multi-process training: Ray Data isn’t supported when you use
torchrunwith local mode for multi-process training. Use standard PyTorch data loading instead.
API behavior differences#
The following table summarizes how ray.train APIs behave differently in local mode:
API |
Behavior in local mode |
|---|---|
Stores checkpoints in memory only and doesn’t persist them to storage. Ignores the |
|
Returns the last checkpoint from memory. Doesn’t load checkpoints from persistent storage. |
|
Always returns an empty list. Doesn’t track checkpoint history. |
|
No-op. |
|
Returns data as-is. |
|
Raises |