Archon: PyTorch-Native Training Engine

March 30, 2026 · View on GitHub

Overview

Archon is AReaL's PyTorch-native training backend that provides maximum flexibility for RL researchers without Megatron-Core dependencies. It supports full 5D parallelism (DP, TP, PP, CP, EP) using PyTorch's native distributed primitives, making it easier to add RL-specific optimizations and debug distributed training issues.

Easy to get started: Simply run uv sync to install all dependencies. Unlike MegatronEngine which requires C++ compiled packages like transformer_engine, Archon uses only pure Python packages with no complex build steps.

The design and core implementation of Archon are inspired by torchtitan, PyTorch's official reference implementation for large-scale LLM training. We thank the torchtitan team for their excellent work in making distributed training accessible through pure PyTorch APIs.

Engine Comparison

FeatureFSDPEngineMegatronEngineArchonEngine
BackendHuggingFace + FSDP2Megatron-CorePyTorch-native
Model SourceAny HF modelMegatron modelsCustom Archon models
torch.compileLimitedNoYes (default)
Data ParallelFSDP2Megatron DPFSDP2
Tensor ParallelPyTorch DTensorMegatron TPPyTorch DTensor
Pipeline ParallelNoYes (VPP)Yes (1F1B, I1F1B, IZB, ZBV)
Expert ParallelNoFull EP/ETPFull EP/ETP
Context ParallelUlysses SPMegatron CPUlysses SP
Supported ModelsAny HFmbridge/ megatron-bridgeBuilt-in + User-defined
StatusProductionProductionExperimental

Key Features

  • PyTorch-native implementation: No Megatron-Core dependency, using only PyTorch distributed primitives (DTensor, DeviceMesh, FSDP2)
  • Full parallelism support: DP, TP, PP, CP, EP, and ETP with flexible configuration
  • torch.compile by default: Optimized performance with Inductor compilation
  • Flexible activation checkpointing: Supports none, full, selective, and memory_budget modes
  • Native RL training support: Built-in PPO Actor/Critic implementations
  • Pipeline parallel schedules: 1F1B, Interleaved1F1B, InterleavedZeroBubble (ZB1P), and ZBVZeroBubble schedules

Enabling Archon

To use Archon as your training backend, specify it in the actor.backend field:

rollout.backend=sglang:d4 actor.backend=archon:d4

Supported Models

Archon provides built-in support for the following model types:

  • qwen2 - Qwen2 dense models
  • qwen3 - Qwen3 dense models
  • qwen3_moe - Qwen3 MoE models

For unsupported models without custom implementations, use FSDPEngine or MegatronEngine instead.

Adding Custom Models

Users can add custom model implementations by creating a new model spec. The key components are:

  1. Model class (nn.Module): The model architecture implementation
  2. ModelArgs class: Dataclass for model configuration, with from_hf_config() method to convert from HuggingFace config
  3. StateDictAdapter class: Converts between HuggingFace and Archon weight formats
  4. Parallelize function: Applies TP, CP, EP, FSDP, and activation checkpointing
  5. ModelSpec: Registers all components together

Example structure (see areal/experimental/models/archon/qwen3/ for reference):

areal/experimental/models/archon/your_model/
├── __init__.py
├── spec.py                    # ModelSpec registration
├── model/
│   ├── model.py               # Model class
│   ├── args.py                # ModelArgs dataclass
│   └── state_dict_adapter.py  # Weight conversion
└── infra/
    └── parallelize.py         # Parallelization logic

Register your model spec in areal/experimental/models/archon/__init__.py:

from areal.experimental.models.archon.your_model import spec  # noqa: F401

Tip: AI-powered coding tools (e.g., Claude Code, OpenCode) can help accelerate the process. Use the /add-archon-model skill for a semi-automated guide that analyzes HuggingFace source code and generates implementation scaffolding. See the AI-Assisted Development Guide for setup and usage.

Parallelism Configuration

Archon uses the same parallelism syntax as Megatron. See Allocation Mode Reference for the complete syntax guide.

Basic example:

# Dense model: 4 DP × 2 PP × 2 TP = 16 GPUs
rollout.backend=sglang:d4t2 actor.backend=archon:d4p2t2

MoE Support

Unlike FSDPEngine, Archon provides full MoE support with Expert Parallelism (EP) and Expert Tensor Parallelism (ETP). For MoE models, you can use hybrid parallelism with separate configurations for attention and FFN (expert) modules:

# MoE model with hybrid parallelism
rollout.backend=sglang:d4t4 actor.backend=archon:(attn:d1p4t2c2|ffn:d1p4t1e4)

This enables MoE Parallel Folding, reducing GPU requirements for combined context and expert parallelism.

Advanced Configuration

Archon-specific options are configured under actor.archon.*:

