Skip to content

Commit c27a739

Browse files
committed
Merge remote-tracking branch 'upstream/master' into pr/_fake_quantize_learnable_per_channel_affine_backward
2 parents f877976 + 6c80b09 commit c27a739

52 files changed

Lines changed: 5782 additions & 9 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import pytest
2+
import torch
3+
4+
from . import base, consts
5+
6+
7+
class NormBenchmark(base.GenericBenchmark):
8+
def set_more_shapes(self):
9+
return [
10+
# 3D shapes represented as [batch_size, channels, hidden_size]
11+
(16, 16, 64),
12+
(16, 16, 1024),
13+
(16, 16, 4098),
14+
# 4D shapes represented as [batch_size, channels, H, W]
15+
(1, 8, 4, 4),
16+
(16, 8, 128, 128),
17+
]
18+
19+
20+
@pytest.mark.batch_norm_impl_index
21+
def test__batch_norm_impl_index():
22+
def batch_norm_impl_index_input_fn(shape, dtype, device):
23+
C = shape[1]
24+
inp = torch.randn(shape, dtype=dtype, device=device)
25+
weight = torch.randn(C, dtype=dtype, device=device)
26+
bias = torch.randn(C, dtype=dtype, device=device)
27+
running_mean = torch.zeros(C, dtype=dtype, device=device)
28+
running_var = torch.ones(C, dtype=dtype, device=device)
29+
yield inp, weight, bias, running_mean, running_var, True, 0.1, 1e-5, True
30+
31+
bench = NormBenchmark(
32+
input_fn=batch_norm_impl_index_input_fn,
33+
op_name="_batch_norm_impl_index",
34+
torch_op=torch._batch_norm_impl_index,
35+
dtypes=consts.FLOAT_DTYPES,
36+
)
37+
from flag_gems.ops._batch_norm_impl_index import batch_norm_impl_index as gems_bn
38+
39+
bench.set_gems(gems_bn)
40+
bench.run()
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import pytest
2+
import torch
3+
4+
from . import base, consts
5+
6+
# Shapes for adaptive_avg_pool3d backward benchmark
7+
ADAPTIVE_AVG_POOL3D_BACKWARD_SHAPES = [
8+
(1, 3, 8, 8, 8),
9+
(2, 3, 16, 16, 16),
10+
(1, 1, 32, 32, 32),
11+
(4, 8, 64, 64, 64),
12+
]
13+
14+
15+
class AdaptiveAvgPool3DBackwardBenchmark(base.Benchmark):
16+
def set_shapes(self, shape_file_path=None):
17+
self.shapes = ADAPTIVE_AVG_POOL3D_BACKWARD_SHAPES
18+
self.output_sizes = [(4, 4, 4), (8, 8, 8), (16, 16, 16), (32, 32, 32)]
19+
20+
def get_input_iter(self, cur_dtype):
21+
for shape, output_size in zip(self.shapes, self.output_sizes):
22+
x = torch.randn(shape, dtype=cur_dtype, device=self.device)
23+
# Compute forward to get output shape
24+
out = torch.nn.functional.adaptive_avg_pool3d(x, output_size)
25+
grad = torch.ones_like(out)
26+
yield grad, x
27+
28+
29+
@pytest.mark.adaptive_avg_pool3d_backward
30+
def test_adaptive_avg_pool3d_backward():
31+
bench = AdaptiveAvgPool3DBackwardBenchmark(
32+
op_name="adaptive_avg_pool3d_backward",
33+
torch_op=torch.ops.aten._adaptive_avg_pool3d_backward,
34+
dtypes=consts.FLOAT_DTYPES,
35+
)
36+
bench.run()

benchmark/test_addbmm_.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import pytest
2+
import torch
3+
4+
from . import base, consts
5+
6+
7+
def _input_fn(b, m, n, k, dtype, device, b_column_major):
8+
inp1 = torch.randn([b, m, k], dtype=dtype, device=device, requires_grad=True)
9+
10+
if b_column_major:
11+
inp2 = torch.randn([b, n, k], dtype=dtype, device=device, requires_grad=True)
12+
inp2 = inp2.transpose(1, 2).contiguous()
13+
else:
14+
inp2 = torch.randn([b, k, n], dtype=dtype, device=device, requires_grad=True)
15+
16+
# addbmm_ is inplace, bias must not require grad (leaf tensor constraint)
17+
bias = torch.randn([m, n], dtype=dtype, device=device, requires_grad=False)
18+
19+
yield bias, inp1, inp2
20+
21+
22+
@pytest.mark.addbmm_
23+
def test_addbmm_():
24+
bench = base.BlasBenchmark(
25+
op_name="addbmm_",
26+
input_fn=_input_fn,
27+
torch_op=lambda bias, inp1, inp2: bias.addbmm_(inp1, inp2),
28+
dtypes=consts.FLOAT_DTYPES,
29+
)
30+
bench.run()

