-
Notifications
You must be signed in to change notification settings - Fork 1.5k
misc: Add runtime validation for plan/run consistency in BatchMLAPagedAttentionWrapper #2246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -346,6 +346,8 @@ def plan( | |
| self._page_size = page_size | ||
| self._sm_scale = sm_scale | ||
| self._use_profiler = use_profiler | ||
| # Store total query count for validation in run() | ||
| self._total_num_queries = int(qo_indptr_host[-1].item()) | ||
|
|
||
| self._plan_info = self._cached_module.plan( | ||
| self._float_workspace_buffer, | ||
|
|
@@ -433,6 +435,23 @@ def run( | |
| page_table : Optional[torch.Tensor] | ||
| The page table of the paged kv-cache, shape: ``[batch_size, num_pages]``. Required when ``backend`` is ``cutlass``. | ||
| """ | ||
|
|
||
| if self._backend != "cutlass": | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe check for cutlass backend also. |
||
| # Validate that run() inputs match the plan() configuration. | ||
| # Note: cutlass backend doesn't use plan() | ||
| if q_nope.shape[0] != self._total_num_queries: | ||
| raise ValueError( | ||
| f"q_nope.shape[0] ({q_nope.shape[0]}) does not match " | ||
| f"qo_indptr[-1] ({self._total_num_queries}) from plan(). " | ||
| f"The total number of query tokens must be consistent between plan() and run()." | ||
| ) | ||
| if q_pe.shape[0] != self._total_num_queries: | ||
| raise ValueError( | ||
| f"q_pe.shape[0] ({q_pe.shape[0]}) does not match " | ||
| f"qo_indptr[-1] ({self._total_num_queries}) from plan(). " | ||
| f"The total number of query tokens must be consistent between plan() and run()." | ||
| ) | ||
|
Comment on lines
+442
to
+453
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These two checks for if q_nope.shape[0] != self._total_num_queries or q_pe.shape[0] != self._total_num_queries:
raise ValueError(
f"Total number of query tokens mismatch. Expected {self._total_num_queries} from plan(), "
f"but got q_nope={q_nope.shape[0]} and q_pe={q_pe.shape[0]} in run()."
)
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This nit comment is valid.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. agreed
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure whether to assert For the bug in #2236, it's clearly q_nope.shape[0] < qo_indptr[-1] to cause the IMA.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given that the
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This check could be handled at the framework level, and closing this PR looks reasonable to me. |
||
|
|
||
| if self._backend == "cutlass": | ||
| if return_lse: | ||
| raise ValueError("return_lse does not support cutlass backend for now.") | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have some concern if qo_indptr will be a device tensor in the future (because [-1].item() will call a cuda sync in that case). But considering we expect user to pass a host-side tensor at the moment I'm good with this.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I initially thought the same, but a few lines above, we have:
which means that the plan() function already requires a CUDA sync and is therefore cannot be placed in CUDA graph, so I figured it is okay here