Skip to content

Konsti/olmo sft example - #1

Merged
KonstiNik merged 8 commits into
devfrom
konsti/olmo-sft-example
Jun 17, 2026
Merged

Konsti/olmo sft example#1
KonstiNik merged 8 commits into
devfrom
konsti/olmo-sft-example

Conversation

@KonstiNik

Copy link
Copy Markdown
Owner

vatis v0.2.0: cross-pair gradient offload + OLMo-3 SFT example

Adds cross_grad_storage (auto/gpu/cpu) so cross-pair observables fit on large models — the cached gradients offload to host RAM and the dot runs on the CPU when two full gradients won't co-reside on the GPU; small models stay on-device unchanged. Also: an attn_implementation passthrough in load_hf_model, and a fix so the analyzer only caches a batch's gradient when a cross pair needs it (the unconditional cache OOM'd large models).

New example examples/olmo_sft_analysis/: the LNP decomposition (incl. the code×English cross pair) on Olmo-3-7B-Think-SFT over real SFT chat data, with completion-only loss masking and wall-time / memory / GPU-activity tracking; a worked end-to-end demonstration on a real 7B checkpoint.

Unit suite green (incl. a CUDA-gated offload-equivalence test); ruff + mypy clean.

The self-pair loop cached each eval batch's flat parameter-space gradient unconditionally, but only cross pairs consume it. For large models that kept a P-sized fp32 vector (~29 GB for a 7B model) resident while subsequent batches ran their own backward — enough to OOM a 94 GB H100 even when no cross pair was requested (the second batch's ~84 GB compute peak coincided with the first batch's retained gradient).

Cache a batch's gradient only if some cross pair references it, and drop the local reference otherwise so it is freed before the next batch's backward. Self-pair-only runs now peak at a single batch's footprint.

Unit suite green; ruff + mypy --strict clean.
A realistic, production-scale vatis example: load Olmo-3-7B-Think-SFT and compute the LNP decomposition (chi_loss/chi_net/delta_loss and the headline chi_pos spectral position) on real Dolci-Think-SFT data — 10 code + 10 English samples, chat-templated with completion-only loss masking (the actual SFT objective).

Two-stage offline workflow for the internet-less compute nodes: prefetch.py (login node, online) selects samples -> samples.json and warms the model into the HF cache (needs 'datasets', a documented manual venv install, deliberately not a repo dep); olmo_sft_analyze.py (GPU node, offline) runs analyze() with resource tracking; analyze_results.py turns parquet+resources into plots/tables with zero vatis imports.

resource_tracker.py records wall time, torch peak memory, and GPU engine activity via DCGM dmon (nvidia-smi fallback). mem_profile.py is the GPU memory profiler used to localize the 7B memory cost. Adds tokenize_chat_sft_sample / stack_lm_batch to examples/_helpers.py.

First run (1x H100): chi_pos ~1e-9 — the SFT loss gradient sits deep in the spectral tail, as the dpo_spectral_filter hypothesis predicts for a late-SFT checkpoint; peak 84 GB, 195 s, autograd/memory-bound (tensor-core ~0%). Cross-pair alignment is left off (needs two gradients resident); CPU-offload is the planned follow-up.
…t RAM

The cross-pair dot needs both batches' full P-sized gradients; holding the second on the GPU during a later batch's backward OOMs large models (~104 GB for a 7B). Add cross_grad_storage='auto'|'gpu'|'cpu' (default auto): auto offloads the cached gradients to host RAM when an on-GPU cache wouldn't leave room for a self-pair backward (the device-agnostic chunked _dot_fp64 then runs on CPU), and keeps small models on-device (no transfer, no numeric change — preserves the perspic cross-validation numerics). One-time ~29 GB host copy, negligible vs the analyze phase.

Adds gpu-vs-cpu equivalence + validation tests; 54 unit tests pass, ruff + mypy --strict clean.
Expose from_pretrained's attn_implementation (e.g. 'sdpa', 'flash_attention_2', 'eager'). Default None keeps the model's own default. Useful where the attention backend changes the activation-memory class at long sequence lengths.
…sh outputs

run.sbatch now computes the (english, code) cross pair with --cross-grad-storage auto (offloads the cached gradients to host RAM, dot on CPU; GPU peak stays ~84 GB) and exposes --attn-implementation (a no-op for OLMo3, which is O(S^2) under sdpa regardless). Refreshed results.parquet / resources.json / plots from the cross-enabled run.

README trimmed to the running version: how-to-run (two-stage offline workflow), the analyzer config + rationale for adapting to your own model, and a resources-only findings section (wall ~210 s, peak ~84 GB, memory-bandwidth-bound). Documents the ~3k seq_len ceiling (O(S^2) attention) with gradient checkpointing as the future long-context lever. Drops the diagnostic mem_profile.md (keeps mem_profile.py as a pre-flight utility).
Move the auto offload size-arithmetic out of _resolve_cross_grad_storage into a pure, device-free _should_offload_cross_grads() so it is unit-testable. Add a near-threshold boundary test and a CUDA-gated test that exercises the real GPU->CPU offload (skipped in CI).
M1: default --chi-net-method to hutchinson (matches README/sbatch; per_sequence_cv OOMs at 7B). M4: tokenize_chat_sft_sample raises if truncation leaves zero completion tokens. m4: resource_tracker probes nvidia-smi before selecting it (else sampler='none'). Strip the dpo_spectral_filter research ref from the example README. Untrack samples.json/results.parquet/resources.json (regenerable; gitignored); keep the committed plots.
Bump 0.1.0 -> 0.2.0 (pyproject + _version.py); CHANGELOG [0.2.0] with date + compare link. README: document cross_grad_storage=auto and link the production-scale olmo_sft_analysis example. hf.py: note attn_implementation's O(S) win is model-dependent (OLMo3 stays O(S^2) under sdpa).
@KonstiNik
KonstiNik merged commit 8f489f3 into dev Jun 17, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant