@@ -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" ])
1528def _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
9194def 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