Skip to content

Commit abe806c

Browse files
committed
[KernelGen][MThreads] Add mish_ Moore Threads specialized operator
1 parent 4350421 commit abe806c

2 files changed

Lines changed: 98 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
@@ -45,6 +45,7 @@
4545
)
4646
from .max import max, max_dim
4747
from .min import min, min_dim
48+
from .mish_ import mish_
4849
from .mode import mode
4950
from .nonzero_numpy import nonzero_numpy
5051
from .norm import norm, norm_scalar, norm_scalaropt_dim
@@ -120,6 +121,7 @@
120121
"max_dim",
121122
"min",
122123
"min_dim",
124+
"mish_",
123125
"mode",
124126
"nonzero_numpy",
125127
"norm",
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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.mish import mish_ as default_mish_
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 mish_kernel(
35+
x_ptr,
36+
out_ptr,
37+
n_elements,
38+
BLOCK_SIZE: tl.constexpr,
39+
EVEN: tl.constexpr,
40+
):
41+
# mish(x) = x * tanh(softplus(x)) = x * u * (u + 2) / (u * u + 2 * u + 2),
42+
# where u = exp(x). u is computed via exp2(x * log2e) to hit the fast
43+
# hardware exp2 path on Moore Threads.
44+
LOG2E: tl.constexpr = 1.4426950408889634
45+
pid = tl.program_id(0)
46+
offs = pid * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)
47+
if EVEN:
48+
x = tl.load(x_ptr + offs)
49+
xf = x.to(tl.float32)
50+
u = tl.exp2(xf * LOG2E)
51+
y = xf * u * (u + 2.0) / (u * u + 2.0 * u + 2.0)
52+
tl.store(out_ptr + offs, y.to(x.dtype))
53+
else:
54+
mask = offs < n_elements
55+
x = tl.load(x_ptr + offs, mask=mask, other=0.0)
56+
xf = x.to(tl.float32)
57+
u = tl.exp2(xf * LOG2E)
58+
y = xf * u * (u + 2.0) / (u * u + 2.0 * u + 2.0)
59+
tl.store(out_ptr + offs, y.to(x.dtype), mask=mask)
60+
61+
62+
def _use_triton_kernel(x: torch.Tensor) -> bool:
63+
if not isinstance(x, torch.Tensor):
64+
return False
65+
if x.device.type != "musa" or x.dtype not in _SUPPORTED_DTYPES:
66+
return False
67+
if not x.is_contiguous() or x.numel() == 0:
68+
return False
69+
return True
70+
71+
72+
def _launch_mish(x: torch.Tensor, out: torch.Tensor):
73+
x_flat = x.view(-1)
74+
out_flat = out.view(-1)
75+
n = x_flat.numel()
76+
BLOCK_SIZE = 1024
77+
grid = (triton.cdiv(n, BLOCK_SIZE),)
78+
with torch_device_fn.device(x.device):
79+
mish_kernel[grid](
80+
x_flat,
81+
out_flat,
82+
n,
83+
BLOCK_SIZE=BLOCK_SIZE,
84+
EVEN=(n % BLOCK_SIZE == 0),
85+
)
86+
return out
87+
88+
89+
def mish_(x):
90+
logger.debug("GEMS_MTHREADS MISH_")
91+
if not _use_triton_kernel(x):
92+
return default_mish_(x)
93+
return _launch_mish(x, x)
94+
95+
96+
__all__ = ["mish_"]

0 commit comments

Comments
 (0)