Skip to content

Commit e3a355f

Browse files
author
yuerui
committed
optimize for mlu grouprmsnorm
1 parent e9b55e7 commit e3a355f

1 file changed

Lines changed: 67 additions & 55 deletions

File tree

mojo_opset/backends/ttx/kernels/mlu/group_rmsnorm.py

Lines changed: 67 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,20 @@ def check_supported_dtype(dtype: torch.dtype) -> None:
1111
torch.float32,
1212
), f"dtype must be one of [torch.float16, torch.bfloat16, torch.float32], got {dtype}"
1313

14-
@triton.jit
14+
15+
def cfggen():
16+
block_m = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048]
17+
num_stages = [4]
18+
configs = [
19+
triton.Config({"BLOCK_M": m}, num_stages=s)
20+
for m in block_m
21+
for s in num_stages
22+
]
23+
return configs
24+
25+
26+
@triton.autotune(configs=cfggen(), key=["T", "H", "N"])
27+
@triton.jit(do_not_specialize=["eps"])
1528
def _rmsnorm_fwd_impl(
1629
x_ptr, # x base ptr, shape [T, H, N]
1730
w_ptr, # weight ptr, shape [N]
@@ -27,66 +40,56 @@ def _rmsnorm_fwd_impl(
2740
stride_yn, # y stride for norm dim,要求=1
2841
eps,
2942
BLOCK_N: tl.constexpr,
43+
BLOCK_M: tl.constexpr,
3044
HAS_WEIGHT: tl.constexpr,
45+
USE_DOT: tl.constexpr,
3146
):
3247
pid = tl.program_id(0)
3348
num_pid = tl.num_programs(0)
3449
M = T * H
50+
ones = tl.full((1, BLOCK_N), 1.0, dtype=tl.float32)
3551

36-
row = pid
37-
while row < M:
38-
token_id = row // H
39-
head_id = row % H
40-
41-
# x[token_id, head_id, :]
42-
# = x_ptr + token_id * stride_xt + head_id * stride_xh + n * stride_xn
43-
#
44-
x_row_base = token_id * stride_xt + head_id * stride_xh
45-
y_row_base = token_id * stride_yt + head_id * stride_yh
46-
47-
acc = 0.0
48-
start_n = 0
49-
while start_n < N:
50-
offs_n = start_n + tl.arange(0, BLOCK_N)
51-
mask = offs_n < N
52-
x = tl.load(
53-
x_ptr + x_row_base + offs_n * stride_xn,
54-
mask=mask,
55-
other=0.0,
56-
)
57-
x = x.to(tl.float32)
58-
acc += tl.sum(x * x, axis=0)
59-
start_n += BLOCK_N
52+
for row_start in range(pid * BLOCK_M, M, num_pid * BLOCK_M):
53+
offs_m = row_start + tl.arange(0, BLOCK_M)
54+
mask_m = offs_m < M
55+
56+
token_id = offs_m // H
57+
head_id = offs_m % H
58+
59+
x_base = token_id * stride_xt + head_id * stride_xh
60+
y_base = token_id * stride_yt + head_id * stride_yh
61+
62+
# 一次性加载整行 N 个元素(因为 BLOCK_N >= N)
63+
offs_n = tl.arange(0, BLOCK_N)
64+
mask_n = offs_n < N
65+
66+
addr_x = x_ptr + x_base[:, None] + offs_n[None, :] * stride_xn
67+
mask_2d = mask_m[:, None] & mask_n[None, :]
68+
x_f32 = tl.load(addr_x, mask=mask_2d, other=0.0).to(tl.float32)
69+
70+
if USE_DOT:
71+
sq = x_f32 * x_f32
72+
acc = tl.reshape(tl.dot(ones, tl.trans(sq), allow_tf32=False), (BLOCK_M,))
73+
else:
74+
acc = tl.sum(x_f32 * x_f32, axis=1)
6075
mean_sq = acc / N
6176
rstd = tl.rsqrt(mean_sq + eps)
6277

63-
start_n = 0
64-
while start_n < N:
65-
offs_n = start_n + tl.arange(0, BLOCK_N)
66-
mask = offs_n < N
67-
x = tl.load(
68-
x_ptr + x_row_base + offs_n * stride_xn,
69-
mask=mask,
70-
other=0.0,
71-
)
72-
x_fp32 = x.to(tl.float32)
73-
if HAS_WEIGHT:
74-
w = tl.load(
75-
w_ptr + offs_n,
76-
mask=mask,
77-
other=1.0,
78-
)
79-
w_fp32 = w.to(tl.float32)
80-
y_fp32 = x_fp32 * rstd * w_fp32
78+
if HAS_WEIGHT:
79+
w = tl.load(w_ptr + offs_n, mask=mask_n, other=1.0)
80+
w_f32 = w.to(tl.float32)
81+
if USE_DOT:
82+
y_f32 = tl.dot(tl.reshape(rstd, (BLOCK_M, 1)), ones, allow_tf32=False) * x_f32 * w_f32[None, :]
8183
else:
82-
y_fp32 = x_fp32 * rstd
83-
tl.store(
84-
y_ptr + y_row_base + offs_n * stride_yn,
85-
y_fp32,
86-
mask=mask,
87-
)
88-
start_n += BLOCK_N
89-
row += num_pid
84+
y_f32 = x_f32 * rstd[:, None] * w_f32[None, :]
85+
else:
86+
if USE_DOT:
87+
y_f32 = tl.dot(tl.reshape(rstd, (BLOCK_M, 1)), ones, allow_tf32=False) * x_f32
88+
else:
89+
y_f32 = x_f32 * rstd[:, None]
90+
91+
addr_y = y_ptr + y_base[:, None] + offs_n[None, :] * stride_yn
92+
tl.store(addr_y, y_f32, mask=mask_2d)
9093

9194
def rmsnorm_fwd_triton(
9295
x,
@@ -98,13 +101,15 @@ def rmsnorm_fwd_triton(
98101
assert x.ndim == 3, f"x must be 3D [token, num_head, norm_size], got {x.shape}"
99102
T, H, N = x.shape
100103
assert x.stride(2) == 1, f"x last dim must be contiguous, got stride={x.stride()}"
104+
assert N <= 8192, f"x last size must be <= 8192, got token={x.size(-1)}"
101105
if weight is not None:
102106
assert weight.dtype == x.dtype
103107
assert weight.shape == (N,)
104108
assert weight.is_contiguous()
105109
has_weight = True
106110
else:
107111
has_weight = False
112+
108113
if output_like_input_stride:
109114
y = torch.empty_strided(
110115
size=x.shape,
@@ -116,10 +121,16 @@ def rmsnorm_fwd_triton(
116121
y = torch.empty_like(x, memory_format=torch.contiguous_format)
117122
assert y.stride(2) == 1, f"y last dim must be contiguous, got stride={y.stride()}"
118123

119-
block_n = min(triton.next_power_of_2(N), 1024)
120-
grid_size = get_mlu_total_cores()
121-
total_rows = T * H
122-
grid = (min(grid_size, total_rows),)
124+
block_n = min(triton.next_power_of_2(N), 8192)
125+
126+
grid = lambda meta: (
127+
min(get_mlu_total_cores(), triton.cdiv(T * H, meta['BLOCK_M'])),
128+
)
129+
if N > 1024:
130+
use_dot = False
131+
else:
132+
use_dot = True
133+
123134
_rmsnorm_fwd_impl[grid](
124135
x,
125136
weight,
@@ -136,6 +147,7 @@ def rmsnorm_fwd_triton(
136147
eps,
137148
BLOCK_N=block_n,
138149
HAS_WEIGHT=has_weight,
150+
USE_DOT=use_dot,
139151
)
140152
return y
141153

0 commit comments

Comments
 (0)