Skip to content

Refactor KV Cache Manager with a new torch exportable KVCache backend#400

Open
geoffreyQiu wants to merge 9 commits into
NVIDIA:mainfrom
geoffreyQiu:aoti_kvcache
Open

Refactor KV Cache Manager with a new torch exportable KVCache backend#400
geoffreyQiu wants to merge 9 commits into
NVIDIA:mainfrom
geoffreyQiu:aoti_kvcache

Conversation

@geoffreyQiu

@geoffreyQiu geoffreyQiu commented May 20, 2026

Copy link
Copy Markdown
Collaborator

Description

  • Refactor KV Cache Manager with a new torch exportable KVCache backend
  • Implement KV Cache custom ops for torch export and AOTInductor.
  • Add PyTorch & C++ torch runtime example for exported aoti HSTU model inference with KVCache.
  • Add triton server deployment example for exported aoti HSTU model inference with KVCache.

Checklist

  • I am familiar with the Contributing Guidelines.
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

Introduce KVCacheBackend, split the default Python backend from the public KVCacheManager facade, and add the initial export lookup path.
Comment on lines +9 to +13
1. Building required custom operators and runtime libraries
2. Exporting the HSTU ranking model with KV-cache support through `torch.export` and AOTInductor
3. Starting the FlexKV-based KV-cache runtime service
4. Running the C++ replay executable against exported artifacts and dumped tensors
5. Running the Triton Server demo path for the exported KV-cache AOTI model

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is already GUIDE_TO_RUN_CPP_INFERENCE_DEMO.md, i am wondering if we can consolidated them.
Does step 1, 2, 4 already covered in CPP_INFERENCE_DEMO?

from model.inference_ranking_gr import _STRIP_CACHED_TOKENS_OP


class ExportKVCachedInferenceRankingGR(torch.nn.Module):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need a sepeate ExportKVCAchedRankingGR instead of reusing existing python kvcache ranking GR?

@@ -0,0 +1,151 @@
# Export KVCache Design

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would prefer to have a directory corelib/recsys_kvcache_manager/doc and put those under it

* Support PyTorch export and AOTI compile/package with test coverage.
* Support C++ Torch runtime validation for AOTI-compiled KV-cache graphs.
* Support Triton Inference Server validation using the PyTorch AOTI backend.
* Add required KV-cache/runtime/custom-op plumbing and export fake-op shims.
* extract and simplify HSTU KV-cache export wrapper
* remove stale debug instrumentation and export bring-up prints
* standardize macro-gated logging in KV-cache runtime/binding/client code
* rename AOTI ordering placeholder tensors consistently
* clean C++ replay demo logging and CUDA check behavior
* document end-to-end HSTU KV-cache AOTI C++ and Triton Server workflows
@geoffreyQiu geoffreyQiu marked this pull request as ready for review June 30, 2026 14:13
@greptile-apps

greptile-apps Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR refactors the KV cache manager by introducing a KVCacheBackend ABC, splitting the existing logic into DefaultKVCacheBackend and a new ExportKVCacheBackend, and adding C++ torch custom ops (kvcache_manager_ops) to enable torch export and AOTInductor compilation of HSTU inference with KV caching.

  • New backend abstraction (kvcache_backend.py, default_kvcache_backend.py): migrates existing KVCacheManager logic into a clean pluggable backend interface; the default backend correctly delegates to the GPU/host storage managers.
  • Export backend (export_kvcache_backend.py): a new stub that wraps the C++ torch custom ops — currently has several argument-level bugs (wrong op names already noted, plus lookup missing its required ordering_tensor third argument and onboard_launch passing individual tensor fields instead of the required Tensor[] list) that will prevent any method from running successfully.
  • HSTU layer changes (paged_hstu_infer_layer.py): adds export_mode flag and hstu_attn_export_impl, but the KV-cache branch unconditionally calls the sm80-only export impl even when export_mode=False, breaking inference on non-sm80 hardware.

Confidence Score: 2/5

The export backend is not functional in its current state; multiple method calls will fail at runtime even after fixing op names, and the HSTU layer's KV-cache path crashes on any GPU newer than sm80.

ExportKVCacheBackend.lookup_kvcache omits the required third ordering_tensor argument to the lookup op, and onboard_launch passes 9 individual tensors where the C++ schema expects 5 arguments with lookup_results as a flat list — both will raise TypeError on first use. On top of previously flagged defects (wrong op names, undefined classes, out-of-scope variables), the backend has no path to a working invocation. Additionally, PagedHSTUInferLayer now unconditionally routes any KV-cache request through hstu_attn_export_impl, which raises RuntimeError on H100/sm89+ hardware regardless of the export_mode setting.

export_kvcache_backend.py has the most concentrated defects and needs a full rewrite of every method body. paged_hstu_infer_layer.py needs a hardware-agnostic fallback for the KV-cache attention path.

Important Files Changed

Filename Overview
corelib/recsys_kvcache_manager/recsys_kvcache_manager/export_kvcache_backend.py New Export/AOTI backend stub with multiple runtime-breaking bugs: wrong op names, missing arguments, undefined references, and incorrect return-value handling throughout nearly every method.
corelib/recsys_kvcache_manager/recsys_kvcache_manager/kvcache_backend.py New ABC defining the KVCacheBackend interface with abstract methods mirroring the default backend surface — clean contract definition.
corelib/recsys_kvcache_manager/recsys_kvcache_manager/fake_kvcache_manager_ops.py New fake/shape-only implementations for torch.export/fake-tensor tracing; op signatures match C++ schema, though most input validations are commented out.
corelib/recsys_kvcache_manager/src/torch_binding/kvcache_manager_ops.cpp New C++ torch custom ops — schemas and implementations look consistent, with CPU/CUDA dispatch registrations for all 11 ops.
examples/hstu/modules/paged_hstu_infer_layer.py Refactored to support export mode; KV cache path unconditionally routes to sm80-only hstu_attn_export_impl regardless of export_mode flag, breaking inference on H100/sm89+ hardware.
examples/hstu/model/export_kvcached_inference_ranking_gr.py New ExportKVCachedInferenceRankingGR model class; op calls correctly use 3-arg lookup, 5-arg onboard_launch with list, and properly indexes the flat 13-tensor allocate result.
corelib/recsys_kvcache_manager/recsys_kvcache_manager/default_kvcache_backend.py New DefaultKVCacheBackend refactored from kvcache_manager.py; logic appears correctly migrated with proper host/GPU manager delegation.
examples/hstu/inference/export_inference_gr_ranking_kvcache.py New end-to-end export/inference script for AOTI model with KV cache; extensive setup code for export and AOTI compilation.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Model as ExportKVCachedInferenceRankingGR
    participant Ops as kvcache_manager_ops (C++)
    participant Layer as PagedHSTUInferLayer
    participant Backend as ExportKVCacheBackend

    Note over Model,Backend: Correct path (ExportKVCachedInferenceRankingGR)
    Model->>Ops: offload_reap_completed(user_ids) → completed_offloads
    Model->>Ops: lookup(user_ids, seqlens, completed_offloads) → lookup_res[7]
    Model->>Ops: allocate(user_ids, seqlens, lookup_res[1], lookup_res[5]) → alloc_result[13]
    Model->>Ops: onboard_launch(user_ids, seqlens, lookup_res, alloc_result[0], alloc_result[2]) → (mappings, offsets, task_ids)
    Model->>Ops: onboard_wait(task_ids, ordering) → kv_cache_table[]
    Model->>Layer: forward(batch, kvcache_metadata)
    Layer->>Layer: append_kvcache(...) → updated kv_cache_table
    Layer->>Layer: hstu_attn_export_impl(...) [sm80 only]
    Model->>Ops: offload_launch(..., slot_mappings, ordering) → task_ids

    Note over Backend: Broken path (ExportKVCacheBackend)
    Backend->>Ops: lookup_kvcache(user_ids, seqlens) wrong name + missing arg
    Backend->>Ops: allocate_kvcache(...) wrong name + wrong unpack
    Backend->>Ops: onboard_kvcache_launch(u, s, t1, t2, t3, t4, t5, idx, ptr) wrong name + 9 args vs 5
    Backend->>Ops: onboard_kvcache_wait(...) wrong name + returns None
    Backend->>Ops: offload_launch(task_handle.task_ids) task_handle out of scope + 1 arg vs 10
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Model as ExportKVCachedInferenceRankingGR
    participant Ops as kvcache_manager_ops (C++)
    participant Layer as PagedHSTUInferLayer
    participant Backend as ExportKVCacheBackend

    Note over Model,Backend: Correct path (ExportKVCachedInferenceRankingGR)
    Model->>Ops: offload_reap_completed(user_ids) → completed_offloads
    Model->>Ops: lookup(user_ids, seqlens, completed_offloads) → lookup_res[7]
    Model->>Ops: allocate(user_ids, seqlens, lookup_res[1], lookup_res[5]) → alloc_result[13]
    Model->>Ops: onboard_launch(user_ids, seqlens, lookup_res, alloc_result[0], alloc_result[2]) → (mappings, offsets, task_ids)
    Model->>Ops: onboard_wait(task_ids, ordering) → kv_cache_table[]
    Model->>Layer: forward(batch, kvcache_metadata)
    Layer->>Layer: append_kvcache(...) → updated kv_cache_table
    Layer->>Layer: hstu_attn_export_impl(...) [sm80 only]
    Model->>Ops: offload_launch(..., slot_mappings, ordering) → task_ids

    Note over Backend: Broken path (ExportKVCacheBackend)
    Backend->>Ops: lookup_kvcache(user_ids, seqlens) wrong name + missing arg
    Backend->>Ops: allocate_kvcache(...) wrong name + wrong unpack
    Backend->>Ops: onboard_kvcache_launch(u, s, t1, t2, t3, t4, t5, idx, ptr) wrong name + 9 args vs 5
    Backend->>Ops: onboard_kvcache_wait(...) wrong name + returns None
    Backend->>Ops: offload_launch(task_handle.task_ids) task_handle out of scope + 1 arg vs 10
