-
Notifications
You must be signed in to change notification settings - Fork 4.4k
FA4 Inference #4186
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
FA4 Inference #4186
Changes from all commits
db6fe05
ba8f399
481be87
439e670
982c77a
bab7ba2
3c4218b
7e4574c
96ff336
2b6f083
dafec0e
fbebe00
92d7ed2
64089ba
cb53f72
6129fa0
3ebe0bf
9234ce7
ca59f81
66cb837
c68d142
2bfbabe
ff8a941
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 |
|---|---|---|
|
|
@@ -81,6 +81,13 @@ | |
| except ImportError as e: | ||
| pass | ||
|
|
||
| try: | ||
| from flash_attn.cute import flash_attn_varlen_func as flash_attn4_varlen_func | ||
|
|
||
| HAVE_FA4 = True | ||
| except ImportError: | ||
| HAVE_FA4 = False | ||
|
|
||
| try: | ||
| from flash_mla import flash_mla_with_kvcache, get_mla_metadata | ||
|
|
||
|
|
@@ -828,7 +835,21 @@ def flash_decode_and_prefill( | |
| softmax_scale = self.softmax_scale | ||
| else: | ||
| softmax_scale = q.shape[-1] ** -0.5 | ||
| if HAVE_FA3: | ||
| if HAVE_FA4: | ||
| output_total, _ = flash_attn4_varlen_func( | ||
| q, | ||
| k, | ||
| v, | ||
| cu_seqlens_q=cu_seqlens_q, | ||
| max_seqlen_q=max_seqlen_q, | ||
| max_seqlen_k=max_seqlen_k, | ||
| seqused_k=seqlens_k, | ||
| page_table=block_table, | ||
| softmax_scale=softmax_scale, | ||
| causal=True, | ||
| num_splits=1, | ||
| ) | ||
| elif HAVE_FA3: | ||
| # TODO(ksanthanam): Replace with call to flash_attn_varlen_func once | ||
| # it accepts block_table | ||
| output_total = self._flash_attention_3_forward_wrapper( | ||
|
|
@@ -898,22 +919,47 @@ def flash_decode_and_prefill( | |
| causal=True, | ||
| ) | ||
| else: | ||
| flash_attn_args = { | ||
| "q": q, | ||
| "k_cache": k, | ||
| "v_cache": v, | ||
| "cache_seqlens": seqlens_k, | ||
| "causal": True, | ||
| "page_table" if HAVE_FA3 else "block_table": block_table, | ||
| "num_splits": 0 if not self.batch_invariant_mode else 1, | ||
| } | ||
| if HAVE_FA3: | ||
| output_total = flash_attn3_with_kvcache(**flash_attn_args) | ||
| if HAVE_FA4: | ||
| if getattr(self, "softmax_scale", None) is not None: | ||
| softmax_scale = self.softmax_scale | ||
| else: | ||
| softmax_scale = q.shape[-1] ** -0.5 | ||
| # Reshape q from (B, S, H, D) to (B*S, H, D) for varlen interface | ||
| q_varlen = q.reshape(-1, q.shape[-2], q.shape[-1]) | ||
| output_total, _ = flash_attn4_varlen_func( | ||
|
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. Why are we using varlen func for decode phase?
Contributor
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. I dont see the with_kv function in FA4.
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. As discussed today, maybe we can look at what vLLM is doing here to confirm
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. Could we add a comment that there is no explicit decode API for FA4? |
||
| q_varlen, | ||
| k, | ||
| v, | ||
| cu_seqlens_q=cu_seqlens_q, | ||
| max_seqlen_q=tokens_per_request, | ||
| max_seqlen_k=max_seqlen_k, | ||
| seqused_k=seqlens_k, | ||
| page_table=block_table, | ||
| softmax_scale=softmax_scale, | ||
| causal=True, | ||
| num_splits=1, | ||
| ) | ||
| # Reshape back to (B, S, H, D) | ||
| output_total = output_total.reshape( | ||
| num_requests, tokens_per_request, *output_total.shape[1:] | ||
| ) | ||
| else: | ||
| assert ( | ||
| not self.batch_invariant_mode | ||
| ), "Batch invariant mode is not supported for flash attention 2" | ||
| output_total = flash_attn_with_kvcache(**flash_attn_args) | ||
| flash_attn_args = { | ||
| "q": q, | ||
| "k_cache": k, | ||
| "v_cache": v, | ||
| "cache_seqlens": seqlens_k, | ||
| "causal": True, | ||
| "page_table" if HAVE_FA3 else "block_table": block_table, | ||
| "num_splits": 0 if not self.batch_invariant_mode else 1, | ||
| } | ||
| if HAVE_FA3: | ||
| output_total = flash_attn3_with_kvcache(**flash_attn_args) | ||
| else: | ||
| assert ( | ||
| not self.batch_invariant_mode | ||
| ), "Batch invariant mode is not supported for flash attention 2" | ||
| output_total = flash_attn_with_kvcache(**flash_attn_args) | ||
|
|
||
| # Reshape back to (B*S, 1, H, D) for consistent output shape. | ||
| output_total = output_total.reshape( | ||
|
|
@@ -973,8 +1019,8 @@ def forward( | |
| inference_context = deprecate_inference_params(inference_context, inference_params) | ||
|
|
||
| if inference_context and inference_context.is_dynamic_batching(): | ||
| assert HAVE_FA3 or is_fa_min_version( | ||
| "2.7.3" | ||
| assert ( | ||
| HAVE_FA4 or HAVE_FA3 or is_fa_min_version("2.7.3") | ||
| ), "flash attn verion v2.7.3 and above is required for dynamic batching." | ||
|
|
||
| # hidden_states: [sq, b, h] | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.