Repository navigation
cuda: a process-wide cap on DeviceBuffer and pinned HostBuffer bytes - #915
plotarmordev wants to merge 2 commits into
Conversation
setAllocationLimit bounds the bytes of device buffers plus pinned host buffers. An allocation reserves its bytes before the driver call and a failed call refunds them, so concurrent allocations cannot overshoot the cap and a refused one leaves usage and the measured peak unchanged. Host counts now take the same lock as device counts. An engine that admits a model against a memory budget can hold its own allocations to it.
|
Thank you, @plotarmordev, the public-wrapper refusal/refund tests give the combined Drama family a useful allocation gate. We will land #915 with that one native family, combining your stack and @drowzeys' work with both credited. The cap reserves device and pinned bytes before the driver call and refunds failures. We will retain the strict cap tests, add an overlapping-allocation control and bind configuration/restoration to the combined family owner. Its ordinary unset-cap and memory/performance checks remain part of that landing. This resolves the first-consumer hold; the family still needs its lane, fidelity and audio gates. Posted by Ash's AI Assistant Synthena |
…tal, with #915-#926 and #939 beneath them #927's stack brings the process-wide cap on device and pinned host bytes, direct reads a file system refuses going through the page cache, Module.holds, the Drama 3 backbone, tower and speech codec on CUDA (codec.pth read without Python), speech requests and audio events in engine_api, POST /v1/audio/speech with streamed PCM, and its decode kernels; #956's (with #939) the family's shared parts, its Metal backend and drama3-generate on macOS. Laid as the maintained series: the bridges between the two, qualification, and owners that keep buffers and modules until their completion is proved. On this line the cap's reservations join the pinned peaks' accounting, the learner's API moves to core/learning_api.zig with engine_api.zig re-exporting it (Example keeps its context row), the CUDA family list holds LFM2 and fish_omni, and both build files keep this line's layout with Drama's steps added. The tests are named for what they check.
|
Thank you, @plotarmordev, for the speech protocol and infrastructure, and @drowzeys for the family, backends and codec. The selected work from #915 is included through #927 ( Posted by Ash's AI Assistant Synthena |
|
The consolidated Drama contribution shipped in 1.1.0 as Posted by Ash's AI Assistant Synthena |
…on CUDA and Metal, with ashhart#915-ashhart#926 and ashhart#939 beneath them ashhart#927's stack brings the process-wide cap on device and pinned host bytes, direct reads a file system refuses going through the page cache, Module.holds, the Drama 3 backbone, tower and speech codec on CUDA (codec.pth read without Python), speech requests and audio events in engine_api, POST /v1/audio/speech with streamed PCM, and its decode kernels; ashhart#956's (with ashhart#939) the family's shared parts, its Metal backend and drama3-generate on macOS. Laid as the maintained series: the bridges between the two, qualification, and owners that keep buffers and modules until their completion is proved. On this line the cap's reservations join the pinned peaks' accounting, the learner's API moves to core/learning_api.zig with engine_api.zig re-exporting it (Example keeps its context row), the CUDA family list holds LFM2 and fish_omni, and both build files keep this line's layout with Drama's steps added. The tests are named for what they check.
What this changes
cuda.setAllocationLimitcaps the bytes this process holds in device buffers plus pinned host buffers (part of#914). Each allocation reserves before the driver call, so a refused one never reaches the driver and a failed
driver call refunds its reservation.
Receipt
881cccaa4d87, on mainc7137bb3. No MLX or PyTorch.tools/bench_concurrent.py --alone --serialortoken_shaagainst"draft": false: not run.The change is limited to allocation accounting and touches no token or output path.
tools/bench_openai.py: not run. Allocation accounting now reserves under thecounts lock before the driver call, and pinned-host accounting also takes that lock. Decode performance was not
measured.
ttft_sfromtools/bench_cache.py --require-coldon a long prompt, or "n/a" with the reason when the change cannot reach prompt processing: not run, for the samereason as decode.
CUDA_VISIBLE_DEVICES= zig build test-cuda-host --summary allfrom an empty local cache: 27/27 steps, 467 passed, 0 failed, 0 skipped.calls" covers the accounting. "public allocations refused by the cap skip the driver, and failed driver calls
are refunded" drives
DeviceBuffer.allocandHostBuffer.allocthrough a fake driver table whose allocationsfail. A refusal by the cap must not call the driver, a driver failure must refund its reservation, and usage
and the peak must stay unchanged.
DeviceBuffer.alloc's refund (errdefer finishAllocation(null, len)) removed fails thesecond test: 151 passed, 1 failed (that test).
zig build native -Dnvcc=/usr/local/cuda/bin/nvcc --summary all: 42/42 steps.python3 tools/zig/lean_check.py: 527 problems, the same as main's 527 (tools/zig/lean_new.py: 0 new).zig fmt --check build.zig zig: clean.Checklist
path is touched.)
"draft": false, a resumed prompt equals a fresh one, and concurrent equals solo. (Notrun; no output path is touched.)
arithmetic changes.)
GPU. The allocator test fails with the refund removed. The accounting test calls the new API, so before the
change it does not build.)