Skip to content

Commit faa7a2b

Browse files
committed
[KernelGen] Support bfloat16 for bitwise_not bitwise_or div embedding logical_and polar on Ascend and update tests & benchmark
1 parent c0868b3 commit faa7a2b

12 files changed

Lines changed: 890 additions & 108 deletions

benchmark/test_binary_pointwise_perf.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,27 @@
77
from benchmark.performance_utils import Benchmark, generate_tensor_input
88

99

10+
def _polar_baseline(abs, angle):
11+
if abs.dtype == torch.bfloat16:
12+
return torch.polar(abs.to(torch.float32), angle.to(torch.float32))
13+
return torch.polar(abs, angle)
14+
15+
16+
def _bitwise_or_baseline(a, b):
17+
if a.dtype == torch.bfloat16:
18+
return torch.bitwise_or(a.view(torch.int16), b.view(torch.int16)).view(
19+
torch.bfloat16
20+
)
21+
return torch.bitwise_or(a, b)
22+
23+
24+
def _bitwise_or_inplace_baseline(a, b):
25+
if a.dtype == torch.bfloat16:
26+
a.view(torch.int16).bitwise_or_(b.view(torch.int16))
27+
return a
28+
return a.bitwise_or_(b)
29+
30+
1031
class BinaryPointwiseBenchmark(Benchmark):
1132
"""
1233
Base class for benchmarking binary pointwise operations.
@@ -47,11 +68,11 @@ def get_tflops(self, op, *args, **kwargs):
4768
("mul", torch.mul, FLOAT_DTYPES),
4869
("sub", torch.sub, FLOAT_DTYPES),
4970
("pow", torch.pow, FLOAT_DTYPES),
50-
("polar", torch.polar, [torch.float32]),
71+
("polar", _polar_baseline, [torch.float32, torch.bfloat16]),
5172
("floor_divide", torch.floor_divide, INT_DTYPES),
5273
("remainder", torch.remainder, INT_DTYPES),
5374
("logical_or", torch.logical_or, INT_DTYPES + BOOL_DTYPES),
54-
("logical_and", torch.logical_and, INT_DTYPES + BOOL_DTYPES),
75+
("logical_and", torch.logical_and, FLOAT_DTYPES + INT_DTYPES + BOOL_DTYPES),
5576
("logical_xor", torch.logical_xor, INT_DTYPES + BOOL_DTYPES),
5677
# Comparison operations
5778
("eq", torch.eq, FLOAT_DTYPES),
@@ -66,7 +87,7 @@ def get_tflops(self, op, *args, **kwargs):
6687
("minimum", torch.minimum, FLOAT_DTYPES),
6788
# Bitwise operations
6889
("bitwise_and", torch.bitwise_and, INT_DTYPES + BOOL_DTYPES),
69-
("bitwise_or", torch.bitwise_or, INT_DTYPES + BOOL_DTYPES),
90+
("bitwise_or", _bitwise_or_baseline, INT_DTYPES + BOOL_DTYPES + [torch.bfloat16]),
7091
# Numerical Checks
7192
("isclose", torch.isclose, FLOAT_DTYPES + INT_DTYPES),
7293
("allclose", torch.allclose, FLOAT_DTYPES + INT_DTYPES),
@@ -97,10 +118,10 @@ def test_general_binary_pointwise_perf(op_name, torch_op, dtypes):
97118
("floor_divide_", lambda a, b: a.floor_divide_(b), INT_DTYPES),
98119
("remainder_", lambda a, b: a.remainder_(b), INT_DTYPES),
99120
("logical_or_", lambda a, b: a.logical_or_(b), INT_DTYPES + BOOL_DTYPES),
100-
("logical_and_", lambda a, b: a.logical_and_(b), INT_DTYPES + BOOL_DTYPES),
121+
("logical_and_", lambda a, b: a.logical_and_(b), FLOAT_DTYPES + INT_DTYPES + BOOL_DTYPES),
101122
# Bitwise operations
102123
("bitwise_and_", lambda a, b: a.bitwise_and_(b), INT_DTYPES + BOOL_DTYPES),
103-
("bitwise_or_", lambda a, b: a.bitwise_or_(b), INT_DTYPES + BOOL_DTYPES),
124+
("bitwise_or_", _bitwise_or_inplace_baseline, INT_DTYPES + BOOL_DTYPES + [torch.bfloat16]),
104125
]
105126
],
106127
)

benchmark/test_special_perf.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -365,10 +365,7 @@ def test_perf_embedding():
365365
input_fn=embedding_input_fn,
366366
op_name="embedding",
367367
torch_op=torch.nn.functional.embedding,
368-
dtypes=[
369-
torch.float32,
370-
torch.float16,
371-
], # Note(Zhengzekang): triton do not support bfloat16 atomic add which is used in embedding grad.
368+
dtypes=FLOAT_DTYPES,
372369
)
373370
bench.run()
374371

@@ -379,10 +376,7 @@ def test_perf_embedding_backward():
379376
input_fn=embedding_backward_input_fn,
380377
op_name="embedding",
381378
torch_op=torch.nn.functional.embedding,
382-
dtypes=[
383-
torch.float32,
384-
torch.float16,
385-
], # Note(Zhengzekang): triton do not support bfloat16 atomic add which is used in embedding grad.
379+
dtypes=FLOAT_DTYPES,
386380
is_backward=True,
387381
)
388382
bench.run()

benchmark/test_unary_pointwise_perf.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@
1717
fp64_is_supported = flag_gems.runtime.device.support_fp64
1818

1919

20+
def _bitwise_not_baseline(a):
21+
if a.dtype == torch.bfloat16:
22+
return torch.bitwise_not(a.view(torch.int16)).view(torch.bfloat16)
23+
return torch.bitwise_not(a)
24+
25+
26+
def _bitwise_not_inplace_baseline(a):
27+
if a.dtype == torch.bfloat16:
28+
a.view(torch.int16).bitwise_not_()
29+
return a
30+
return a.bitwise_not_()
31+
32+
2033
class UnaryPointwiseBenchmark(Benchmark):
2134
"""
2235
Base class for benchmarking unary pointwise operations.
@@ -72,7 +85,7 @@ def get_tflops(self, op, *args, **kwargs):
7285
("atan", torch.atan, FLOAT_DTYPES),
7386
("acos", torch.acos, FLOAT_DTYPES),
7487
# Bitwise operations
75-
("bitwise_not", torch.bitwise_not, INT_DTYPES),
88+
("bitwise_not", _bitwise_not_baseline, INT_DTYPES + [torch.bfloat16]),
7689
# Numerical Checks
7790
("isinf", torch.isinf, FLOAT_DTYPES),
7891
("isnan", torch.isnan, FLOAT_DTYPES),
@@ -127,7 +140,7 @@ def test_general_unary_pointwise_perf(op_name, torch_op, dtypes):
127140
("tanh_", torch.tanh_, FLOAT_DTYPES),
128141
("atan_", torch.atan_, FLOAT_DTYPES),
129142
# Bitwise operations
130-
("bitwise_not_", lambda a: a.bitwise_not_(), INT_DTYPES),
143+
("bitwise_not_", _bitwise_not_inplace_baseline, INT_DTYPES + [torch.bfloat16]),
131144
]
132145

