Skip to content

Commit 9256c0b

Browse files
committed
fix: address PR review issues
- P1: keep use_fused_kernels opt-in (false default) for backward compat - P1: split weight at midpoint not at K, supporting expansion_factor != 1 - P2: add N param (GLU output dim) separate from K (input/conraction dim) - P2: save ctx.N for backward wrapper calculations
1 parent 6058ec5 commit 9256c0b

2 files changed

Lines changed: 44 additions & 37 deletions

File tree

configs/base.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ nccl_p2p: true
8585
###########
8686
# fusing
8787
###########
88-
use_fused_kernels: true
88+
use_fused_kernels: false
8989

9090
###########
9191
# finetune

modules/kernels/fused_linear_softsign_glu.py

Lines changed: 43 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
def _fused_linear_softsign_glu_fwd_kernel(
4040
x_ptr, w_left_ptr, w_right_ptr, b_left_ptr, b_right_ptr,
4141
y_ptr, left_ptr, gate_ptr,
42-
M, K,
42+
M, N, K,
4343
stride_x_b, stride_x_k,
4444
stride_wl_n, stride_wl_k,
4545
stride_wr_n, stride_wr_k,
@@ -50,13 +50,15 @@ def _fused_linear_softsign_glu_fwd_kernel(
5050
):
5151
"""
5252
y = (x @ W_left^T + b_left) * softsign(x @ W_right^T + b_right)
53-
where softsign(x) = x / (1 + |x|).
5453
55-
2D grid over (M // BLOCK_M, K // BLOCK_N).
54+
N = output dim per GLU half (= inner_dim = dim × expansion_factor)
55+
K = input feature dim (= dim for first Linear, inner_dim for second)
56+
57+
2D grid over (M // BLOCK_M, N // BLOCK_N).
5658
"""
5759
pid = tl.program_id(0)
5860
num_pid_m = tl.cdiv(M, BLOCK_M)
59-
num_pid_n = tl.cdiv(K, BLOCK_N)
61+
num_pid_n = tl.cdiv(N, BLOCK_N)
6062
pid_m = pid // num_pid_n
6163
pid_n = pid % num_pid_n
6264

@@ -65,9 +67,9 @@ def _fused_linear_softsign_glu_fwd_kernel(
6567
offs_k = tl.arange(0, BLOCK_K)
6668

6769
m_mask_2d = offs_m[:, None] < M
68-
n_mask_nk = offs_n[:, None] < K # [BLOCK_N, 1] for N×K weight access
69-
n_mask_mn = offs_n[None, :] < K # [1, BLOCK_N] for M×N output access
70-
n_mask_1d = offs_n < K
70+
n_mask_nk = offs_n[:, None] < N # [BLOCK_N, 1] for N×K weight access
71+
n_mask_mn = offs_n[None, :] < N # [1, BLOCK_N] for M×N output access
72+
n_mask_1d = offs_n < N
7173

7274
acc_left = tl.zeros([BLOCK_M, BLOCK_N], dtype=tl.float32)
7375
acc_gate = tl.zeros([BLOCK_M, BLOCK_N], dtype=tl.float32)
@@ -137,7 +139,7 @@ def _fused_linear_softsign_glu_bwd_kernel(
137139
left_ptr, gate_ptr, grad_y_ptr,
138140
grad_x_ptr,
139141
w_left_ptr, w_right_ptr,
140-
M, K,
142+
M, K, N,
141143
stride_l_b, stride_l_n,
142144
stride_g_b, stride_g_n,
143145
stride_gy_b, stride_gy_n,
@@ -166,10 +168,10 @@ def _fused_linear_softsign_glu_bwd_kernel(
166168
k_mask_nk = offs_k[None, :] < K
167169
acc = tl.zeros([BLOCK_M, BLOCK_K], dtype=tl.float32)
168170

169-
for n_start in range(0, K, BLOCK_N):
171+
for n_start in range(0, N, BLOCK_N):
170172
n_offs = n_start + offs_n
171-
n_mask_mn = n_offs[None, :] < K
172-
n_mask_nk = n_offs[:, None] < K
173+
n_mask_mn = n_offs[None, :] < N
174+
n_mask_nk = n_offs[:, None] < N
173175

174176
left = tl.load(
175177
left_ptr + offs_m[:, None] * stride_l_b + n_offs[None, :] * stride_l_n,
@@ -278,24 +280,25 @@ class FusedLinearSoftSignGLUFn(torch.autograd.Function):
278280
@staticmethod
279281
def forward(ctx, x, weight, bias):
280282
orig_shape = x.shape
281-
K = weight.shape[1]
283+
K = weight.shape[1] # input feature dim (contraction dim)
284+
N = weight.shape[0] // 2 # output dim per GLU half
282285
x_2d = x.reshape(-1, K)
283286
M = x_2d.shape[0]
284287

285-
w_left, w_right = weight.split(K, dim=0)
286-
b_left, b_right = bias.split(K, dim=0)
288+
w_left, w_right = weight.split(N, dim=0)
289+
b_left, b_right = bias.split(N, dim=0)
287290

288-
out = torch.empty(M, K, device=x.device, dtype=x.dtype)
289-
left = torch.empty(M, K, device=x.device, dtype=x.dtype)
290-
gate = torch.empty(M, K, device=x.device, dtype=x.dtype)
291+
out = torch.empty(M, N, device=x.device, dtype=x.dtype)
292+
left = torch.empty(M, N, device=x.device, dtype=x.dtype)
293+
gate = torch.empty(M, N, device=x.device, dtype=x.dtype)
291294

292295
def grid(meta):
293-
return (triton.cdiv(M, meta['BLOCK_M']) * triton.cdiv(K, meta['BLOCK_N']),)
296+
return (triton.cdiv(M, meta['BLOCK_M']) * triton.cdiv(N, meta['BLOCK_N']),)
294297

295298
_fused_linear_softsign_glu_fwd_kernel[grid](
296299
x_2d, w_left, w_right, b_left, b_right,
297300
out, left, gate,
298-
M, K,
301+
M, N, K,
299302
x_2d.stride(0), x_2d.stride(1),
300303
w_left.stride(0), w_left.stride(1),
301304
w_right.stride(0), w_right.stride(1),
@@ -305,34 +308,36 @@ def grid(meta):
305308
)
306309

307310
if x.dim() > 2:
308-
out = out.view(*orig_shape[:-1], K)
309-
left = left.view(M, K)
310-
gate = gate.view(M, K)
311+
out = out.view(*orig_shape[:-1], N)
312+
left = left.view(M, N)
313+
gate = gate.view(M, N)
311314

312315
ctx.save_for_backward(x_2d, weight, left, gate)
313316
ctx.orig_x_shape = orig_shape
317+
ctx.N = N
314318
return out
315319

316320
@staticmethod
317321
def backward(ctx, grad_y):
318322
x, weight, left, gate = ctx.saved_tensors
319323
M, K = x.shape
320-
w_left, w_right = weight.split(K, dim=0)
324+
N = ctx.N
325+
w_left, w_right = weight.split(N, dim=0)
321326

322327
if grad_y.dim() > 2:
323-
grad_y = grad_y.reshape(-1, K)
328+
grad_y = grad_y.reshape(-1, N)
324329

325330
# Step 1: Fused element-wise SoftSignGLU backward
326-
grad_left_pre = torch.empty(M, K, device=x.device, dtype=x.dtype)
327-
grad_gate = torch.empty(M, K, device=x.device, dtype=x.dtype)
331+
grad_left_pre = torch.empty(M, N, device=x.device, dtype=x.dtype)
332+
grad_gate = torch.empty(M, N, device=x.device, dtype=x.dtype)
328333

329334
def elem_grid(meta):
330-
return (triton.cdiv(M, meta['BLOCK_M']) * triton.cdiv(K, meta['BLOCK_K']),)
335+
return (triton.cdiv(M, meta['BLOCK_M']) * triton.cdiv(N, meta['BLOCK_K']),)
331336

332337
_softsign_glu_bwd_elem_kernel[elem_grid](
333338
left, gate, grad_y,
334339
grad_left_pre, grad_gate,
335-
M, K,
340+
M, N, N,
336341
left.stride(0), left.stride(1),
337342
gate.stride(0), gate.stride(1),
338343
grad_y.stride(0), grad_y.stride(1),
@@ -356,7 +361,7 @@ def bwd_grid(meta):
356361
left, gate, grad_y,
357362
grad_x,
358363
w_left, w_right,
359-
M, K,
364+
M, K, N,
360365
left.stride(0), left.stride(1),
361366
gate.stride(0), gate.stride(1),
362367
grad_y.stride(0), grad_y.stride(1),
@@ -376,20 +381,22 @@ def bwd_grid(meta):
376381
# ---------------------------------------------------------------------------
377382

378383
def fused_linear_softsign_glu(x, weight, bias):
379-
"""Fused Linear(2K, K) + SoftSignGLU.
384+
"""Fused Linear(C, 2*C) + SoftSignGLU, where C = dim (expansion_factor×dim).
380385
381386
y = left * gate / (1 + |gate|)
382387
388+
Supports expansion_factor != 1 by splitting weight at midpoint.
389+
383390
Args:
384-
x: Input [..., K]
385-
weight: [2*K, K]
386-
bias: [2*K]
391+
x: Input [..., K] where K = weight.shape[1] (input dim)
392+
weight: [2*N, K] where N = output dim per GLU half (= K × expansion_factor)
393+
bias: [2*N]
387394
388395
Returns:
389-
[..., K]
396+
[..., N]
390397
"""
391-
assert weight.shape[0] == 2 * weight.shape[1], \
392-
f"Expected [2*K, K], got {weight.shape}"
398+
N = weight.shape[0] // 2
399+
K = weight.shape[1]
393400
# Match weight/bias dtype to input (handles 16-mixed precision where
394401
# weights are fp32 but activations are autocast to fp16)
395402
if weight.dtype != x.dtype:

0 commit comments

Comments
 (0)