Advanced GPU Workflows
Last updated on 2026-08-24 | Edit this page
Overview
Questions
- How do I monitor GPU utilization?
- How do I write PyTorch and TensorFlow GPU code?
- How do I run multi-GPU training?
- How do I troubleshoot GPU errors?
Objectives
- Monitor GPU utilization with
nvidia-smi - Write GPU-aware code in PyTorch and TensorFlow
- Submit multi-GPU training jobs
- Troubleshoot common GPU errors (CUDA OOM, GPU not detected)
Monitoring GPU Usage
nvidia-smi
From a terminal on the GPU node:
BASH
nvidia-smi # One-time snapshot
watch -n 5 nvidia-smi # Update every 5 seconds
nvidia-smi dmon # Continuous monitoring
Key metrics:
- GPU-Util: Should be above 80% for well-utilized GPU jobs
- Memory-Usage: How much of GPU memory is consumed
- Power: Higher power = busier GPU
GPU Code Examples
Multi-GPU Training
BASH
#!/bin/bash -l
#SBATCH --job-name=dist_train
#SBATCH --partition=gpu
#SBATCH --gres=gpu:2
#SBATCH --cpus-per-task=16
#SBATCH --mem=128G
#SBATCH --time=12:00:00
module load cuda miniconda3
python -m torch.distributed.launch \
--nproc_per_node=2 \
train_distributed.py
Request only multiple GPUs if your code actually supports distributed training.
Troubleshooting GPU Errors
Low GPU Utilization
Causes: data loading bottleneck, code not on GPU, small batch size.
Fixes:
- Add parallel data loading (
num_workersin PyTorch DataLoader) - Verify
.to(device)or.cuda()in your code - Increase batch size if GPU memory allows
- If utilization stays low, use CPU instead
Job Killed for Exceeding Memory
GPU jobs have both CPU RAM and GPU memory limits:
Challenge 1: GPU Benchmark
Create a script that benchmarks GPU vs CPU matrix multiplication:
BASH
#!/bin/bash -l
#SBATCH --job-name=gpu_bench
#SBATCH --partition=gpu
#SBATCH --gres=gpu:1
#SBATCH --cpus-per-task=2
#SBATCH --mem=16G
#SBATCH --time=00:10:00
#SBATCH --output=bench_%j.out
module load cuda miniconda3
python << 'EOF'
import torch, time
size = 10000
x_gpu = torch.randn(size, size).cuda()
y_gpu = torch.randn(size, size).cuda()
torch.cuda.synchronize()
start = time.time()
z = torch.mm(x_gpu, y_gpu)
torch.cuda.synchronize()
gpu_time = time.time() - start
x_cpu = x_gpu.cpu(); y_cpu = y_gpu.cpu()
start = time.time()
z_cpu = torch.mm(x_cpu, y_cpu)
cpu_time = time.time() - start
print(f"GPU: {gpu_time:.4f}s, CPU: {cpu_time:.4f}s, Speedup: {cpu_time/gpu_time:.1f}x")
EOF
Submit and compare the GPU vs CPU times.
The GPU should be significantly faster for large matrix multiplication (often 10-100x). The exact speedup depends on the GPU type and matrix size. This demonstrates why GPU acceleration matters for linear algebra and deep learning workloads.
- Monitor GPU utilization with
nvidia-smi; aim for over 80% GPU-Util - PyTorch uses
.to(device)or.cuda(); TensorFlow auto-places on GPU - Multi-GPU training requires both
--gres=gpu:2and distributed training code - CUDA OOM: reduce batch size or request a larger GPU (A100 has 80 GB)
- GPU not detected: check
--gres,module load cuda, and partition selection - Low utilization often means a CPU data-loading bottleneck or undersized batches