performance: post-compilation kvcache_num_blocks CLI and memory_budget for estimation - #629
performance: post-compilation kvcache_num_blocks CLI and memory_budget for estimation#629rebel-jongho wants to merge 9 commits into
Conversation
Add `optimum-rbln-cli --get-kvcache-num-blocks` / `--set-kvcache-num-blocks N` to read and resize the kv-cache block count of an already-compiled artifact directory without recompiling. `rescale_kvcache_num_blocks` rescales the kv-cache buffers by the rational ratio N/current (current = rbln_config.kvcache_num_blocks) via rebel-compiler's new `exp_rescale_buffer_size`, then rewrites the .rbln files and rbln_config.json. Stateless: rbln_config.json is the single source of truth for the current count. Enforces num_min_blocks as a hard lower bound, warns when N exceeds the compile-time count, and raises a clear error on older rebel-compiler lacking the API. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Write the resized artifact to --output-dir instead of editing in place. Copies the non-.rbln files (config.json, generation_config.json, torch artifacts, etc.) into the destination so it is a complete, loadable artifact; the source is left untouched. Without --output-dir the edit stays in place as before. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
In addition to the device-fit warning, warn when the requested block count exceeds num_full_blocks (the blocks needed to cover the full batch at max_seq_len), since the excess blocks are never used at runtime. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add `memory_budget` as a member of RBLNDecoderOnlyModelConfig to cap the device
DRAM the auto kvcache_num_blocks estimation may assume. Accepts an int (bytes),
a byte string ("10GB"/"512MB"), or a percentage ("80%") of the NPU total DRAM;
defaults to the NPU total DRAM and must not exceed it. It overrides the device
total used by get_available_dram_per_chiplet (sys reserve still subtracted, so
the default reproduces current behavior).
Also add RBLNDecoderOnlyFlashAttentionMixin._required_memory_at(num_blocks),
which returns the device-wide kv-cache DRAM at a given block count with 2MB
alignment applied (bytes are non-linear in the block count). The aligned
per-chiplet computation is factored into _kvcache_bytes_per_chiplet, shared by
the block search and _required_memory_at.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Normalize resizable kv tensors to per-block bytes (size // current_blocks) before scaling to the target block count, where current_blocks is rbln_config.kvcache_num_blocks (0 baseline treated as 1). Previously it assumed the block-size-1 compile baseline and over-counted on an already-resized model. The block search still passes current_blocks=1, preserving estimation behavior. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Interpret memory_budget against the device's available DRAM (after the per-chiplet system reserve) rather than the raw total. A percentage is now a fraction of the available DRAM, and per-chiplet is budget // num_chiplets with no further system-reserve subtraction (the reserve is already excluded from the available total). Default (None) uses the full available DRAM, reproducing the prior estimation. Drops the now-unused get_total_dram and total_memory override. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
| def _resolve_memory_budget(memory_budget: Optional[object], available_total: int) -> int: | ||
| """Resolve `memory_budget` to usable DRAM bytes (system reserve excluded), capped at available_total. | ||
|
|
||
| None -> available_total; "80%" -> that fraction of it; int/"10GB"/"512MB" -> parsed bytes. |
There was a problem hiding this comment.
How about using a decimal to express a percentage? e.g. using 0.8 to express 80%.
Upstream vllm is using decimal.
https://github.com/vllm-project/vllm/blob/dcfebf93f4eccf30f71872283331eee757915daf/vllm/config/cache.py#L68
There was a problem hiding this comment.
It can also be tricky to validate strictly when we stick with the % representation.
There was a problem hiding this comment.
Thanks for the pointer — I made the float fraction the recommended form (e.g. 0.8), matching vllm's gpu_memory_utilization, and the docstring now steers users to it.
I did keep the "80%" string as an accepted alias, for one reason: it's convenient to pass through the compile CLI, where values arrive as strings (e.g. optimum-rbln-cli --memory-budget 80%). The float form works there too (--memory-budget 0.8).
Per review, accept a float in (0, 1] as a fraction of the available DRAM (e.g. 0.8 for 80%), matching vllm's gpu_memory_utilization, instead of a "80%" string that is awkward to validate. Bytes (int / "10GB") are unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Keep the float fraction as the recommended form, but also accept a "80%" percentage string so it can be passed through the compile CLI as an argument. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@rebel-jongho Since |
|
Split as requested, thanks @rebel-jonghewk:
Closing this in favor of those two. |
Type of Change
Changes Overview
Two related capabilities for controlling the decoder-only kv-cache block count:
kvcache_num_blockson an already-compiled artifact, without recompiling.memory_budgetto bound the DRAM the automatic block estimation may assume.1. Post-compilation CLI
Two subcommands on
optimum-rbln-clioperating on an artifact directory (--model-id DIR):--get-kvcache-num-blocks— printskvcache_num_blocksfromrbln_config.json.--set-kvcache-num-blocks N— resizes the kv-cache of every*.rblntoNblocks and writes the.rblnfiles andrbln_config.json. Edits in place, or with--output-dirwrites a full resized copy there (copying the non-.rblnfiles too) and leaves the source untouched.Internals — new
RBLNDecoderOnlyFlashAttentionMixin.rescale_kvcache_num_blocks(compiled_models, rbln_config, target):per_block * currentbytes (current = rbln_config.kvcache_num_blocks). Rescaling by the rational ratiotarget / current(rebel-compilerexp_rescale_buffer_size) yields exactlyper_block * target.rbln_config.jsonis the single source of truth for the current block count.target < num_min_blocks→ValueError(config only). Non-fatal warnings (config only):targetabove the compile-time count (may not fit device DRAM), andtargetabovenum_full_blocks(excess blocks never used). Older rebel-compiler without the API → clearRuntimeErrorviahasattrcapability detection.Depends on rebel-compiler's new
exp_rescale_buffer_size(rebellions-sw/rebel_compiler#12067).2. Compile-time
memory_budgetRBLNDecoderOnlyModelConfiggains amemory_budgetmember that caps the device DRAM the automatickvcache_num_blocksestimation may assume:0.8for 80%, matching vllm'sgpu_memory_utilization). A"80%"string is also accepted (handy for passing through the compile CLI), as are bytes given as an int or string ("10GB","512MB"). The fraction is of usable memory (after the per-chiplet system reserve), not the raw total.ValueErrorotherwise). The budget is split evenly per chiplet with no further reserve subtraction (already excluded), so the default reproduces current estimation exactly.rbln_configkey:Also adds
RBLNDecoderOnlyFlashAttentionMixin._required_memory_at(compiled_models, rbln_config, num_blocks), returning the device-wide kv-cache DRAM at a given block count with 2MB alignment applied (non-linear in the block count). It works for any current block size — resizable tensors are normalized to per-block bytes usingrbln_config.kvcache_num_blocks. The aligned per-chiplet math is factored into_kvcache_bytes_per_chiplet, shared with the block search (unchanged behavior).Motivation and Context
kvcache_num_blockson a compiled artifact without recompiling the whole model (CLI).memory_budget).How to test
--getprints the stored count;--set N(N ≥ num_min_blocks) rewrites the kv-cache buffers toper_block * Nand updates the config (verified by reloading the.rbln);--setbelownum_min_blocksraisesValueError;--output-dirleaves the source untouched.memory_budget: estimation with a smaller budget yields fewer blocks (monotonic),Nonereproduces the current result, and a budget above the NPU total raisesValueError._required_memory_at(N)is monotonic inN, equals the current footprint atN = kvcache_num_blocks, and stays correct for an already-resized artifact.