SageMaker V3 Instance Preferences (Multi-Instance-Type) Example#
Instead of one fixed instance_type, a training job can name an ordered list of up to 5
acceptable instance types. SageMaker launches the job on the first candidate with
available capacity, so a busy first choice no longer means resubmitting.
Step 1: Setup Session#
Initialize the SageMaker session, execution role, and a training image.
The image is fixed at submission time while the instance type is not, so resolve it from one of the candidate types you will list in Step 2 and make sure every candidate can run it. Here both candidates are GPU types and share the same GPU image.
from sagemaker.core.helper.session_helper import Session, get_execution_role
from sagemaker.core import image_uris
from sagemaker.core.shapes import InstancePreference
from sagemaker.train.model_trainer import ModelTrainer
from sagemaker.core.training.configs import Compute, InputData, OutputDataConfig
sagemaker_session = Session()
role = get_execution_role()
region = sagemaker_session.boto_region_name
bucket = sagemaker_session.default_bucket()
training_image = image_uris.retrieve(
framework="pytorch",
region=region,
version="2.0.0",
py_version="py310",
instance_type="ml.p5.48xlarge", # a Step 2 candidate; ml.p4d.24xlarge resolves to the same image
image_scope="training",
)
Step 2: Train with an ordered list of instance preferences#
The job asks for ml.p5.48xlarge first and falls back to ml.p4d.24xlarge if p5
capacity is unavailable. The top-level instance_count=2 applies to whichever type wins.
Leave the classic instance_type field unset — it is mutually exclusive with the
preference list.
compute = Compute(
instance_preferences=[
InstancePreference(instance_type="ml.p5.48xlarge"), # priority 1
InstancePreference(instance_type="ml.p4d.24xlarge"), # priority 2 (fallback)
],
instance_count=2, # applies to whichever preference wins
volume_size_in_gb=500,
)
trainer = ModelTrainer(
base_job_name="instance-prefs-example",
training_image=training_image,
role=role,
compute=compute,
output_data_config=OutputDataConfig(
s3_output_path=f"s3://{bucket}/instance-preferences-example/output"
),
)
trainer.train(
input_data_config=[
InputData(
channel_name="train",
data_source=f"s3://{bucket}/instance-preferences-example/input",
)
],
wait=False,
)
training_job = trainer._latest_training_job
print(f"Started: {training_job.training_job_name}")
Step 3: Find out which instance type actually ran#
The submitted list is a set of candidates, not the outcome. Once a type is selected, the
job reports it in the read-only selected_instance_type / selected_instance_count fields;
the top-level instance_type you never set stays empty.
training_job.refresh()
rc = training_job.resource_config
print(f"Status: {training_job.training_job_status}")
print(f"Submitted preferences: {[p.instance_type for p in rc.instance_preferences]}")
print(f"Selected instance type: {rc.selected_instance_type}") # None until selected
print(f"Selected instance count: {rc.selected_instance_count}") # None until selected
Step 4: Per-preference instance counts#
When candidate types have different sizes, give every element its own instance_count
and leave the top-level count unset. Counts go one way or the other — never both, never only
some elements.
per_preference_compute = Compute(
instance_preferences=[
# 2 of the larger type...
InstancePreference(instance_type="ml.p5.48xlarge", instance_count=2),
# ...or 4 of the smaller type
InstancePreference(instance_type="ml.p4d.24xlarge", instance_count=4),
],
volume_size_in_gb=500,
)
Step 5: Per-preference training plans (reserved capacity)#
A preference with a training plan draws from that plan’s reserved capacity, and one without
falls back to on-demand — the job starts on whichever has capacity first. Each plan’s
instance type must match its preference, one plan per preference, and per-preference
training_plan_arns is mutually exclusive with the whole-job training_plan_arn (which
instead applies to whichever preference matches its type).
p5_plan_arn = f"arn:aws:sagemaker:{region}:<ACCOUNT_ID>:training-plan/<P5_PLAN_NAME>"
p4d_plan_arn = f"arn:aws:sagemaker:{region}:<ACCOUNT_ID>:training-plan/<P4D_PLAN_NAME>"
plan_backed_compute = Compute(
instance_preferences=[
InstancePreference(
instance_type="ml.p5.48xlarge",
training_plan_arns=[p5_plan_arn],
),
InstancePreference(
instance_type="ml.p4d.24xlarge",
training_plan_arns=[p4d_plan_arn],
),
InstancePreference(instance_type="ml.p4de.24xlarge"), # on-demand fallback
],
instance_count=2,
)
Notes#
Backward compatible: jobs that don’t set
instance_preferencesbehave exactly as before.Not supported with: local mode, training recipes, JumpStart models, AWS Batch training queues, heterogeneous clusters (
instance_groups),instance_placement_config, and managed spot training.Selection is based on capacity, not on workload fit: cross-type differences such as architecture or GPU memory are not validated, so list only types your job can run on.
max_pending_time_in_secondsbounds the total time spent working through the list rather than each preference, and takes effect only when the list includes an accelerated instance type (ml.p,ml.g,ml.trn).Billing is based on the selected instance type and count.
Processing jobs support the same feature: see the processing example.