NVIDIA
GPU Usage
Keras
TensorFlow
Machine Learning

Low NVIDIA GPU Usage with Keras and Tensorflow

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Low GPU utilization in TensorFlow and Keras is usually a pipeline problem, not a GPU defect. If data loading, augmentation, or small batch execution cannot keep up, the GPU waits idle even though model code is correct. This guide shows a practical path to diagnose and improve utilization systematically.

Core Topic Sections

Confirm TensorFlow sees the GPU

Start with basic visibility checks before tuning.

python
1import tensorflow as tf
2
3print("TensorFlow:", tf.__version__)
4print("GPUs:", tf.config.list_physical_devices("GPU"))

If no GPU is listed, utilization tuning is irrelevant until CUDA and driver alignment are fixed.

Measure utilization and bottleneck location

Use runtime tools to observe where time is spent.

  1. nvidia-smi for utilization and memory patterns.
  2. TensorFlow profiler for input pipeline versus kernel execution.
  3. Step time tracking in training logs.

Quick loop while training:

bash
watch -n 1 nvidia-smi

If utilization spikes briefly then drops, input pipeline starvation is likely.

Optimize tf.data input pipeline

Many low-usage cases are solved by parallel map and prefetch.

python
1import tensorflow as tf
2
3
4def preprocess(x, y):
5    x = tf.cast(x, tf.float32) / 255.0
6    return x, y
7
8train_ds = tf.keras.datasets.mnist.load_data()
9(x_train, y_train), _ = train_ds
10
11ds = tf.data.Dataset.from_tensor_slices((x_train, y_train))
12ds = ds.shuffle(10000)
13ds = ds.map(preprocess, num_parallel_calls=tf.data.AUTOTUNE)
14ds = ds.batch(256)
15ds = ds.prefetch(tf.data.AUTOTUNE)

Prefetch overlaps CPU data work with GPU compute and often improves steady utilization quickly.

Increase workload per step carefully

Very small batches or tiny models may not generate enough GPU work.

Tuning direction:

  1. Increase batch size until memory limit approaches safe range.
  2. Use larger input resolution only if it matches task goals.
  3. Avoid unnecessarily frequent logging or callback overhead.

Larger batches can increase throughput but may affect optimization dynamics, so validate model quality after changes.

Enable mixed precision on supported GPUs

On modern NVIDIA hardware, mixed precision can improve throughput.

python
1import tensorflow as tf
2from tensorflow.keras import mixed_precision
3
4mixed_precision.set_global_policy("mixed_float16")
5
6model = tf.keras.Sequential([
7    tf.keras.layers.Input(shape=(28, 28)),
8    tf.keras.layers.Flatten(),
9    tf.keras.layers.Dense(512, activation="relu"),
10    tf.keras.layers.Dense(10, activation="softmax", dtype="float32")
11])

Keep final output layer in float32 for numerical stability in many classification setups.

Reduce host-side overhead

If Python code in training loop is heavy, GPU waits.

Common issues:

  1. Expensive Python preprocessing outside tf.data graph.
  2. Data read from slow disks without caching.
  3. Synchronous augmentations on CPU per step.

Move deterministic transforms into tf.data map and cache where appropriate.

Check CPU and storage constraints

A weak CPU or slow network storage can cap GPU usage. When data source is remote:

  1. Stage datasets on local SSD.
  2. Increase worker parallelism in data loader.
  3. Use compressed formats that decode efficiently.

GPU tuning without input throughput improvements often has little effect.

Multi-GPU and distribution considerations

For multi-GPU training, imbalance can reduce average utilization. Ensure consistent shard sizes and avoid tiny per-replica batches.

If synchronization overhead dominates, scaling may flatten or regress. Measure global throughput, not just individual device percentages.

Validate improvements with controlled experiments

After each change, record:

  1. Samples per second.
  2. Mean step time.
  3. GPU utilization trend.
  4. Validation metric impact.

This prevents tuning choices that look faster but hurt model quality.

Common Pitfalls

  • Tuning CUDA flags before confirming the real bottleneck is input starvation.
  • Using tiny batch sizes that do not create enough GPU work per step.
  • Running heavy Python preprocessing outside optimized tf.data pipelines.
  • Interpreting short utilization spikes as healthy sustained throughput.
  • Ignoring model quality changes after throughput-focused tuning.

Summary

  • Low GPU usage is usually caused by data and scheduling bottlenecks.
  • Verify GPU visibility first, then profile input pipeline and step timing.
  • Optimize tf.data, batch size, and mixed precision where hardware supports it.
  • Reduce CPU and storage bottlenecks that starve device kernels.
  • Measure throughput and model quality together for reliable optimization.

Course illustration
Course illustration

All Rights Reserved.