Skip to content

Commit 91980a2

Browse files
Schopenhauer-loves-Hegelfactnnclaude
authored andcommitted
feat: add rsub operator with tests and benchmark (flagos-ai#1761)
Co-authored-by: factnn <1050552884@qq.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 9bf465e commit 91980a2

5 files changed

Lines changed: 115 additions & 0 deletions

File tree

benchmark/test_rsub.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import pytest
2+
import torch
3+
4+
from . import base, consts, utils
5+
6+
7+
def _tensor_input_fn(shape, dtype, device):
8+
inp1 = utils.generate_tensor_input(shape, dtype, device)
9+
inp2 = utils.generate_tensor_input(shape, dtype, device)
10+
yield inp1, inp2
11+
12+
13+
def _scalar_input_fn(shape, dtype, device):
14+
inp1 = utils.generate_tensor_input(shape, dtype, device)
15+
yield inp1, 0.5
16+
17+
18+
@pytest.mark.rsub_tensor
19+
def test_rsub_tensor():
20+
bench = base.GenericBenchmark(
21+
input_fn=_tensor_input_fn,
22+
op_name="rsub.Tensor",
23+
torch_op=torch.rsub,
24+
dtypes=consts.FLOAT_DTYPES,
25+
)
26+
bench.run()
27+
28+
29+
@pytest.mark.rsub_scalar
30+
def test_rsub_scalar():
31+
bench = base.GenericBenchmark(
32+
input_fn=_scalar_input_fn,
33+
op_name="rsub.Scalar",
34+
torch_op=torch.rsub,
35+
dtypes=consts.FLOAT_DTYPES,
36+
)
37+
bench.run()

src/flag_gems/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,8 @@ def torch_ge(v):
410410
("rrelu_with_noise_backward", rrelu_with_noise_backward),
411411
("rsqrt", rsqrt),
412412
("rsqrt_", rsqrt_),
413+
("rsub.Scalar", rsub_scalar),
414+
("rsub.Tensor", rsub_tensor),
413415
("scaled_softmax_backward", scaled_softmax_backward),
414416
("scaled_softmax_forward", scaled_softmax_forward),
415417
("scatter.reduce", scatter),

src/flag_gems/ops/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@
277277
from flag_gems.ops.round import round, round_, round_out
278278
from flag_gems.ops.rrelu_with_noise_backward import rrelu_with_noise_backward
279279
from flag_gems.ops.rsqrt import rsqrt, rsqrt_
280+
from flag_gems.ops.rsub import rsub_scalar, rsub_tensor
280281
from flag_gems.ops.scaled_softmax import scaled_softmax_backward, scaled_softmax_forward
281282
from flag_gems.ops.scatter import scatter, scatter_
282283
from flag_gems.ops.scatter_add_ import scatter_add_
@@ -697,6 +698,8 @@
697698
"rrelu_with_noise_backward",
698699
"rsqrt",
699700
"rsqrt_",
701+
"rsub_scalar",
702+
"rsub_tensor",
700703
"scaled_dot_product_attention",
701704
"scaled_dot_product_attention_backward",
702705
"scaled_dot_product_attention_forward",

src/flag_gems/ops/rsub.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import logging
2+
3+
import triton
4+
5+
from flag_gems.utils import pointwise_dynamic
6+
7+
logger = logging.getLogger(__name__)
8+
9+
10+
@pointwise_dynamic(is_tensor=[True, True, False], promotion_methods=[(0, 1, "DEFAULT")])
11+
@triton.jit
12+
def rsub_func(x, y, alpha):
13+
return y - x * alpha
14+
15+
16+
@pointwise_dynamic(
17+
is_tensor=[True, False, False], promotion_methods=[(0, 1, "DEFAULT")]
18+
)
19+
@triton.jit
20+
def rsub_func_tensor_scalar(x, y, alpha):
21+
return y - x * alpha
22+
23+
24+
def rsub_tensor(A, B, *, alpha=1):
25+
logger.debug("GEMS RSUB_TENSOR")
26+
return rsub_func(A, B, alpha)
27+
28+
29+
def rsub_scalar(A, B, alpha=1):
30+
logger.debug("GEMS RSUB_SCALAR")
31+
return rsub_func_tensor_scalar(A, B, alpha)

tests/test_rsub.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import pytest
2+
import torch
3+
4+
import flag_gems
5+
6+
from .accuracy_utils import (
7+
FLOAT_DTYPES,
8+
POINTWISE_SHAPES,
9+
gems_assert_close,
10+
to_reference,
11+
)
12+
13+
14+
@pytest.mark.rsub_tensor
15+
@pytest.mark.parametrize("shape", POINTWISE_SHAPES)
16+
@pytest.mark.parametrize("dtype", FLOAT_DTYPES)
17+
def test_rsub_tensor(shape, dtype):
18+
inp1 = torch.randn(shape, dtype=dtype, device=flag_gems.device)
19+
inp2 = torch.randn(shape, dtype=dtype, device=flag_gems.device)
20+
ref_inp1 = to_reference(inp1)
21+
ref_inp2 = to_reference(inp2)
22+
23+
ref_out = torch.rsub(ref_inp1, ref_inp2)
24+
with flag_gems.use_gems():
25+
res_out = torch.rsub(inp1, inp2)
26+
27+
gems_assert_close(res_out, ref_out, dtype)
28+
29+
30+
@pytest.mark.rsub_scalar
31+
@pytest.mark.parametrize("shape", POINTWISE_SHAPES)
32+
@pytest.mark.parametrize("dtype", FLOAT_DTYPES)
33+
def test_rsub_scalar(shape, dtype):
34+
inp1 = torch.randn(shape, dtype=dtype, device=flag_gems.device)
35+
ref_inp1 = to_reference(inp1)
36+
inp2 = 0.5
37+
38+
ref_out = torch.rsub(ref_inp1, inp2)
39+
with flag_gems.use_gems():
40+
res_out = torch.rsub(inp1, inp2)
41+
42+
gems_assert_close(res_out, ref_out, dtype)

0 commit comments

Comments
 (0)