benchmark/test_addr_.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Generated by KernelGen: https://github.com/flagos-ai/KernelGen
2+
from typing import Generator
3+
4+
import pytest
5+
import torch
6+
7+
from . import base, consts
8+
9+
10+
class AddrInplaceBenchmark(base.BlasBenchmark):
11+
def set_more_shapes(self):
12+
return []
13+
14+
def get_input_iter(self, dtype) -> Generator:
15+
for shape in self.shapes:
16+
m, n = shape[0], shape[1]
17+
yield from self.input_fn(m, n, dtype, self.device)
18+
19+
20+
def _input_fn(m, n, cur_dtype, device):
21+
inp1 = torch.randn([m, n], dtype=cur_dtype, device=device)
22+
inp2 = torch.randn([m], dtype=cur_dtype, device=device)
23+
inp3 = torch.randn([n], dtype=cur_dtype, device=device)
24+
yield inp1, inp2, inp3, {"alpha": 0.5, "beta": 0.5}
25+
26+
27+
@pytest.mark.addr_
28+
def test_addr_():
29+
bench = AddrInplaceBenchmark(
30+
op_name="addr_",
31+
input_fn=_input_fn,
32+
torch_op=torch.Tensor.addr_,
33+
dtypes=consts.FLOAT_DTYPES,
34+
)
35+
bench.run()

benchmark/test_avg_pool1d.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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+
from typing import Generator
16+
17+
import pytest
18+
import torch
19+
20+
from . import base, consts, utils
21+
22+
23+
class AvgPool1dBenchmark(base.GenericBenchmark):
24+
def get_input_iter(self, dtype) -> Generator:
25+
shapes_3d = [
26+
(4, 3, 224),
27+
(16, 64, 128),
28+
(32, 128, 64),
29+
(64, 256, 32),
30+
(128, 512, 16),
31+
]
32+
33+
for shape in shapes_3d:
34+
yield from self.input_fn(shape, dtype, self.device)
35+
36+
37+
def avg_pool1d_input_fn(shape, dtype, device):
38+
inp = utils.generate_tensor_input(shape, dtype, device)
39+
40+
# Common case
41+
yield inp, {
42+
"kernel_size": [3],
43+
"stride": [2],
44+
"padding": [1],
45+
"ceil_mode": False,
46+
"count_include_pad": True,
47+
}
48+
49+
if base.Config.bench_level == consts.BenchLevel.COMPREHENSIVE:
50+
# With count_include_pad=False
51+
yield inp, {
52+
"kernel_size": [3],
53+
"stride": [2],
54+
"padding": [1],
55+
"ceil_mode": False,
56+
"count_include_pad": False,
57+
}
58+
59+
# With ceil_mode
60+
yield inp, {
61+
"kernel_size": [3],
62+
"stride": [2],
63+
"padding": [1],
64+
"ceil_mode": True,
65+
"count_include_pad": True,
66+
}
67+
68+
69+
@pytest.mark.avg_pool1d
70+
def test_avg_pool1d():
71+
bench = AvgPool1dBenchmark(
72+
input_fn=avg_pool1d_input_fn,
73+
op_name="avg_pool1d",
74+
torch_op=torch.ops.aten.avg_pool1d,
75+
dtypes=consts.FLOAT_DTYPES,
76+
)
77+
bench.run()

