Sunday, March 17, 2024

Efficient Load Balancing with Ray on Amazon SageMaker | by Chaim Rand | Sep, 2023

Must read

A technique for rising DNN coaching effectivity and decreasing coaching prices

Towards Data Science
Photograph by Fineas Anton on Unsplash

In earlier posts (e.g., right here) we expanded on the significance of profiling and optimizing the efficiency of your DNN coaching workloads. Coaching deep studying fashions — particularly giant ones — could be an costly enterprise. Your means to maximize the utilization of your coaching assets in a fashion that each accelerates your mannequin convergence and minimizes coaching prices, generally is a decisive issue within the success of your challenge. Efficiency optimization is an iterative course of wherein we determine and deal with the efficiency bottlenecks in our software, i.e., the parts in our software which might be stopping us from rising useful resource utilization and/or accelerating the run time.

This publish is the third in a sequence of posts that target one of many extra widespread efficiency bottlenecks that we encounter when coaching deep studying fashions, the information pre-processing bottleneck. An information pre-processing bottleneck happens when our GPU (or various accelerator) — sometimes the most costly useful resource in our coaching setup — finds itself idle whereas it waits for information enter from overly tasked CPU assets.

A picture from the TensorBoard profiler tab demonstrating a typical footprint of a bottleneck on the information enter pipeline. We will clearly see lengthy durations of GPU idle time on each seventh coaching step. (By Writer)

In our first publish on the subject we mentioned and demonstrated other ways of addressing such a bottleneck, together with:

  1. Selecting a coaching occasion with a CPU to GPU compute ratio that’s extra suited to your workload,
  2. Enhancing the workload steadiness between the CPU and GPU by transferring a few of the CPU operations to the GPU, and
  3. Offloading a few of the CPU computation to auxiliary CPU-worker units.

We demonstrated the third possibility utilizing the TensorFlow Information Service API, an answer particular to TensorFlow, wherein a portion of the enter information processing could be offloaded onto different units utilizing gRPC because the underlying communication protocol.

In our second publish, we proposed a extra general-purpose gRPC-based resolution for utilizing auxiliary CPU staff and demonstrated it on a toy PyTorch mannequin. Though it required a bit extra guide coding and tuning than the TensorFlow Information Service API, the answer offered a lot better robustness and allowed for a similar optimization in coaching efficiency.

Load Balancing with Ray

On this publish we’ll show an extra methodology for utilizing auxiliary CPU staff that goals to mix the robustness of the general-purpose resolution with the simplicity and ease-of-use of the TensorFlow-specific API. The tactic we’ll show will use Ray Datasets from the Ray Information library. By leveraging the complete energy of Ray’s useful resource administration and distributed scheduling programs, Ray Information is ready to run our coaching information enter pipeline in method that’s each scalable and distributed. Specifically, we’ll configure our Ray Dataset in such a approach that the library will robotically detect and make the most of the entire obtainable CPU assets for pre-processing the coaching information. We are going to additional wrap our mannequin coaching loop with a Ray AIR Coach in order to allow seamless scaling to a multi-GPU setting.

Deploying a Ray Cluster on Amazon SageMaker

A prerequisite for utilizing the Ray framework and the utilities it gives in a multi-node atmosphere is the deployment of a Ray cluster. On the whole, designing, deploying, managing, and sustaining such a compute cluster generally is a daunting process and sometimes requires a devoted devops engineer (or crew of engineers). This will pose an insurmountable impediment for some improvement groups. On this publish we’ll show find out how to overcome this impediment utilizing AWS’s managed coaching service, Amazon SageMaker. Specifically, we’ll create a SageMaker heterogenous cluster with each GPU situations and CPU situations and use it to deploy a Ray cluster at startup. We are going to then run the Ray AIR coaching software on this Ray cluster whereas counting on Ray’s backend to carry out efficient load balancing throughout the entire assets within the cluster. When the coaching software is accomplished, the Ray cluster will probably be torn down robotically. Utilizing SageMaker on this method, allows us to deploy and use a Ray cluster with out the overhead that’s generally related to cluster administration.

