Configuration system#
Primus experiments are described in YAML. The loader resolves environment variables, extends: inheritance, and module/model/platform presets before training starts. This document focuses on the Python configuration pipeline (primus/core/config/ and primus/core/launcher/parser.py).
Related documentation
Topic |
Location |
|---|---|
CLI launcher and |
|
Setting env vars and |
|
Backend parameter references |
Megatron parameters, TorchTitan parameters, MaxText parameters |
Overview: Three-layer YAML#
A typical experiment ties together:
Experiment YAML—your run: identity, workspace, and a
modulessection naming framework presets plus overrides.Module preset—training defaults for a backend (optimizer, schedule, parallelism hooks) under
primus/configs/modules/<framework>/.Model preset—architecture and tokenizer metadata under
primus/configs/models/<framework>/.
All of these are deep-merged (see primus/core/config/yaml_loader.py and primus/core/config/merge_utils.py). A platform preset (primus/configs/platforms/) maps distributed environment variable names and logging defaults; if omitted, the parser injects platform_azure.yaml (see PrimusParser.parse_platform in primus/core/launcher/parser.py).
Experiment config structure#
work_group: ${PRIMUS_TEAM:amd}
user_name: ${PRIMUS_USER:root}
exp_name: ${PRIMUS_EXP_NAME:my_experiment}
workspace: ${PRIMUS_WORKSPACE:./output}
env: # optional: env vars exported before training starts
XLA_PYTHON_CLIENT_MEM_FRACTION: "0.96"
modules:
pre_trainer:
framework: megatron # backend name (megatron, torchtitan, maxtext, megatron_bridge, …)
config: pre_trainer.yaml # module preset file under primus/configs/modules/<framework>/
model: llama3_8B.yaml # model preset file under primus/configs/models/<framework>/
overrides: # training overrides (deep-merged last)
train_iters: 50
micro_batch_size: 4
Required top-level keys are validated in PrimusParser.parse_meta_info: work_group, user_name, exp_name, workspace.
Module presets#
Location:
primus/configs/modules/<framework>/(for exampleprimus/configs/modules/megatron/pre_trainer.yaml).Purpose: Default training behavior (iterations, batching, optimizer, logging, parallelism-related flags for that backend).
Inheritance: Use
extends:to compose files in the same directory (or relative paths). Multiple entries merge in order; the current file wins on conflicts (_apply_extendsinyaml_loader.py).
Example chain (excerpt): pre_trainer.yaml extends trainer_base.yaml, which extends ../module_base.yaml and other shared fragments (primus/configs/modules/megatron/trainer_base.yaml).
Model presets#
Location:
primus/configs/models/<framework>/(for exampleprimus/configs/models/megatron/llama3_8B.yaml).Purpose: Architecture dimensions, tokenizer identifiers, and other model metadata.
Inheritance: Same
extends:mechanism as modules (for examplellama3_8B.yaml→llama3_base.yaml→ …).
Platform presets#
Location:
primus/configs/platforms/(for exampleprimus/configs/platforms/platform_azure.yaml).Purpose: Names of environment variables used for distributed launch (
NNODES,NODE_RANK,MASTER_ADDR, …) and defaults such asmaster_sink_levelandworkspace.Default: If the experiment omits
platform, the parser setsconfig: platform_azure.yaml(primus/core/launcher/parser.py).
Environment variable substitution#
primus/core/config/yaml_loader.py expands:
Pattern |
Behavior |
|---|---|
|
Required. Raises if |
|
Uses |
After substitution, purely numeric strings may be converted to int or float.
The env: block#
An optional top-level env: mapping (sibling of modules:) is exported into the process environment before distributed init and before the backend imports its framework, so JAX, XLA, PyTorch, and RCCL all observe it. It is read from the file separately by PrimusRuntime._apply_config_env, so the ${VAR:default} form above does not apply here — only $VAR and ${VAR} for already-set variables are expanded.
env:
XLA_PYTHON_CLIENT_MEM_FRACTION: "0.96"
XLA_FLAGS_APPEND: "--xla_gpu_autotune_level=5"
Quote the values, and keep the block at the top level: an env: nested under a module silently becomes a training parameter on that module instead of being exported. See Environment and XLA flags for the precedence rules, which matter for XLA_FLAGS in particular.
extends: inheritance#
For each YAML file:
Each path in
extends:is resolved relative to the directory of the current file.Presets are loaded recursively (each may have its own
extends:).Merge order: earlier presets in the list are merged first; later presets override earlier ones; the current file overrides all (
_apply_extends).
PresetLoader.load (primus/core/config/preset_loader.py) resolves primus/configs/<config_type>/<framework>/<name>.yaml and runs the same parse_yaml pipeline.
CLI overrides (training)#
After the main arguments are parsed, unknown tokens are interpreted as key=value overrides and deep-merged into the active training module namespace (module_cfg.params). The core runtime applies them in PrimusRuntime._apply_overrides (primus/core/runtime/train_runtime.py) using parse_cli_overrides (primus/core/utils/arg_utils.py) followed by deep_merge. Both key=value and --key value forms are accepted. Unknown keys are merged in (not rejected) and forwarded to the backend; the stricter key-existence check in parse_args / _check_keys_exist (primus/core/launcher/parser.py) belongs to a legacy path that the train subcommand does not exercise.
Example (conceptual):
./runner/primus-cli direct -- train pretrain --config exp.yaml \
--train_iters 100 --micro_batch_size 2
Merge priority (training config)#
The effective ordering of training parameters is:
CLI overrides (key=value after the main
trainarguments)—highest. Applied last by the runtime (PrimusRuntime._apply_overrides), after preset and experiment merging.modules.pre_trainer.overridesin the experiment YAML (applied inPrimusParser.parse_trainer_module).Module preset with model preset additions: the module preset is loaded first, then the model preset is merged in with
allow_override=False, so duplicate top-level module keys are preserved while non-duplicate model keys are added (merge_namespaceinparse_trainer_module).Preset chains via
extends:inside those files—base layers first, specialized layers later, file body last.
A concise mental model:
CLI overrides > experiment overrides > module preset with model preset additions > each preset’s own extends: chain > shared bases such as module_base.yaml.
Config resolution walkthrough: llama2_7B-BF16-pretrain.yaml#
Example experiment: examples/megatron/configs/MI300X/llama2_7B-BF16-pretrain.yaml.
Load experiment—
parse_yamlreads the file;${PRIMUS_*:…}placeholders resolve.Meta—
work_group,user_name,exp_name,workspaceare checked.Platform—If not present, default
platform_azure.yamlloads fromprimus/configs/platforms/.Module preset—
PresetLoader.load("pre_trainer.yaml", "megatron", "modules")loadsprimus/configs/modules/megatron/pre_trainer.yamland applies itsextends:chain (for exampletrainer_base.yaml→ …).Model preset—
PresetLoader.load("llama2_7B.yaml", "megatron", "models")loadsprimus/configs/models/megatron/llama2_7B.yaml(which extendsllama2_base.yaml→llama_base.yaml→ …).Merge—Module and model namespaces are merged for
pre_trainer.Experiment overrides—Keys under
modules.pre_trainer.overridesin the example file (for examplemock_data: true, parallelism, LR) are applied on top.CLI overrides—Any key=value pairs from the command line are merged last.
How to write a new config for a new model#
Add or reuse a model preset under
primus/configs/models/<framework>/, usingextends:from the closest existing architecture (for example copyllama3_8B.yamland adjust hidden size, layers, tokenizer).Point an experiment YAML at it—set
modules.pre_trainer.framework,config: <module_preset>.yaml, andmodel: <your_model>.yaml.Set overrides in the experiment file for run-specific values (batch sizes, paths,
mock_data, parallelism). Prefer small experiment files that reference presets instead of duplicating hundreds of keys.Validate with
--dry-runand by tracing the referenced experiment, module, and model presets (see below).Optional: add an example under
examples/<backend>/configs/<platform>/for others to copy.
Debugging config issues#
Technique |
What it does |
|---|---|
|
Parsed by the training config parser, but the default core |
|
Shows the launcher command without executing (shell layer). |
|
Enables verbose logging for launcher and Python ( |
Inspect presets |
Open the resolved |
If ${VAR} substitution fails, set the variable or switch to ${VAR:default} in the YAML.
Cross-references#
Default launcher YAML:
runner/.primus.yamlYAML loader (env + extends):
primus/core/config/yaml_loader.pyParser and merge:
primus/core/launcher/parser.pyPreset paths:
primus/core/config/preset_loader.py