OptionDefaultDescription
pp_scheduleInterleaved1F1BPP schedule: 1F1B, I1F1B, IZB, or ZBV
enable_compileTrueEnable torch.compile
ac_modeselectiveActivation checkpointing mode
offload_paramsFalseOffload FSDP parameters to CPU
reshard_after_forward_policydefaultFSDP reshard after forward (default/always/never)
use_deterministic_algorithmsFalseDeterministic training for reproducibility (see below)

See Performance Tuning for detailed guidance on these options.

(performance-tuning)=

Performance Tuning

torch.compile

Archon enables torch.compile by default for optimized performance. When compile is enabled, pad_to_maximum=True is automatically set to avoid dynamic shape issues with Inductor.

To disable compilation (useful for debugging or unsupported operations):

+actor.archon.enable_compile=False

Activation Checkpointing Selection

Choose the appropriate AC mode based on your memory constraints:

ModeMemory UsageRecomputationUse Case
noneHighestNoneSmall models, sufficient memory
selectiveMediumPartialDefault, balanced trade-off
fullLowestAll layersLarge models, memory constrained
memory_budgetConfigurableAuto-tunedFine-grained control (requires compile)

For memory_budget mode, adjust ac_memory_budget (0.0 = max recompute, 1.0 = no recompute):

+actor.archon.ac_mode=memory_budget +actor.archon.ac_memory_budget=0.5

Limitations

Current limitations of Archon Engine:

  • Weight tying not supported with PP: Models with tie_word_embeddings=True cannot use Pipeline Parallelism (PP > 1) because embeddings and output layers are on different GPUs
  • Tree training: Not yet supported (enable_tree_training will show a warning)
  • Experimental status: APIs may change in future releases

Debugging Tips

Viewing Parallel Configuration

Archon logs parallel dimensions at initialization:

Initialized Archon engine with parallel dims: pp=2, dp_shard=4, tp=2, cp=1, ep=1, etp=1

Common Issues

IssuePossible CauseSolution
Shape mismatch across microbatchesVariable sequence lengths with PPSet pad_to_maximum=True
OOM during compilationtorch.compile memory overheadTry +actor.archon.enable_compile=False
"tie_word_embeddings" errorPP with weight-tied modelUse PP=1 or different model
Slow first iterationtorch.compile warmupExpected behavior, subsequent iterations faster
Non-deterministic loss across runsGPU-level non-determinism in MoESet +actor.archon.use_deterministic_algorithms=True

Activation Checkpointing Debug

Enable AC debugging to capture detailed information (slower):

+actor.archon.ac_debug=True

(deterministic-mode)=

Deterministic Mode

Models can exhibit non-deterministic behavior across training runs due to GPU-level non-determinism in matmuls, NCCL collective reductions, and torch.compile code generation. This makes debugging training instability difficult — you cannot tell whether a loss spike is from your algorithm change or random hardware noise.

Enable deterministic mode to eliminate these sources of variance:

+actor.archon.use_deterministic_algorithms=True

This sets:

  • torch.use_deterministic_algorithms(True, warn_only=True) — forces PyTorch to use deterministic algorithm variants where available
  • CUBLAS_WORKSPACE_CONFIG=:4096:8 — deterministic cuBLAS matmul workspace
  • NCCL_ALGO=Ring — deterministic NCCL collective reductions
  • TORCH_COMPILE_DETERMINISTIC=1 — deterministic Inductor code generation (when compile is enabled)
  • ac_config.preserve_rng_state=True — deterministic activation checkpointing recompute

Migration from FSDPEngine

To migrate from FSDPEngine to Archon:

1. Update actor.backend

# Before (FSDPEngine)
rollout.backend=sglang:d4t2 actor.backend=fsdp:d8t2

# After (Archon)
rollout.backend=sglang:d4t2 actor.backend=archon:d8t2

2. Configuration Mapping

FSDPEngine OptionArchon Equivalent
gradient_checkpointingSame (controls AC globally)
N/Aactor.archon.ac_mode
N/Aactor.archon.enable_compile
N/Aactor.archon.pp_schedule

3. Model Compatibility

Ensure your model is supported by Archon (qwen2, qwen3, qwen3_moe) or implement a custom model spec.

4. New Capabilities

With Archon, you gain access to:

  • Pipeline Parallelism (p dimension)
  • Expert Parallelism for MoE (e dimension)
  • torch.compile optimization
  • Flexible activation checkpointing modes

Examples

Dense Model (Qwen3-8B)

Create a config file archon_qwen3_8b.yaml:

``$\text{yaml}

\text{Archon} \text{config} \text{for} \text{Qwen3}-8\text{B} \text{on} 3 \text{nodes} (24 \text{GPUs})

\text{SGLang}: 4 \text{replicas} \times 2 \text{TP} = 8 \text{GPUs}

\text{Archon}: 4 \text{DP} \times 2 \text{PP} \times 2 \text{TP} = 16 \text{GPUs}

\text{experiment_name}: \text{archon}-\text{gsm8k}-\text{grpo} \text{trial_name}: \text{trial}-0

\text{cluster}: \text{n_nodes}: 3 \text{n_gpus_per_node}: 8

\text{rollout}: \text{backend}: "\text{sglang}:\text{d4t2}"

\text{scheduler}: \text{type}: \text{ray}

\text{actor}: \text{backend}: "\text{archon}:\text{d4p2t2}" \text{path}: \text{Qwen}/\text{Qwen3}-8\text{B} \text{gradient_checkpointing}: \text{true} \text{archon}: \text{pp_schedule}: \text{Interleaved1F1B} \text{enable_compile}: \text{true} \text{ac_mode}: \text{selective} $``

Run the experiment:

python3 examples/math/gsm8k_rl.py --config archon_qwen3_8b.yaml

MoE Model (Qwen3-30B-A3B)

Create a config file archon_qwen3_moe.yaml:

``$\text{yaml}

\text{Archon} \text{config} \text{for} \text{Qwen3}-30\text{B}-\text{A3B} \text{MoE} \text{on} 4 \text{nodes} (32 \text{GPUs})

\text{SGLang}: 4 \text{replicas} \times 4 \text{TP} = 16 \text{GPUs}

\text{Archon}: 1 \text{DP} \times 4 \text{PP} \times (\text{attn}: \text{TP2} \times \text{CP2}, \text{ffn}: \text{TP1} \times \text{EP4}) = 16 \text{GPUs}

\text{experiment_name}: \text{archon}-\text{moe}-\text{gsm8k}-\text{grpo} \text{trial_name}: \text{trial}-0

\text{cluster}: \text{n_nodes}: 4 \text{n_gpus_per_node}: 8

\text{rollout}: \text{backend}: "\text{sglang}:\text{d4t4}"

\text{scheduler}: \text{type}: \text{ray}

\text{actor}: \text{backend}: "\text{archon}:(\text{attn}:\text{d1p4t2c2}|\text{ffn}:\text{d1p4t1e4})" \text{path}: \text{Qwen}/\text{Qwen3}-30\text{B}-\text{A3B} \text{gradient_checkpointing}: \text{true} \text{archon}: \text{pp_schedule}: \text{Interleaved1F1B} \text{enable_compile}: \text{true} \text{ac_mode}: \text{selective} $``

Run the experiment:

python3 examples/math/gsm8k_rl.py --config archon_qwen3_moe.yaml

See Also

(appendix-pipeline-parallelism-memory-guide)=

Appendix: Pipeline Parallelism Memory Guide

Pipeline parallelism (PP) in the Archon engine introduces unique memory challenges compared to pure data parallelism. This appendix explains the root causes and practical mitigations.

A.1 Microbatch Count and Warmup Accumulation

Interleaved PP schedules (e.g., Interleaved1F1B, InterleavedZeroBubble) have a warmup phase that accumulates multiple forward passes before any backward pass runs. When n_microbatches < num_total_stages, most or all forward passes pile up before the first backward, causing peak GPU memory to spike far beyond what the steady-state 1F1B phase requires.

For example, with pp_size=2 and stages_per_rank=2 (num_total_stages=4):

mb_spec.n_mbsActual microbatchesWarmup forwards (rank 0)Peak activation setsPer-set size
1 (default)2 (auto-raised to pp_size)34 (all before backward)batch / 2
4 (recommended)434 (transient)batch / 4
8834 (transient)batch / 8

While the peak count of in-flight activation sets stays the same (~num_total_stages), each set shrinks proportionally with more microbatches.

Fix: Set mb_spec.n_mbs to at least num_total_stages:

actor:
  mb_spec:
    n_mbs: 4  # >= pp_size * stages_per_rank
AReaL automatically raises `n_mbs` to `num_total_stages` when it is too low and logs a
warning. To silence the warning and ensure optimal splitting, set `n_mbs` explicitly.

A.2 Zero Bubble Schedules and retain_graph

Zero bubble schedules (InterleavedZeroBubble, ZBVZeroBubble, DualPipeV) split each backward pass into two phases:

  • I step (stage_backward_input): computes input gradients with retain_graph=True
  • W step (stage_backward_weight): computes weight gradients, then releases the graph

The I step must keep the forward computation graph alive (retain_graph=True) because the W step still needs it. This single design choice cascades into several memory penalties:

ConsequenceWhyMemory impact
Activations live longerGraph between I->W cannot be freed+15--20 GB (model-dependent)
donated_buffer disabledDonated buffers are freed after backward, conflicts with retain_graphBackward temp buffers cannot be reused
torch.compile disabledCompile's donated buffer optimization has the same conflictLose Inductor memory optimizations
Op-level selective AC unusablePer-op cache is consumed by I step, nothing left for W stepMust use full AC or layer-level selective AC

Non-zero-bubble schedules (1F1B, Interleaved1F1B) perform backward in a single pass without retain_graph=True, so none of these penalties apply. If memory is tight and you do not need zero-bubble throughput, switching to Interleaved1F1B is the simplest mitigation:

actor:
  archon:
    pp_schedule: Interleaved1F1B  # no split backward, no retain_graph overhead

If you need zero-bubble throughput but IZB causes OOM, try ZBVZeroBubble first. ZBV uses a V-shape stage assignment that is significantly more memory-friendly than IZB's interleaved assignment:

IZB (interleaved)ZBV (V-shape)
Rank 0 stages (4 total)[0, 2] (same side)[0, 3] (opposite ends)
Rank 1 stages (4 total)[1, 3] (same side)[1, 2] (opposite ends)

The V-shape co-locates the first and last pipeline stages on the same rank. This matters because the last stage produces the loss directly -- its backward can start immediately after forward with no cross-rank communication. In ZBV's warmup, chunk1 activations follow an F->I->W pattern where each activation is created and freed locally, never piling up.

IZB's interleaved assignment places all of a rank's stages on the same side of the pipeline. Backward requires gradient propagation from downstream ranks, creating a real bubble where warmup activations sit in memory waiting. This difference -- typically a few GB -- can be decisive at the OOM boundary.

actor:
  archon:
    pp_schedule: ZBVZeroBubble  # V-shape: less warmup memory than IZB
`ZBVZeroBubble` requires exactly 2 stages per rank (`stages_per_rank=2`).

A.3 FSDP Parameter Resharding

With PP enabled, FSDP defaults to keeping parameters unsharded after forward (reshard_after_forward=False) to avoid redundant all-gather communication per microbatch. This trades memory for speed -- each rank holds the full (unsharded) parameters of its assigned layers, adding ~model_params_per_rank * (1 - 1/dp_shard) in bf16.

Override with reshard_after_forward_policy: always if communication overhead is acceptable:

actor:
  archon:
    reshard_after_forward_policy: always  # reshard after each forward, saves memory

A.4 Gradient Accumulation Overhead (FSDP + PP)

This is an inherent cost of combining FSDP with PP and applies to all PP schedules (not just zero bubble).

PyTorch's PP scheduler disables gradient synchronization (set_requires_gradient_sync(False)) and parameter resharding (set_reshard_after_backward(False)) for all backward microbatches except the last one. This means gradients accumulate in unsharded fp32 form across microbatches rather than being reduce-scattered immediately.

For a model with P parameters per rank, this adds up to P * 4 bytes (fp32) of gradient memory. For example, a 30B MoE model with PP=2 holds ~13.5B parameters per rank, resulting in ~54 GB of unsharded gradient buffers during the backward phase.

This overhead cannot be reduced by AReaL configuration alone -- the only mitigation is to reduce parameters per rank via TP or EP.

A.5 When to Add TP/EP

If OOM persists after tuning n_mbs, reshard_after_forward_policy, and activation checkpointing, the model likely exceeds the per-rank memory budget. Add tensor parallelism (t2 or t4) or expert parallelism (e2, e4) to reduce parameters per rank. For MoE models, EP is preferred because expert weights typically dominate model size:

# Before: archon:d2p2 (PP only, OOM)
# After: archon:d1p2e2 (PP + EP, fits in memory)
rollout:
  backend: "sglang:d4"
actor:
  backend: "archon:d1p2e2"

A.6 Activation Checkpointing with PP

Full AC (gradient_checkpointing: true) is strongly recommended with PP since the warmup phase holds activations from multiple forward passes simultaneously.

For zero bubble schedules, the AC mode is further constrained:

AC modeZero bubble compatibleNotes
fullYesRecommended for maximum memory savings
selective (layer-level, e.g. "2")YesGood balance of speed and memory
selective ("op")NoPer-op cache conflicts with split backward
memory_budgetNoDepends on torch.compile, which is disabled

A.7 Memory Budget Rule of Thumb

Each rank needs memory for:
1. Sharded model parameters: `model_size / (dp_shard * tp * ep)` in bf16
2. Unsharded gradients during backward: `model_size / (tp * ep * pp)` in fp32
3. Optimizer states: `2 * model_size / (dp_shard * tp * ep)` in fp32 (AdamW)
4. Activations: ~`num_total_stages * (batch_tokens / n_mbs) * hidden_dim` in bf16

If the sum exceeds GPU memory, increase TP, EP, or PP to reduce per-rank load.