Distributed Training
Distributed training scales models across multiple GPUs or machines. TensorFlow ships several strategies: MirroredStrategy for single-host multi-GPU, MultiWorkerMirroredStrategy for multi-host, TPUStrategy for TPU pods, and ParameterServerStrategy for asynchronous training. Pick the smallest that solves your problem.
Single-host multi-GPU + multi-host distributed training
EXAMPLE
import tensorflow as tf
import os
import json
# ============================================================
# 1) Single host, multiple GPUs — MirroredStrategy
# ============================================================
# Each GPU has a replica of the model. Gradients are AllReduced
# across replicas after each batch. Effectively scales batch size
# by num_gpus; tune learning rate accordingly.
strategy = tf.distribute.MirroredStrategy()
print('replicas:', strategy.num_replicas_in_sync)
GLOBAL_BATCH = 256 * strategy.num_replicas_in_sync
ds = (tf.data.Dataset.from_tensor_slices((tf.random.normal((50_000, 32)),
tf.random.uniform((50_000,), 0, 10, dtype=tf.int32)))
.shuffle(10_000)
.batch(GLOBAL_BATCH)
.prefetch(tf.data.AUTOTUNE))
with strategy.scope():
model = tf.keras.Sequential([
tf.keras.layers.Input(shape=(32,)),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(10),
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
model.fit(ds, epochs=3)
# ============================================================
# 2) Multi-host — MultiWorkerMirroredStrategy
# ============================================================
# Each worker runs the SAME script and reads its rank from TF_CONFIG.
# Launch via your scheduler (k8s Job, SLURM, Ray, Vertex AI Training).
# Example TF_CONFIG (on worker 0):
# {
# "cluster": { "worker": ["w0:12345", "w1:12345"] },
# "task": { "type": "worker", "index": 0 }
# }
os.environ['TF_CONFIG'] = json.dumps({
'cluster': {'worker': ['w0:12345', 'w1:12345']},
'task': {'type': 'worker', 'index': 0},
})
mw_strategy = tf.distribute.MultiWorkerMirroredStrategy()
# Sharded dataset — each worker reads its own slice
options = tf.data.Options()
options.experimental_distribute.auto_shard_policy = tf.data.experimental.AutoShardPolicy.DATA
ds = ds.with_options(options)
with mw_strategy.scope():
model = tf.keras.Sequential([
tf.keras.layers.Input(shape=(32,)),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(10),
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
model.fit(ds, epochs=3,
callbacks=[
tf.keras.callbacks.BackupAndRestore('./bk/'), # survive worker restarts
tf.keras.callbacks.TensorBoard('./logs/mw'),
])
# Save the model from ONE worker only (worker 0); writing the same file
# from every worker will corrupt the checkpoint.
if json.loads(os.environ['TF_CONFIG'])['task']['index'] == 0:
model.save('/checkpoints/distributed.keras')
# ============================================================
# 3) TPU — TPUStrategy
# ============================================================
# resolver = tf.distribute.cluster_resolver.TPUClusterResolver(tpu='local')
# tf.config.experimental_connect_to_cluster(resolver)
# tf.tpu.experimental.initialize_tpu_system(resolver)
# strategy = tf.distribute.TPUStrategy(resolver)
# ============================================================
# 4) Common pitfalls
# ============================================================
# - global_batch_size vs per_replica_batch_size: confusing both is the #1 bug.
# - learning rate that worked for 1 GPU underperforms at 8; warm up + linear scale.
# - tf.data input pipeline cannot keep the GPUs fed -> use AUTOTUNE, prefetch, cache.
# - Mixed precision: with strategy.scope(): tf.keras.mixed_precision.set_global_policy('mixed_bfloat16')
# gives 2x speed on TPUs and recent GPUs without code changes.
# - Logging metrics: aggregate via strategy.experimental_local_results then average.
Why it matters
For a single host with 1–8 GPUs, MirroredStrategy is almost always the right pick — one line of code, no orchestration, near-linear scaling. Reach for MultiWorkerMirrored or TPU only when one host stops being enough; the operational cost climbs sharply and so does the chance of subtle bugs (sharding, batch normalisation across hosts, checkpoint races).
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
strategy = tf.distribute.MirroredStrategy()
with strategy.scope():
model = build_model()
model.compile(...)
model.fit(...) # automatically sharded across GPUs
Try it Yourself »
Discussion
Loading…