Debugging and Profiling Tools Taught in Phase 0: Complete AI Debugging Toolkit
Phase 0 of the AI Engineering from Scratch curriculum teaches a five-layer debugging strategy spanning Python fundamentals, CPU profiling, GPU memory management, visualization tools, and AI-specific sanity checks to diagnose NaN losses, shape mismatches, and memory leaks before they corrupt experiments.
The rohitg00/ai-engineering-from-scratch repository dedicates its Phase 0 "Setup & Tooling" module to debugging and profiling tools essential for production AI workflows. Mastering these utilities early prevents the silent failures—such as undetected NaN gradients or device mismatches—that commonly waste compute resources in deep learning experiments. All implementations reside in phases/00-setup-and-tooling/12-debugging-and-profiling/code/debug_tools.py, providing copy-paste-ready utilities for immediate use.
Python Debugging Fundamentals
Phase 0 begins with core Python debugging techniques before introducing AI-specific tooling. These foundations enable developers to inspect variables and control flow in any training script.
Interactive Debugging with breakpoint() and pdb
The curriculum emphasizes breakpoint() (Python 3.7+) and the pdb module for interactive inspection. In debug_tools.py (line 55‑65), learners implement tactical pauses to examine tensor values, shapes, and devices mid-execution. This allows real-time verification of data integrity before silent corruption propagates through the model.
Structured Logging and Custom Utilities
For non-interactive monitoring, the logging module provides timestamped output with severity levels (INFO/WARN/ERROR) as shown in debug_tools.py (line 84‑100). Complementing this is a custom debug_print helper (line 42‑48) that prints a tensor’s shape, dtype, device, min/max/mean statistics, and NaN status in a single line.
def debug_print(name, tensor):
print(
f"{name}: shape={tensor.shape}, dtype={tensor.dtype}, "
f"device={tensor.device}, min={tensor.min():.4f}, "
f"max={tensor.max():.4f}, mean={tensor.mean():.4f}, "
f"has_nan={tensor.isnan().any()}"
)
Performance Timing with Context Managers
The Timer class in debug_tools.py (line 11‑22) measures elapsed time for arbitrary code blocks using time.perf_counter(). This context manager wraps data loading or forward passes to identify bottlenecks without external dependencies.
class Timer:
def __init__(self, name=""):
self.name = name
def __enter__(self):
self.start = time.perf_counter()
return self
def __exit__(self, *exc):
elapsed = time.perf_counter() - self.start
print(f"[{self.name}] {elapsed:.4f}s")
CPU Profiling and Memory Tracking
Once basic debugging is mastered, Phase 0 introduces systematic profiling to locate performance bottlenecks and memory leaks in Python code.
Whole-Program Profiling with cProfile
The cProfile module provides function-level timing statistics sorted by cumulative time. As implemented in debug_tools.py (line 39‑41), developers run:
python -m cProfile -s cumtime train.py
This reveals which functions consume the most execution time across the entire training pipeline.
Line-by-Line Analysis
For granular inspection, the curriculum covers line_profiler using the @profile decorator (line 49‑56). This tool reports per-line execution times for targeted functions, essential when optimizing hot loops in data loaders or custom loss functions.
@profile
def train_step(model, data, target):
out = model(data)
loss = F.cross_entropy(out, target)
loss.backward()
return loss
Execute with kernprof -l -v train.py to view line-level statistics.
Memory Allocation Tracking
Two tools track RAM usage: tracemalloc captures Python-level allocations and reports the hottest source lines (line 64‑71), while memory_profiler (line 81‑89) displays per-line RAM consumption via the @profile decorator. The tracemalloc implementation starts before training and snapshots peak usage:
tracemalloc.start()
# …run training…
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')
for stat in top_stats[:10]:
print(stat)
GPU Memory Management and Debugging
AI-specific debugging requires monitoring GPU memory to prevent out-of-memory (OOM) crashes during large batch training.
PyTorch CUDA Memory Inspection
debug_tools.py (line 98‑104) demonstrates torch.cuda.memory_summary(), which prints a concise snapshot of GPU memory usage, allocations, and fragmentation. Complementary numeric queries (line 106‑108) provide exact GB totals:
if torch.cuda.is_available():
print(torch.cuda.memory_summary())
print(f"Allocated: {torch.cuda.memory_allocated()/1e9:.2f} GB")
print(f"Cached: {torch.cuda.memory_reserved()/1e9:.2f} GB")
Cache Management and Mixed Precision
When memory pressure peaks, torch.cuda.empty_cache() (line 110‑112) clears the PyTorch CUDA cache to recover memory after large tensors are freed. The curriculum also references torch.cuda.amp for automatic mixed precision (line 112‑115), which halves GPU memory consumption while preserving numerical stability.
Visualization and IDE Integration
Modern debugging extends beyond print statements to graphical monitoring and integrated development environments.
Real-Time Monitoring with TensorBoard
The curriculum integrates TensorBoard for real-time plotting of loss curves, learning rates, weight histograms, and gradient distributions. The implementation in debug_tools.py (line 122‑140) uses SummaryWriter to stream metrics during training:
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter("runs/exp1")
for step in range(num_steps):
loss = train_step(model, batch)
writer.add_scalar("loss/train", loss.item(), step)
writer.add_scalar("lr", optimizer.param_groups[0]["lr"], step)
writer.close()
Launch the dashboard with tensorboard --logdir=runs.
VS Code Debugger Configuration
For deep inspection, Phase 0 includes a VS Code Debugger configuration (line 144‑162). The launch.json setup enables full IDE debugging with breakpoints, variable inspection, and a Debug Console for live tensor queries:
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Training",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": false
}
]
}
AI-Specific Sanity Checks
Phase 0 culminates with utilities designed specifically for neural network validation, catching AI-specific failures that standard debuggers miss.
Shape and Device Verification
The check_shapes helper (line 166‑186) registers forward hooks to print each module’s input/output shapes for a sample batch, catching dimension mismatches before training begins. The check_devices helper (line 220‑229) verifies that all tensors share the same device as the model, warning on silent CPU/GPU mismatches that crash training mid-epoch.
Numerical Stability and Data Integrity
To detect gradient explosions, detect_nan (line 188‑206) propagates NaN loss values back to the offending layer. For dataset validation, check_data_leakage (line 208‑218) identifies overlapping samples between train and test sets or temporal leakage in time-series data.
The Five-Layer Debugging Workflow
According to the rohitg00/ai-engineering-from-scratch source code, these tools form a sequential workflow:
- Pre-training sanity checks – Run
check_shapeson a dummy batch to confirm model I/O dimensions. - Early-training monitoring – Insert
debug_printand conditionalbreakpoint()to stop on abnormal loss values. - Logging and profiling – Switch to
logging, enablecProfileorline_profiler, and capture memory withtracemallocormemory_profiler. - GPU health monitoring – Watch
torch.cuda.memory_summary()and proactively free cache or enable mixed precision. - Visualization and deep inspection – Feed metrics to TensorBoard and use the VS Code debugger when manual intervention is required.
Summary
- Python fundamentals (
breakpoint(),logging,Timer) provide immediate variable inspection and timing for any script. - CPU profiling (
cProfile,line_profiler,tracemalloc) identifies runtime bottlenecks and memory leaks at function and line levels. - GPU tooling (
torch.cuda.memory_summary(),empty_cache(), AMP) prevents OOM errors and optimizes VRAM usage. - Visualization (TensorBoard, VS Code Debugger) enables real-time metric tracking and interactive debugging.
- AI-specific checks (
check_shapes,detect_nan,check_data_leakage) catch neural network-specific failures like shape mismatches and NaN gradients.
Frequently Asked Questions
What is the primary debugging file in Phase 0?
The main implementation resides in phases/00-setup-and-tooling/12-debugging-and-profiling/code/debug_tools.py. This file contains all helper functions, context managers, and profiling decorators taught in the lesson, organized by complexity from basic Python debugging to AI-specific sanity checks.
How does Phase 0 recommend handling GPU out-of-memory errors?
According to debug_tools.py (line 98‑115), developers should first check torch.cuda.memory_summary() to identify fragmentation, then call torch.cuda.empty_cache() to recover cached memory. For persistent issues, the curriculum recommends enabling torch.cuda.amp automatic mixed precision to reduce memory consumption by approximately 50%.
Can these debugging tools be used outside of PyTorch?
While Phase 0 focuses on AI workflows, the Level 1 (Python fundamentals) and Level 2 (CPU profiling) tools work with any Python codebase. The debug_print helper requires PyTorch tensors, but breakpoint(), logging, cProfile, and tracemalloc function identically in standard Python applications.
What is the difference between tracemalloc and memory_profiler in the curriculum?
As implemented in debug_tools.py (line 64‑71 vs. line 81‑89), tracemalloc captures system-wide Python object allocations and reports the source lines creating the most memory pressure, while memory_profiler attaches to specific functions via the @profile decorator to show line-by-line RAM increments. Use tracemalloc for global analysis and memory_profiler for targeted function inspection.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →