Repository navigation
v0.3.2a3 (beta)
Pre-releaseFixes two kernel bugs found while benchmarking the 50M and 30M multilingual configs on the real corpus. Nothing new is switched on by default.
Fixed
-
cluster_locality_mode="segment"could not be compiled. The loss found document ids with NumPy (segment_ids,np.unique) on a traced array, soCHRONOS_MLX_COMPILE=onraised "Attempting to eval an array during function transformations", and the defaultautomode crashed on the nextmx.eval. The loss now usessegment_ids_mx(input_ids, chunk=window), which has a static shape (row * S + idaddressesB * Ssegment slots and unused slots weigh 0), and runs inside the compiled step. It matches the NumPy ids on 300 random batches and the Torch loss within 1.7e-5 on 60. -
A compile trace that failed part way left tracers in the model weights, the RNG key and the router outputs, because
mx.compileswaps them back only on success. The eager fallback then trained on them and the nextmx.evalraised "Attempting to eval an array without a primitive".CompiledStepnow snapshots those on a first trace and restores them on failure; the RNG is re-seeded from the saved key words, so the random stream continues exactly (checked on 2,000 random keys). -
run_mlx_stageand LongRun now check every batch's token ids against the model'svocab_sizeand raise aValueErrorthat names the range. MLX does not bounds-check embedding gathers, so an id beyond the table read neighbouring memory and crashed the process at random.tests/test_smoke.py::test_mlx_training_six_stage_loss_pathshit this about one run in two on CPU: its GRPO stage tokenizes with the bundled 6,400-token tokenizer while the model hadvocab_size=64. The test now uses 6400 (25 of 25 runs pass), andtests/test_vocab_range_guard.pycovers the check.
Measured
- Segment mode, compiled, real corpus, 10 steps, document masking on, steady tokens/s: 50M 24,856 at ctx 2048 and 20,416 at 4096; 30M 22,454 and 16,416. The eager fallback cost 15-17%.
Tests
tests/test_segment_compile.py(5 cases) fails on 0.3.2a2 (4 of 5) and passes here: ids equal the NumPy rule with chunking, loss equals the Torch reference eagerly and compiled, a one-segment batch gives 0, a compiled segment-mode step matches the eager gradients, and a failed trace leaves weights, RNG and side outputs usable.