Loading

Reviews (4): Last reviewed commit: "Fix Docker" | Re-trigger Greptile

Comment on lines +27 to +156
def lookup_kvcache(
self,
user_ids: torch.Tensor,
sequence_lengths: torch.Tensor,
) -> Tuple[KVIndexMeta, KVLookupResult]:
(
cached_start_indices,
cached_lengths,
gpu_cached_start_indices,
gpu_cached_lengths,
host_cached_start_indices,
host_cached_lengths,
task_ids,
) = torch.ops.kvcache_manager_ops.lookup_kvcache(user_ids, sequence_lengths)

index_meta = KVIndexMeta(
user_ids=user_ids,
seq_lengths=sequence_lengths,
)
lookup_result = KVLookupResult(
user_ids=user_ids,
cached_start_indices=cached_start_indices,
cached_lengths=cached_lengths,
gpu_cached_start_indices=gpu_cached_start_indices,
gpu_cached_lengths=gpu_cached_lengths,
host_cached_start_indices=host_cached_start_indices,
host_cached_lengths=host_cached_lengths,
extra={
"task_ids": task_ids
}
)
return index_meta, lookup_result

def allocate_kvcache(
self,
index_meta: KVIndexMeta,
lookup_results: KVLookupResult,
output_kvcache_metadata: Optional[KVCacheMetadata] = None,
) -> KVCacheMetadata:
# assert output_kvcache_metadata is None, "Pre-allocated KVCacheMetadata is not supported in ExportKVCacheBackend yet."

(metadata_buffer, metadata_tensors) = torch.ops.kvcache_manager_ops.allocate_kvcache(
index_meta.user_ids,
index_meta.seq_lengths,
lookup_results.cached_lengths,
lookup_results.host_cached_lengths,
)

return KVCacheMetadata(
page_ids_gpu_buffer=metadata_buffer[0],
metadata_gpu_buffer=metadata_buffer[1],
kv_indices=metadata_buffer[0],

kv_indptr=metadata_tensors[0],
kv_last_page_len=metadata_tensors[1],
total_history_lengths=metadata_tensors[2],
total_history_offsets=metadata_tensors[3],
new_history_offsets=metadata_tensors[4],
batch_indices=metadata_tensors[5],
position=metadata_tensors[6],

new_history_nnz=metadata_tensors[7],
new_history_nnz_cuda=metadata_tensors[8],

kv_seqlens=metadata_tensors[9],
kv_seqlen_offsets=metadata_tensors[10],
kv_onload_handle=None,
)

