debug-distributed
Systematic troubleshooting guide for distributed machine learning training errors in AReaL.
Install
mkdir -p .claude/skills/debug-distributed && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/3466" && unzip -o skill.zip -d .claude/skills/debug-distributed && rm skill.zipInstalls to .claude/skills/debug-distributed
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Guide for debugging distributed training issues in AReaL. Use when user encounters hangs, wrong results, OOM, or communication errors.Key capabilities
- →Capture process call stacks from hung GPUs
- →Isolate collective communication issues (NCCL)
- →Visualize training performance using flame graphs
- →Verify tensor shape matching across ranks
- →Automate minimal reproduction script generation
How it works
Invokes diagnostic tools (py-spy, NCCL logs, environment variables) to inspect the execution state of distributed training processes in real-time.
Inputs & outputs
When to use debug-distributed
- →Fix training deadlocks
- →Resolve OOM errors
- →Debug NCCL communication
About this skill
Debug Distributed Training
Debugging guide for distributed training issues in AReaL (FSDP2, TP, CP, EP).
When to Use
This skill is triggered when:
- Training hangs or deadlocks
- Results differ across ranks or are numerically wrong
- OOM errors in distributed settings
- NCCL/communication errors or device mesh issues
Debugging Principles
Minimal Reproduction
Always follow the minimal demo principle: Reproduce with the least amount of code to narrow down the issue faster.
# Bad: Debug in full training loop
# Good: Create minimal script
import torch
import torch.distributed as dist
dist.init_process_group("nccl")
rank = dist.get_rank()
# Reproduce the exact operation that fails
tensor = torch.ones(10).cuda()
dist.all_reduce(tensor) # <-- Isolate the failing op
print(f"Rank {rank}: {tensor}")
Reduction strategy:
- Remove unrelated model components
- Use small tensor sizes
- Reduce world_size to minimum (e.g., 2 GPUs)
- Remove torch.compile if possible
- Disable activation checkpointing
Step-by-Step Debugging Guide
1. Hang Debugging (Deadlocks, Synchronization)
Environment Variables for Debugging:
# Full debug logging
export TORCH_DISTRIBUTED_DEBUG=DETAIL
export NCCL_DEBUG=INFO
export NCCL_DEBUG_SUBSYS=ALL
# torch.compile debugging
export TORCH_LOGS="+dynamo,recompiles"
export TORCHDYNAMO_VERBOSE=1
Dump Call Stack with py-spy (for hung processes):
# Find process IDs
ps aux | grep python
# Dump call stack of specific rank
py-spy dump --pid <PID>
# Record flame graph for performance analysis
py-spy record -o profile.svg --pid <PID> --duration 30
Common Causes:
- Mismatched Collectives: One rank calls
all_reduce, another doesn't. - Wrong Process Group: Using wrong group for collective.
- Tensor Shape Mismatch: Different shapes across ranks.
Debug Steps:
# Verify group membership
mesh = parallel_dims.get_mesh("dp_shard_cp")
group = mesh.get_group()
print(f"Rank {dist.get_rank()}: group size = {dist.get_world_size(group)}")
# Print shapes on all ranks
print(f"Rank {dist.get_rank()}: tensor.shape = {tensor.shape}")
dist.barrier()
Timeout Adjustment (for debugging only):
from areal.engine.core.distributed import patch_dist_group_timeout
from datetime import timedelta
patch_dist_group_timeout(timedelta(minutes=30))
2. Wrong Results (Gradient, Reduction Issues)
Check DTensor Placements:
from torch.distributed.tensor import DTensor
if isinstance(param, DTensor):
print(f"Param {name}: placements={param.placements}, mesh={param.device_mesh}")
Verify Gradient Reduction:
for name, param in model.named_parameters():
if param.grad is not None:
print(f"Rank {dist.get_rank()}: {name} grad_sum = {param.grad.sum().item()}")
3. OOM Issues (Memory, Sharding)
Check Memory Usage:
print(f"Rank {dist.get_rank()}: "
f"allocated={torch.cuda.memory_allocated()/1e9:.2f}GB, "
f"reserved={torch.cuda.memory_reserved()/1e9:.2f}GB")
Check FSDP Coverage:
for name, param in model.named_parameters():
is_dtensor = isinstance(param, DTensor)
print(f"{name}: is_dtensor={is_dtensor}, shape={param.shape}")
4. Communication Errors
| Error | Cause | Solution |
|---|---|---|
NCCL WARN Cuda failure | GPU communication | Check NCCL version, GPU topology |
RuntimeError: Timed out | Rank synchronization | Increase timeout, check code paths |
Invalid device mesh | Mesh configuration | Verify world_size = dp * tp * cp |
Debugging Tools
Environment Variables Reference
| Variable | Purpose |
|---|---|
TORCH_DISTRIBUTED_DEBUG=DETAIL | Detailed distributed logging |
NCCL_DEBUG=INFO | NCCL communication logging |
NCCL_DEBUG_SUBSYS=ALL | All NCCL subsystems |
TORCH_LOGS="+dynamo,recompiles" | torch.compile logging |
TORCHDYNAMO_VERBOSE=1 | Dynamo verbose output |
CUDA_LAUNCH_BLOCKING=1 | Synchronous CUDA (slow, for debugging) |
py-spy for Call Stack Analysis
# Install
pip install py-spy
# Dump call stack of hung process
py-spy dump --pid <PID>
# Dump all Python processes
pgrep -f python | xargs -I {} py-spy dump --pid {}
# Record flame graph
py-spy record -o profile.svg --pid <PID> --duration 30
Rank-Conditional Printing
def print_all_ranks(msg):
for r in range(dist.get_world_size()):
if dist.get_rank() == r:
print(f"[Rank {r}] {msg}")
dist.barrier()
Check Device Mesh
def debug_mesh(parallel_dims):
mesh = parallel_dims.world_mesh
for dim_name in mesh.mesh_dim_names:
submesh = parallel_dims.get_mesh(dim_name)
if submesh:
print(f"Rank {dist.get_rank()}: {dim_name} size={submesh.size()}")
Validate Tensor Consistency
def check_tensor_consistency(tensor, name, group=None):
local_sum = tensor.sum().item()
tensor_sums = [None] * dist.get_world_size(group)
dist.all_gather_object(tensor_sums, local_sum, group=group)
if dist.get_rank() == 0 and len(set(tensor_sums)) > 1:
print(f"WARNING: {name} inconsistent: {tensor_sums}")
Key Files Reference
| Component | File |
|---|---|
| Parallel Dims | areal/experimental/models/archon/parallel_dims.py |
| Expert Parallel | areal/experimental/models/archon/expert_parallel.py |
| Ulysses (CP) | areal/experimental/models/archon/ulysses.py |
| FSDP/TP Apply | areal/experimental/models/archon/qwen2/infra/parallelize.py |
<!-- ================================================================================ MAINTAINER GUIDE ================================================================================ Location: .claude/skills/debug-distributed/SKILL.md Invocation: /debug-distributed ## Purpose Debugging guide for distributed training issues. Covers FSDP2, Tensor Parallelism, Context Parallelism, and Expert Parallelism. ## How to Update ### When Adding New Parallelism Features 1. Add section for the parallelism type 2. Document common error patterns and debugging snippets ### When PyTorch Distributed APIs Change 1. Update DTensor/DeviceMesh examples 2. Update environment variable references ### When New Error Patterns Emerge 1. Add to "Common Errors and Solutions" table 2. Reference relevant source files ================================================================================ -->
When not to use it
- →Debugging high-level python application logic errors
- →Fixing syntax or standard compilation errors
- →Troubleshooting external cloud provider outages
Prerequisites
Limitations
- →Limited by the observability provided by the underlying NCCL stack
- →Requires access to the execution environment logs
How it compares
It moves from 'guesswork' to empirical analysis by dumping thread state and logging communication internals at the process level.
Compared to similar skills
debug-distributed side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| debug-distributed (this skill) | 1 | 6mo | Review | Advanced |
| langsmith-observability | 4 | 7mo | Review | Intermediate |
| mflux-debugging | 3 | 2mo | No flags | Advanced |
| aoti-debug | 1 | 5mo | Review | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by inclusionAI
View all by inclusionAI →You might also like
langsmith-observability
davila7
LLM observability platform for tracing, evaluation, and monitoring. Use when debugging LLM applications, evaluating model outputs against datasets, monitoring production systems, or building systematic testing pipelines for AI applications.
mflux-debugging
filipstrand
Debug MLX ports by comparing against a PyTorch/diffusers reference via exported tensors/images (export-then-compare).
aoti-debug
pytorch
Debug AOTInductor (AOTI) errors and crashes. Use when encountering AOTI segfaults, device mismatch errors, constant loading failures, or runtime errors from aot_compile, aot_load, aoti_compile_and_package, or aoti_load_package.
benchmark-kernel
flashinfer-ai
Guide for benchmarking FlashInfer kernels with CUPTI timing
debug-model
vladmandic
Debug a broken SD.Next or Diffusers model integration. Use when a newly added or ported model fails to load, misdetects, crashes during prompt encoding or sampling, or produces incorrect outputs.
tokenizer-checker
openvinotoolkit
Validate a HuggingFace tokenizer with OpenVINO Tokenizers and OpenVINO GenAI. Use when: checking if a tokenizer converts and works correctly, verifying tokenizer/detokenizer accuracy, testing normalization steps, checking GenAI Tokenizer compatibility.