Uh oh!
There was an error while loading. Please reload this page.
[MLX] C++ runner for HF LLMs with the off-graph KV cache - #21683
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/21683
Note: Links to docs will display an error until the docs builds have been completed. ❌ 3 New FailuresAs of commit 589d63c with merge base 9958d39 ( NEW FAILURES - The following jobs have failed:
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
This PR needs a |
metascroy
commented
Aug 10, 2026
Can you add something to the readme about this? |
metascroy
commented
Aug 10, 2026
@claude review this code |
Claude finished @metascroy's task in 6m 49s —— View job Code review — MLX C++ runner for off-graph KV cacheRead 1. Missing |
| // Usage: | ||
| // run_llm_hf --pte <model.pte> --tokenizer <tokenizer.json> \ | ||
| // [--kv-max-capacity N] [--kv-storage-dtype bf16|fp16|fp32] \ | ||
| // [--kv-initial-capacity N] [--kv-max-write N] \ |
There was a problem hiding this comment.
Why is kv-max-write a param?
Isn't it deriable from prefill-chunk-size?
There was a problem hiding this comment.
There was no chunking, but added --prefill-chunk-size (default 512, overrideable) and dropped --kv-max-write.
There was a problem hiding this comment.
Yeah, we can add a --prefill-chunk-size to export script with default value of 512.
Write the chunk size to metadata that can be read in the runner.
Error out during export if chunk size is bigger than ring size on sliding wndow.
There was a problem hiding this comment.
Updated to this and if in runtime --kv-windows narrows window size it also narrows the chunk with it.
| } // namespace | ||
| int main(int argc, char** argv) { | ||
| const std::string pte = arg(argc, argv, "--pte", ""); |
There was a problem hiding this comment.
Changed to gflags.
| } | ||
| if (off_graph) { | ||
| cache::CacheConfig cfg{}; |
There was a problem hiding this comment.
It's just a demo, but can we extract some of this cache config construction from pte metadata into a helper?
| // argmax over the last position's vocab row of a [1, T, vocab] logits tensor, | ||
| // reading whatever float dtype the op emitted. | ||
| int64_t argmax_last(const ::executorch::aten::Tensor& logits) { |
There was a problem hiding this comment.
Don't we have a sampler/runner in ExecuTorch extension llm?
See llama runner and some of the other runners we have.
There was a problem hiding this comment.
Changed it to reuse extension.
| const double pf_t = prompt_len / (pf / 1000.0); | ||
| const double dc_t = dc > 0 ? generated / (dc / 1000.0) : 0.0; | ||
| std::cout << "\n[iter " << iter << (measured ? "" : " warmup") | ||
| << "] prefill " << pf_t << " tok/s (" << prompt_len << " tok, " |
There was a problem hiding this comment.
I think we have something that collects stats on running?
Can you see some of the other C++ runners and reuse existign abstractions?
There was a problem hiding this comment.
Switched to the shared Stats/print_report, removed --iters and changed --warmup to a bool to match the other runners and be able to use stats directly. Additionally adopted load_tokenizer and get_eos_ids abstractions.
dd06901 to
977de44Comparekiymetakdemir
commented
Aug 11, 2026
The MLX LLM jobs skip on fork PRs (they need HF secrets), is there anything I can do to run those jobs? |
metascroy
commented
Aug 11, 2026
@claude review this code |
Claude finished @metascroy's task in 5m 56s —— View job Code review — MLX C++ runner for off-graph KV cache (re-review)Re-read Resolved since last review
Minor / nits (non-blocking)
Confirmed correct
Nothing here blocks. #1 is the only item I'd bother touching before merge, and it's a comment/label fix. |
metascroy
commented
Aug 11, 2026
You should be able to add the "ciflow/mlx" label to trigger the MLX jobs. I just added it. |
kiymetakdemir
commented
Aug 11, 2026
I removed the kwargs check, HuggingFace forwards model-level arguments into attention (gemma 4 sends labels), so refusing anything unrecognised broke its export. |
Uh oh!
There was an error while loading. Please reload this page.
Summary
This runner builds an MLXSequenceCache, installs it, and passes the cache key, so it's the run path for .pte files exported with --use-offgraph-cache. The cache's shape is read from the .pte metadata. The flags left are policy the model can't imply: --kv-max-capacity, --kv-storage-dtype, --kv-initial-capacity, --kv-max-write, --kv-windows.
Depends on #21680; the new CI job fails until that lands.
Files
Test
CI builds the runner, then for llama-1b, gemma3-1b and gemma4-e2b exports off-graph and asserts the same "Paris" answer test-mlx-llm checks.