-
-
Notifications
You must be signed in to change notification settings - Fork 20.1k
[Kernel][Performance] Enable smaller Scaling Factor tiling for NVFP4 small-batch decoding #30885
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 1 commit
e0ca865
45c8d87
d3bfcec
dfabb02
c852f04
f528094
e351eee
0209578
fee91f0
30ec1f7
6d9b39b
80958f3
5e51fee
798ff53
01a7e5d
e833be8
36e70cd
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 |
|---|---|---|
|
|
@@ -389,12 +389,21 @@ def flashinfer_mm_fp4( | |
| B_scale: torch.Tensor, | ||
| g_scale: torch.Tensor, | ||
| dtype: torch.dtype, | ||
| use_8x4_sf_layout: bool, | ||
| backend: str, | ||
| ) -> torch.Tensor: | ||
| from flashinfer import mm_fp4 as flashinfer_mm_fp4_ | ||
|
|
||
| return flashinfer_mm_fp4_( | ||
| A, B, A_scale, B_scale, g_scale, dtype, block_size=16, backend=backend | ||
| A, | ||
| B, | ||
| A_scale, | ||
| B_scale, | ||
| g_scale, | ||
| dtype, | ||
| block_size=16, | ||
| use_8x4_sf_layout=use_8x4_sf_layout, | ||
|
Member
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. Perhaps make this an automated setting based on when 8x4_sf would be a better choice like
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. Yes, based on my benchmarks this is the right choice. I would also make this backend the default automatically in those cases. |
||
| backend=backend, | ||
| ) | ||
|
|
||
| @torch.library.register_fake( | ||
|
|
@@ -407,6 +416,7 @@ def flashinfer_mm_fp4_fake( | |
| B_scale: torch.Tensor, | ||
| g_scale: torch.Tensor, | ||
| dtype: torch.dtype, | ||
| use_8x4_sf_layout: bool, | ||
| backend: str, | ||
| ) -> torch.Tensor: | ||
| return torch.empty(A.shape[0], B.shape[1], dtype=dtype, device=A.device) | ||
|
|
@@ -443,6 +453,36 @@ def bmm_fp8_fake( | |
| A.shape[0], A.shape[1], B.shape[2], dtype=dtype, device=A.device | ||
| ) | ||
|
|
||
| @torch.library.custom_op( | ||
| "vllm::flashinfer_nvfp4_quantize", | ||
| mutates_args=[], | ||
| device_types="cuda", | ||
| ) | ||
| def flashinfer_nvfp4_quantize( | ||
| a: torch.Tensor, | ||
| a_global_sf: torch.Tensor | ||
| ) -> tuple[torch.Tensor, torch.Tensor]: | ||
| from flashinfer import SfLayout | ||
| from flashinfer import nvfp4_quantize as nvfp4_quantize_ | ||
|
|
||
| return nvfp4_quantize_( | ||
| a, a_global_sf, sfLayout=SfLayout.layout_8x4, do_shuffle=False | ||
| ) | ||
|
|
||
| @torch.library.register_fake( | ||
| "vllm::flashinfer_nvfp4_quantize", | ||
| ) | ||
| def flashinfer_nvfp4_quantize_fake( | ||
| a: torch.Tensor, | ||
| a_global_sf: torch.Tensor | ||
| ) -> tuple[torch.Tensor, torch.Tensor]: | ||
| padded_rows = ((a.shape[0] + 7) // 8) * 8 | ||
| return torch.empty( | ||
| a.shape[0], a.shape[1] // 2, dtype=torch.uint8, device=a.device | ||
| ), torch.empty( | ||
| padded_rows, a.shape[1] // 16, dtype=torch.uint8, device=a.device | ||
| ) | ||
|
|
||
|
|
||
| def flashinfer_scaled_fp4_mm( | ||
| a: torch.Tensor, | ||
|
|
@@ -462,13 +502,20 @@ def flashinfer_scaled_fp4_mm( | |
| block_scale_a = block_scale_a.view(torch.uint8) | ||
| block_scale_b = block_scale_b.view(torch.uint8) | ||
|
|
||
| if backend == "trtllm_8x4_sf_layout": | ||
| use_8x4_sf_layout = True | ||
| backend = "trtllm" | ||
| else: | ||
| use_8x4_sf_layout = False | ||
|
|
||
| return flashinfer_mm_fp4( | ||
| a, | ||
| b.t(), | ||
| block_scale_a, | ||
| block_scale_b.t(), | ||
| alpha, | ||
| out_dtype, | ||
| use_8x4_sf_layout=use_8x4_sf_layout, | ||
| backend=backend, | ||
| ) | ||
|
|
||
|
|
@@ -503,6 +550,12 @@ def flashinfer_scaled_fp8_mm( | |
| return output | ||
|
|
||
|
|
||
| def flashinfer_quant_nvfp4_8x4_sf_layout( | ||
| a: torch.Tensor, a_global_sf: torch.Tensor | ||
| ) -> tuple[torch.Tensor, torch.Tensor]: | ||
| return flashinfer_nvfp4_quantize(a, a_global_sf) | ||
|
|
||
|
|
||
| __all__ = [ | ||
| "has_flashinfer", | ||
| "flashinfer_trtllm_fp8_block_scale_moe", | ||
|
|
@@ -525,4 +578,5 @@ def flashinfer_scaled_fp8_mm( | |
| "use_trtllm_attention", | ||
| "flashinfer_scaled_fp4_mm", | ||
| "flashinfer_scaled_fp8_mm", | ||
| "nvfp4_quantize", | ||
|
LopezCastroRoberto marked this conversation as resolved.
Outdated
|
||
| ] | ||
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 wonder if we should enable this by default and let the autotuner pick the suitable tile size. I'm concerned it may cause unintended confusion to the users.