benchmark/test_cdist.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import pytest
2+
import torch
3+
4+
from . import base
5+
6+
# Shapes for cdist benchmark: (P, M), (R, M) -> (P, R)
7+
# torch.cdist doesn't support float16 on CUDA
8+
CDIST_SHAPES = [
9+
((4, 8), (6, 8)),
10+
((8, 16), (8, 16)),
11+
((16, 32), (16, 32)),
12+
((32, 64), (32, 64)),
13+
((64, 128), (64, 128)),
14+
]
15+
16+
17+
class CdistBenchmark(base.Benchmark):
18+
def set_shapes(self, shape_file_path=None):
19+
self.shapes = CDIST_SHAPES
20+
21+
def get_input_iter(self, cur_dtype):
22+
for shape1, shape2 in self.shapes:
23+
x1 = torch.randn(*shape1, dtype=cur_dtype, device=self.device)
24+
x2 = torch.randn(*shape2, dtype=cur_dtype, device=self.device)
25+
yield x1, x2, 2.0
26+
27+
def get_tflops(self, op, *args, **kwargs):
28+
x1, x2, _ = args
29+
# FLOPs = 2 * P * R * M (for L2 distance computation)
30+
return 2 * x1.shape[-2] * x2.shape[-2] * x1.shape[-1]
31+
32+
33+
@pytest.mark.cdist
34+
def test_cdist():
35+
bench = CdistBenchmark(
36+
op_name="cdist",
37+
torch_op=torch.cdist,
38+
# torch.cdist doesn't support float16 on CUDA; only float32 is numerically stable
39+
dtypes=[torch.float32],
40+
)
41+
bench.run()

benchmark/test_dropout.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ def test_dropout():
3838
bench.run()
3939

4040

41-
@pytest.mark.dropout_backward
41+
@pytest.mark.native_dropout_backward
4242
@pytest.mark.skipif(
4343
flag_gems.vendor_name == "tsingmicro", reason="Issue #4131: not working"
4444
)
45-
def test_dropout_backward():
45+
def test_native_dropout_backward():
4646
bench = base.GenericBenchmark(
47-
op_name="dropout_backward",
47+
op_name="native_dropout_backward",
4848
input_fn=_dropout_backward_input_fn,
4949
torch_op=torch.ops.aten.native_dropout_backward,
5050
dtypes=consts.FLOAT_DTYPES,

benchmark/test_empty.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,23 @@ def empty_input_fn(shape, dtype, device):
2222
yield shape
2323

2424

25+
def empty_permuted_input_fn(shape, dtype, device):
26+
# Reverse the physical layout so the allocation exercises a non-contiguous
27+
# memory ordering rather than the plain contiguous one.
28+
yield shape, list(reversed(range(len(shape))))
29+
30+
31+
@pytest.mark.empty_permuted
32+
def test_empty_permuted():
33+
bench = base.GenericBenchmark(
34+
op_name="empty_permuted",
35+
torch_op=torch.empty_permuted,
36+
dtypes=consts.FLOAT_DTYPES,
37+
input_fn=empty_permuted_input_fn,
38+
)
39+
bench.run()
40+
41+
2542
@pytest.mark.empty
2643
def test_empty():
2744
bench = base.GenericBenchmark(
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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 pytest
16+
import torch
17+
18+
from . import base, consts
19+
20+
21+
@pytest.mark.fake_quantize_per_channel_affine
22+
def test_fake_quantize_per_channel_affine():
23+
class BenchmarkFakeQuantizePerChannelAffine(base.Benchmark):
24+
"""
25+
Benchmark fake_quantize_per_channel_affine operator
26+
"""
27+
28+
axis_configs = (0, 1)
29+
DEFAULT_SHAPES = [
30+
(4, 4),
31+
(64, 64),
32+
(128, 256),
33+
(512, 512),
34+
(1024, 1024),
35+
(2, 3, 128, 128),
36+
(8, 16, 64, 64),
37+
]
38+
39+
def set_shapes(self, shape_file_path=None):
40+
self.shapes = self.DEFAULT_SHAPES
41+
42+
def get_input_iter(self, dtype):
43+
for shape in self.shapes:
44+
for axis in self.axis_configs:
45+
if axis >= len(shape):
46+
continue
47+
inp = torch.randn(shape, dtype=dtype, device="cuda")
48+
n_channels = shape[axis]
49+
scale = (
50+
torch.rand(n_channels, dtype=torch.float32, device="cuda") * 0.1
51+
+ 0.01
52+
)
53+
zero_point = torch.zeros(
54+
n_channels, dtype=torch.int32, device="cuda"
55+
)
56+
quant_min = 0
57+
quant_max = 255
58+
yield inp, scale, zero_point, axis, quant_min, quant_max
59+
60+
def forward(self, inp, scale, zero_point, axis, quant_min, quant_max):
61+
return torch.fake_quantize_per_channel_affine(
62+
inp, scale, zero_point, axis, quant_min, quant_max
63+
)
64+
65+
bench = BenchmarkFakeQuantizePerChannelAffine(
66+
op_name="fake_quantize_per_channel_affine",
67+
torch_op=torch.fake_quantize_per_channel_affine,
68+
dtypes=consts.FLOAT_DTYPES,
69+
)
70+
bench.run()

0 commit comments

Comments
 (0)