Repository navigation
Make the compiler memory headroom a preparation setting - #122
javieratomic wants to merge 1 commit into
Conversation
6297427 to
d2fb206
Compare
d2fb206 to
2ca9cfa
Compare
|
@javieratomic GitHub reports that this PR has merge conflicts with Conflicting files:
Please update the branch against |
2ca9cfa to
57b4de5
Compare
|
@original-el8 Rebased onto |
|
@javieratomic GitHub reports merge conflicts with
Please reconcile these files with main and rerun the checks affected by the resolution. |
57b4de5 to
9ebe5bd
Compare
When a core is assembled, `core_engram` resolves each Engram plane's payload source in turn, and `payload_source` hashes each plane, or copies and hashes it when it spans several files, with one synchronous reader. On DeepSeek V4.1 Flash the two weight planes are about 98 GB each, so "Assemble core payloads" spends most of its time hashing one plane at a time while one reader at a time cannot keep the NVMe device busy. Before this change `core_engram` validated each table and resolved its planes one after another. Now it first validates every table and lists its planes (shared weights and scales, or each shard's weights and scales) with the same checks as before; the new `plane_sources` then resolves those planes with `payload_source` on up to eight workers, largest first, stops scheduling at the first error and returns it once running planes finish. The sources come back in declared order, and the tables, shards and installed payloads are built from them in the same order as before, so the published layout does not change. Measured result, on an earlier base: on a TP3 export on three DGX Spark GB10 hosts, "Assemble package payloads" (now "Assemble core payloads") took 169.1 s instead of 262.0 s. Evidence: helios `cargo test --release --features server,runtime-core --lib`: 1334 passed, 0 failed, 26 ignored. heliopause `cargo test --release`: 190 passed, 0 failed, 3 ignored, including `core_engram_preserves_shared_and_partitioned_plane_layouts`. The new test `plane_sources_keep_declared_order_and_report_failures` resolves three planes of different sizes, one of them spanning two source files, checks that they come back in declared order with the right identities and sizes, and checks that a plane beyond the payload fails. The measurement used full exports with the same model and recipe flags, one per configuration, on builds based on `a161b17f` that also contained earlier versions of NVIDIA#122, NVIDIA#124 and NVIDIA#125 and the local checkpoint reading proposed in NVIDIA#126, none of which change this phase in those versions; the export completed and committed the core, including the data of all three ranks. This model has four planes, so four readers run at once; the other two planes are about 3 GB each, so most of the remaining time is the two weight planes, each still hashed by one reader. The change was not measured on `bbad44fe`, nor together with the read-ahead digest of NVIDIA#124 (`50c664a3`), which also shortens this phase. Design-Signed-Off-By: Claude Opus 5.5; design-review=cfcf Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Javier López <59578422+javieratomic@users.noreply.github.com>
9ebe5bd to
bf5ca91
Compare
|
Reworked onto |
|
Hardware measurements of
The first export stopped with Memory was sampled every 2 s on each host. In the two exports that compiled, each compiler worker peaked at 4771 to 4995 MiB resident ( |
Forward compiler admission and kernel tuning leave a fixed 8 GiB of system memory free on each host. On a unified-memory GPU such as DGX Spark (GB10), the model's resident storage already occupies most of that memory: in a DeepSeek V4.1 Flash export with tensor parallelism 3 on three GB10 hosts (NVIDIA#242), two ranks had 12038 and 11939 MiB available after kernel tuning, with weights, KV cache and graph operands resident. Admission needs at least 4 GiB beyond the floor for one integrated compiler worker (the 2 GiB minimum host allowance plus 2 GiB of device storage), so a host with 12038 MiB available admits no worker and the export stops (NVIDIA#242). The right floor depends on the host and the model, so it should be a setting rather than a constant. Lowering it keeps the existing safety rule: on unified-memory GPUs, admission and tuning still leave free the greater of this floor and the preparation headroom (the recipe's preparation headroom plus `[memory] reserve`). Before this change the floor was the private constant `_HEADROOM_BYTES` in `ignition/preparation/host_memory.py`. It is now `COMPILE_HEADROOM_BYTES` (still 8 GiB), the default of a `compile_headroom_bytes` argument in `compiler_resources` and `CompilePool`, which admit forward compiler workers, and in `worker_limit`, `tuning_limits` and `candidate_scratch_limit`, which size kernel tuning. The value comes from the new `[preparation] compile_headroom` setting (a size string such as "6G", default "8G") or the advanced `--compile-headroom SIZE` flag of `export`, `debug-serve` and `bench`, which overrides the file; negative, empty and unparsable values are usage errors. It is carried as `Plan.compile_headroom_bytes` through every recipe's `PreparationConfig` to the tuning session (including the nested session of Kimi K3.1 candidate-selection tuning) and `ForwardCache`, and multi-host peers receive rank zero's value, as they do for `compile_workers`. The plan dictionary, the "Select GPUs." line, the tuning report and the `bench` result record it. The low-memory threshold in `release_unused` keeps 8 GiB, and the 32 GiB per-worker concurrency estimate and single Inductor thread per worker are unchanged. docs/cli-design.md and docs/model-preparation.md document the setting and flag. With the default, admission and tuning are unchanged. Expected result: on the host above, `--compile-headroom 6G` admits one compiler worker where the default admits none, and on hosts with more free memory a lower value can admit more workers under the 32 GiB estimate. A lower headroom is a per-host decision that trades the risk of exhausting host memory for being able to compile at all, or with more workers, which is why the default stays at 8 GiB. This version was not measured on hardware. Evidence: CPU tests on `0572fd12` plus this commit (CUDA hidden, environment from uv.lock): tests/cli, tests/preparation, tests/recipes/test_declarations.py, tests/recipes/test_minimax_m3.py and tests/recipes/muse_spark gave 2294 passed, 70 failed and 248 skipped. `0572fd12` alone gives 2249 passed, 248 skipped and the same 70 failures in the same environment; they are pre-existing, mostly in the native recipe contract (21) and chat-template patch (15) tests. New tests cover setting and flag parsing and validation, the plan and startup line, every recipe's `PreparationConfig`, `worker_limit`, `tuning_limits`, `candidate_scratch_limit` and the tuning report, and `CompilePool` admission: with 12038 MiB available, the default admits no worker and reports the headroom, 6 GiB admits one, and with 72 GiB available 4 GiB admits two workers where the default admits one. GPU tests and exports were not run on this version. Design-Signed-Off-By: Claude Fable 5.2; design-review=ed22 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Signed-off-by: Javier López <59578422+javieratomic@users.noreply.github.com>
bf5ca91 to
f25a038
Compare
|
@javieratomic GitHub reports merge conflicts with
Please reconcile the branch with main and rerun the checks affected by the resolution. |
Related to #73 (a kernel-tuning
MemoryErroron GLM-5.3-Flash TP2), #242 (a multi-host export that stops when a host has no room for a forward compiler) and #270 (a DeepSeek V4.1 Flash TP3 export that stops in kernel tuning at0572fd12); the #73 path was not tested on hardware, and the exports measured for the #242 and #270 conditions are summarized under Result.Why
Forward compiler admission and kernel tuning leave a fixed 8 GiB of system memory free on each host. On a unified-memory GPU such as DGX Spark (GB10), the model's resident storage already occupies most of that memory: in a DeepSeek V4.1 Flash export with tensor parallelism 3 on three GB10 hosts (#242), two ranks had 12038 and 11939 MiB available after kernel tuning, with weights, KV cache and graph operands resident. Admission needs at least 4 GiB beyond the floor for one integrated compiler worker (the 2 GiB minimum host allowance plus 2 GiB of device storage), so a host with 12038 MiB available admits no worker and the export stops (#242). The right floor depends on the host and the model, so it should be a setting rather than a constant. Lowering it keeps the existing safety rule: on unified-memory GPUs, admission and tuning still leave free the greater of this floor and the preparation headroom (the recipe's preparation headroom plus
[memory] reserve).What changed
Before this change the floor was the private constant
_HEADROOM_BYTESinignition/preparation/host_memory.py. It is nowCOMPILE_HEADROOM_BYTES(still 8 GiB), the default of acompile_headroom_bytesargument incompiler_resourcesandCompilePool, which admit forward compiler workers, and inworker_limit,tuning_limitsandcandidate_scratch_limit, which size kernel tuning. The value comes from the new[preparation] compile_headroomsetting (a size string such as "6G", default "8G") or the advanced--compile-headroom SIZEflag ofexport,debug-serveandbench, which overrides the file; negative, empty and unparsable values are usage errors. It is carried asPlan.compile_headroom_bytesthrough every recipe'sPreparationConfigto the tuning session (including the nested session of Kimi K3.1 candidate-selection tuning) andForwardCache, and multi-host peers receive rank zero's value, as they do forcompile_workers. The plan dictionary, the "Select GPUs." line, the tuning report and thebenchresult record it. The low-memory threshold inrelease_unusedkeeps 8 GiB, and the 32 GiB per-worker concurrency estimate and single Inductor thread per worker are unchanged. docs/cli-design.md and docs/model-preparation.md document the setting and flag. With the default, admission and tuning are unchanged.Result
Expected: on the host above,
--compile-headroom 6Gadmits one compiler worker where the default admits none, and on hosts with more free memory a lower value can admit more workers under the 32 GiB estimate. A lower headroom is a per-host decision that trades the risk of exhausting host memory for being able to compile at all, or with more workers, which is why the default stays at 8 GiB.Measured on
bbad44fe, with an earlier head of this PR, on three GB10 hosts with DeepSeek V4.1 Flash, tensor parallelism 3 and one rank per host (details): with the default,bbad44festopped at admission in one export, 713 MiB short of the 12288 MiB minimum on rank 0's host, and passed in another by under 0.3 GiB.bf5ca911(this change onbbad44fe) with--compile-headroom 6Gadmitted one compiler per host and compiled 38/38 forwards in 1484.4 s, against 1488.6 s in the default export that passed. In that 6 GiB export all three hosts were also above the default minimum at admission, so it does not show a case that only 6 GiB admits; 6 GiB lowers the admission minimum by 2 GiB. During its kernel tuning, swap use on rank 0's host rose by about 2.5 GiB; the exports do not show whether the setting caused it.Measured on
0572fd12and on the current head, same hosts and model (#270): with recipe defaults,0572fd12stops 17.3 to 18.9 s into kernel tuning with a 0-byte scratch limit, because the hosts have 7314 to 8083 MiB available before the scratch reservation, below the 8 GiB floor.f25a0386(this PR) with--compile-headroom 4Gcompleted the export in 9527 s: kernel tuning took 4611.9 s and all 38 forwards compiled in 1848.1 s with one compiler worker per host. With 6 GiB, the 7256 to 7483 MiB that rank 0's host had before the reservation leave at most 315 MiB for the scratch limit before the pending bytes are subtracted; that export was not run. The 4 GiB export is a way past #270, not a fix for it: during kernel tuning rank 0's host fell to 3381 MiB available and its swap use grew from 628 to 4456 MiB. The core that export wrote was not served: the runtime of0572fd12rejects its RoCE proxy ABI (#271).Evidence
CPU tests on
0572fd12plus this commit (CUDA hidden, environment from uv.lock): tests/cli, tests/preparation, tests/recipes/test_declarations.py, tests/recipes/test_minimax_m3.py and tests/recipes/muse_spark gave 2294 passed, 70 failed and 248 skipped.0572fd12alone gives 2249 passed, 248 skipped and the same 70 failures in the same environment; they are pre-existing, mostly in the native recipe contract (21) and chat-template patch (15) tests. New tests cover setting and flag parsing and validation, the plan and startup line, every recipe'sPreparationConfig,worker_limit,tuning_limits,candidate_scratch_limitand the tuning report, andCompilePooladmission: with 12038 MiB available, the default admits no worker and reports the headroom, 6 GiB admits one, and with 72 GiB available 4 GiB admits two workers where the default admits one. GPU tests were not run. The hardware exports onbbad44fe, with their memory samples, are in this comment; those on0572fd12are in #270.🤖 Generated with Claude Code