Skip to content

Commit f04b970

Browse files
micah-wilcharlifu
authored andcommitted
Use fusion pass to select AITER group quant RMSNorm and w8a8 gemm (#707)
* initial aiter rms group quant fusion work * aiter rms norm group quant fusion * remove debug prints Signed-off-by: charlifu <charlifu@amd.com>
1 parent 42a395e commit f04b970

2 files changed

Lines changed: 228 additions & 1 deletion

File tree

vllm/compilation/fusion.py

Lines changed: 151 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from torch._inductor.pattern_matcher import PatternMatcherPass
1010
from torch._ops import OpOverload
1111

12+
import vllm.envs as envs
1213
from vllm.config import VllmConfig
1314
from vllm.logger import init_logger
1415
from vllm.model_executor.layers.quantization.utils.quant_utils import (
@@ -76,6 +77,22 @@ def __str__(self):
7677
torch.ops._C.rms_norm_dynamic_per_token_quant.default, # noqa: E501
7778
}
7879

80+
if current_platform.is_rocm() and envs.VLLM_ROCM_USE_AITER:
81+
AITER_RMS_GROUP_QUANT_OP = \
82+
torch.ops.vllm.rocm_aiter_rmsnorm_fp8_group_quant.default
83+
AITER_RMS_ADD_GROUP_QUANT_OP = \
84+
torch.ops.vllm.rocm_aiter_rmsnorm_with_add_fp8_group_quant.default
85+
86+
BLOCK_LINEAR_OP = torch.ops.vllm.apply_w8a8_block_fp8_linear.default
87+
AITER_BLOCK_LINEAR_OP = \
88+
torch.ops.vllm.rocm_aiter_gemm_w8a8_blockscale.default
89+
90+
AITER_RMS_OP = torch.ops.vllm.rocm_aiter_rms_norm.default
91+
AITER_RMS_ADD_OP = torch.ops.vllm.rocm_aiter_rmsnorm2d_fwd_with_add.default
92+
93+
import aiter as rocm_aiter
94+
rocm_aiter_fp8_dtype = rocm_aiter.dtypes.fp8
95+
rocm_aiter_fp8_quant_group_size = 128
7996

8097
class RMSNormQuantPattern:
8198

@@ -336,6 +353,129 @@ def replacement(result: torch.Tensor, input: torch.Tensor,
336353
pm.fwd_only,
337354
pm_pass,
338355
)
356+
357+
358+
class AiterRMSGroupQuantFP8Pattern():
359+
360+
def __init__(self,
361+
epsilon: float,
362+
quant_dtype: torch.dtype):
363+
self.epsilon = epsilon
364+
self.quant_dtype = quant_dtype
365+
366+
def register(self, pm_pass: PatternMatcherPass):
367+
368+
def pattern(input: torch.Tensor, weight: torch.Tensor, #result_rms: torch.Tensor,
369+
linear_weight: torch.Tensor,
370+
linear_weight_scale: torch.Tensor):
371+
at1 = AITER_RMS_OP(x=input,
372+
weight=weight,
373+
variance_epsilon=self.epsilon)
374+
375+
at2 = BLOCK_LINEAR_OP(input=at1,
376+
weight=linear_weight,
377+
block_size=[128, 128],
378+
weight_scale=linear_weight_scale,
379+
input_scale=None,
380+
bias=None,
381+
cutlass_block_fp8_supported=False,
382+
use_aiter_and_is_supported=True)
383+
384+
return at2
385+
386+
def replacement(input: torch.Tensor, weight: torch.Tensor,
387+
linear_weight: torch.Tensor,
388+
linear_weight_scale: torch.Tensor):
389+
at1 = AITER_RMS_GROUP_QUANT_OP(x=input,
390+
residual=None,
391+
weight=weight,
392+
variance_epsilon=self.epsilon)
393+
394+
at2 = AITER_BLOCK_LINEAR_OP(A=at1[0],
395+
B=linear_weight,
396+
As=at1[1],
397+
Bs=linear_weight_scale,
398+
block_size=[128, 128],
399+
output_dtype=input.dtype)
400+
401+
return at2
402+
403+
inputs = [
404+
empty_bf16(5, 4), # input
405+
empty_bf16(1, 5), # weight
406+
torch.empty((2, 5), device="cuda", dtype=FP8_DTYPE), # linear_weight
407+
empty_fp32(1, 1), # linear_weight_scale
408+
]
409+
410+
pm.register_replacement(
411+
pattern,
412+
replacement,
413+
inputs,
414+
pm.fwd_only,
415+
pm_pass)
416+
417+
418+
class AiterFusedAddRMSGroupQuantPattern():
419+
420+
def __init__(self,
421+
epsilon: float,
422+
quant_dtype: torch.dtype):
423+
self.epsilon = epsilon
424+
self.quant_dtype = quant_dtype
425+
426+
def register(self, pm_pass: PatternMatcherPass):
427+
428+
def pattern(input: torch.Tensor, residual: torch.Tensor, weight: torch.Tensor,
429+
linear_weight: torch.Tensor,
430+
linear_weight_scale: torch.Tensor):
431+
at1 = AITER_RMS_ADD_OP(x=input,
432+
residual=residual,
433+
weight=weight,
434+
variance_epsilon=self.epsilon)
435+
436+
at2 = BLOCK_LINEAR_OP(input=at1[0],
437+
weight=linear_weight,
438+
block_size=[128, 128],
439+
weight_scale=linear_weight_scale,
440+
input_scale=None,
441+
bias=None,
442+
cutlass_block_fp8_supported=False,
443+
use_aiter_and_is_supported=True)
444+
# result, residual
445+
return at2, at1[1]
446+
447+
def replacement(input: torch.Tensor, residual: torch.Tensor, weight: torch.Tensor,
448+
linear_weight: torch.Tensor,
449+
linear_weight_scale: torch.Tensor):
450+
451+
at1 = AITER_RMS_ADD_GROUP_QUANT_OP(x=input,
452+
residual=residual,
453+
weight=weight,
454+
variance_epsilon=self.epsilon)
455+
456+
at2 = AITER_BLOCK_LINEAR_OP(A=at1[0],
457+
B=linear_weight,
458+
As=at1[1],
459+
Bs=linear_weight_scale,
460+
block_size=[128, 128],
461+
output_dtype=input.dtype)
462+
# result, residual
463+
return at2, at1[2]
464+
465+
inputs = [
466+
empty_bf16(5, 4), # input
467+
empty_bf16(5, 4), # residual
468+
empty_bf16(1, 5), # weight
469+
torch.empty((2, 5), device="cuda", dtype=FP8_DTYPE), # linear_weight
470+
empty_fp32(1, 1), # linear_weight_scale
471+
]
472+
473+
pm.register_replacement(
474+
pattern,
475+
replacement,
476+
inputs,
477+
pm.fwd_only,
478+
pm_pass)
339479

340480

341481
class RMSNormQuantFusionPass(VllmPatternMatcherPass):
@@ -367,6 +507,14 @@ def __init__(self, config: VllmConfig):
367507
# Fuse fused_add_rms_norm + dynamic per-token fp8 quant
368508
FusedAddRMSNormDynamicQuantPattern(epsilon, FP8_DTYPE).register(
369509
self.patterns)
510+
511+
if envs.VLLM_ROCM_USE_AITER:
512+
# Fuse rms_norm + dynamic group fp8 quant
513+
AiterRMSGroupQuantFP8Pattern(epsilon, FP8_DTYPE).register(
514+
self.patterns)
515+
516+
AiterFusedAddRMSGroupQuantPattern(epsilon, FP8_DTYPE).register(
517+
self.patterns)
370518

371519
self.dump_patterns(config, self.patterns)
372520

@@ -380,4 +528,6 @@ def uuid(self) -> Any:
380528
RMSNormStaticQuantPattern,
381529
RMSNormDynamicQuantPattern,
382530
FusedAddRMSNormStaticQuantPattern,
383-
FusedAddRMSNormDynamicQuantPattern)
531+
FusedAddRMSNormDynamicQuantPattern,
532+
AiterRMSGroupQuantFP8Pattern,
533+
AiterFusedAddRMSGroupQuantPattern)

vllm/model_executor/layers/layernorm.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ def is_rocm_aiter_rmsnorm_enabled() -> bool:
1616
return envs.VLLM_ROCM_USE_AITER_RMSNORM \
1717
and envs.VLLM_ROCM_USE_AITER
1818

19+
if current_platform.is_rocm() and is_rocm_aiter_rmsnorm_enabled():
20+
import aiter as rocm_aiter
21+
from aiter.ops.triton.fused_fp8_quant import fused_rms_fp8_group_quant
22+
rocm_aiter_fp8_dtype = rocm_aiter.dtypes.fp8
23+
rocm_aiter_fp8_quant_group_size = 128
1924

2025
def rms_norm(x: torch.Tensor, weight: torch.Tensor,
2126
variance_epsilon: float) -> torch.Tensor:
@@ -88,6 +93,44 @@ def rocm_aiter_rmsnorm2d_fwd_with_add_impl(
8893
return output, residual_out
8994

9095

96+
def rocm_aiter_rmsnorm_with_add_fp8_group_quant_impl(
97+
x: torch.Tensor, residual: torch.Tensor, weight: torch.Tensor,
98+
variance_epsilon: float) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
99+
import aiter as rocm_aiter
100+
(x_quant, x_quant_scales), _, _, res = \
101+
fused_rms_fp8_group_quant(
102+
x,
103+
weight,
104+
variance_epsilon,
105+
None,
106+
None,
107+
None,
108+
group_size=rocm_aiter_fp8_quant_group_size,
109+
dtype_quant=rocm_aiter_fp8_dtype,
110+
res1=residual,
111+
)
112+
return (x_quant, x_quant_scales, res)
113+
114+
115+
def rocm_aiter_rmsnorm_fp8_group_quant_impl(
116+
x: torch.Tensor, residual: torch.Tensor, weight: torch.Tensor,
117+
variance_epsilon: float) -> tuple[torch.Tensor, torch.Tensor]:
118+
import aiter as rocm_aiter
119+
(x_quant, x_quant_scales), _, _, res = \
120+
fused_rms_fp8_group_quant(
121+
x,
122+
weight,
123+
variance_epsilon,
124+
None,
125+
None,
126+
None,
127+
group_size=rocm_aiter_fp8_quant_group_size,
128+
dtype_quant=rocm_aiter_fp8_dtype,
129+
res1=residual,
130+
)
131+
return (x_quant, x_quant_scales)
132+
133+
91134
def rocm_aiter_rms_norm_fake(x: torch.Tensor, weight: torch.Tensor,
92135
variance_epsilon: float) -> torch.Tensor:
93136
return torch.empty_like(x)
@@ -99,6 +142,24 @@ def rocm_aiter_rmsnorm2d_fwd_with_add_fake(
99142
return torch.empty_like(x), torch.empty_like(residual)
100143

101144

145+
def rocm_aiter_rmsnorm_with_add_fp8_group_quant_fake(
146+
x: torch.Tensor, residual: torch.Tensor, weight: torch.Tensor,
147+
variance_epsilon: float) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
148+
M, N = x.shape
149+
scale_shape = (M, (N + rocm_aiter_fp8_quant_group_size - 1) // rocm_aiter_fp8_quant_group_size)
150+
return (torch.empty_like(x, dtype=rocm_aiter_fp8_dtype, device=x.device),
151+
torch.empty(scale_shape, dtype=torch.float32, device=x.device),
152+
torch.empty_like(residual, device=residual.device))
153+
154+
155+
def rocm_aiter_rmsnorm_fp8_group_quant_fake(
156+
x: torch.Tensor, residual: torch.Tensor, weight: torch.Tensor,
157+
variance_epsilon: float) -> tuple[torch.Tensor, torch.Tensor]:
158+
M, N = x.shape
159+
scale_shape = (M, (N + rocm_aiter_fp8_quant_group_size - 1) // rocm_aiter_fp8_quant_group_size)
160+
return (torch.empty_like(x, dtype=rocm_aiter_fp8_dtype, device=x.device), torch.empty(scale_shape, dtype=torch.float32, device=x.device))
161+
162+
102163
if current_platform.is_rocm():
103164
direct_register_custom_op(
104165
op_name="rocm_aiter_rms_norm",
@@ -115,6 +176,22 @@ def rocm_aiter_rmsnorm2d_fwd_with_add_fake(
115176
fake_impl=rocm_aiter_rmsnorm2d_fwd_with_add_fake,
116177
dispatch_key=current_platform.dispatch_key,
117178
)
179+
180+
direct_register_custom_op(
181+
op_name="rocm_aiter_rmsnorm_fp8_group_quant",
182+
op_func=rocm_aiter_rmsnorm_fp8_group_quant_impl,
183+
mutates_args=[],
184+
fake_impl=rocm_aiter_rmsnorm_fp8_group_quant_fake,
185+
dispatch_key=current_platform.dispatch_key,
186+
)
187+
188+
direct_register_custom_op(
189+
op_name="rocm_aiter_rmsnorm_with_add_fp8_group_quant",
190+
op_func=rocm_aiter_rmsnorm_with_add_fp8_group_quant_impl,
191+
mutates_args=[],
192+
fake_impl=rocm_aiter_rmsnorm_with_add_fp8_group_quant_fake,
193+
dispatch_key=current_platform.dispatch_key,
194+
)
118195

119196

120197
def dispatch_rocm_rmsnorm_func(with_fused_add: bool, dtype: torch.dtype):

0 commit comments

Comments
 (0)