133146

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

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22
from .all import all, all_dim, all_dims
33
from .amax import amax
44
from .angle import angle
5+
from .bitwise_not import bitwise_not, bitwise_not_
6+
from .bitwise_or import (
7+
bitwise_or_scalar,
8+
bitwise_or_scalar_,
9+
bitwise_or_scalar_tensor,
10+
bitwise_or_tensor,
11+
bitwise_or_tensor_,
12+
)
513
from .any import any, any_dim, any_dims
614
from .arange import arange
715
from .argmax import argmax
@@ -10,6 +18,17 @@
1018
from .cat import cat
1119
from .count_nonzero import count_nonzero
1220
from .cumsum import cumsum, normed_cumsum
21+
from .div import (
22+
div_mode,
23+
div_mode_,
24+
floor_divide,
25+
floor_divide_,
26+
true_divide,
27+
true_divide_,
28+
true_divide_out,
29+
trunc_divide,
30+
trunc_divide_,
31+
)
1332
from .diag import diag
1433
from .diag_embed import diag_embed
1534
from .diagonal import diagonal_backward
@@ -28,6 +47,7 @@
2847
from .index_select import index_select
2948
from .isin import isin
3049
from .linspace import linspace
50+
from .logical_and import logical_and, logical_and_
3151
from .log_softmax import log_softmax, log_softmax_backward
3252
from .masked_fill import masked_fill, masked_fill_
3353
from .masked_select import masked_select
@@ -148,9 +168,27 @@
148168
"any_dims",
149169
"any_dim",
150170
"angle",
171+
"bitwise_not",
172+
"bitwise_not_",
173+
"bitwise_or_scalar",
174+
"bitwise_or_scalar_",
175+
"bitwise_or_scalar_tensor",
176+
"bitwise_or_tensor",
177+
"bitwise_or_tensor_",
151178
"multinomial",
152179
"index_add",
153180
"_unique2",
154181
"upsample_nearest2d",
155182
"randperm",
183+
"true_divide",
184+
"true_divide_",
185+
"true_divide_out",
186+
"trunc_divide",
187+
"trunc_divide_",
188+
"floor_divide",
189+
"floor_divide_",
190+
"div_mode",
191+
"div_mode_",
192+
"logical_and",
193+
"logical_and_",
156194
]
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import logging
2+
3+
import torch
4+
import triton
5+
6+
from flag_gems.utils import pointwise_dynamic
7+
8+
logger = logging.getLogger(f'flag_gems.runtime._ascend.ops.{__name__.split(".")[-1]}')
9+
10+
11+
@pointwise_dynamic(promotion_methods=[(0, "DEFAULT")])
12+
@triton.jit
13+
def bitwise_not_func(x):
14+
return ~x
15+
16+
17+
def bitwise_not(A):
18+
logger.debug("GEMS_ASCEND BITWISE NOT")
19+
if A.dtype == torch.bfloat16:
20+
return bitwise_not_func(A.view(torch.int16)).view(torch.bfloat16)
21+
return bitwise_not_func(A)
22+
23+
24+
def bitwise_not_(A):
25+
logger.debug("GEMS_ASCEND BITWISE NOT_")
26+
if A.dtype == torch.bfloat16:
27+
bitwise_not_func(A.view(torch.int16), out0=A.view(torch.int16))
28+
return A
29+
bitwise_not_func(A, out0=A)
30+
return A
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import logging
2+
3+
import torch
4+
import triton
5+
6+
from flag_gems.utils import pointwise_dynamic
7+
8+
logger = logging.getLogger(f'flag_gems.runtime._ascend.ops.{__name__.split(".")[-1]}')
9+
10+
11+
@pointwise_dynamic(promotion_methods=[(0, 1, "DEFAULT")])
12+
@triton.jit
13+
def bitwise_or_func(x, y):
14+
return x | y
15+
16+
17+
def bitwise_or_tensor(A, B):
18+
logger.debug("GEMS_ASCEND BITWISE OR")
19+
if A.dtype == torch.bfloat16:
20+
return bitwise_or_func(
21+
A.view(torch.int16), B.view(torch.int16)
22+
).view(torch.bfloat16)
23+
return bitwise_or_func(A, B)
24+
25+
26+
def bitwise_or_tensor_(A, B):
27+
logger.debug("GEMS_ASCEND BITWISE OR_")
28+
if A.dtype == torch.bfloat16:
29+
bitwise_or_func(A.view(torch.int16), B.view(torch.int16), out0=A.view(torch.int16))
30+
return A
31+
return bitwise_or_func(A, B, out0=A)
32+
33+
34+
@pointwise_dynamic(is_tensor=[True, False], promotion_methods=[(0, 1, "DEFAULT")])
35+
@triton.jit
36+
def bitwise_or_func_scalar(x, y):
37+
return x | y
38+
39+
40+
def bitwise_or_scalar(A, B):
41+
logger.debug("GEMS_ASCEND BITWISE OR SCALAR")
42+
if A.dtype == torch.bfloat16:
43+
return bitwise_or_func_scalar(
44+
A.view(torch.int16), int(B)
45+
).view(torch.bfloat16)
46+
return bitwise_or_func_scalar(A, B)
47+
48+
49+
def bitwise_or_scalar_(A, B):
50+
logger.debug("GEMS_ASCEND BITWISE OR_ SCALAR")
51+
if A.dtype == torch.bfloat16:
52+
bitwise_or_func_scalar(A.view(torch.int16), int(B), out0=A.view(torch.int16))
53+
return A
54+
return bitwise_or_func_scalar(A, B, out0=A)
55+
56+
57+
def bitwise_or_scalar_tensor(A, B):
58+
logger.debug("GEMS_ASCEND BITWISE OR SCALAR TENSOR")
59+
if B.dtype == torch.bfloat16:
60+
return bitwise_or_func_scalar(
61+
B.view(torch.int16), int(A)
62+
).view(torch.bfloat16)
63+
return bitwise_or_func_scalar(B, A)

0 commit comments

Comments
 (0)