Ray is a strong framework that permits a variety of machine studying workloads. On this publish we’ll show only a few of its capabilities and APIs utilizing Ray model 2.6.1. This publish shouldn’t be used as a alternative for the Ray documentation. Make sure you try the official documentation for probably the most acceptable and up-to-date use of the Ray utilities.

Earlier than we get began, particular due to Boruch Chalk for introducing me to the Ray Information library and its distinctive capabilities.

To facilitate our dialogue, we’ll outline and prepare a easy PyTorch (2.0) Imaginative and prescient Transformer-based classification mannequin that we are going to prepare on an artificial dataset comprised of random photographs and labels. The Ray AIR documentation contains all kinds of examples that show find out how to construct various kinds of coaching workloads utilizing Ray AIR. The script we create right here loosely follows the steps described within the PyTorch picture classifier instance.

Defining the Ray Dataset and Preprocessor

The Ray AIR Coach API distinguishes between the uncooked dataset and the preprocessing pipeline that’s utilized to the weather of the dataset earlier than feeding them into the coaching loop. For our uncooked Ray dataset we create a easy vary of integers of dimension num_records. Subsequent, we outline the Preprocessor that we want to apply to our dataset. Our Ray Preprocesser accommodates two elements: The primary is a BatchMapper that maps the uncooked integers to random image-label pairs. The second is a TorchVisionPreprocessor that performs a torchvision remodel on our random batches which converts them to PyTorch tensors and applies a sequence of GaussianBlur operations. The GaussianBlur operations are meant to simulate a comparatively heavy information pre-processing pipeline. The 2 Preprocessors are mixed utilizing a Chain Preprocessor. The creation of the Ray dataset and Preprocessor is demonstrated within the code block beneath:

import ray
from typing import Dict, Tuple
import numpy as np
import torchvision.transforms as transforms
from ray.information.preprocessors import Chain, BatchMapper, TorchVisionPreprocessor

def get_ds(batch_size, num_records):
# create a uncooked Ray tabular dataset
ds = ray.information.vary(num_records)