def onboard_launch(
self,
index_meta: KVIndexMeta,
lookup_result: KVLookupResult,
kvcache_metadata: KVCacheMetadata,
) -> HostKVTaskHandle:
slot_mappings = torch.ops.kvcache_manager_ops.onboard_kvcache_launch(
index_meta.user_ids,
index_meta.seq_lengths,
lookup_result.cached_lengths,
lookup_result.host_cached_lengths,
lookup_result.gpu_cached_start_indices,
lookup_result.gpu_cached_lengths,
lookup_result.extra["task_ids"],
kvcache_metadata.kv_indices,
kvcache_metadata.kv_indptr,
)

# In export backend, all user_ids and slot mappings are recorded. User ids with no cache to onboard will have task_id of -1, and the corresponding slot mapping can be ignored in the downstream processing.
onload_handle = _FlexKVOnloadHandle(
task_ids=lookup_result.extra["task_ids"],
uids=index_meta.user_ids,
slot_mappings=slot_mappings,
)
return HostKVTaskHandle(
backend="flexkv",
user_ids=onload_handle.uids,
handle=onload_handle,
status=HostKVTaskStatus.LAUNCHED,
# metadata={
# "onboard_start_indices": torch.tensor(
# onboard_start_indices, dtype=torch.int32
# ),
# "onboard_lengths": torch.tensor(onboard_lengths, dtype=torch.int32),
# },
)

def onboard_try_wait(
self,
kv_index_meta: KVIndexMeta,
task_handle: Optional[HostKVTaskHandle],
) -> Optional[HostKVWaitResult]:
raise NotImplementedError("ExportKVCacheBackend.onboard_try_wait is not implemented yet.")

def onboard_wait(
self,
kv_index_meta: KVIndexMeta,
task_handle: Optional[HostKVTaskHandle],
) -> Optional[HostKVWaitResult]:
torch.ops.kvcache_manager_ops.onboard_kvcache_wait(
task_handle.handle.task_ids,
)

