[XNNPACK] Add the off-graph flat KV-cache - #21822
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/21822
Note: Links to docs will display an error until the docs builds have been completed. ❌ 6 New Failures, 4 Unrelated Failures, 1 Unclassified FailureAs of commit 601c570 with merge base 564e655 ( NEW FAILURES - The following jobs have failed:
UNCLASSIFIED FAILURE - DrCI could not classify the following job because the workflow did not run on the merge base. The failure may be pre-existing on trunk or introduced by this PR:
FLAKY - The following jobs failed but were likely due to flakiness present on trunk:
BROKEN TRUNK - The following job failed but were present on the merge base:👉 Rebase onto the `viable/strict` branch to avoid these failures
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
This PR needs a
|
Summary
Adds the byte layer for the off-graph KV cache on XNNPACK:
XnnSequenceCachestores K/V in per-layer host pools behind the neutralSequenceCache, which keeps the length bookkeeping and step planning. A step's tokens are copied to the slots the planner names, and the window comes back as anAttendSpec: base pointers plus the pool's extent (slots) and the live prefix (valid_len), pointer-typed so the consumer wraps it at the call site instead of the cache owning tensor state.Files
backends/xnnpack/runtime/XnnCache.h—AttendSpec(K/V base pointers,slots,valid_len, and the mask kindNone/Causal/Explicitwith an optional additive mask) plus theXnnCacheop face, kept separate from the neutraltensor-free face so one cache exposes both without a diamond. Masking is the cache's to declare, not the caller's, which is what lets a windowed or tree layer slot in behind the same op;
Explicithas no producer until a ring layer needs one.backends/xnnpack/runtime/XnnSequenceCache.h—Pool(per-layer host buffer, BHSD-major[1, H, slots, D], one copy per head at the slots the planner names, lazy doubling growth that re-lays-out every head because the row stride widens) andXnnSequenceCache : cache::SequenceCache, XnnCache. Construction goes through a staticcreate()returningResult, since a constructor cannot reject a bad config without exceptions. A ring step can span two runs or start mid-pool, andupdate_and_fetchrejects both rather than half-serving them.backends/xnnpack/test/runtime/test_xnn_sequence_cache.cpp,backends/xnnpack/test/CMakeLists.txt— the tests.Testing
20 GTest cases. The centrepiece drives the cache through a realistic step sequence — prefill, chunked prefill, decodes, crossing four pool doublings — while an independent naive model appends each step to a flat per-head history, and compares the pool read as
[1, H, slots, D]over[0, valid_len)after every step.cmake . -DEXECUTORCH_BUILD_XNNPACK=ON -DEXECUTORCH_BUILD_TESTS=ON -Bcmake-out
cmake --build cmake-out --target backends_xnnpack_test
ctest --test-dir cmake-out -R backends_xnnpack_test --output-on-failure