# map an integer to a random image-label pair
def synthetic_ds(batch: Tuple[int]) -> Dict[str, np.ndarray]:
labels = batch['id']
batch_size = len(labels)
photographs = np.random.randn(batch_size, 224, 224, 3).astype(np.float32)
labels = np.array([label % 1000 for label in labels]).astype(
return {"picture": photographs, "label": labels}

# step one of the prepocessor maps batches of ints to
# random image-label pairs
synthetic_data = BatchMapper(synthetic_ds,

# we outline a torchvision remodel that converts the numpy pairs to
# tensors after which applies a sequence of gaussian blurs to simulate
# heavy preprocessing
remodel = transforms.Compose(
[transforms.ToTensor()] + [transforms.GaussianBlur(11)]*10

# the second step of the prepocessor appplies the torchvision tranform
vision_preprocessor = TorchVisionPreprocessor(columns=["image"],

# mix the preprocessing steps
preprocessor = Chain(synthetic_data, vision_preprocessor)
return ds, preprocessor

Notice that the Ray information pipeline will robotically use the entire CPUs which might be obtainable within the Ray cluster. This contains the CPU assets which might be on the GPU occasion in addition to the CPU assets of any further auxiliary situations within the cluster.

Defining the Coaching Loop

The following step is to outline the coaching sequence that can run on every of the coaching staff (e.g., GPUs). First we outline the mannequin utilizing the favored timm (0.6.13) Python bundle and wrap it utilizing the prepare.torch.prepare_model API. Subsequent, we extract the suitable shard from the dataset and outline an iterator that yields information batches with the requested batch dimension and copies them to the coaching gadget. Then comes the coaching loop itself which is comprised of ordinary PyTorch code. After we exit the loop, we report again the resultant loss metric. The per-worker coaching sequence is demonstrated within the code block beneath:

import time
from ray import prepare
from ray.air import session
import torch.nn as nn
import torch.optim as optim
from timm.fashions.vision_transformer import VisionTransformer

# construct a ViT mannequin utilizing timm
def build_model():
return VisionTransformer()

# outline the coaching loop per employee
def train_loop_per_worker(config):
# wrap the PyTorch mannequin with a Ray object
mannequin = prepare.torch.prepare_model(build_model())
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(mannequin.parameters(), lr=0.001, momentum=0.9)

# get the suitable dataset shard
train_dataset_shard = session.get_dataset_shard("prepare")

# create an iterator that returns batches from the dataset
train_dataset_batches = train_dataset_shard.iter_torch_batches(

t0 = time.perf_counter()

for i, batch in enumerate(train_dataset_batches):
# get the inputs and labels
inputs, labels = batch["image"], batch["label"]

# zero the parameter gradients

# ahead + backward + optimize
outputs = mannequin(inputs)
loss = criterion(outputs, labels)

# print statistics
if i % 100 == 99: # print each 100 mini-batches
avg_time = (time.perf_counter()-t0)/100
print(f"Iteration {i+1}: avg time per step {avg_time:.3f}")
t0 = time.perf_counter()

metrics = dict(running_loss=loss.merchandise())

Defining the Ray Torch Coach

As soon as we’ve outlined our information pipeline and coaching loop, we are able to transfer on to establishing the Ray TorchTrainer. We configure the Coach in a fashion that takes under consideration the obtainable assets within the cluster. Particularly, we set the variety of coaching staff in line with the variety of GPUs and we set the batch dimension in line with the reminiscence obtainable on our goal GPU. We construct our dataset with the variety of information required to coach for exactly 1000 steps.

from ray.prepare.torch import TorchTrainer
from ray.air.config import ScalingConfig

def train_model():
# we'll configure the variety of staff, the dimensions of our
# dataset, and the dimensions of the information storage in line with the
# obtainable assets
num_gpus = int(ray.available_resources().get("GPU", 0))

# set the variety of coaching staff in line with the variety of GPUs
num_workers = num_gpus if num_gpus > 0 else 1

# we set the batch dimension primarily based on the GPU reminiscence capability of the
# Amazon EC2 g5 occasion household
batch_size = 64

# create an artificial dataset with sufficient information to coach for 1000 steps
num_records = batch_size * 1000 * num_workers
ds, preprocessor = get_ds(batch_size, num_records)

ds = preprocessor(ds)
coach = TorchTrainer(
train_loop_config={"batch_size": batch_size},
datasets={"prepare": ds},
use_gpu=num_gpus > 0),

Deploy a Ray Cluster and Run the Coaching Sequence

We now outline the entry level of our coaching script. It’s right here that we setup the Ray cluster and provoke the coaching sequence on the top node. We use the Atmosphere class from the sagemaker-training library to find the situations within the heterogenous SageMaker cluster as described on this tutorial. We outline the primary node of the GPU occasion group as our Ray cluster head node and run the suitable command on the entire different nodes to attach them to the cluster. (See the Ray documentation for extra particulars on creating clusters.) We program the top node to attend till all of the nodes have related after which begin the coaching sequence. This ensures that Ray will make the most of the entire obtainable assets when defining and distributing the underlying Ray duties.

import time
import subprocess
from sagemaker_training import atmosphere

if __name__ == "__main__":
# use the Atmosphere() class to auto-discover the SageMaker cluster
env = atmosphere.Atmosphere()
if env.current_instance_group == 'gpu' and
env.current_instance_group_hosts.index(env.current_host) == 0:
# the top node begins a ray cluster
p = subprocess.Popen('ray begin --head --port=6379',

# calculate the entire variety of nodes within the cluster
teams = env.instance_groups_dict.values()
cluster_size = sum(len(v['hosts']) for v in checklist(teams))

# wait till all SageMaker nodes have related to the Ray cluster
connected_nodes = 1
whereas connected_nodes < cluster_size:
assets = ray.available_resources().keys()
connected_nodes = sum(1 for s in checklist(assets) if 'node' in s)

# name the coaching sequence

# tear down the ray cluster
p = subprocess.Popen("ray down", shell=True).wait()
# employee nodes connect to the top node
head = env.instance_groups_dict['gpu']['hosts'][0]
p = subprocess.Popen(
f"ray begin --address='{head}:6379'",

# utility for checking if the cluster continues to be alive
def is_alive():
from subprocess import Popen
p = Popen('ray standing', shell=True)[0]
return p.returncode

# preserve node alive till the method on head node completes
whereas is_alive() == 0:

Coaching on an Amazon SageMaker Heterogenous Cluster

With our coaching script full, we at the moment are tasked with deploying it to an Amazon SageMaker Heterogenous Cluster. To do that we comply with the steps described on this tutorial. We begin by making a source_dir listing into which we place the our script and a necessities.txt file containing the 2 pip packages our script is determined by, timm and ray[air]. These are robotically put in on every of the nodes within the SageMaker cluster. We outline two SageMaker Occasion Teams, the primary with a single ml.g5.xlarge occasion (containing 1 GPU and 4 vCPUs), and the second with a single ml.c5.4xlarge occasion (containing 16 vCPUs). We then use the SageMaker PyTorch estimator to outline and deploy our coaching job to the cloud.

from sagemaker.pytorch import PyTorch
from sagemaker.instance_group import InstanceGroup
cpu_group = InstanceGroup("cpu", "ml.c5.4xlarge", 1)
gpu_group = InstanceGroup("gpu", "ml.g5.xlarge", 1)

estimator = PyTorch(
position='<arn position>',
instance_groups=[gpu_group, cpu_group]


Within the desk beneath we examine the runtime outcomes of operating our coaching script in two totally different settings: a single ml.g5.xlarge GPU occasion and a heterogenous cluster containing an ml.g5.xlarge occasion and an ml.c5.4xlarge. We consider the system useful resource utilization utilizing Amazon CloudWatch and estimate the coaching value utilizing the Amazon SageMaker pricing obtainable as of the time of this writing ($0.816 per hour for the ml.c5.4xlarge occasion and $1.408 for the ml.g5.xlarge).

Comparative Efficiency Outcomes (By Writer)

The comparatively excessive CPU utilization mixed with the low GPU utilization of the only occasion experiment signifies a efficiency bottleneck within the information pre-processing pipeline. These are clearly addressed when transferring to the heterogenous cluster. Not solely does the GPU utilization improve, however so does the coaching velocity. General, the value effectivity of coaching will increase by 23%.

We must always emphasize that these toy experiments have been created purely for the aim of demonstrating the automated load balancing options enabled by the Ray ecosystem. It’s potential that tuning of the management parameters could have led to improved efficiency. Additionally it is probably that selecting a special resolution for addressing the CPU bottleneck (similar to selecting an occasion from the EC2 g5 household with extra CPUs) could have resulted in higher value efficiency.

On this publish we have now demonstrated how Ray datasets can be utilized to steadiness the load of a heavy information pre-processing pipeline throughout the entire obtainable CPU staff within the cluster. This allows us to simply deal with CPU bottlenecks by merely including auxiliary CPU situations to the coaching atmosphere. Amazon SageMaker’s heterogenous cluster assist is a compelling strategy to run a Ray coaching job within the cloud because it handles all sides of the cluster administration avoiding the necessity for devoted devops assist.

Remember that the answer introduced right here is only one of many alternative methods of addressing CPU bottlenecks. One of the best resolution for you’ll extremely depend upon the main points of your challenge.

As standard, please be happy to achieve out with feedback, corrections, and questions.

Supply hyperlink

More articles


Please enter your comment!
Please enter your name here

Latest article