Keras
GPU
Machine Learning
Deep Learning
Parallel Processing

How to run multiple keras programs on single gpu?

Master System Design with Codemia

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

Introduction

Yes, you can run multiple Keras programs on a single GPU, but only if the processes cooperate on memory usage. The real limit is usually TensorFlow's default GPU allocation behavior, not a hard rule inside Keras itself.

If each program tries to reserve the whole device, the second process will fail even when the first job is only lightly loaded. The fix is to control memory allocation and accept that shared execution trades isolation for flexibility.

Why Multiple Processes Fail By Default

Most Keras programs today run on top of TensorFlow. By default, TensorFlow may reserve a large amount of GPU memory as soon as the runtime starts. That behavior is convenient for a single training job, but it is a problem if you want two or more Python processes to coexist on the same card.

The usual failure mode is simple:

  • process A starts first and reserves most of the VRAM
  • process B starts second and crashes with an out-of-memory error

That does not necessarily mean the GPU lacks total capacity for both jobs. It often means the first program claimed memory too aggressively.

Enable Memory Growth

The most common solution is enabling memory growth. That tells TensorFlow to allocate GPU memory gradually instead of reserving everything up front.

python
1import tensorflow as tf
2
3gpus = tf.config.list_physical_devices("GPU")
4if gpus:
5    tf.config.experimental.set_memory_growth(gpus[0], True)
6
7model = tf.keras.Sequential([
8    tf.keras.layers.Input(shape=(20,)),
9    tf.keras.layers.Dense(64, activation="relu"),
10    tf.keras.layers.Dense(1)
11])
12
13model.compile(optimizer="adam", loss="mse")

This configuration must happen before TensorFlow initializes the GPU in earnest. If tensors or models are created first, changing the GPU policy later will usually fail.

Memory growth is the least disruptive option because it lets each process consume only what it needs. It does not guarantee fairness, though. One job can still grow until the other has no room left.

Cap Memory Per Process

If you need stronger boundaries, set a per-process memory cap. This is useful when you know roughly how much VRAM each training job should consume.

python
1import tensorflow as tf
2
3gpus = tf.config.list_physical_devices("GPU")
4if gpus:
5    tf.config.set_logical_device_configuration(
6        gpus[0],
7        [tf.config.LogicalDeviceConfiguration(memory_limit=8192)]
8    )
9
10print(tf.config.list_logical_devices("GPU"))

In that example, the current process gets an 8 GB budget. A second process can start with its own limit as long as the combined limits and runtime overhead still fit on the device.

Separate Processes And Target The Same GPU

If the goal is to run separate Keras programs, launch them as separate operating system processes. Each script should configure GPU behavior near startup.

bash
CUDA_VISIBLE_DEVICES=0 python train_model_a.py
CUDA_VISIBLE_DEVICES=0 python train_model_b.py

That environment variable makes both processes use GPU 0. If the machine has several GPUs and you omit the variable, the programs may choose different visible devices depending on the runtime and host setup.

Sharing Does Not Always Improve Throughput

Running two jobs at once is not automatically faster. If both models are large and GPU-bound, they fight over the same compute units, memory bandwidth, and scheduler time. In that situation, wall-clock time per job often increases.

Shared execution is most useful when:

  • each job is relatively small
  • one job spends part of its time on input or preprocessing
  • you are running short experiments rather than long full-capacity training runs

If each model already saturates the card, queueing jobs sequentially is often more efficient.

Minimal Runnable Example

This script is small enough to test the setup quickly:

python
1import numpy as np
2import tensorflow as tf
3
4gpus = tf.config.list_physical_devices("GPU")
5if gpus:
6    tf.config.experimental.set_memory_growth(gpus[0], True)
7
8x = np.random.rand(1024, 20).astype("float32")
9y = np.random.rand(1024, 1).astype("float32")
10
11model = tf.keras.Sequential([
12    tf.keras.layers.Input(shape=(20,)),
13    tf.keras.layers.Dense(32, activation="relu"),
14    tf.keras.layers.Dense(1)
15])
16
17model.compile(optimizer="adam", loss="mse")
18model.fit(x, y, epochs=3, batch_size=32)

Launch two copies and watch nvidia-smi to confirm that both are using the same card without exhausting VRAM.

Common Pitfalls

  • Configuring memory growth after TensorFlow has already initialized the GPU.
  • Assuming two concurrent jobs will finish sooner than one queued job.
  • Forgetting that a memory cap solves VRAM contention, not compute contention.
  • Running two large models that each need nearly the full device.
  • Treating one multi-model script as equivalent to truly separate Keras programs.

Summary

  • Multiple Keras programs can share a single GPU if total memory and compute demand fit.
  • TensorFlow memory growth is the first setting to try for shared execution.
  • Per-process memory limits provide stronger isolation when needed.
  • Use separate processes and CUDA_VISIBLE_DEVICES to target the same GPU deliberately.
  • Measure real throughput, because concurrency can make each job slower on a saturated card.

Course illustration
Course illustration

All Rights Reserved.