High-level approach: capture a compact, deterministic snapshot of everything needed to reproduce the failure, then automatically reduce artifacts (dataset, model, randomness) to a minimal failing example and run reproducibility attempts in isolated environments until validated or deemed non-reproducible.Artifacts to capture- Code: git commit hash + patch of local uncommitted changes (git diff).- Config: full training config/flags (JSON/YAML).- Randomness: RNG seeds for Python, NumPy, framework (torch.manual_seed, tf.random.set_seed), CUDA deterministic flags.- Dataset slice: original input pointers + export of the minimal subset used in the failing run (see reduction).- Model state: latest checkpoint and a small checkpoint if available.- Logs & metrics: stdout/stderr, framework logs, stack traces, profiler traces.- Environment: OS, python version, package versions (pip freeze), GPU driver, CUDA/cuDNN versions, Dockerfile or container image digest.- Hardware trace: GPU memory, power, host load if available.Artifact reduction strategies- Binary-search dataset slicing: run on progressively smaller slices (half-size, quarter) to find smallest subset that still fails.- Input delta debugging: remove single examples or features and re-run to find minimal trigger set.- Model size reduction: train shorter epochs, smaller batch, or freeze layers to isolate.- Deterministic replay: ensure all randomness fixed; if flaky, introduce repeated runs to detect nondeterminism.- Compress artifacts: use dataset serialization (TFRecord/Parquet) and gzip; store diffs not full repos.Automated reproduction script (outline)- Creates clean container (Docker) from captured environment or pulls image.- Checks out commit and applies patch.- Restores packages (pip install -r requirements.txt).- Loads minimal dataset slice and checkpoint.- Sets all RNG seeds and deterministic flags.- Runs training script for N attempts (e.g., 5) capturing exit code, logs, and stack traces.- Validates failure by checking error patterns or metric divergence.Example reproducibility runner (Python wrapper)python
#!/usr/bin/env python3
import subprocess, json, os, shutil, sys, time
CONF = "repro_config.json" # contains commit, patch, seeds, dataset_path, docker_image
with open(CONF) as f:
cfg = json.load(f)
def run_in_container(cmd, mounts):
base = ["docker", "run", "--rm"]
for src, dst in mounts.items():
base += ["-v", f"{src}:{dst}"]
base += [cfg["docker_image"]] + cmd
return subprocess.run(base, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# prepare workspace
subprocess.run(["git", "checkout", cfg["commit"]])
if cfg.get("patch"):
subprocess.run(["git", "apply", cfg["patch"]])
# attempts
for attempt in range(cfg.get("attempts",3)):
env = {"PYTHONHASHSEED": str(cfg["seed"]),
"TORCH_DETERMINISTIC": "1"}
mounts = {os.path.abspath(cfg["workspace"]): "/workspace",
os.path.abspath(cfg["dataset"]): "/data"}
cmd = ["python", "/workspace/train.py", "--config", "/workspace/config.yaml", "--data", "/data/min_slice"]
r = run_in_container(cmd, mounts)
open(f"run_{attempt}.log","wb").write(r.stdout+r.stderr)
if r.returncode != 0:
print("Failure reproduced on attempt", attempt)
sys.exit(0)
print("No failure reproduced")
Validation and CI integration- Trigger this runner from CI when flaky failure detected (sentry/alert hook).- If reproduced, capture final minimal artifacts and open an automated issue with artifacts attached and steps to reproduce.- If unreproducible after N attempts, mark flaky and schedule longer isolation runs with richer telemetry (profiling, hardware counters).Trade-offs and best practices- Aim for smallest deterministic artifact set to speed debugging; but preserve provenance (commit, seed).- Use containers to remove host differences; if hardware-dependent, collect hardware telemetry.- Automate TTL for stored artifacts and use artifact storage (S3) with content-addressed keys.This process yields deterministic, small, shareable reproductions that speed root-cause analysis and reduce noise from environmental nondeterminism.