how to run tensorflow distributed mnist example
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Running the TensorFlow MNIST example in distributed mode usually means using tf.distribute so the same model trains across multiple devices or workers. The simplest entry point is MirroredStrategy on one machine with multiple GPUs, then MultiWorkerMirroredStrategy if you want the same pattern across several machines.
Start with the Single-Machine Distributed Pattern
For local distributed training, TensorFlow’s normal pattern is:
- create a distribution strategy
- build the model inside the strategy scope
- feed a batched dataset into
model.fit
MNIST is a good fit because the dataset is small and already packaged with Keras:
If multiple GPUs are visible on the same machine, MirroredStrategy replicates the model on each one and reduces gradients automatically.
Build the Model Inside strategy.scope()
This is the most important structural rule. Variables, optimizer state, and model weights should be created inside the distribution scope so TensorFlow knows how to mirror or shard them correctly.
If you create the model outside the scope and then try to train under a strategy, you can end up with placement errors or unexpectedly non-distributed variables.
Understand the Batch Size Rule
With distribution strategies, the batch size you pass to the dataset is usually the global batch size, not the per-device batch size. TensorFlow splits that batch across the replicas.
For example, with two GPUs and global_batch_size = 256, each replica processes 128 examples per step. If you accidentally treat 256 as per replica and scale again, the effective batch size becomes much larger than intended and training dynamics change.
That matters even for MNIST, because optimizers and learning rates are sensitive to batch size.
Multi-Worker Training Uses the Same Model Code
If you move from one machine to multiple workers, the model code can stay almost the same. The main extra step is setting TF_CONFIG so each process knows the cluster layout:
Then in Python:
Everything else still follows the same broad idea: build inside the scope, feed datasets, call fit.
Make the Input Pipeline Efficient
The MNIST example is small enough that data loading is rarely the bottleneck, but the habit still matters. A good distributed input pipeline should:
- batch after shuffling
- prefetch data
- avoid unnecessary Python work during training
That is why prefetch(tf.data.AUTOTUNE) is present in the example. The data pipeline stays out of the way while the devices train.
Common Pitfalls
The most common mistake is building the model or optimizer outside strategy.scope(). That breaks the variable-placement assumptions of the distribution API.
Another pitfall is confusing global batch size with per-replica batch size. The number you batch in the dataset is usually the total batch seen across all replicas together.
It is also easy to expect MirroredStrategy to distribute work without actual multiple visible devices. If TensorFlow sees only a CPU or one GPU, the code still runs, but the “distributed” effect is limited.
Finally, multi-worker training fails quickly if TF_CONFIG is inconsistent across workers. When moving beyond one machine, cluster configuration becomes just as important as model code.
Summary
- Use
MirroredStrategyfor one machine with multiple GPUs andMultiWorkerMirroredStrategyfor multiple workers. - Build the model and optimizer inside
strategy.scope(). - Treat the dataset batch size as the global batch size unless you are doing something custom.
- Use a batched, prefetched
tf.datapipeline even for simple MNIST examples. - For multi-worker runs, correct
TF_CONFIGis part of the setup, not an optional extra.

