iree-android: stateful KV session (IreeKvSession / IreeKvDecoder, libskainet_iree_kv.so) — prefill once, snapshot, chunk per utterance, step per token (#410) - #418
Merged
Conversation
…skainet_iree_kv.so) — prefill once, snapshot, chunk per utterance, step per token (#410) Three IREE sessions on one device (prefill_at, prefill_with_past, with_past — each archive has its own key numbering). Device-resident per-layer K/V; the sliding layers only ever see their last slidingWindow positions through zero-copy tail views; RoPE tables (split-half, sign folded) and the chunk graph's per-head additive masks (causal band, padding, window) are built natively; token embedding rows are read from the with-past archive (bf16 -> f32) and passed as the host-gather input, so the Kotlin API stays token ids only. Snapshot/restore retain the current views (no copy). Every failure throws IllegalStateException with the formatted IREE status. armeabi-v7a .so built with skainet/iree-android:3.11.0 --vulkan; arm64-v8a to follow.
…e KV session with the measured numbers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the stateful KV contract of #410 for Android. Stacked on #416 (same module, same error-reporting style) — merge that first. Uses the graphs from #415 and #417.
What
IreeKvSession/IreeKvSpec/IreeKvDecoderover a newlibskainet_iree_kv.so(native/iree_kv_jni.c,native/build-iree-kv.sh; both ABIs checked in, built withskainet/iree-android:3.11.0 --vulkan):gemma_prefill_at,gemma_prefill_with_past,gemma_with_past— each archive has its own key numbering, so they cannot share a parameter scope). The prefill session can be released once the catalog snapshot exists.slidingWindow(512) positions through zero-copy tail views (iree_hal_buffer_subspan+ a new buffer view) — the with-past graphs carry no window mask (found in iree-android: stateful prefill/step contract with a reusable prompt-prefix KV snapshot (and an embeddings-input variant for Vulkan) #410's measurements: without this the token after a 852-token prompt is wrong).GemmaKvDecoder.splitHalfCosSin) and the chunk graph's per-head additive masks (causal band, padding, window) are built natively for the absolute positions, so the Kotlin side deals in token ids only.vocab × hiddenbf16 entry, located through the parameter index and mmapped) and passed as theembinput — IREE 3.11's SPIR-V backend cannot lower the in-graph gather.snapshot()/restore()retain and release the current views — no copy; restore measured at 0 ms.IllegalStateExceptionwith the formattediree_status_t(and logs underskainet_iree_kv).IreeKvDecoder:prefillPrefix(ids) → Snapshotonce,generate(snapshot, utteranceIds, eos, maxNew)per turn (chunk calls ofspec.chunk, then greedy steps), with per-stage timing.Measured in-process (arm32 Android device, Android 14, armeabi-v7a, Mali via Vulkan, bf16 archives, chunk 32)
Golden-8 German voice-command utterances with the 843-token shared tool-catalog prefix (ids tokenised on the host with the official template) and 16 decode tokens:
releasePrefill()8/8 utterances return a complete
<start_function_call>call:…(or the model's refusal prose) within budget; 2/8 token streams are identical to the eager JVM run for all 16 tokens, the rest diverge after the function name (bf16 weights vs the FP32 eager reference).Notes
nKvHeadsmust be 1 for the zero-copy row views (FunctionGemma); other layouts would need a copy.IreeRedecodeSession(kept for the redecode contract), CMake/Gradle (the.sostays a checked-in artifact as before).