Configuration#
pimm separates experiment state from execution state. This distinction is the key to moving one recipe across machines without copying cluster details into the science config.
Two layers#
Layer |
Format |
Examples |
|---|---|---|
experiment |
Python under |
model, data, transforms, loss, optimizer, scheduler, hooks, epochs, global batch sizes |
execution |
YAML under |
site, nodes/GPUs/CPUs, paths, Slurm, container, environment, run name, resume |
Python inheritance#
# configs/my_study/semseg.py
_base_ = ["../panda/semseg/semseg-pt-v3m2-pilarnet-ft-5cls-fft.py"]
seed = 7
batch_size = 16
data = dict(train=dict(max_len=100_000))
optimizer = dict(lr=3e-5)
Paths in _base_ are relative to the child file. Dictionaries merge
recursively. Scalars replace scalars. Lists replace lists; redefining
hooks, transform, criteria, or param_dicts drops the inherited list.
Overrides from the launcher#
Launcher flags come before a bare --; experiment overrides come after it:
uv run pimm launch \
--train.config my_study/semseg \
--resources.nproc-per-node 4 \
--run.name semseg-seed7 \
-- \
batch_size=16 \
optimizer.lr=3e-5 \
data.train.max_len=100000
Values are parsed as YAML-like scalars/containers and dotted keys patch nested
dictionaries. Tokens beginning with -- after the separator are invalid.
Use an override for a short probe. Use a child config for anything reviewed, resumed, compared, or published.
Precedence#
Experiment values:
base Python config(s) → child Python config → post-`--` overrides
Execution values:
launch/defaults.yaml → site YAML → optional recipe YAML → launcher flags
pimm launch/submit materialize both layers into the run. config.py and
resolved_config.json are the authoritative experiment record after
inheritance and overrides.
Common experiment fields#
Field |
Meaning |
|---|---|
|
model/checkpoint source for warm start or resume |
|
restore trainer state rather than only weights |
|
RNG initialization and deterministic-mode request |
|
global training event count across all ranks |
|
global explicit totals; |
|
global worker total across all ranks |
|
loop/evaluation scheduling fields used by trainers |
|
automatic mixed precision behavior |
|
registered top-level model and nested components |
|
dataset/split configs and scientific metadata |
|
optimization |
|
ordered lifecycle behavior |
|
trainer and tester implementations |
|
|
|
DDP/FSDP2 strategy settings |
Constructor-level details belong in the API; do not duplicate entire live configs into prose.
Common execution fields#
Flag/YAML path |
Meaning |
|---|---|
|
profile under |
|
checkout and experiment roots |
|
|
|
nodes, GPUs/processes per node, and CPUs per process |
|
scheduler requests and policy |
|
experiment path naming |
|
training entry and provenance behavior |
|
runtime, image, binds, interpreter |
|
shell bootstrap lines run before training |
|
repeated/requeued job attempts |
The current exhaustive flag set comes from the typed dataclasses and is listed in CLI reference.
Inspect before running#
uv run pimm launch --train.config <config> --dry-run
After a bounded run:
uv run python - <<'PY'
import json
from pathlib import Path
run = Path("exp/<group>/<run>")
cfg = json.loads((run / "resolved_config.json").read_text())
for key in ("seed", "batch_size", "num_worker", "enable_amp", "checkpoint_format"):
print(key, cfg.get(key))
print("model", cfg["model"]["type"])
print("train data", cfg["data"]["train"])
PY
Common mistakes#
Writing
batch_sizeas per-GPU. It is global and must divide world size.Editing a base config for one study. Create a child so other recipes do not change.
Redefining one hook in a list and accidentally deleting every inherited hook.
Passing
--optionsafter the launcher’s bare--; use barekey=value.Keeping absolute data/checkpoint paths in a config intended for publication.
Assuming resume re-reads the current original config rather than the saved run artifacts and launch state.