def offload_launch(
self,
index_meta: KVIndexMeta,
kvcache_metadata: Optional[KVCacheMetadata] = None,
):
torch.ops.kvcache_manager_ops.offload_launch(
task_handle.handle.task_ids,
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Multiple runtime-crashing defects in ExportKVCacheBackend

The file has several bugs that will each raise an exception the first time the backend is exercised:

  1. Wrong op name (line 40): torch.ops.kvcache_manager_ops.lookup_kvcache does not exist — the C++ library registers the op as lookup (m.def("lookup(...)")). Same pattern at line 102 (onboard_kvcache_launchonboard_launch) and line 145 (onboard_kvcache_waitonboard_wait).

  2. _FlexKVOnloadHandle is undefined (line 115): the class is defined in flex_kvcache_manager.py but is never imported here, causing a NameError whenever onboard_launch is called.

  3. HostKVTaskStatus is undefined (line 124): the import at line 10 brings in HostKVStorageBase, HostKVTaskHandle, and HostKVWaitResult, but not HostKVTaskStatus (which lives in host_kvstorage_manager).

  4. task_handle is out of scope (line 155): offload_launch(self, index_meta, kvcache_metadata) references task_handle.handle.task_ids, but task_handle is not a parameter of this method; this is a NameError on every call.

Comment on lines 253 to +290

return parallel_input

def hstu_attn_export_impl(
self,
query,
key,
value,
jd: JaggedData,
kv_cache_metadata,
kv_cache_table,
batch_size: int,
):
sm_major_version = torch.cuda.get_device_properties(0).major
if sm_major_version != 8:
raise RuntimeError(
"Export-mode paged-KV HSTU attention currently calls "
"torch.ops.fbgemm.hstu_varlen_fwd_80 directly. Add the matching "
"direct dispatcher path before exporting this on non-sm80 GPUs."
)
jagged_attn_output, _ = torch.ops.fbgemm.hstu_varlen_fwd_80(
query,
key,
value,
jd.seqlen_offsets[: batch_size + 1],
kv_cache_metadata.kv_seqlen_offsets[: batch_size + 1],
None,
None, # seqused_q, seqused_k
jd.max_seqlen,
jd.max_seqlen,
jd.scaling_seqlen,
None, # num_contexts
jd.num_candidates[:batch_size],
self._target_group_size,
-1,
0,
self._alpha,
None,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 KV cache path always routes to sm80-only hstu_attn_export_impl, breaking inference on H100/sm90+

After the refactor, every call that has kv_cache_metadata is not None unconditionally calls self.hstu_attn_export_impl(...) — there is no branch that falls back to the original hstu_attn_varlen_func for the non-export case. Inside hstu_attn_export_impl, line ~259 raises a RuntimeError whenever sm_major_version != 8. This means any deployment on H100 (sm90), RTX 4090 (sm89), or later hardware that uses KV caching will immediately crash — regardless of whether export_mode is True or False. The previous hstu_attn_varlen_func call, which used a proper kv_cache= path and had no such restriction, was completely removed from this branch.

Comment on lines +104 to +105
item_offsets = _offsets(item_lengths).cpu()
action_offsets = _offsets(item_lengths).cpu()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The reference implementation computes action_offsets from item_lengths instead of action_lengths. The test only passes today because the test fixture sets action_lengths = item_lengths.clone(). If a future test case uses different lengths for actions and items, the reference will silently produce incorrect offsets and the test would pass against a wrong expected value.

Suggested change
item_offsets = _offsets(item_lengths).cpu()
action_offsets = _offsets(item_lengths).cpu()
item_offsets = _offsets(item_lengths).cpu()
action_offsets = _offsets(action_lengths).cpu()

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +68 to +73
(metadata_buffer, metadata_tensors) = torch.ops.kvcache_manager_ops.allocate_kvcache(
index_meta.user_ids,
index_meta.seq_lengths,
lookup_results.cached_lengths,
lookup_results.host_cached_lengths,
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 The allocate_kvcache op name used here doesn't exist in the registered C++ library. The TORCH_LIBRARY_FRAGMENT(kvcache_manager_ops) in kvcache_manager_ops.cpp registers it as allocate (line 17: m.def("allocate(...)")). Calling allocate_kvcache will raise AttributeError at runtime on the first request that hits this backend.

Suggested change
(metadata_buffer, metadata_tensors) = torch.ops.kvcache_manager_ops.allocate_kvcache(
index_meta.user_ids,
index_meta.seq_lengths,
lookup_results.cached_lengths,
lookup_results.host_cached_lengths,
)
(metadata_buffer, metadata_tensors) = torch.ops.kvcache_manager_ops.allocate(
index_meta.user_ids,
index_meta.seq_lengths,
lookup_results.cached_lengths,
lookup_results.host_cached_lengths,
)

Comment on lines +158 to +162
def offload_try_wait(self) -> None:
raise NotImplementedError("ExportKVCacheBackend.offload_try_wait is not implemented yet.")

def offload_reap_completed(self) -> None:
torch.ops.kvcache_manager_ops.offload_reap_completed()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 offload_reap_completed missing required ordering_tensor argument

The C++ op is registered as m.def("offload_reap_completed(Tensor ordering_tensor) -> Tensor") — it requires exactly one tensor argument. Calling torch.ops.kvcache_manager_ops.offload_reap_completed() with no arguments will raise a TypeError at runtime every time this method is invoked. The fake implementation (_offload_reap_completed_fake) also documents the expected dummy tensor parameter.

Comment on lines +140 to +147
def onboard_wait(
self,
kv_index_meta: KVIndexMeta,
task_handle: Optional[HostKVTaskHandle],
) -> Optional[HostKVWaitResult]:
torch.ops.kvcache_manager_ops.onboard_kvcache_wait(
task_handle.handle.task_ids,
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 onboard_wait discards the KV cache table result and returns None

torch.ops.kvcache_manager_ops.onboard_wait returns Tensor[] — the list of per-layer KV cache tables. The C++ implementation calls runtime->get_kvcache_tables() and returns those tensors as the op result. The Python method here never captures or returns that result; it falls off the end and returns None. Any caller of KVCacheManager.onboard_wait(...) will receive None instead of the cache tables, silently corrupting downstream attention computation.

Comment on lines +60 to +93
def allocate_kvcache(
self,
index_meta: KVIndexMeta,
lookup_results: KVLookupResult,
output_kvcache_metadata: Optional[KVCacheMetadata] = None,
) -> KVCacheMetadata:
# assert output_kvcache_metadata is None, "Pre-allocated KVCacheMetadata is not supported in ExportKVCacheBackend yet."

(metadata_buffer, metadata_tensors) = torch.ops.kvcache_manager_ops.allocate_kvcache(
index_meta.user_ids,
index_meta.seq_lengths,
lookup_results.cached_lengths,
lookup_results.host_cached_lengths,
)

return KVCacheMetadata(
page_ids_gpu_buffer=metadata_buffer[0],
metadata_gpu_buffer=metadata_buffer[1],
kv_indices=metadata_buffer[0],

kv_indptr=metadata_tensors[0],
kv_last_page_len=metadata_tensors[1],
total_history_lengths=metadata_tensors[2],
total_history_offsets=metadata_tensors[3],
new_history_offsets=metadata_tensors[4],
batch_indices=metadata_tensors[5],
position=metadata_tensors[6],

new_history_nnz=metadata_tensors[7],
new_history_nnz_cuda=metadata_tensors[8],

kv_seqlens=metadata_tensors[9],
kv_seqlen_offsets=metadata_tensors[10],
kv_onload_handle=None,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Flat Tensor[] return cannot be unpacked into a 2-tuple

After fixing the op name (allocate_kvcacheallocate), this code will still fail. The C++ allocate op returns a flat list of 13 tensors (confirmed by _allocate_fake returning 13 torch.empty calls). The line (metadata_buffer, metadata_tensors) = torch.ops.kvcache_manager_ops.allocate(...) attempts to unpack that 13-element list into exactly two variables, raising ValueError: too many values to unpack. The correct approach — as used in ExportKVCachedInferenceRankingGR._kvcache_metadata_from_ops — is to index the flat result directly: result[0], result[1], etc.

Comment on lines +38 to +46
host_cached_lengths,
task_ids,
) = torch.ops.kvcache_manager_ops.lookup_kvcache(user_ids, sequence_lengths)

index_meta = KVIndexMeta(
user_ids=user_ids,
seq_lengths=sequence_lengths,
)
lookup_result = KVLookupResult(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 lookup called with 2 arguments — C++ schema requires 3

The C++ op schema registers lookup(Tensor user_ids, Tensor seqlens, Tensor ordering_tensor) -> Tensor[] (three arguments). This call passes only user_ids and sequence_lengths, omitting the required ordering_tensor (a dependency tensor for ordering/sync). The correct three-argument form is demonstrated in ExportKVCachedInferenceRankingGR.forward() where completed_offloads is passed as the third argument. After fixing the op name (separately flagged), this call would still raise a TypeError at runtime due to the missing argument.

Comment on lines +108 to +118
lookup_result.gpu_cached_lengths,
lookup_result.extra["task_ids"],
kvcache_metadata.kv_indices,
kvcache_metadata.kv_indptr,
)

# In export backend, all user_ids and slot mappings are recorded. User ids with no cache to onboard will have task_id of -1, and the corresponding slot mapping can be ignored in the downstream processing.
onload_handle = _FlexKVOnloadHandle(
task_ids=lookup_result.extra["task_ids"],
uids=index_meta.user_ids,
slot_mappings=slot_mappings,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 onboard_launch called with 9 individual tensors — C++ schema expects 5 arguments with a list

The C++ schema is onboard_launch(Tensor user_ids, Tensor seqlens, Tensor[] lookup_results, Tensor kv_page_indices, Tensor kv_page_indptr). The lookup_results parameter is a Tensor[] that must receive the full 7-tensor output of the lookup op as a single list, not the individual fields broken out as separate positional arguments. ExportKVCachedInferenceRankingGR.forward() demonstrates the correct 5-argument call: onboard_launch(user_ids, total_history_lengths, lookup_res, alloc_result[0], alloc_result[2]). Even after fixing the op name, passing 9 arguments instead of 5 will raise a TypeError.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants