Skip to content

Commit 2f17de1

Browse files
committed
[KernelGen][MThreads] Add silu_backward Moore Threads specialized operator
1 parent b44d2fd commit 2f17de1

2 files changed

Lines changed: 90 additions & 0 deletions

File tree

src/flag_gems/runtime/backend/_mthreads/ops/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
from .resolve_conj import resolve_conj
8686
from .round_ import round_
8787
from .softplus_backward import softplus_backward
88+
from .silu_backward import silu_backward
8889
from .sort import sort, sort_stable
8990
from .special_gammainc import special_gammainc
9091
from .tile import tile
@@ -180,6 +181,7 @@
180181
"resolve_conj",
181182
"round_",
182183
"softplus_backward",
184+
"silu_backward",
183185
"sort",
184186
"sort_stable",
185187
"special_gammainc",
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Copyright 2026 FlagOS Contributors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import logging
16+
17+
import torch
18+
import triton
19+
import triton.language as tl
20+
21+
from flag_gems.ops.silu import silu_backward as default_silu_backward
22+
from flag_gems.runtime import torch_device_fn
23+
from flag_gems.utils import libentry
24+
25+
logger = logging.getLogger(
26+
f'flag_gems.runtime.backend._mthreads.ops.{__name__.split(".")[-1]}'
27+
)
28+
29+
_SUPPORTED_DTYPES = {torch.float16, torch.bfloat16, torch.float32}
30+
31+
32+
@libentry()
33+
@triton.jit
34+
def silu_bwd_kernel(
35+
grad_ptr,
36+
x_ptr,
37+
out_ptr,
38+
n_elements,
39+
BLOCK: tl.constexpr,
40+
):
41+
pid = tl.program_id(0)
42+
offs = pid * BLOCK + tl.arange(0, BLOCK)
43+
mask = offs < n_elements
44+
g = tl.load(grad_ptr + offs, mask=mask)
45+
x = tl.load(x_ptr + offs, mask=mask)
46+
# silu'(x) = sigmoid(x) * (1 + x * (1 - sigmoid(x)))
47+
gf = g.to(tl.float32)
48+
xf = x.to(tl.float32)
49+
sig = 1.0 / (1.0 + tl.exp(-xf))
50+
res = gf * (sig * (1.0 + xf * (1.0 - sig)))
51+
tl.store(out_ptr + offs, res.to(x.dtype), mask=mask)
52+
53+
54+
def _use_triton_kernel(grad: torch.Tensor, x: torch.Tensor) -> bool:
55+
if not isinstance(grad, torch.Tensor) or not isinstance(x, torch.Tensor):
56+
return False
57+
if grad.device.type != "musa" or grad.dtype not in _SUPPORTED_DTYPES:
58+
return False
59+
if grad.dtype != x.dtype or grad.shape != x.shape:
60+
return False
61+
if not grad.is_contiguous() or not x.is_contiguous():
62+
return False
63+
if grad.numel() == 0:
64+
return False
65+
return True
66+
67+
68+
def silu_backward(grad_output: torch.Tensor, self_input: torch.Tensor):
69+
logger.debug("GEMS_MTHREADS SILU_BACKWARD")
70+
if not _use_triton_kernel(grad_output, self_input):
71+
return default_silu_backward(grad_output, self_input)
72+
73+
n = grad_output.numel()
74+
# dtype/size-tuned block: fp16/bf16 use BLOCK=512, large fp32 uses 4096,
75+
# otherwise 2048. Hardcoded (no autotune) — the kernel is out-of-place so
76+
# autotune would be safe, but the tuned bands above already cover the
77+
# working set regimes.
78+
if grad_output.dtype.itemsize == 2:
79+
BLOCK = 512
80+
elif n >= (1 << 26):
81+
BLOCK = 4096
82+
else:
83+
BLOCK = 2048
84+
grid = (triton.cdiv(n, BLOCK),)
85+
with torch_device_fn.device(grad_output.device):
86+
out = torch.empty_like(grad_output)
87+
silu_bwd_kernel[grid](grad_output, self_input, out, n, BLOCK=BLOCK, num_warps=4)
88+
return out

0 commit comments

Comments
 (0)